Bug 870419

Summary: gcc 4.7.2.2 (64bit) does not inline compile the following properly, gcc 4.6.3 (16bit) inline compiles properly (fedora 17 for 64bit) fedora 16 (for 32bit)
Product: [Fedora] Fedora Reporter: Leslie Satenstein <lsatenstein>
Component: gcc4Assignee: Jakub Jelinek <jakub>
Status: CLOSED NOTABUG QA Contact:
Severity: high Docs Contact:
Priority: unspecified    
Version: 4   
Target Milestone: ---   
Target Release: ---   
Hardware: x86_64   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2012-11-19 13:59:49 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description Leslie Satenstein 2012-10-26 12:36:03 UTC
Description of problem:

Getting bad inline code 

Version-Release number of selected component (if applicable):
gcc 4.7.2.2 (64bit) does not compile the following properly, (SEE BELOW)
gcc 4.6.3 (16bit) compiles properly  
fedora 17 for 64bit 4.7.2.2.  
fedora 16 4.6.3 for 32bit)

Hardware  Intel e7300 dual core 64bit for both systems.
Memory available (free unused) 2.5+ gig) 

How reproducible:

everytime

Steps to Reproduce:
1.
2.
3.
  
Actual results:



Expected results:


Additional info:

The following code fragment indicates a bug that took me 2 days to discover.
It was used for the past 2 years.
It is compiled and used correctly on 32 bit system but generates 
incorrect results for 64 bit systems.
The fix is shown below the actual code.
The code works with the fix.


/* 
 * do an xor of an 8 byte block
 * optimized to two loops vs an 8 char loop 
 */
static inline void memxor(unsigned char *dest, char *src)
{
    register int i = 8 / sizeof(uint32);  //uint32 is 4 bytes
    uint32 *d = (uint32 *) dest;
    uint32 *s = (uint32 *) src;

    while (0 < i--)		//two  loops  if unsigned long  is 4 bytes
	*d++ ^= *s++;		
}

The fixed code that works

/* 
 * do an xor of an 8 byte block
 * optimized vs an 8 char loop 
 */
static inline void memxor(unsigned char *dest, char *src)
{
    register int i = 8 / sizeof(uint32);  //uint32 is 4 bytes
    uint32 *d = (uint32 *) dest;
    uint32 *s = (uint32 *) src;

    while (0 < i--)		//two  loops  if unsigned long  is 4 bytes
    {	                        //added { and } and code generation is correct.
       *d++ ^= *s++;
    }		
}

Comment 1 Jakub Jelinek 2012-10-26 15:52:11 UTC
Please read http://gcc.gnu.org/bugs.html, this bugreport is completely useless.
You haven't provided self-contained preprocessed testcase, so one can only guess you have aliasing violation (if what dest/src point to aren't actually objects of uint32 or compatible type).  See if your testcase works with
-fno-strict-aliasing, then it is likely user fault.  I very much doubt adding a pair of {}s would change anything in that regard, but without a self-contained testcase there is nothing I can try to compile.  Furthermore, there is no 4.7.2.2 gcc version.