Recent

Author Topic: Proposition — new modifier to force compiler to inline or throw warning/error  (Read 13456 times)

furious programming

  • Hero Member
  • *****
  • Posts: 864
This is only a free proposition.

Currently we have a inline modifier, which may or may not cause the compiler to inline a subroutine. There is also noinline to prevent compiler from inlining. But there is no modifier to force FPC to inline, so if the compiler can inline, it do so but if not, the appropriate compilation warning/error should be thrown (in the case of error, compilation should be aborted). IDK if currently is it possible to check if a given inlined subroutine was actually inlined or not, but AFAIK it's not.

My proposition is to use new doinline or forceinline keyword.
Lazarus 3.4 with FPC 3.2.2, Windows 10 — all 64-bit

Working solo on an arcade, action/adventure game in retro style (pixel art), programming the engine and shell from scratch, using Free Pascal and SDL. Release planned in 2026.

Bart

  • Hero Member
  • *****
  • Posts: 5348
    • Bart en Mariska's Webstek
IDK if currently is it possible to check if a given inlined subroutine was actually inlined or not, but AFAIK it's not.
If the compiler does not inline, it'll give a hint/warning (one of the 2, too lazy to look it up).

Bart

Eugene Loza

  • Hero Member
  • *****
  • Posts: 729
    • My games in Pascal
Quote
it'll give a hint/warning
Note: Call to subroutine "$1" marked as inline not inlined
My FOSS games in FreePascal&CastleGameEngine: https://decoherence.itch.io/ (Sources: https://gitlab.com/EugeneLoza)

furious programming

  • Hero Member
  • *****
  • Posts: 864
I'm aware of this, but the compiler generates a note that is filtered by default in the message window. However, when I turn off filtering to see this note, there are hundreds of items in the message window and it is difficult to find anything, especially in the case of a large project for which the compiler generates hundreds/thousands of notes.

If you at least raised the rank from a note to a warning, I wouldn't need new modifiers to always know what's going on.
Lazarus 3.4 with FPC 3.2.2, Windows 10 — all 64-bit

Working solo on an arcade, action/adventure game in retro style (pixel art), programming the engine and shell from scratch, using Free Pascal and SDL. Release planned in 2026.

Marc

  • Administrator
  • Hero Member
  • *
  • Posts: 2607
Is there reason why you want a forced inline ? IMO if the compiler diceides a routine ins't inlined, there is a reason for it, and I don't see a reason why forcing it would help
//--
{$I stdsig.inc}
//-I still can't read someones mind
//-Bugs reported here will be forgotten. Use the bug tracker

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11731
  • FPC developer.
Forcing might not be possible in all cases anyway. So even with a forced inline it might not inline. Which means the name is wrong. It is a "try harder" not a guaranteed inline.

So if were really needed, I think a local directive to give the normal inline a bit more weight would be more sensible then yet another language extension.

And brings us to why you need this. You don't give much examples or reasons for that.

Thaddy

  • Hero Member
  • *****
  • Posts: 15516
  • Censorship about opinions does not belong here.
Well Marco:
to some a note to understand what is happening is not good enough or clear enough. So the above suggestion to promote it to a hint or warning is a good idea and easy to fix.

That said, OP does not fully understand that in any inline mode, be it local or global, the compiler already does a best effort. The compiler is usually better than the programmer to decide this.
My great hero has found the key to the highway. Rest in peace John Mayall.
Playing: "Broken Wings" in your honour. As well as taking out some mouth organs.

furious programming

  • Hero Member
  • *****
  • Posts: 864
Forcing might not be possible in all cases anyway. So even with a forced inline it might not inline. Which means the name is wrong. It is a "try harder" not a guaranteed inline.

Exactly — that's why I would like to know that the compiler could not do something what I want. if something cannot be inlined (even if force it), I can  change my code, remove this function, place its code where it was previously called and create longer function without such calls. Currently, the inlining feature is more or less a mystery box.



By the way, I have an additional question about inline.

If the {$AUTOINLINE} is disabled, compiler will inline only routines that are marked as inlined (if it can do it). But what is going on if the {$AUTOINLINE} is enabled? Does the compiler decide to inline each routine separately, regardless of whether it is marked as inline or not? What if a routine is marked as inline? Does autoinline determine its inline in the same way as regular routines, or is the inline modifier taken into account and the compiler tries to inline it? In short, does autoiline treat routines marked with this modifier differently from those not marked?

I'm asking because I would like to understand how exactly this autoinline works.
« Last Edit: November 08, 2023, 01:03:25 pm by furious programming »
Lazarus 3.4 with FPC 3.2.2, Windows 10 — all 64-bit

Working solo on an arcade, action/adventure game in retro style (pixel art), programming the engine and shell from scratch, using Free Pascal and SDL. Release planned in 2026.

MarkMLl

  • Hero Member
  • *****
  • Posts: 7485
That said, OP does not fully understand that in any inline mode, be it local or global, the compiler already does a best effort. The compiler is usually better than the programmer to decide this.

In that case, by any reasonable standards, the compiler is broken.

If the programmer explicitly says "I want this to be inlined", and the compiler can't do it, then it's an error. "I prefer not to" is not an option here.

It's exactly the same as a programmer (back in the day) defining a procedure as an interrupt handler, or (more recently) declaring that a record is to be packed or that something must be stored as a threadvar, or a C programmer declaring a variable as volatile.

It is not the compiler's job to tell the programmer what to do.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

PascalDragon

  • Hero Member
  • *****
  • Posts: 5644
  • Compiler Developer
This is only a free proposition.

Currently we have a inline modifier, which may or may not cause the compiler to inline a subroutine. There is also noinline to prevent compiler from inlining. But there is no modifier to force FPC to inline, so if the compiler can inline, it do so but if not, the appropriate compilation warning/error should be thrown (in the case of error, compilation should be aborted). IDK if currently is it possible to check if a given inlined subroutine was actually inlined or not, but AFAIK it's not.

My proposition is to use new doinline or forceinline keyword.

No, because the decision to inline not only depends on the routine that is marked as inline, but also on the routine that is calling the routine (and thus would receive the inlined body). If the node count becomes to complex (e.g. due to multiple inlinings) then the compiler will not inline it. Enforcing inlining goes against this.

If the {$AUTOINLINE} is disabled, compiler will inline only routines that are marked as inlined (if it can do it). But what is going on if the {$AUTOINLINE} is enabled? Does the compiler decide to inline each routine separately, regardless of whether it is marked as inline or not? What if a routine is marked as inline? Does autoinline determine its inline in the same way as regular routines, or is the inline modifier taken into account and the compiler tries to inline it? In short, does autoiline treat routines marked with this modifier differently from those not marked?

$AutoInline is as if all routines are marked with inline (at least if they are technically inlinable anyway) though the compiler won't warn if it can't inline them anyway.

If the programmer explicitly says "I want this to be inlined", and the compiler can't do it, then it's an error. "I prefer not to" is not an option here.

No. There might be reasons on the callsite that the compiler can't inline a routine marked as inline.

furious programming

  • Hero Member
  • *****
  • Posts: 864
It is not the compiler's job to tell the programmer what to do.

There's no better way to say it. They should print these words on T-shirts and mugs.

I hate abstractions, things that do something beyond my knowledge and control. Currently, as you probably know, I'm working on an engine for my future game. I write all the code, both for the engine and the game itself, as low-level as possible — procedural-structural paradigm, manual memory management, pointers everywhere. I want to know everything about how the code works and control every aspect of it. I have a lot of small functions marked as inline, so I need to know which ones are and which are not ultimately inlined.

The compiler generates notes in case a given function cannot be inlined, but for some reason I had these notes hidden in the project settings. After enabling this particular message, the Note: Call to subroutine "$1" marked as inline not inlined notes are normally visible in the message window, with default filtering (filter hints and below). So here is my fault.

However, this still does not change the fact that there is no way to force the compiler to inline, so the proposal is still valid.



No, because the decision to inline not only depends on the routine that is marked as inline, but also on the routine that is calling the routine (and thus would receive the inlined body). If the node count becomes to complex (e.g. due to multiple inlinings) then the compiler will not inline it. Enforcing inlining goes against this.

And that's why the compiler should throw a compilation error that inlining is not technically possible. That's what I mean, this is what my proposal is about. In short, regular inline tells the compiler to inline but lets it decide whether to do so, whereas forceinline commands the compiler to inline and if it can't do so, compilation aborts and a error is emitted.

Quote
$AutoInline is as if all routines are marked with inline (at least if they are technically inlinable anyway) though the compiler won't warn if it can't inline them anyway.

Ok, thank you for explanation, now everything is clear to me.
Lazarus 3.4 with FPC 3.2.2, Windows 10 — all 64-bit

Working solo on an arcade, action/adventure game in retro style (pixel art), programming the engine and shell from scratch, using Free Pascal and SDL. Release planned in 2026.

MarkMLl

  • Hero Member
  • *****
  • Posts: 7485
If the programmer explicitly says "I want this to be inlined", and the compiler can't do it, then it's an error. "I prefer not to" is not an option here.

No. There might be reasons on the callsite that the compiler can't inline a routine marked as inline.

In that case the compiler should report it as an error, so that the programmer can sort his stuff out and have another shot.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

MarkMLl

  • Hero Member
  • *****
  • Posts: 7485
I hate abstractions, things that do something beyond my knowledge and control. Currently, as you probably know, I'm working on an engine for my future game. I write all the code, both for the engine and the game itself, as low-level as possible — procedural-structural paradigm, manual memory management, pointers everywhere. I want to know everything about how the code works and control every aspect of it. I have a lot of small functions marked as inline, so I need to know which ones are and which are not ultimately inlined.

I'm OK with abstractions, provided that they can be explained. In principle at least, one can work by hand from a fragment of sourcecode, through the code generation, and then through the optimisation.

OTOH, I'm not at all OK with the current "AI" craze where it's impossible to derive a reason for some given output.

I've just managed to find an affordable copy of https://web.engr.oregonstate.edu/~budd/Books/leda/ The three free chapters demonstrate- among other things- how a language facility intended for Prolog-style inference is equivalent to a facility for processing a much more mundane directed graph. However The really important point being made by the author is that people with different backgrounds and expectations might approach a problem differently, and it might be a mistake to try to shoehorn everything into the same syntax.

Quote
The compiler generates notes in case a given function cannot be inlined, but for some reason I had these notes hidden in the project settings. After enabling this particular message, the Note: Call to subroutine "$1" marked as inline not inlined notes are normally visible in the message window, with default filtering (filter hints and below). So here is my fault.

I normally define "_INLINE_" as a macro, which either contains "inline" or is blank depending on whether I actually want to inline setters/getters etc. That usefully eliminates some of the extraneous error messages without relying on the Lazarus IDE.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

Kays

  • Hero Member
  • *****
  • Posts: 602
  • Whasup!?
    • KaiBurghardt.de
[…] But there is no modifier to force FPC to inline, […]
Yes, there is. However, it has the misleading name {$include} and requires some changes (in comparison to simply appending a keyword to the routine declaration).
Code: Pascal  [Select][+][-]
  1. program myProgram(input, output, stdErr);
  2.         {$include myroutine-declarations}
  3.         begin
  4.                 {$include myroutine-definition}
  5.                 {$include myroutine-definition}
  6.                 {$include myroutine-definition}
  7.         end.
Code: Pascal  [Select][+][-]
  1.         var
  2.                 x: integer;
Code: Pascal  [Select][+][-]
  1.                 x := 0;
  2.                 writeLn('Hell', x:1, '.');
Guaranteed to work just as you want. The compiler will not complain that something could not be inlined. Obviously recursive routines cannot be used that way, but they could not be inlined anyway (except tail-recursive routines).
Yours Sincerely
Kai Burghardt

MarkMLl

  • Hero Member
  • *****
  • Posts: 7485
Yes, there is. However, it has the misleading name {$include} and requires some changes (in comparison to simply appending a keyword to the routine declaration).

Three things there. First, Donald Knuth- universally respected, when I last checked- has in the past gone to a lot of trouble to promote the idea of "literate programming" where everything is basically defined in the same place... or at least in the most obvious place. Having to constantly refer to external files flies in the face of that, even in the era of multi-window programming environments.

I would add that having to define e.g. SQL queries in an external resource file rather than encoding them inline is offensive for the same reason.

Second, unless something's been fixed that I don't know about the Lazarus IDE doesn't track changes to .inc file content reliably, so on occasion won't recompile units when it should.

Third, I've done quite a lot with machine-generated sourcecode in the past, and have learnt to be wary lest a compiler suddenly turn out to have an x,000- line compilation limit. And in this context, I would suggest that repeatedly including files is even more cruel to the compiler than expecting it to repeatedly inline some modest number of precompiled AST nodes.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

 

TinyPortal © 2005-2018