[fpc-devel] Constant propagation: params yes, locals no -- Is it an oversight, or more complex?

Martin Frb lazarus at mfriebe.de
Thu Oct 9 09:11:09 CEST 2025


If you inline code, and call it with constants for its parameters, then 
those constants are propagated through the entire inlined method.

In the example below (most opts may not be needed, but haven't yet 
tested...)


"foo1(11,22)" gets inlined. All 6 invocations of "random" are done with 
the pre-computed (compile time) constant. The 2 variable a and b do no 
longer exist.


In "foo2" the exact same code, but instead of 2 params, there are 2 
locals. Those are unconditionally assigned with constant values. Yet the 
code compiles the with 2 variables, A+b and a*b are done at runtime.

3.2.3 and 3.3.1


Is there something less obvious that the compiler does not know when its 
2 locals? Or is that just an oversight?

I admit, at first sight, code like this is not to be expected, because 
the locals could be declared as const.

Except in generics. If the locals are initialized from a GEN_PARAM.

    generic foo<GP> = class

       x: GP;

       procedure some;

    end

    ...

    LocalVar := x.bar;


The param may be

    record bar: integer; end;

    record public const bar = 11; end;

----------------------------

Another curiosity (but not to bother): if the param is modified, by 
either of the 2 commented statements, then

- the modified value becomes a local var (ok, that probably takes more 
work to optimize)

- The statement ONE BEFORE the modification, no longer uses the 
constant, but uses the value from a local var (at least if opt REGVAR)

   That seems to be (my guess), because the register for "var a" is 
already loaded, and will keep its value for the modification statement.


-----------------------------

program project1;

   {$INLINE on}
   {$Optimization AUTOINLINE}
   {$Optimization REMOVEEMPTYPROCS}
   {$Optimization DFA}
   {$Optimization DEADSTORE}
   {$Optimization DEADVALUES}
   {$Optimization CONSTPROP}
   {$Optimization CSE}

procedure foo1(a,b: integer); inline;
begin
   writeln(random(a));
   writeln(random(b));
   writeln(random(a+b));
   //a:=a+1;
   //inc(a);
   writeln(random(a*2));
   writeln(random(b*2));
   writeln(random(a*b));
end;

procedure foo2();
var a,b: integer;
begin
   a:=11;
   b:=22;
   writeln(random(a));
   writeln(random(b));
   writeln(random(a+b));
   writeln(random(a*2));
   writeln(random(b*2));
   writeln(random(a*b));
end;


begin
   foo1(11,22);
   foo2();
end.



More information about the fpc-devel mailing list