Delphi 什么时候尊重“内联”,什么时候不尊重?

发布于 2024-11-16 04:03:18 字数 820 浏览 4 评论 0原文

我试图优化一段具有以下构造的代码:

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 指令?

I was tying to optimize a piece of code that has this construct:

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

This looks inefficient, so I tried to do this:

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

That doesn't work because Dec is a procedure and not a function.

So I rewrite it to:

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

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

But this gets compiled into:

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

However in another part of the program, it inlines a function just fine.
What rule of thumb (or hard rule) can I use to know to Delphi will honor the inline directive?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

与他有关 2024-11-23 04:03:18

Delphi 文档 枚举了以下条件:内联发生或不发生:

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

对于您的情况,请检查此条件:

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

The Delphi Documentation enumerates the conditions under which inlining does or does not occur:

  • Inlining will not occur on any form of late-bound method. This includes
    virtual, dynamic, and message methods.
  • Routines containing assembly code will not be inlined.
  • Constructors and destructors will not be inlined.
  • The main program block, unit initialization, and unit finalization
    blocks cannot be inlined.
  • Routines that are not defined before use cannot be inlined.
  • Routines that take open array parameters cannot be inlined.
  • Code can be inlined within packages, however, inlining never occurs across
    package boundaries.
  • No inlining is done between units that are circularly dependent. This
    includes indirect circular
    dependencies, for example, unit A uses
    unit B, and unit B uses unit C which
    in turn uses unit A. In this example,
    when compiling unit A, no code from
    unit B or unit C will be inlined in
    unit A.
  • The compiler can inline code when a unit is in a circular dependency, as
    long as the code to be inlined comes
    from a unit outside the circular
    relationship. In the above example, if
    unit A also used unit D, code from
    unit D could be inlined in A, since it
    is not involved in the circular
    dependency.
  • If a routine is defined in the interface section and it accesses
    symbols defined in the implementation
    section, that routine cannot be
    inlined.
  • If a routine marked with inline uses external symbols from other units, all
    of those units must be listed in the
    uses statement, otherwise the routine
    cannot be inlined.
  • Procedures and functions used in conditional expressions in while-do
    and repeat-until statements cannot be
    expanded inline.
  • Within a unit, the body for an inline function should be defined
    before calls to the function are made.
    Otherwise, the body of the function,
    which is not known to the compiler
    when it reaches the call site, cannot
    be expanded inline.

In your case check this condition:

Procedures and functions used in conditional expressions in while-do and repeat-until statements cannot be expanded inline.

安穩 2024-11-23 04:03:18

由于某种原因,编译器不会内联 while 循环控制表达式。 Hallvard Vassbotn 不久前讨论过这个问题(阅读文章结尾)。

For some reason the compiler does not inline while loop control expressions. Hallvard Vassbotn discussed the problem some time ago (read the end of the article).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文