From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 23811 invoked by alias); 2 Aug 2008 00:11:48 -0000 Received: (qmail 23797 invoked by uid 22791); 2 Aug 2008 00:11:46 -0000 X-Spam-Check-By: sourceware.org Received: from dessent.net (HELO dessent.net) (69.60.119.225) by sourceware.org (qpsmtpd/0.31) with ESMTP; Sat, 02 Aug 2008 00:11:17 +0000 Received: from localhost.localdomain ([127.0.0.1] helo=dessent.net) by dessent.net with esmtp (Exim 4.50) id 1KP4iI-0002gY-FM; Sat, 02 Aug 2008 00:11:14 +0000 Message-ID: <4893A622.23D87C16@dessent.net> Date: Sat, 02 Aug 2008 00:11:00 -0000 From: Brian Dessent Reply-To: gcc-help@gcc.gnu.org X-Mailer: Mozilla 4.79 [en] (Windows NT 5.0; U) MIME-Version: 1.0 To: Mateusz Loskot CC: gcc-help@gcc.gnu.org Subject: Re: [GCC 4.3] Strange -O2 optimization issue References: <4893866F.9050800@loskot.net> Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit X-IsSubscribed: yes Mailing-List: contact gcc-help-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-help-owner@gcc.gnu.org X-SW-Source: 2008-08/txt/msg00005.txt.bz2 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: .) 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: 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: 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