Bug 37867 - inconsistent results on -O2 when reading bits from packed struct
Summary: inconsistent results on -O2 when reading bits from packed struct
Status: RESOLVED INVALID
Alias: None
Product: gcc
Classification: Unclassified
Component: tree-optimization (show other bugs)
Version: 4.3.2
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2008-10-18 13:31 UTC by Török Edwin
Modified: 2008-10-18 18:11 UTC (History)
2 users (show)

See Also:
Host: x86_64-linux-gnu
Target: x86_64-linux-gnu
Build: x86_64-linux-gnu
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 Török Edwin 2008-10-18 13:31:59 UTC
Running gcc-4.3 -O2 on PR1386.c I get different results than with -O1.

$ gcc-4.3 -O2 PR1386.c && ./a.out
PR1386.c: In function ‘main’:
PR1386.c:15: warning: large integer implicitly truncated to unsigned type
PR1386.c:17: warning: large integer implicitly truncated to unsigned type
bad bits: fffffffffffffff0
$ gcc-4.3 -O2 PR1386.c && ./a.out
PR1386.c: In function ‘main’:
PR1386.c:15: warning: large integer implicitly truncated to unsigned type
PR1386.c:17: warning: large integer implicitly truncated to unsigned type
bad bits: fffffffffffffff0

gcc-4.2 is fine:
$ gcc-4.2 -O2 PR1386.c && ./a.out
PR1386.c: In function ‘main’:
PR1386.c:15: warning: large integer implicitly truncated to unsigned type
PR1386.c:17: warning: large integer implicitly truncated to unsigned type
bad bits: 0

$ gcc-4.2 -O3 PR1386.c && ./a.out
PR1386.c: In function ‘main’:
PR1386.c:15: warning: large integer implicitly truncated to unsigned type
PR1386.c:17: warning: large integer implicitly truncated to unsigned type
bad bits: 0

The file is from an LLVM testcase http://llvm.org/bugs/show_bug.cgi?id=1386

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

struct X {
  unsigned char pad : 4;
  uint64_t a : 64;
  uint64_t b : 60;
} __attribute__((packed));

int main (void)
{
  struct X x;
  uint64_t bad_bits;

  x.pad = 255;
  x.a = -1ULL;
  x.b = -1ULL;

  bad_bits = ((uint64_t)-1ULL) ^ *(1+(uint64_t *) &x);
  printf("bad bits: %llx\n", bad_bits);
  return bad_bits != 0;
}
Comment 1 Török Edwin 2008-10-18 13:39:05 UTC
(In reply to comment #0)
> Running gcc-4.3 -O2 on PR1386.c I get different results than with -O1.
> 
> $ gcc-4.3 -O2 PR1386.c && ./a.out
> PR1386.c: In function ‘main’:
> PR1386.c:15: warning: large integer implicitly truncated to unsigned type
> PR1386.c:17: warning: large integer implicitly truncated to unsigned type
> bad bits: fffffffffffffff0

$ gcc-4.3 -O1 PR1386.c && ./a.out
PR1386.c: In function ‘main’:
PR1386.c:15: warning: large integer implicitly truncated to unsigned type
PR1386.c:17: warning: large integer implicitly truncated to unsigned type
bad bits: 0
Comment 2 Richard Biener 2008-10-18 14:05:19 UTC
You invoke undefined behavior by accessing parts of a and b via
*(1+(uint64_t *) &x).  This access is not valid because of C aliasing rules.
Comment 3 Chris Lattner 2008-10-18 18:06:39 UTC
Does it work with -fno-strict-aliasing?
Comment 4 Török Edwin 2008-10-18 18:07:59 UTC
(In reply to comment #3)
> Does it work with -fno-strict-aliasing?
> 

It doesn't.

edwin@debian:~$ g++ -O2 -fno-strict-aliasing x.c
x.c: In function ‘int main()’:
x.c:15: warning: large integer implicitly truncated to unsigned type
x.c:17: warning: large integer implicitly truncated to unsigned type
edwin@debian:~$ ./a.out
bad bits: fffffffffffffff0
Comment 5 Chris Lattner 2008-10-18 18:11:50 UTC
Please clone/reopen this bug, it should work with -fno-strict-aliasing.