An optimization that is predicated on the idea that a program won't do X will be useful when processing tasks that don't involve doing X, but will be at best counter-productive when performing a task which could be best accomplished by doing X.
Because the C language is used for many purposes, the Standard deliberately allows compilers which are designed for specialized purposes to make assumptions about program behavior that would render them unsuitable for many other purposes. The authors of the Standard allowed implementations to extend the semantics of the language by specifying how they will behave in situations where the Standard imposes no requirements, and expected that quality implementations would seek to do so in cases where their customers would find it useful, without regard for whether the Standard required them to do so.
Programs that need to perform tasks not anticipated or accommodated by the Standard will often need to exploit constructs whose behavior is defined by many implementations, but not mandated by the Standard. Such programs are not "broken", but are merely written in a dialect that the Standard doesn't require that all implementations support.\
As an example, consider the following function test
and whether it satisfies the following behavioral requirements:
If passed a value whose bottom 16 bits would match those of some power of 17, return the bottom 32 bits of that power of 17.
Do not write to arr[65536] under any circumstances.
The code would appear like it should obviously meet the second requirement, but can it be relied upon to do so?
#include <stdint.h>
int arr[65537];
uint32_t doSomething(uint32_t x)
{
uint32_t i=1;
while ((uint16_t)i != x)
i*=17;
if (x < 65536)
arr[x] = 1;
return i;
}
void test(uint32_t x)
{
doSomething(x);
}
If the code is fed to clang with a non-zero optimization level, the generated machine code for test
will fail the second requirement if x
is 65536, since the generated code will be equivalent to simply arr[x] = 1;
. Clang will perform this "optimization" even at -O1
, and none of the normal options to limit broken optimizations will prevent it other than those which force C89 or C99 mode.
-O2
but not at-O1
. – Carbrey-O2
with GCC during development (and usually identical flags for release), no exceptions, no ifs and no whens. Works perfectly well, even in the debugger (except you might not be able to break at a particular line or watch a particular local when it has been completely optimized out, but that's not surprising -- you simply can't watch something that isn't there). – Astrogation