[fpc-devel] Pure function development
J. Gareth Moreton
gareth at moreton-family.com
Wed Apr 29 22:08:11 CEST 2020
Constant propagation is only really beneficial for inline functions,
although there is some crossover with pure functions. I was more meaning
a system of tracking and storing these constants, or rather how they
manipulate variables throughout a pure function.
I've also found some annoying limitations with constant propagation that
leads to a lot of dead code. The biggest example of this is in the
compiler itself with the peephole optimizer's debug messages that are
meant to be dummied out in a release build. The string concatenation
functions are still called, because the compiler can't see that the
individual string fragments, which come from other functions, are
constant ("StrConst1 + StrConst2" is otherwise concatenated at
compile-time). Pure functions will help here, although admittedly with
this example, I might consider re-evaluating how strings are
concatenated in the node passes, since if there are more than 3 parts to
concatenate, it's built in a way that doesn't give the compiler a chance
to merge adjacent string constants, among other things.
The main thing with pure functions is that constant propagation is far
more in-depth, and that its result can be assigned to a constant (e.g.
const RootPi: Double = Gamma(0.5);", if Gamma is defined as "function
Gamma(const N: Double): Double; pure;"... the value of the function is
computed at compile-time and only its result is stored in the binary).
There are also some optimisations you can potentially make in the
knowledge that a pure function doesn't have any side-effects. For
example, if N, X and Count are Integers:
for N := 0 to Count - 1 do
SomeOtherProc(N * SomePureFunc(X));
Here, because X is not modified by the for-loop, the entire call to
SomePureFunc can be moved outside of the for-loop and its result stored
for re-use - that is, the equivalent of:
R := SomePureFunc(X);
for N := 0 to Count - 1 do
SomeOtherProc(N * R);
Even though the value of X is unknown, because pure functions have no
side-effects, it is guaranteed to give the same output for a given input.
The C++ equivalent of this functionality is the 'constexpr' directive.
To get back to my original question, I'm going to be using TConstValue
for now for most things, and using its ability to store pointers and
lengths for more complex things like records, arrays and strings.
Thanks for the suggestion Sven.
Gareth aka. Kit
On 29/04/2020 18:46, Jonas Maebe wrote:
> On 29/04/2020 13:41, J. Gareth Moreton wrote:
>> Thanks for the response. Yes, this is all inside the compiler.
>> Basically I need a means to keep track of the internal state of a
>> function as I step through the nodes (a process I call 'node
>> emulation'), namely local variables, parameters (if they're not const,
>> they're basically just like local variables), and the function Result
>> and out parameters. Since these may be all sorts of things like
>> integers, floating-point values, strings or record types, I need a
>> system that can handle all of these value types. I figure the compiler
>> has an existing structure somewhere, but I'm not sure what it is.
> It's called constant propagation. -Ooconstprop enables this, but the
> current support is very limited.
> fpc-devel maillist - fpc-devel at lists.freepascal.org
This email has been checked for viruses by Avast antivirus software.
More information about the fpc-devel