Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2021-11

Inline function parameters

10 messages · 3 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Ryan Joseph

Is there anyway a function parameter could be inlined in FPC? This would go a long way in helping to parameterize functions that have tight loops in them.

If there isn't I wonder if this is an area where the proposed "pure" function modifier could be used to make it possible.

===============

type
  TSomeFunc = function: boolean;
procedure DoThis(func: TSomeFunc);
begin
  if func then
    ;
end;
function MyFunc: boolean; inline;
begin
end;
begin
  DoThis(MyFunc);
end;

Regards,
Ryan Joseph

Reply by email

Jonas Maebe
to Ryan Joseph
Ryan Joseph wrote
Is there anyway a function parameter could be inlined in FPC? This would go a long way in helping to parameterize functions that have tight loops in them.

It's theoretically possible through constant propagation.

If there isn't I wonder if this is an area where the proposed "pure" function modifier could be used to make it possible.

That's completely unrelated.

Jonas

Reply by email

Ryan Joseph
to Jonas Maebe
Show quoted text 5 lines
On Nov 7, 2021, at 2:17 PM, Jonas Maebe via fpc-pascal wrote: > Is there anyway a function parameter could be inlined in FPC? This would go a long way in helping to parameterize functions that have tight loops in them. It's theoretically possible through constant propagation.

I understand simple constant propagation cases but how does this apply to inlining entire functions? I think C++ can do this with closures so it's something worth looking in to for the future.

Regards,
Ryan Joseph

Reply by email

Sven Barth
to Ryan Joseph
Ryan Joseph wrote 6 lines
> On Nov 7, 2021, at 2:17 PM, Jonas Maebe via fpc-pascal wrote: > >> Is there anyway a function parameter could be inlined in FPC? This would go a long way in helping to parameterize functions that have tight loops in them. > It's theoretically possible through constant propagation. I understand simple constant propagation cases but how does this apply to inlining entire functions? I think C++ can do this with closures so it's something worth looking in to for the future.

This has nothing to do with closures.

Take a look at this:

=== code begin ===

type
   TFunc = function(aArg: LongInt): LongInt;
   TLongIntArray = array of LongInt;
function MultBy2(aArg: LongInt): LongInt; inline;
begin
   Result := aArg * 2;
end;
function Map(aArr: TLongIntArray; aFunc: TFunc): TLongIntArray; inline;
begin
   SetLength(Result, Length(aArr));
   for i := 0 to High(aArr) do
     Result[i] := aFunc(aArr[i]);
end;
var
   l1, l2: TLongIntArray;
begin
   l1 := [1, 2, 3, 4];
   l2 := Map(l1, @MultBy2);
end.

=== code end ===

Assuming constant propagation of function variables would work correctly what would happen in the compiler would be as follows (this is how the compiler already works):

Step 1: Inline Map function

=== code begin ===

// ...
begin
   l1 := [1, 2, 3, 4];
   SetLength(l2, 4);
   for i := 0 to 3 do
     Result[i] := MultBy2(aArr[i]);
end.

=== code end ===

Step 2: Check whether inlining provided new optimization possibilities (which again includes inlining and thus allows inlining of MultBy2!)

=== code begin ===

// ...
begin
   l1 := [1, 2, 3, 4];
   SetLength(l2, 4);
   for i := 0 to 3 do
     Result[i] := aArr[i] * 2;
end.

=== code end ===

And there you have it (simplified obviously). As long as the compiler can determine *at compile time* the code of the function (and the function is inlineable) it should in theory be able to inline it. This is true no matter if it's a function variable, a method variable (pointing to a non-virtual method) or an anonymous function. However if somewhere between passing in the function address and calling the function inlining does not work for one reason or the other (e.g. due to open array parameters which are currently not supported by inlining) then the compiler obviously can't inline the provided function either.

Regards,
Sven

Reply by email

Ryan Joseph
to Sven Barth
On Nov 8, 2021, at 1:27 PM, Sven Barth via fpc-pascal wrote: And there you have it (simplified obviously). As long as the compiler can determine *at compile time* the code of the function (and the function is inlineable) it should in theory be able to inline it. This is true no matter if it's a function variable, a method variable (pointing to a non-virtual method) or an anonymous function. However if somewhere between passing in the function address and calling the function inlining does not work for one reason or the other (e.g. due to open array parameters which are currently not supported by inlining) then the compiler obviously can't inline the provided function either.

Interesting, so the inlining the containing function is the key. I guess if the container were not inlined it would basically be like a generic where a new function body would be generated which contained the inline function pointers body with arguments replaced.

For example:

function Map_MultBy2(aArr: TLongIntArray): TLongIntArray;
begin
  SetLength(Result, Length(aArr));
  for i := 0 to High(aArr) do
    Result[i] := aArr[i] * 2; { MultBy2 is inlined here }
end;

Regards,
Ryan Joseph

Reply by email

Sven Barth
to Ryan Joseph

Ryan Joseph via fpc-pascal schrieb am
Mo., 8. Nov. 2021, 15:31:

Show quoted text 20 lines
> On Nov 8, 2021, at 1:27 PM, Sven Barth via fpc-pascal < > wrote: > > And there you have it (simplified obviously). As long as the compiler can determine *at compile time* the code of the function (and the function is inlineable) it should in theory be able to inline it. This is true no matter if it's a function variable, a method variable (pointing to a non-virtual method) or an anonymous function. However if somewhere between passing in the function address and calling the function inlining does not work for one reason or the other (e.g. due to open array parameters which are currently not supported by inlining) then the compiler obviously can't inline the provided function either. Interesting, so the inlining the containing function is the key. I guess if the container were not inlined it would basically be like a generic where a new function body would be generated which contained the inline function pointers body with arguments replaced.

I don't know what you mean with "new function body". If a function is inlined its code is contained within the surrounding function and if it's not inlined then nothing changes.

Regards,
Sven

Reply by email

Ryan Joseph
to Sven Barth
On Nov 8, 2021, at 11:20 PM, Sven Barth via fpc-pascal wrote: I don't know what you mean with "new function body". If a function is inlined its code is contained within the surrounding function and if it's not inlined then nothing changes.

I mean if in theory you were to inline that function variables code into the function it would need to generate a new function (I guess the name also, so the entire thing) because the function being passed in could change on per-call basis (like a normal generic function).

Regards,
Ryan Joseph

Reply by email

Sven Barth
to Ryan Joseph
Ryan Joseph wrote 6 lines
> On Nov 8, 2021, at 11:20 PM, Sven Barth via fpc-pascal wrote: > > I don't know what you mean with "new function body". If a function is inlined its code is contained within the surrounding function and if it's not inlined then nothing changes. > I mean if in theory you were to inline that function variables code into the function it would need to generate a new function (I guess the name also, so the entire thing) because the function being passed in could change on per-call basis (like a normal generic function).

No, because the function that is called with a function pointer needs to be inlined itself (thus becoming part of its caller) so that constant propagation works at all for the parameters. If a function isn't inlined then there won't be any change and the passed in function variable will be called as usual.

Regards,
Sven

Reply by email

Ryan Joseph
to Sven Barth
On Nov 9, 2021, at 1:09 PM, Sven Barth via fpc-pascal wrote: No, because the function that is called with a function pointer needs to be inlined itself (thus becoming part of its caller) so that constant propagation works at all for the parameters. If a function isn't inlined then there won't be any change and the passed in function variable will be called as usual.

I mean in theory if the compiler were to support inlining function pointers that is how it could be done.

Regards,
Ryan Joseph

Reply by email

Sven Barth
to Ryan Joseph
Ryan Joseph wrote 5 lines
> On Nov 9, 2021, at 1:09 PM, Sven Barth via fpc-pascal wrote: > > No, because the function that is called with a function pointer needs to be inlined itself (thus becoming part of its caller) so that constant propagation works at all for the parameters. If a function isn't inlined then there won't be any change and the passed in function variable will be called as usual. I mean in theory if the compiler were to support inlining function pointers that is how it could be done.

No, because that is not how inlining and constant propagation works. And we're not going to implement something new just for this when perfectly fine mechanisms exist already.
What needs to be done is to extend constant propagation to function/method variables and then things would work out automatically already.

Regards,
Sven

Reply by email