I am trying to understand pure functions, and have been reading through the Wikipedia article on that topic. I wrote the minimal sample program as follows:
#include <stdio.h>
static int a = 1;
static __attribute__((pure)) int pure_function(int x, int y)
{
return x + y;
}
static __attribute__((pure)) int impure_function(int x, int y)
{
a++;
return x + y;
}
int main(void)
{
printf("pure_function(0, 0) = %d\n", pure_function(0, 0));
printf("impure_function(0, 0) = %d\n", impure_function(0, 0));
return 0;
}
I compiled this program with gcc -O2 -Wall -Wextra
, expecting that an error, or at least a warning, should have been issued for decorating impure_function()
with __attribute__((pure))
. However, I received no warnings or errors, and the program also ran without issues.
Isn't marking impure_function()
with __attribute__((pure))
incorrect? If so, why does it compile without any errors or warnings, even with the -Wextra
and -Wall
flags?
Thanks in advance!
A pure function is a hint for the optimizing compiler. Probably, gcc
don't care about pure functions when you pass just -O0
to it (the default optimizations). So if f
is pure (and defined outside of your translation unit, e.g. in some outside library), the GCC compiler might optimize y = f(x) + f(x);
into something like
{
int tmp = f(x); /// tmp is a fresh variable, not appearing elsewhere
y = tmp + tmp;
}
but if f
is not pure (which is the usual case: think of f
calling printf
or malloc
), such an optimization is forbidden.
Standard math functions like sin
or sqrt
are pure (except for IEEE rounding mode craziness, see http://floating-point-gui.de/ and Fluctuat for more), and they are complex enough to compute to make such optimizations worthwhile.
You might compile your code with gcc -O2 -Wall -fdump-tree-all
to guess what is happening inside the compiler. You could add the -fverbose-asm -S
flags to get a generated *.s
assembler file.
You could also read the Bismon draft report (notably its section §1.4). It might give some intuitions related to your question.
In your particular case, I am guessing that gcc
is inlining your calls; and then purity matters less.
If you have time to spend, you might consider writing your own GCC plugin to make such a warning. You'll spend months in writing it! These old slides might still be useful to you, even if the details are obsolete.
At the theoretical level, be aware of Rice's theorem. A consequence of it is that perfect optimization of pure functions is probably impossible.
Be aware of the GCC Resource Center, located in Bombay.