Re: [GCC 4.3] Strange -O2 optimization issue

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Mateusz Loskot wrote:

> Why the first value printed is different (136623933) in the 3rd
> test case.

Your suspicion is correct, as this violates the ISO C aliasing rules:

> static unsigned long HashDouble(double* pdfVal)
> {
>      unsigned int* pnValue = (unsigned int*)pdfVal;

You're accessing a variable of type double through a pointer of type
unsigned int.  For the purposes of optimization the compiler is allowed
to assume that values of type double will only be accessed through
variables of type double, and thus it can assume that pdfVal and pnValue
can't refer to the same thing.  It may seem nonsensical in this instance
that it would assume that, but it's still legal for the compiler to do
so.  And being able to make this assumption allows for interesting
optimizations, for example consider something like:

typedef struct { int size; float *data; } foo;

void bar (foo *src, foo *dest)
{
  for (int i = 0; i < src->size; i++)
    dest->data[i] += src->data[i];
}

In this example all the stuff happening in the loop with the data arrays
involves floats so the compiler can prove to itself that src->size (an
integer) cannot change, and thus it can hoist it out of the loop so that
it only need be computed once.  This comes up in code that uses STL
containers for example.  (This example was brought up in the following
thread which has more to say on the topic:
<http://gcc.gnu.org/ml/gcc/2006-11/threads.html#00877>.)

If you want to rewrite your code in a conformant way you can use a union
or memcpy; or you can disable strict aliasing with
-fno-strict-aliasing.  -Wstrict-aliasing is intended to warn about
things like this, but since it's included in -Wall it obviously failed
to warn in your case.  There are several levels of -Wstrict-aliasing
though, so you may need to turn to -Wstrict-aliasing=2 to catch this
case.  See the docs for details:
<http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#index-Wstrict_002daliasing-312>

As to why only the first value printed differs, or why taking the
address of pnValue changes the outcome, or why older versions of gcc
worked fine: that is the general nature of undefined behavior.  It can
take on any form whatsoever, from working perfectly, to failing
spectacularly, or anywhere in between.  All rules are out the window. 
It is best not to try to understand the effects or outcome but rather to
understand how to fix the code so that it is no longer undefined.

> Also, could anyone enlighten me and explain what kind of optimization is
> applied when -O2 flag is used, so the first value printed is different?

To quote the manual:
<http://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html#index-fstrict_002daliasing-698>

    The -fstrict-aliasing option is enabled at levels -O2, -O3, -Os. 

> I'd be also very thankful for references in C/C++ standards
> explaining this behavior of GCC.

See section 6.5.7 of the C99 standard.

Brian

[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux