I was reading this paper on undefined behaviour and one of the example \"optimisations\" looks highly dubious:
if (arg2 == 0) ereport(ERROR,
The paper does not say that the if (arg2 == 0) check is removed. It says that the division is moved before the check.
Quoting the paper:
... GCC moves the division before the zero check
arg2 == 0, causing division by zero.
The result is the same, but the reasoning is different.
If the compiler believes ereport will return, then it "knows" that the division will be performed in all cases. Furthermore, the if-statement doesn't affect the arguments of the division. And obviously, the division doesn't affect the if-statement. And while call to ereport might have observable side effects, the division does not (if we ignore any divide-by-zero exception).
Therefore, the compiler believes the as-if rule gives it the freedom to reorder these statements with respect to each other--it can move the division before the test because the observable behavior should be identical (for all of the cases that yield defined behavior).
One way to look at it is that undefined behavior includes time travel. ;-)
I'd argue that undefined behavior (e.g., dividing by 0), should be considered observable behavior. That would prevent this reordering because the observable behavior of the division must happen after the observable behavior of the call to ereport. But I don't write standards or compilers.