delphi – 为什么优化器不会在循环中消除High?

人们表示,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

据我所知,它在循环中一遍又一遍地调用High()函数

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

相关文章

ffmpeg 是一套强大的开源的多媒体库 一般都是用 c/c++ 调用, 抽空研究了一下该库的最新版 ,把...
32位CPU所含有的寄存器有:4个数据寄存器(EAX、EBX、ECX和EDX)2个变址和指针寄存器(ESI和EDI) 2个指针寄...
1 mov dst, src dst是目的操作数,src是源操作数,指令实现的功能是:将源操作数送到目的操作数中,即:...
有三个API函数可以运行可执行文件WinExec、ShellExecute和CreateProcess。 1.CreateProcess因为使用复杂...
API原型: Declare Function MoveFileEx& Lib "kernel32" Alias "MoveFileExA" (By...