Note: This bug is displayed in read-only format because the product is no longer active in Red Hat Bugzilla.
For bugs related to Red Hat Enterprise Linux 4 product line. The current stable release is 4.9. For Red Hat Enterprise Linux 6 and above, please visit Red Hat JIRA https://issues.redhat.com/secure/CreateIssue!default.jspa?pid=12332745 to report new issues.

Bug 202952

Summary: Optimizer problem in gcc with -O2 or -O3
Product: Red Hat Enterprise Linux 4 Reporter: Tom Fredian <twf>
Component: gccAssignee: Jakub Jelinek <jakub>
Status: CLOSED NOTABUG QA Contact:
Severity: medium Docs Contact:
Priority: medium    
Version: 4.4   
Target Milestone: ---   
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2006-08-17 15:30:04 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

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.