jus*_*tyy 10 delphi compiler-construction compiler-optimization
人们说Delphi在整数运算上产生了相当不错的优化代码.我在Delphi 2007中尝试以下示例,并查看编译器生成的汇编代码.
program p1000;
{$APPTYPE CONSOLE}
procedure test;
var
arr: array of integer;
i: integer;
begin
SetLength(arr, 100);
for i := 0 to High(arr) do
begin
if (i = High(arr)) then
begin
arr[i] := -9;
end;
end;
end;
begin
test;
readln;
end.
Run Code Online (Sandbox Code Playgroud)
当构建配置设置为DEBUG时,我可以设置断点并使用短键Ctrl+ Alt+ D来查看其汇编代码,如下所示:
Project3.dpr.11: for i := 0 to High(arr) do
004045A1 8B45FC mov eax,[ebp-$04]
004045A4 E8F7FAFFFF call @DynArrayHigh
004045A9 8BF0 mov esi,eax
004045AB 85F6 test esi,esi
004045AD 7C1D jl $004045cc
004045AF 46 inc esi
004045B0 33DB xor ebx,ebx
Project3.dpr.13: if (i = High(arr)) then
004045B2 8B45FC mov eax,[ebp-$04]
004045B5 E8E6FAFFFF **call @DynArrayHigh**
004045BA 3BD8 cmp ebx,eax
004045BC 750A jnz $004045c8
Project3.dpr.15: arr[i] := -9;
004045BE 8B45FC mov eax,[ebp-$04]
004045C1 C70498F7FFFFFF mov [eax+ebx*4],$fffffff7
Project3.dpr.17: end;
004045C8 43 inc ebx
Project3.dpr.11: for i := 0 to High(arr) do
004045C9 4E dec esi
004045CA 75E6 jnz $004045b2
Run Code Online (Sandbox Code Playgroud)
据我所知,它High()在循环中一次又一次地调用函数:
Project3.dpr.13: if (i = High(arr)) then
004045B2 8B45FC mov eax,[ebp-$04]
004045B5 E8E6FAFFFF **call @DynArrayHigh**
004045BA 3BD8 cmp ebx,eax
Run Code Online (Sandbox Code Playgroud)
当构建配置设置为RELEASE时,断点不可用,所以我按F8/ F7进入循环.
00404589 6A64 push $64
0040458B 8D45FC lea eax,[ebp-$04]
0040458E B901000000 mov ecx,$00000001
00404593 8B1554454000 mov edx,[$00404554]
00404599 E8B6FCFFFF call @DynArraySetLength
0040459E 83C404 add esp,$04
004045A1 8B45FC mov eax,[ebp-$04]
004045A4 E8F7FAFFFF call @DynArrayHigh
004045A9 8BF0 mov esi,eax
004045AB 85F6 test esi,esi
004045AD 7C1D jl $004045cc
004045AF 46 inc esi
004045B0 33DB xor ebx,ebx
004045B2 8B45FC mov eax,[ebp-$04]
004045B5 E8E6FAFFFF call @DynArrayHigh
004045BA 3BD8 cmp ebx,eax
004045BC 750A jnz $004045c8
004045BE 8B45FC mov eax,[ebp-$04]
004045C1 C70498F7FFFFFF mov [eax+ebx*4],$fffffff7
004045C8 43 inc ebx
004045C9 4E dec esi
004045CA 75E6 jnz $004045b2
004045CC 33C0 xor eax,eax
004045BC 750A jnz $004045c8
Run Code Online (Sandbox Code Playgroud)
再次,同样call @DynArrayHigh的产生...
所以我的问题是,为什么编译器不能优化这个?只需将High()值保存在本地寄存器/变量中,因为数组大小不会更改.
这不是答案,而是(自毁)评论:)
在我看来,编译器不能尝试优化它.
为什么编译器会尝试优化(非确定性)High函数而不是其他函数?(如Length)
在动态阵列长度可能在循环或者通过内被改变SetLenth,或通过其它手段.该数组可能在运行时重新启动,您的代码可能依赖于:
for i := 0 to High(arr) do
begin
if (i = High(arr)) then
arr[i] := -9
else
if foo() then
arr := nil; // or SetLength(arr, 0);
if High(arr) = -1 then Exit; // arr is nil
end;
Run Code Online (Sandbox Code Playgroud)
你怎么建议这应该优化?编译器是否应该尝试对此进行优化?即使编译器将其转换为,我也没有看到关于functionm的任何特殊内容.High@DynArrayHigh
如果你希望你的代码进行优化,优化它自己 .eg:
var
arrHigh: Integer;
arrHigh := High(arr);
for i := 0 to arrHigh do
if i = arrHigh then...
Run Code Online (Sandbox Code Playgroud)