| |||
| 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.