Bug 6377 - Optimization (>= -O2) with bitfields yields incorrect result
Summary: Optimization (>= -O2) with bitfields yields incorrect result
Status: RESOLVED DUPLICATE of bug 21920
Alias: None
Product: gcc
Classification: Unclassified
Component: rtl-optimization (show other bugs)
Version: 3.0.3
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: wrong-code
Depends on:
Blocks:
 
Reported: 2002-04-19 11:36 UTC by charles
Modified: 2005-06-05 09:44 UTC (History)
2 users (show)

See Also:
Host: sparc-sun-solaris2.8
Target: sparc-sun-solaris2.8
Build: sparc-sun-solaris2.8
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 charles 2002-04-19 11:36:07 UTC
   gcc versions 2.96 and later have a problem with bitfields
and optimization.  There appears to be a mismatch between where the
results are left and where they should go, especially when there
is an intermediate cast.  The result is that the bitfield structure
is left with random data in it.  This happens on Solaris (with 3.0.3)
and Linux (with 2.96, 3.0.3, and 3.0.4) using optimization levels -O2
or higher.

Release:
3.0.3

Environment:
System: SunOS dog 5.8 Generic_108528-12 sun4u sparc SUNW,Sun-Blade-100
Architecture: sun4

	
host: sparc-sun-solaris2.8
build: sparc-sun-solaris2.8
target: sparc-sun-solaris2.8
configured with: ../gcc-3.0.3/configure

How-To-Repeat:
/* 
To Repeat: save this example program (self-contained
except for the printf at the bottom) and compile with -O3.  The
result should contain nonzero bits, but doesn't.  (The problem is
that the result in the getFoo is being put in the stack frame, while
the calling program expects the result in edx:eax.)

Charles Rennolet (charles@provis.com, clr@thurse.mn.org)

Example: (A very short one.)
*/
typedef struct
{
    unsigned int   device   : 28;
    unsigned int   stuckat  : 2;
    unsigned int   direction: 2;
    unsigned int   pin      : 12;
    unsigned int   port     : 12;
    unsigned int   status   : 4;
    unsigned int   type     : 4;
} *pFoo;

unsigned long long getFoo(int type,
                     int device,
                     int port,
                     int pin,
                     int InOut,
                     int stuckat)
{
    unsigned long long retValue = 0;

    ((pFoo)&retValue)->status    = 0;
    ((pFoo)&retValue)->type      = type;
    ((pFoo)&retValue)->device    = device;
    ((pFoo)&retValue)->port      = port;
    ((pFoo)&retValue)->pin       = pin;
    ((pFoo)&retValue)->direction = InOut;
    ((pFoo)&retValue)->stuckat   = stuckat;
    return(retValue);
}

int main( int argc, char **argv)
{
    unsigned long long foo;
    unsigned int one = 1;
    unsigned int two = 2;
    unsigned int three = 3;
    unsigned int four = 4;
    unsigned int five = 5;
    unsigned int six = 6;
    unsigned int seven = 7;
    unsigned int tmp;

    foo = getFoo( one, two, three, four, five, six);

    printf("foo = %016llx\n", foo);
}

/* ============================Example Ends============================= */

Preprocessed input file:

# 22 "foo.c"
typedef struct
{
    unsigned int device : 28;
    unsigned int stuckat : 2;
    unsigned int direction: 2;
    unsigned int pin : 12;
    unsigned int port : 12;
    unsigned int status : 4;
    unsigned int type : 4;
} *pFoo;

unsigned long long getFoo(int type,
                     int device,
                     int port,
                     int pin,
                     int InOut,
                     int stuckat)
{
    unsigned long long retValue = 0;

    ((pFoo)&retValue)->status = 0;
    ((pFoo)&retValue)->type = type;
    ((pFoo)&retValue)->device = device;
    ((pFoo)&retValue)->port = port;
    ((pFoo)&retValue)->pin = pin;
    ((pFoo)&retValue)->direction = InOut;
    ((pFoo)&retValue)->stuckat = stuckat;
    return(retValue);
}

int main( int argc, char **argv)
{
    unsigned long long foo;
    unsigned int one = 1;
    unsigned int two = 2;
    unsigned int three = 3;
    unsigned int four = 4;
    unsigned int five = 5;
    unsigned int six = 6;
    unsigned int seven = 7;
    unsigned int tmp;

    foo = getFoo( one, two, three, four, five, six);

    printf("foo = %016llx\n", foo);
}
Comment 1 charles 2002-04-19 11:36:07 UTC
Fix:
	Don't compile with -O2 or greater?  Yeah, I know it's lame.
Comment 2 Jakub Jelinek 2002-04-21 14:35:13 UTC
State-Changed-From-To: open->closed
State-Changed-Why: Your testcase is ill-formed, uses illegal type-punning.
    Please see info gcc on -fstrict-aliasing (which is
    the default in these gcc releases at -O2 and above).
    Either compile with -O2 -fno-strict-aliasing or fix
    the code in question (e.g. to access the objects through
    unions).
Comment 3 Andrew Pinski 2005-06-05 09:44:08 UTC
Reopening to ...
Comment 4 Andrew Pinski 2005-06-05 09:44:30 UTC
Mark as a dup of bug 21920

*** This bug has been marked as a duplicate of 21920 ***