Delphi什么时候尊重`inline`而什么时候不?

Joh*_*ica 5 delphi optimization inline delphi-2007

我想要优化一段具有这种结构的代码:

while (i > 0) do begin
  Dec(i);
Run Code Online (Sandbox Code Playgroud)

这看起来效率低下,所以我尝试这样做:

while (Dec(i) >= 0) do begin
Run Code Online (Sandbox Code Playgroud)

这不起作用,因为Dec是一个过程而不是一个函数.

所以我把它重写为:

procedure Withloop;
var
  ....
  function Decr(var a: integer): integer; inline;
  begin
    Dec(a);
    Result:= a;
  end;

...
  while (Decr(i) >= 0) do begin
Run Code Online (Sandbox Code Playgroud)

但这会编译成:

SDIMAIN.pas.448: while (Decr(i) >= 0) do begin
00468EE5 8BC4             mov eax,esp
00468EE7 E8D0FEFFFF       call Decr          <<--- A call??
00468EEC 85C0             test eax,eax
00468EEE 0F8D12FFFFFF     jnl $00468e06
00468EF4 EB01             jmp $00468ef7
Run Code Online (Sandbox Code Playgroud)

然而,在程序的另一部分,它内联函数就好了.
我可以使用哪些经验法则(或硬规则)来了解Delphi将遵守该inline指令?

RRU*_*RUZ 22

Delphi Documentation列举在其下内联或不发生的条件:

  • 任何形式的后期绑定方法都不会进行内联.这包括虚拟,动态和消息方法.
  • 包含汇编代码的例程将不会内联.
  • 构造函数和析构函数不会被内联.
  • 无法内联主程序块,单元初始化和单元终结块.
  • 使用前未定义的例程无法内联.
  • 采用打开数组参数的例程无法内联.
  • 代码可以在包中内联,但是,内联不会跨包边界发生.
  • 在循环相关的单元之间不进行内联.这包括间接循环依赖,例如,单元A使用单元B,单元B使用单元C,单元C又使用单元A.在这个例子中,当编译单元A时,单元B或单元C的代码不会以单元内联一个.
  • 只要要内联的代码来自循环关系之外的单元,编译器就可以在单元处于循环依赖关系时内联代码.在上面的例子中,如果单元A也使用单元D,则单元D中的代码可以在A中内联,因为它不涉及循环依赖性.
  • 如果在接口部分中定义了例程并且它访问了实现部分中定义的符号,则无法内联该例程.
  • 如果标有内联的例程使用来自其他单元的外部符号,则必须在uses语句中列出所有这些单元,否则不能内联例程.
  • while-do和repeat-until语句中的条件表达式中使用的过程和函数不能内联扩展.
  • 在一个单元内,应该在调用函数之前定义内联函数的主体.否则,编译器到达调用站点时不知道的函数体不能内联扩展.

在您的情况下检查这种情况:

while-do和repeat-until语句中的条件表达式中使用的过程和函数不能内联扩展.


klu*_*udg 10

由于某种原因,编译器不内联while循环控制表达式.Hallvard Vassbotn不久前讨论了这个问题(阅读文章的最后部分).

  • 最后一部分或文章的快速摘要:`如果Decr(i)<0则为True,则为Break;`inline Decr. (3认同)