buggy optimization levels...

Erik Trulsson ertr1013 at student.uu.se
Sat Aug 2 10:45:45 PDT 2003

On Sat, Aug 02, 2003 at 12:19:06PM -0400, Chuck Swiger wrote:
> Erik Trulsson wrote:
> >On Thu, Jul 31, 2003 at 10:30:57PM -0400, Chuck Swiger wrote:
> [ ... ]
> >>I understand that figuring out why the kernel died can be hard, 
> >>particularly if the failures aren't concise and completely reproducable, 
> >>and thus tracing the problem back to making the right change to gcc to 
> >>fix the optimization that caused the observed failure is thus also hard.
> >
> >Note that it is not necessarily gcc which is at fault for such
> >failures. It may be a bug in gcc, but it may also be a bug in the code
> >being compiled that has a bug that only shows up under higher
> >optimization levels.
> >The latter is probably somewhat more common actually.
> Does the last comment mean that you can provide at least one example of 
> code which behaves differently when compiled with "cc -O" versus "cc -O2"?
> Otherwise, what does "more common" mean in the context of zero examples?

If you want real world examples you can trawl through the mailing list
archives. I am sure you can find at least a few examples if you look
hard enough. (Searching through list archives is not so fun that I will
do it myself unless there is something that *I* want to know.)

A somewhat contrived example that behaves differently when compiled
with -O3 or when compiled with -O2 or lower optimization follows:

static int f(int a)
    return a/0;
int main(void)
    int x;
    x = f(5);
    return 0;

Compiling this with -O2 or lower and running the program will result
in the program crashing. Compiled with -O3 the program just exits
cleanly.  (FreeBSD 4.8-stable ; gcc 2.95.4)
(The code compiles just fine withouth warnings in either case even when
compiled with -ansi -pedantic -Wall)

Since there is a bug (division by zero) in the program that invokes
undefined behaviour either result is perfectly acceptable, and the
difference is not due to a bug in gcc, but due to a bug in my program.

(The reason for the different behaviour is that -O3 turns on inlining of
functions, and when the call to f() has been inlined gcc is able to
determine that the call has no side-effects that need to be preserved,
and since the result of the call is never used after being assigned to
x the whole line 'x = f(5);' can safely be removed.
When compiled with -O2 or lower the compiler is not able to determine
that the call to f() can be omitted and therefore f() will be called.)

> [ ... ]
> >>...and makes it so that -O2, -O3, etc does not enable GCSE optimization.
> >
> >But if the bug is not in gcc but in the code being compiled (and which
> >only happens to show up when compiled with GCSE optimization) 
> Even if the code contains a bug, "cc -O" and "cc -O -fgcse" should produce 
> the same results.  Excluding certain well-defined exceptions (-ffast-math 
> comes to mind), compiler optimizations likes -fgcse are not allowed to 
> change the meaning of compiled code, do we agree?

Not quite.  Compiler optimization flags (with a few exceptions like
-ffast-math) are not allowed to change the semantics of the compiled
code.  For buggy code that invokes undefined behaviour (divison by
zero, accessing unallocated memory, etc.) there is no semantics to
preserve and therefore the compiled code may well produce different
results when compiled with different flags.
(Undefined behaviour in the context of the C standard means the
compiler is allowed to do whatever it damn well pleases, including, but
not limited to, doing what you wanted and expected it to do, formatting
your harddisk or making demons fly out of your nose.

> > ...such a patch would disable this optimization for correct code also
> > even though it is not necessary there.
> Such a patch would disable the optimization for all cases.
> If there exists any lexically correct input source code (ie, which parses 
> validly) where compiling with -fgcse results in different behavior, that 
> optimization is unsafe and should not be enabled by -O2 in any circumstance.

With that definition just about *all* optimizations would be unsafe.

(And optimization is actually *supposed* to give different behaviour. 
The running time of a program is part of its behaviour and
optimization is generally supposed to reduce the running time, thereby
giving different behaviour.)

<Insert your favourite quote here.>
Erik Trulsson
ertr1013 at student.uu.se

More information about the freebsd-questions mailing list