Оптимизация foreach в for для многократного ускорения цикла для IList<T> (массивов, списков)
Не работает в лямбдах! (техническое ограничение) Плагин запуска ILDasm
This commit is contained in:
parent
3d845a4e80
commit
c94b1037cc
|
|
@ -15,7 +15,7 @@ internal static class RevisionClass
|
||||||
public const string Major = "3";
|
public const string Major = "3";
|
||||||
public const string Minor = "5";
|
public const string Minor = "5";
|
||||||
public const string Build = "1";
|
public const string Build = "1";
|
||||||
public const string Revision = "2281";
|
public const string Revision = "2287";
|
||||||
|
|
||||||
public const string MainVersion = Major + "." + Minor;
|
public const string MainVersion = Major + "." + Minor;
|
||||||
public const string FullVersion = Major + "." + Minor + "." + Build + "." + Revision;
|
public const string FullVersion = Major + "." + Minor + "." + Build + "." + Revision;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
%MINOR%=5
|
%MINOR%=5
|
||||||
%REVISION%=2281
|
%REVISION%=2287
|
||||||
%COREVERSION%=1
|
%COREVERSION%=1
|
||||||
%MAJOR%=3
|
%MAJOR%=3
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
3.5.1.2281
|
3.5.1.2287
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
!define VERSION '3.5.1.2281'
|
!define VERSION '3.5.1.2287'
|
||||||
|
|
|
||||||
26
TestSuite/Foreach_to_for.pas
Normal file
26
TestSuite/Foreach_to_for.pas
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
type Person = class
|
||||||
|
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure P(a: array of Person);
|
||||||
|
begin
|
||||||
|
var s: Person;
|
||||||
|
foreach var x in a do
|
||||||
|
s := x;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure P<T>(a: array of T);
|
||||||
|
begin
|
||||||
|
var s: T;
|
||||||
|
foreach var x in a do
|
||||||
|
s := x;
|
||||||
|
end;
|
||||||
|
|
||||||
|
begin
|
||||||
|
var n := 5000;
|
||||||
|
var a := ArrFill(n,1);
|
||||||
|
var s := 0;
|
||||||
|
foreach var x in a do
|
||||||
|
s += x;
|
||||||
|
Assert(s = n);
|
||||||
|
end.
|
||||||
|
|
@ -13,6 +13,22 @@ namespace PascalABCCompiler.TreeConverter
|
||||||
|
|
||||||
public override void visit(foreach_stmt _foreach_stmt)
|
public override void visit(foreach_stmt _foreach_stmt)
|
||||||
{
|
{
|
||||||
|
// SSM 24.12.19 lambda_capture_foreach_counter.pas не проходит если откомментировать эти 2 строки
|
||||||
|
// Причина - лямбда уже начала разбираться
|
||||||
|
// Пробую сделать так: если foreach в лямбде, то оптимизация не делается, а если нет, то делается
|
||||||
|
|
||||||
|
syntax_tree_node p = _foreach_stmt;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
p = p.Parent;
|
||||||
|
} while (!(p == null || p is procedure_definition || p is function_lambda_definition));
|
||||||
|
|
||||||
|
if (!(p is function_lambda_definition)) // тогда оптимизируем
|
||||||
|
{
|
||||||
|
var feWhat = convert_strong(_foreach_stmt.in_what);
|
||||||
|
if (OptimizeForeachInCase1DArray(_foreach_stmt, feWhat)) return;
|
||||||
|
}
|
||||||
|
|
||||||
statements_list sl2 = new statements_list(get_location(_foreach_stmt));
|
statements_list sl2 = new statements_list(get_location(_foreach_stmt));
|
||||||
convertion_data_and_alghoritms.statement_list_stack_push(sl2);
|
convertion_data_and_alghoritms.statement_list_stack_push(sl2);
|
||||||
|
|
||||||
|
|
@ -120,6 +136,35 @@ namespace PascalABCCompiler.TreeConverter
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private bool IsIList(expression_node en)
|
||||||
|
{
|
||||||
|
var ii = en.type.ImplementingInterfaces;
|
||||||
|
foreach (var itn in ii)
|
||||||
|
{
|
||||||
|
System.Type tt = null;
|
||||||
|
if (itn is compiled_type_node ctn)
|
||||||
|
{
|
||||||
|
tt = ctn.compiled_type;
|
||||||
|
if (tt.IsGenericType)
|
||||||
|
tt = tt.GetGenericTypeDefinition();
|
||||||
|
if (tt == typeof(System.Collections.Generic.IList<>))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (itn is compiled_generic_instance_type_node itnc)
|
||||||
|
{
|
||||||
|
tt = (itnc.original_generic as compiled_type_node).compiled_type;
|
||||||
|
if (tt == typeof(System.Collections.Generic.IList<>))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Преобразует foreach в for, если коллекция это одномерный массив.
|
/// Преобразует foreach в for, если коллекция это одномерный массив.
|
||||||
|
|
@ -145,9 +190,10 @@ namespace PascalABCCompiler.TreeConverter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var il = IsIList(in_what);
|
||||||
|
|
||||||
// SSM 23.08.16 Закомментировал оптимизацию. Не работает с лямбдами. Лямбды обходят старое дерево. А заменить foreach на for на этом этапе пока не получается - не развита инфраструктура
|
// SSM 23.08.16 Закомментировал оптимизацию. Не работает с лямбдами. Лямбды обходят старое дерево. А заменить foreach на for на этом этапе пока не получается - не развита инфраструктура
|
||||||
|
// SSM 24.12.19 Раскомментировал оптимизацию, но только если foreach не вложен в лямбду
|
||||||
if (is1dimdynarr) // Замена foreach на for для массива
|
if (is1dimdynarr) // Замена foreach на for для массива
|
||||||
{
|
{
|
||||||
// сгенерировать код для for и вызвать соответствующий visit
|
// сгенерировать код для for и вызвать соответствующий visit
|
||||||
|
|
@ -175,7 +221,7 @@ namespace PascalABCCompiler.TreeConverter
|
||||||
var newbody = _foreach_stmt.stmt.ToStatementList();
|
var newbody = _foreach_stmt.stmt.ToStatementList();
|
||||||
newbody.AddFirst(vd);
|
newbody.AddFirst(vd);
|
||||||
|
|
||||||
var high = arrid.dot_node("Length").Minus(1);
|
var high = arrid.dot_node("Count").Minus(1);
|
||||||
|
|
||||||
var fornode = new for_node(i, 0, high, newbody, for_cycle_type.to, null, null, true);
|
var fornode = new for_node(i, 0, high, newbody, for_cycle_type.to, null, null, true);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -120,8 +120,10 @@ namespace VisualPascalABCPlugins
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
string s;
|
string s;
|
||||||
if((s= GetVS8Dir())==null) return null;
|
//if((s= GetVS8Dir())==null) return null;
|
||||||
s = s + "\\SDK\\v2.0\\bin\\ildasm.exe";
|
string program_files_x86_folder = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86);
|
||||||
|
s = program_files_x86_folder+"\\ILSpy\\ILSpy.exe";
|
||||||
|
//s = s + "\\SDK\\v2.0\\bin\\ildasm.exe";
|
||||||
if (System.IO.File.Exists(s))
|
if (System.IO.File.Exists(s))
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue