Bug 202952 - Optimizer problem in gcc with -O2 or -O3
Summary: Optimizer problem in gcc with -O2 or -O3
Keywords:
Status: CLOSED NOTABUG
Alias: None
Product: Red Hat Enterprise Linux 4
Classification: Red Hat
Component: gcc
Version: 4.4
Hardware: All
OS: Linux
medium
medium
Target Milestone: ---
: ---
Assignee: Jakub Jelinek
QA Contact:
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2006-08-17 14:06 UTC by Tom Fredian
Modified: 2007-11-17 01:14 UTC (History)
0 users

Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Clone Of:
Environment:
Last Closed: 2006-08-17 15:30:04 UTC
Target Upstream Version:
Embargoed:


Attachments (Terms of Use)

Description Tom Fredian 2006-08-17 14:06:18 UTC
Description of problem:

The gcc compiler seems to be changing the order of execution of statements 
such that pointers to memory are being dereferenced before the contents of the 
memory is initialized when using the -O2 or -O3 options.

Version-Release number of selected component (if applicable):

gcc version 3.4.6 20060404 (Red Hat 3.4.6-3)

How reproducible:

Very reproducible

Steps to Reproduce:
1. Run the program below first using -O1 and then using -O2

#define N 5
int main()
{
  int in[N];
  int out[N];
  short *optr=(short *)out;
  short *iptr=(short *)in;
  int i,j;
  printf("Uninitialized in=%x,%x,%x,%x,%x\n\n",in[0],in[1],in[2],in[3],in[4]);
  for (i=0;i<N;i++) {
    in[i]=i;
    *optr++=*iptr++;   
    *optr++=*iptr++;   
  }
  for (i=0;i<N;i++) 
    printf("in[%d]=%x, out[%d]=%x\n",i,in[i],i,out[i]);
  return 0;
}
  
Actual results:

With -O2 you get the following output:

Uninitialized in=80483ec,80495ec,bff37748,804828d,0

in[0]=0, out[0]=80483ec
in[1]=1, out[1]=80495ec
in[2]=2, out[2]=bff37748
in[3]=3, out[3]=804828d
in[4]=4, out[4]=0

Note that the output array contains the uninitialized values of the in array.


Expected results:

Compiled with -O1 you get the expected results where the output array contains 
the same values as the input array.

Uninitialized in=80483f4,80495f4,bfe21068,804828d,0

in[0]=0, out[0]=0
in[1]=1, out[1]=1
in[2]=2, out[2]=2
in[3]=3, out[3]=3
in[4]=4, out[4]=4

Additional info:

Obviously, this sample program does not represent the real use case where the 
problem was first detected. The original code was swapping the low 16-bits 
with the high 16-bits of a 32-bit integer and was not in doing this in a loop.

Comment 1 Jakub Jelinek 2006-08-17 15:30:04 UTC
The testcase is invalid C, violates the aliasing requirements of the ISO C
standard.
Search info gcc on -fstrict-aliasing or read directly the ISO C99 standard.
-O2 and above turns by default the -fstrict-aliasing option, as a workaround
for broken code you can use -fno-strict-aliasing, but better just fix the code
to conform to the standard.


Note You need to log in before you can comment on or make changes to this bug.