Say for very common math functions, such as sin, cos, etc... does the compiler realise they have no side effects and have the ability to move them to outer loops? For examp
What is needed to permit hoisting this subexpression outside the loop is not purity, but idempotence.
Idempotence means that a function will have the same side-effects and result if it is called once as if it is called many times with the same arguments. Therefore, the compiler can put the function call outside the loop, protected only by a conditional (would the loop iterate at least once?). The actual code after the hoisting optimization then would be:
double YSinX(double x,int y)
{
double total = 0.0;
int i = 0;
if (i < y) {
double sinx = sin(x); // <- this goes between the loop-initialization
// first test of the condition expression
// and the loop body
do {
total += sinx;
i++;
} while (i < y);
}
return total;
}
The distinction between __attribute__(pure) and idempotent is important because, as adl notes in his comment, these functions do have a side-effect of setting errno.
Be careful, though, because idempotence only applies to repeated calls with no intervening instructions. The compiler will have to perform dataflow analysis to prove that the function and the intervening code don't interact (for example, the intervening code uses only locals whose addresses are never taken), before it can take advantage of idempotence. This isn't necessary when the function is known to be pure. But purity is a much stronger condition that doesn't apply to very many functions.