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

时间:2011-06-19 10:05:15

标签: delphi optimization inline delphi-2007

我正在努力优化一段具有此构造的代码:

while (i > 0) do begin
  Dec(i);

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

while (Dec(i) >= 0) do begin

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

所以我把它重写为:

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

...
  while (Decr(i) >= 0) do begin

但是这会编译成:

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

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

2 个答案:

答案 0 :(得分:22)

Delphi Documentation列举了内联发生或不发生的条件:

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

在你的情况下检查这个条件:

  

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

答案 1 :(得分:10)

由于某种原因,编译器没有内联while循环控制表达式。 Hallvard Vassbotn前一段时间讨论了这个问题(请阅读文章末尾)。