Bug 25235 - byte swapping unreliable in optimized builds
Summary: byte swapping unreliable in optimized builds
Status: RESOLVED DUPLICATE of bug 21920
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.0.2
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2005-12-02 23:30 UTC by cdfrey
Modified: 2005-12-05 04:00 UTC (History)
52 users (show)

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


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description cdfrey 2005-12-02 23:30:02 UTC
GCC version:  g++ -v
        Using built-in specs.
        Target: i686-pc-linux-gnu
        Configured with: ../gcc-4.0.2/configure --prefix=/home/source5/rootdir-gcc402 --enable-languages=c,c++ --enable-concept-checks
        Thread model: posix
        gcc version 4.0.2

Sample code that reproduces the bug:

#include <iostream>
#include <stdint.h>

// From glibc
#define pa_bswap_64(x) \
     ((((x) & 0xff00000000000000ull) >> 56)                                   \
      | (((x) & 0x00ff000000000000ull) >> 40)                                 \
      | (((x) & 0x0000ff0000000000ull) >> 24)                                 \
      | (((x) & 0x000000ff00000000ull) >> 8)                                  \
      | (((x) & 0x00000000ff000000ull) << 8)                                  \
      | (((x) & 0x0000000000ff0000ull) << 24)                                 \
      | (((x) & 0x000000000000ff00ull) << 40)                                 \
      | (((x) & 0x00000000000000ffull) << 56))

int main()
{
        double d = 42.42;
        uint64_t conv = *((uint64_t*) &d);
        conv = pa_bswap_64(conv);
        uint64_t back = pa_bswap_64(conv);
        double d2 = *((double*)&back);

        std::cout
                << "d = " << d << " d2 = " << d2 << std::endl
                << "conv = " << conv << " back = " << back << std::endl;
}


When compiled without optimization, I get:

source5@cube tmp $ /home/source5/rootdir-gcc402/bin/g++ -Wall -o swap swap.cc
source5@cube tmp $ ./swap
d = 42.42 d2 = 42.42
conv = 17737528904907048256 back = 4631166901565532406


When compiled with optimization, I get:

source5@cube tmp $ /home/source5/rootdir-gcc402/bin/g++ -Wall -O2 -o swap swap.cc 
source5@cube tmp $ ./swap
d = 42.42 d2 = 10.3501
conv = 17626847325199074312 back = 577737629976797172
Comment 1 Andrew Pinski 2005-12-02 23:32:50 UTC
You are violating C++ aliasing rules:
        uint64_t back = pa_bswap_64(conv);
        double d2 = *((double*)&back);


*** This bug has been marked as a duplicate of 21920 ***
Comment 2 cdfrey 2005-12-03 00:32:13 UTC
Thanks for the info!

I can understand the examples in the article at http://mail-index.netbsd.org/tech-kern/2003/08/11/0001.html but with my example source code in this bug report, I can't seem to follow the optimization path that results in what I'm seeing.

I understand that the optimizer can ignore duplicated code, or unnecessary code, but conv and d2 need to be initialized somehow, and if the compiler doesn't use the code that's there, what does it use?

A warning would be really nice.
Comment 3 Andrew Pinski 2005-12-03 00:40:26 UTC
(In reply to comment #2)
> A warning would be really nice.

The warning was filed as PR 14024 and fixed for 4.2.0.
Comment 4 cdfrey 2005-12-05 04:00:40 UTC
Just adding a link to a comp.lang.c++.moderated discussion on this, for future reference, when other folks run into this again.

Subject line: alias rules and optimization
http://groups.google.ca/group/comp.lang.c++.moderated/browse_thread/thread/e7bf096832526f8e/5714701b02a2a3cc?hl=en#5714701b02a2a3cc