Both routines call a function fact()
to
calculate the sum of n!
and n!
. fact()
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, fact()
is qualified
as __pure
to indicate to the compiler that it
is a pure function.
Table 47 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);
}

The following table shows the corresponding
disassembly of the machine code produced by the compiler for each
of the sample implementations above, where the C code for each implementation has
been compiled using the option O2
, and inlining has
been suppressed.
Table 48 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 where fact()
is
not qualified as __pure
, fact()
is
called twice because the compiler does not know that the function
is a candidate for Common Subexpression Elimination (CSE).
In contrast, in the disassembly 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)
.