2 Aug 2008 04:14
Re: [GCC 4.3] Strange -O2 optimization issue
Mateusz Loskot <mateusz <at> loskot.net>
2008-08-02 02:14:53 GMT
2008-08-02 02:14:53 GMT
Brian Dessent wrote: > 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: Brian, Good to hear I was close>> 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. > [...] Thank you very much for in-depth explanation of the problem. It was greatly helpful. > 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. I fixed my code with memcpy option. > -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> -Wstrict-aliasing=2 does not warn about aliasing rules broken in that line with the case, but -Wstrict-aliasing=1 does. Yes, I've read the manual and understand it why. > 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. Right, I suspected UB from the beginning of my investigation. > 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. Very good point
>> 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 Thank you very much again! Best regards, -- -- Mateusz Loskot, http://mateusz.loskot.net Charter Member of OSGeo, http://osgeo.org
>> 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.
> [...]
Thank you very much for in-depth explanation of the problem.
It was greatly helpful.
> 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.
I fixed my code with memcpy option.
> -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:
> <
>> 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
Thank you very much again!
Best regards,
RSS Feed