* [Linux-ia64] gcc bug
@ 2001-01-26 8:09 David Mosberger
2001-01-26 9:40 ` Keith Owens
` (2 more replies)
0 siblings, 3 replies; 4+ messages in thread
From: David Mosberger @ 2001-01-26 8:09 UTC (permalink / raw)
To: linux-ia64
The attached program demonstrates a gcc code generation bug. I'm
seeing this bug with the November snapshot with all patches applied.
Specifically, if I compile the program with "-O", it works fine and I
get:
$ gcc -O t.c
$ ./a.out
feed0000beef
However, if I compile it with "-O2", I get:
$ gcc -O2 t.c
$ ./a.out
beef
which obviously can't be right.
--david
struct f {
unsigned long lo : 32;
unsigned long hi : 32;
};
unsigned long r;
void
doit (unsigned long value1, unsigned long value2)
{
unsigned long w, t;
((struct f*)&w)->lo = ((struct f*)&value1)->lo;
((struct f*)&w)->hi = ((struct f*)&value2)->hi;
r = w;
}
int
main (int argc, char **argv)
{
doit(0xbeef, 0xfeed00000000);
printf ("%lx\n", r);
}
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [Linux-ia64] gcc bug
2001-01-26 8:09 [Linux-ia64] gcc bug David Mosberger
@ 2001-01-26 9:40 ` Keith Owens
2001-01-27 4:20 ` Jim Wilson
2001-01-27 5:21 ` David Mosberger
2 siblings, 0 replies; 4+ messages in thread
From: Keith Owens @ 2001-01-26 9:40 UTC (permalink / raw)
To: linux-ia64
On Fri, 26 Jan 2001 00:09:55 -0800,
David Mosberger <davidm@hpl.hp.com> wrote:
>The attached program demonstrates a gcc code generation bug.
>
>struct f {
> unsigned long lo : 32;
> unsigned long hi : 32;
>};
K&R says "Fields may be declared only as ints". The C99 rational says
"Three types of bit fields are now defined: plain int calls for
implementation-defined signedness (as in K&R), signed int calls for
assuredly signed fields, and unsigned int calls for unsigned fields".
I am surprised that the compiler accepted unsigned long, it is not
listed as a gcc extension. Do you get the same error when those fields
are changed to unsigned int?
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [Linux-ia64] gcc bug
2001-01-26 8:09 [Linux-ia64] gcc bug David Mosberger
2001-01-26 9:40 ` Keith Owens
@ 2001-01-27 4:20 ` Jim Wilson
2001-01-27 5:21 ` David Mosberger
2 siblings, 0 replies; 4+ messages in thread
From: Jim Wilson @ 2001-01-27 4:20 UTC (permalink / raw)
To: linux-ia64
There was a comment about non-int bitfields. This isn't allowed by the ISO C
standard, but it is a very common extension. Most C compilers support it.
Gcc will give a warning about this construct if you use -pedantic. This
isn't related to the problem though.
The problem with the code is that it uses invalid casts. ISO C says that
if you access an object using a type other than what the object was declared
with, then the result is undefined. There are a few exceptions, signedness
doesn't matter, qualifiers don't matter, aggregate types containing the type
are OK, and char is OK. (In the 1989 ANSI C standard, this is in section 3.3
Expressions.) This rule exists so that C compilers can do type-based alias
analysis. Gcc tries to do aliasing based on addresses first, but if it gets
confused by address arithmetic, then it will try type-based alias analysis.
So in this case, it decides that the read of the unsigned int w and the
store to struct f w can't alias because the types are different, and then it
emits an instruction schedule that causes the code to perform differently than
what you expected. This code would probably work on other targets. The
lack of addressing modes in IA-64 makes it harder for the alias analysis pass
to figure out whether two addresses are the same, and hence we fall back on
type-based aliasing more often than we would on say an IA-32 machine.
Gcc does support type punning via unions, though the ISO C standard technically
does not allow this. If you write the code like this it should work
union g {
struct f f;
unsigned long l;
};
((union g*)&w)->f.lo = ((union g*)&value1)->f.lo;
((union g*)&w)->f.hi = ((union g*)&value2)->f.hi;
However, this is a bit cryptic. It would be clearer, and you will get much
more efficient code, if you write it something like this. Using & usually
forces values onto the stack. If we do it this way, we do everything in
registers until the write to r.
union g {
struct f f;
unsigned long l;
};
doit (unsigned long value1, unsigned long value2)
{
union g w, t, u;
t.l = value1;
w.f.lo = t.f.lo;
u.l = value2;
w.f.hi = u.f.hi;
r = w.l;
}
int
main (int argc, char **argv)
{
doit(0xbeef, 0xfeed00000000);
printf ("%lx\n", r);
}
Jim
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [Linux-ia64] gcc bug
2001-01-26 8:09 [Linux-ia64] gcc bug David Mosberger
2001-01-26 9:40 ` Keith Owens
2001-01-27 4:20 ` Jim Wilson
@ 2001-01-27 5:21 ` David Mosberger
2 siblings, 0 replies; 4+ messages in thread
From: David Mosberger @ 2001-01-27 5:21 UTC (permalink / raw)
To: linux-ia64
>>>>> On Fri, 26 Jan 2001 20:20:31 -0800, Jim Wilson <wilson@cygnus.com> said:
Jim> There was a comment about non-int bitfields. This isn't
Jim> allowed by the ISO C standard, but it is a very common
Jim> extension. Most C compilers support it. Gcc will give a
Jim> warning about this construct if you use -pedantic. This isn't
Jim> related to the problem though.
Yes.
Jim> The problem with the code is that it uses invalid casts.
Oh, you are right.
Jim> Gcc does support type punning via unions, though the ISO C
Jim> standard technically does not allow this.
Good.
Jim>If you write the code like this it should work
Jim>union g {
Jim> struct f f;
Jim> unsigned long l;
Jim>};
Jim> ((union g*)&w)->f.lo = ((union g*)&value1)->f.lo;
Jim> ((union g*)&w)->f.hi = ((union g*)&value2)->f.hi;
OK, that seems to take care of the problem.
Jim> However, this is a bit cryptic. It would be clearer, and you
Jim> will get much more efficient code, if you write it something
Jim> like this. Using & usually forces values onto the stack. If
Jim> we do it this way, we do everything in registers until the
Jim> write to r.
Yes, that would be much cleaner and better for performance.
Unfortunately, it's not my code and it's a large and complex program,
so I'll probably have to make do with the "union" wrapper for now.
Thanks a lot,
--david
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2001-01-27 5:21 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2001-01-26 8:09 [Linux-ia64] gcc bug David Mosberger
2001-01-26 9:40 ` Keith Owens
2001-01-27 4:20 ` Jim Wilson
2001-01-27 5:21 ` David Mosberger
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox