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?
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.
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).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With