| |||
Home > Coding Practices > Functions > __pure |
A pure function is a function that always returns the same result if it is called with the same arguments.
By default, it is sufficient to evaluate any particular call to a pure function only once. Because the result of a call to the function is guaranteed to be the same for any identical call, each subsequent call to the function in code can be replaced with the result of the original call. This is an instance of the compiler optimization known as Common Subexpression Elimination (CSE).
To instruct the compiler that a function is pure, declare
the function as __pure
.
The use of the __pure
keyword is illustrated
in the two sample routines of Table 4.7. Both routines call a function fact
to
calculate the sum of n!
and n!
.
The fact
function depends only on its input
argument n to compute n!
. Therefore fact
is
a pure function.
The first routine shows a naive implementation of the function fact
,
where fact
is not declared __pure
.
In the second implementation, the function fact
is
qualified as __pure
to indicate to the compiler
that it is a pure function.
Table 4.7. C code for pure and impure functions
A pure function not declared __pure | A pure function declared __pure |
---|---|
int fact(int n) { int f = 1; while (n > 0) f *= n--; return f; } int foo(int n) { return fact(n)+fact(n); } | int fact(int n) __pure { int f = 1; while (n > 0) f *= n--; return f; } int foo(int n) { return fact(n)+fact(n); } |
Table 4.8 shows
the corresponding disassembly of the machine code produced by the compiler
for each of the sample implementations of Table 4.7, where the C code for each implementation
has been compiled using the option -O2
.
Table 4.8. Disassembly for pure and impure functions
A pure function not declared __pure | A pure function declared __pure |
---|---|
fact PROC ... foo PROC MOV r3, r0 PUSH {lr} BL fact MOV r2, r0 MOV r0, r3 BL fact ADD r0, r0, r2 POP {pc} ENDP | fact PROC ... foo PROC PUSH {lr} BL fact LSL r0,r0,#1 POP {pc} ENDP |
In the disassembly of the function foo
in
Table 4-8 where fact
is not qualified as __pure
, the
function fact
is called twice, because the compiler
does not know the function is a candidate for CSE. In contrast,
in the disassembly of foo
in Table 4-8 where fact
is qualified
as __pure
,
fact
is
called only once, instead of twice, because the compiler has been
able to perform CSE when adding fact(n) + fact(n)
.
By definition, pure functions cannot have side effects. For
example, a pure function cannot read or write global state by using
global variables or indirecting through pointers, because accessing
global state can violate the rule that the function must return the
same value each time when called twice with the same parameters.
Therefore, you must use __pure
carefully in your
programs. Where functions can be declared __pure
, however,
the compiler can often perform powerful optimizations, such as CSEs.
See __pure in the Compiler Reference Guide for more information about pure functions.