Reputation: 8082
I tried recent versions of gcc (9.2.1) and clang (9.0.1) for such code:
//pure.cpp
int square (int x) __attribute__ ((pure));
int square (int x)
{
return x * x;
}
//test.cpp
#include <stdio.h>
int square (int x) __attribute__ ((pure));
int main(int argc, char *argv[])
{
const int same = argc;
printf("result: %d\n", square(same));
printf("result2: %d\n", square(same));
}
and compile it like this:
g++ -ggdb -Ofast -c test.cpp
g++ -ggdb -Ofast -c pure.cpp
g++ -ggdb -Ofast -o test test.o pure.o
as result I see:
1043: e8 58 01 00 00 callq 11a0 <_Z6squarei>
1048: 48 8d 3d b5 0f 00 00 lea 0xfb5(%rip),%rdi # 2004 <_IO_stdin_used+0x4>
104f: 89 c6 mov %eax,%esi
1051: 31 c0 xor %eax,%eax
1053: e8 d8 ff ff ff callq 1030 <printf@plt>
printf("result2: %d\n", square(same));
1058: 89 ef mov %ebp,%edi
105a: e8 41 01 00 00 callq 11a0 <_Z6squarei>
105f: 48 8d 3d aa 0f 00 00 lea 0xfaa(%rip),%rdi # 2010 <_IO_stdin_used+0x10>
1066: 89 c6 mov %eax,%esi
1068: 31 c0 xor %eax,%eax
106a: e8 c1 ff ff ff callq 1030 <printf@plt>
as you can see there are two calls of _Z6squarei
,
but why? I marked function as pure, and use the same argument,
why gcc and clang can not remove the second call?
Upvotes: 1
Views: 137
Reputation: 7973
The problem is that while square()
is marked pure, printf()
isn't. So the compiler is not free to assume that all state is the same after a call to printf()
, and so square()
itself might read different state and thus produce different output. However, it should be fine if you call square()
twice without any other function call inbetween:
int main(int argc, char *argv[])
{
const int same = argc;
int x = square(same);
int y = square(same);
printf("result: %d\n", x);
printf("result2: %d\n", y);
}
As eerorika mentioned, __attribute__((const))
will work because it adds the further restriction that square()
may not read any state except its inputs. See this question about the difference between pure and const.
Upvotes: 5