public inbox for gcc-help@gcc.gnu.org
 help / color / mirror / Atom feed
From: Brian Dessent <brian@dessent.net>
To: Mateusz Loskot <mateusz@loskot.net>
Cc: gcc-help@gcc.gnu.org
Subject: Re: [GCC 4.3] Strange -O2 optimization issue
Date: Sat, 02 Aug 2008 00:11:00 -0000	[thread overview]
Message-ID: <4893A622.23D87C16@dessent.net> (raw)
In-Reply-To: <4893866F.9050800@loskot.net>

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

  reply	other threads:[~2008-08-02  0:11 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-08-01 21:56 Mateusz Loskot
2008-08-02  0:11 ` Brian Dessent [this message]
2008-08-02  2:15   ` Mateusz Loskot

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4893A622.23D87C16@dessent.net \
    --to=brian@dessent.net \
    --cc=gcc-help@gcc.gnu.org \
    --cc=mateusz@loskot.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).