Reputation: 16129
Take this toy code (godbolt link):
int somefunc(const int&);
void nothing();
int f(int i) {
i = somefunc(i);
i++;
nothing();
i++;
nothing();
i++;
return i;
}
As can be seen in the disassembly at the link, the compiler reloads i
from the stack 3 times, increments and stores back.
If somefunc
is modified to accept int
by value, this doesn't happen.
(1) Is the optimizer 'afraid' that since somefunc
has access to i
s address, it can indirectly modify it? Can you give an example of well defined code that does that? (remember that const_cast'ing away and modifying is undefined behavior).
(2) Even if that was true, I'd expect that decorating somefunc
with __attribute__((pure))
would stop that pessimization. It doesn't. Why?
Are these llvm missed optimizations?
Edit: If somefunc
returns void, __attribute__((pure))
does kick in as expected:
void somefunc(const int&) __attribute__((pure));
void nothing();
int f(int i) {
somefunc(i);
i++;
nothing();
i++;
nothing();
i++;
return i;
}
Maybe this attribute is sort of half baked (it is rare in practice).
Upvotes: 2
Views: 161
Reputation: 41474
As mentioned in a comment, using const_cast
to remove the constness of a reference to an object that was defined as non-const is well-defined. In fact, that's its only real use.
As for __attribute__((pure))
: Who knows. The nothing()
calls are necessary to reproduce the situation; if those are marked pure
then proper optimization is done; the invocation of somefunc
doesn't have much of an impact on that situation. Basically, the compiler tends to be quite conservative unless everything in a code block is pure. While it should arguably be able to deduce that nothing()
doesn't affect i
, that's very much a "best effort" area of optimization and not something that properly optimized code should rely on.
Upvotes: 6