This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
2.95.1 alias analysis bug
- To: gcc-bugs at gcc dot gnu dot org
- Subject: 2.95.1 alias analysis bug
- From: Peter Lawrence <Peter dot Lawrence at Eng dot Sun dot COM>
- Date: Wed, 15 Mar 2000 17:34:49 -0800 (PST)
Guys and Gals,
I'ld be suprised if everyone did not already know this one,
but I thought I should send it anyway (did not see it in the "list of well-
known bugs" which suprised me). I also offer a decent workaround solution
that I hope GNU-C picks up.
The "strict aliasing" new in gcc-2.9 is in conflict with one of gcc's long
standing extensions, namely allowing a cast as an l-value. The example I
first ran into was in Cygnus' own printf library function, but is easily
shown with a test program:
float
fred (float * p)
{
*(int *)p = 0x01230000;
return 5.0f * *p;
}
With strict aliasing the assignment to *p, and the fetch of *p cannot alias
since they refer to different types, so the compiler is free to rearrange
the order of the load and store, even though in reality they do point to
the same address and the load and store cannot really be rearranged.
compiled with -O1 using gcc-2.95.1 for SPARC gives OK code:
sethi %hi(19070976), %g2
st %g2, [%o0] <-- the store
ld [%o0], %f2 <-- and load are in correct order
sethi %hi(.LLC0), %g2
ld [%g2+%lo(.LLC0)], %f0
retl
fmuls %f2, %f0, %f0
compiled with -O2 (includes strict alias analysis) for SPARC gives:
ld [%o0], %f2
sethi %hi(.LLC0), %g3
sethi %hi(19070976), %g2
ld [%g3+%lo(.LLC0)], %f0
fmuls %f2, %f0, %f0
retl
st %g2, [%o0] <-- here the store comes a little late !!!
Since the contents of the pointers for the load and the store are totally
un-ambiguously the same it is incorrect that the strict-type analysis is
being given precedence here, especially when the source level program is
"correct" in the spirit of the GNU-C extension that it uses.
When strict aliasing is turned on this case should be detected and a
warning issued and correct code generated rather than silently generating
incorrect code.
-------------------------------------------------------------
In the compiler I am working on a source level work-around is available:
float
wilma (float * p)
{
*p = (float)(void)0x01230000;
return 5.0f * *p;
}
The language has been enhanced to allow casting to VOID if and only if
the result is immediately cast to another non-void type of the same size
as the original type. The result is transfering bits _without_ converting,
something that everyone wants but that ANSI-C is incapable of doing cleanly.
The compiler change to support this is trivial, and it gets used a lot here.
It also eliminates union-tricks which are ugly and often hard to optimize.
I highly recommend that GNU-C incorporate it. I can provide diffs if anyone
wants them.
-Pete Lawrence, peter.lawrence@eng.sun.com, 408-774-8661.