人们表示,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.
当构建配置设置为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
Project3.dpr.13: if (i = High(arr)) then 004045B2 8B45FC mov eax,[ebp-$04] 004045B5 E8E6FAFFFF **call @DynArrayHigh** 004045BA 3BD8 cmp ebx,eax
当构建配置设置为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,ebx 004045B2 8B45FC mov eax,[ebp-$04] 004045B5 E8E6FAFFFF call @DynArrayHigh 004045BA 3BD8 cmp ebx,eax 004045BC 750A jnz $004045c8 004045BE 8B45FC mov eax,$fffffff7 004045C8 43 inc ebx 004045C9 4E dec esi 004045CA 75E6 jnz $004045b2 004045CC 33C0 xor eax,eax 004045BC 750A jnz $004045c8
再次,同样的调用@DynArrayHigh生成…
所以我的问题是,为什么编译器不能优化这个?只需将High()值保存在本地寄存器/变量中,因为数组大小没有改变.
解决方法
这不是一个答案,而是一个(自毁)的评论:)
在我看来,编译器不能尝试优化这个.
为什么编译器试图优化(非确定性)高功能而不是其他功能? (如长度)
循环中的动态数组长度可能会由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;
你怎么建议应该优化?编译器应该甚至尝试优化吗?
即使编译器将其转换为@DynArrayHigh,我也没有看到有关High functionm的任何特别的内容.
如果您希望优化代码,请自行优化.e.g:
var arrHigh: Integer; arrHigh := High(arr); for i := 0 to arrHigh do if i = arrHigh then...