[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