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.

_______________________________________________
fpc-devel maillist  -  [email protected]
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel

Reply via email to