Оптимизация foreach в for для многократного ускорения цикла для IList<T> (массивов, списков)

Не работает в лямбдах! (техническое ограничение)

Плагин запуска ILDasm
This commit is contained in:
Mikhalkovich Stanislav 2019-12-25 08:43:01 +03:00
parent 3d845a4e80
commit c94b1037cc
7 changed files with 83 additions and 9 deletions

View file

@ -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;

View file

@ -1,4 +1,4 @@
%MINOR%=5 %MINOR%=5
%REVISION%=2281 %REVISION%=2287
%COREVERSION%=1 %COREVERSION%=1
%MAJOR%=3 %MAJOR%=3

View file

@ -1 +1 @@
3.5.1.2281 3.5.1.2287

View file

@ -1 +1 @@
!define VERSION '3.5.1.2281' !define VERSION '3.5.1.2287'

View 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.

View file

@ -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);

View file

@ -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;
} }