Bug 34552 - optimization of bit-shifts leads to strange results
Summary: optimization of bit-shifts leads to strange results
Status: RESOLVED DUPLICATE of bug 21920
Alias: None
Product: gcc
Classification: Unclassified
Component: c (show other bugs)
Version: 4.1.2
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2007-12-22 03:42 UTC by blake tregre
Modified: 2007-12-22 05:38 UTC (History)
23 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments
test code shown in bug report (320 bytes, text/plain)
2007-12-22 03:43 UTC, blake tregre
Details

Note You need to log in before you can comment on or make changes to this bug.
Description blake tregre 2007-12-22 03:42:14 UTC
The example below copies a float from one location to the next.  When compiling with -O1 or less using 4.1.2, z equals *baz, and the program displays "ok, no bug."  When compiling with -O2 or greater, z doesn't equal *baz, and the program prints "whoah: 23423.234375 should equal 8523244312281203485966336.000000".  Also of note, when one prints the value of q before defining *baz using -O2, the value of *baz changes to 0.00000.  This problem did not occur using gcc 4.0.1 with -O2.  


#include <stdio.h>
#include <stdint.h>

int main(int argc, char **argv) {

  float z = 23423.23424;
  uint32_t* foo = (uint32_t*)&z;
  uint8_t zbuf[4] = {0,0,0,0};

  zbuf[3] = ((*foo) & 0x000000ffL);
  zbuf[2] = ((*foo) & 0x0000ff00L) >> 8;
  zbuf[1] = ((*foo) & 0x00ff0000L) >> 16;
  zbuf[0] = ((*foo) & 0xff000000L) >> 24;

  uint32_t q =
    (((uint32_t)zbuf[0] << 24) |
    ((uint32_t)zbuf[1] << 16)  |
    ((uint32_t)zbuf[2] << 8)   |
    ((uint32_t)zbuf[3]));

  float *baz = (float*)&q;

  if (z == *baz)
    fprintf (stderr, "okay, no bug\n");
  else
    fprintf (stderr, "whoah: %f should equal %f\n", z, *baz);

        return 0;
}
Comment 1 blake tregre 2007-12-22 03:43:37 UTC
Created attachment 14806 [details]
test code shown in bug report
Comment 2 Andrew Pinski 2007-12-22 05:38:53 UTC
  uint32_t* foo = (uint32_t*)&z;

  zbuf[3] = ((*foo) & 0x000000ffL);

It is obvious you are violating C/C++ aliasing rules which leads to undefined behavior.

Use either -fno-strict-aliasing, an union, or memcpy.


*** This bug has been marked as a duplicate of 21920 ***