Bug 42179 - Incorrect optimization (-O2) yields wrong code (regression)
Summary: Incorrect optimization (-O2) yields wrong code (regression)
Status: RESOLVED INVALID
Alias: None
Product: gcc
Classification: Unclassified
Component: c (show other bugs)
Version: 4.5.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2009-11-26 02:38 UTC by Vincent Lefèvre
Modified: 2009-11-26 16:39 UTC (History)
1 user (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 Vincent Lefèvre 2009-11-26 02:38:48 UTC
With gcc-snapshot (Debian 20091118-1) 4.5.0 20091119 (experimental) [trunk revision 154312] on an x86_64 GNU/Linux machine and the following code (partly based on GMP):

#include <stdio.h>

union ieee_double_extract
{
  struct
  {
    unsigned int manl:32;
    unsigned int manh:20;
    unsigned int exp:11;
    unsigned int sig:1;
  } s;
  double d;
};

int main (void)
{
  union { double d; unsigned long long i; } x;
  x.d = 0.0 / 0.0;
  printf ("d = %g [%llx]\n", x.d, x.i);
  printf ("exp = %x\n", (unsigned int)
          ((union ieee_double_extract *)&(x.d))->s.exp);
  return 0;
}

$ gcc-snapshot -Wall -Wextra testd.c -o testd
$ ./testd
d = nan [fff8000000000000]
exp = 7ff

This is OK, but with -O2:

$ gcc-snapshot -Wall -Wextra testd.c -o testd -O2
$ ./testd
d = nan [fff8000000000000]
exp = 0

I don't know whether aliasing rules are broken, but note that there are no warnings.

GCC 4.4.2 doesn't have this problem.
Comment 1 Richard Biener 2009-11-26 09:56:08 UTC
Aliasing rules are indeed broken because you access a union of anonymous type
through a pointer to a union of type ieee_double_extract. 

I think you want

  union { union ieee_double_extract d; unsigned long long i; } x;

  x.d.d = 0.0 / 0.0;
  printf ("d = %g [%llx]\n", x.d.d, x.d.i);
  printf ("exp = %x\n", (unsigned int) x.d.s.exp);
  return 0;

or even simplified.
Comment 2 Dmitry Gorbachev 2009-11-26 11:02:48 UTC
> note that there are no warnings

A warning is issued with -Wstrict-aliasing=1 or -Wstrict-aliasing=2, but no warning with -Wstrict-aliasing=3 (or -Wall).

I see there are already a few bug reports about this.
Comment 3 Richard Biener 2009-11-26 11:25:13 UTC
Correct.  We can either produce possibly lots of false positives or not warn.
Warning in the cases where we can prove your code is wrong would be pointless
as in that case we'd better take measures to not miscompile it (and we then
can do so as we were able to detect the situation).  With 4.4 one alias
warning machinery did exactly this (warn but then not miscompile - but then
it didn't warn in cases where it _did_ miscompile).

It's generally impossible to please all folks here ;)
Comment 4 Vincent Lefèvre 2009-11-26 15:53:37 UTC
(In reply to comment #1)
> Aliasing rules are indeed broken because you access a union of anonymous type
> through a pointer to a union of type ieee_double_extract.

OK, the real code in MPFR is a "double" accessed through a pointer to a union of type ieee_double_extract, but I suppose this is the same problem.

BTW, could my testcase be used to improve GCC's -Wstrict-aliasing=3 (i.e. to have fewer false negatives without introducing more false positives), or is it too difficult / not possible?
Comment 5 Richard Biener 2009-11-26 16:39:25 UTC
The frontend code should indeed be able to unconditionally warn for
((union ieee_double_extract *)&(x.d))->s.exp because it can see both
the underlying object and the access through the non-conflicting type.