This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: ICE outputting unaligned fp constant on powerpc-apple-darwin5.1
- From: Stuart Hastings <stuart at apple dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Wed, 5 Dec 2001 10:28:48 -0800
- Subject: Re: ICE outputting unaligned fp constant on powerpc-apple-darwin5.1
A quick analysis of http://gcc.gnu.org/ml/gcc/2001-11/msg01595.html
This static initialization fragment causes an ICE on the
TARGET_POWERPC GCC3:
struct { int i ; double d ; } x = { 1, 42.0 } ;
The trouble seems to be an alignment check in
varasm.c:assemble_real(). BTW, "BIGGEST_FIELD_ALIGNMENT" is not
defined for TARGET_POWERPC:
1.200 (rth 18-Aug-01): assemble_real (d, mode, align)
...
1.200 (rth 18-Aug-01): /* We cannot emit unaligned
floating point constants. This is slightly
1.200 (rth 18-Aug-01): complicated in that we don't
know what "unaligned" means exactly. */
1.200 (rth 18-Aug-01): #ifdef BIGGEST_FIELD_ALIGNMENT
1.200 (rth 18-Aug-01): if (align >=
BIGGEST_FIELD_ALIGNMENT)
1.200 (rth 18-Aug-01): ;
1.200 (rth 18-Aug-01): else
1.200 (rth 18-Aug-01): #endif
1.200 (rth 18-Aug-01): if (align < GET_MODE_ALIGNMENT
(mode))
1.200 (rth 18-Aug-01): abort ();
...
On PPC, structures are aligned to accomodate their most restrictive
member, maxing out at word alignment, except 1) if the *first* member
of the struct requires more alignment, the struct follows, and 2) if
any field has type 'vector' (AltiVec), the entire struct will be
16-byte (AltiVec) aligned.
Any field of type double that isn't the first field of a struct will
be word-aligned. Structure size is always a multiple of its alignment
(for array-of-struct indexing).
These rules have some curious properties. For example,
/* a twelve-byte struct requiring 4-byte alignment */
struct { int i ; double d ; } x = { 1, 42.0 } ;
/* a sixteen-byte struct requiring 8-byte alignment */
struct { double d ; int i ; } y = { 42.0, 1 } ;
The real problem is that PPC violates the assumption stated in the
comment: "cannot emit unaligned floating point constants." On PPC,
we're *supposed* to violate that principle. The rest of the comment
foreshadows our current problem :-) .
My preferred solution would be for some enlightened person to explain
that I've misunderstood the PPC alignment rules :-) .
Failing that, my next idea was to delete the sanity check, and Apple
is currently using such a patch. However, that leaves the "align"
parameter unreferenced, and presumably this is a useful check for
every other GCC target.
There are several possible fixes, all unpalatable. Either we 1) delete
the check, 2) pass down more information to facilitate a smarter
check, or 3) conditionalize it away for PPC.
1) will work, but loses this useful check for every non-PPC target.
2) is architecturally unpalatable, as it means complicating this
low-level routine in a way that is useless to every non-PPC target.
3) is ugly, as this is clearly supposed to be a target-independent file.
Nevertheless, IMHO it seems the least unpalatable of these alternatives.
Accordingly, below is a patch implementing alternative 3).
Instead of "#ifndef TARGET_POWERPC", I offer "#ifndef
IRRATIONAL_ALIGNMENT_RULES", basically a synonym for "TARGET_POWERPC"
(and TARGET_POWER, etc.). 'Tis ugly, and I dislike the
double-negative, but it's very localized. More usefully, it imposes
no further burden on any other (rationally aligned) target, and it can
be employed by any future target with similarly baroque alignment
rules.
This patch has bootstrapped C, C++, and ObjC on powerpc-apple-darwin
and i686-pc-linux-gnu. No regressions.
I've been told that AIX (and, by inference, powerpc-linux) employs the
same alignment rules. Since I've seen no reference to this problem
from any AIX users, I would have guessed otherwise. How was this
resolved on AIX and powerpc-linux, or is it still undiscovered there?
I'm a bit disturbed that such a fundamental bug escaped detection for
more than three months. (Perhaps all of our double fields have been
carefully pre-aligned by hand in our sources? Maybe nobody uses double
fields?) I did a quick scan of the compile and execute sections of
gcc.c-torture, and didn't notice any unaligned-double-in-struct
checks. I have already posted a suitable testcase.
stuart hastings
2001-12-05 Stuart Hastings <stuart@apple.com>
* rs6000.h (IRRATIONAL_ALIGNMENT_RULES) New macro.
* varasm.c (assemble_real): Use it.
Index: gcc/gcc/config/rs6000/rs6000.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000.h,v
retrieving revision 1.151
diff -c -d -c -5 -p -r1.151 rs6000.h
*** rs6000.h 2001/12/03 19:13:35 1.151
--- rs6000.h 2001/12/05 17:39:54
*************** extern int rs6000_altivec_abi;
*** 630,639 ****
--- 630,642 ----
#define FUNCTION_BOUNDARY 32
/* No data type wants to be aligned rounder than this. */
#define BIGGEST_ALIGNMENT 128
+ /* Structs with 64-bit doubles may be 64-bit or 32-bit aligned. */
+ #define IRRATIONAL_ALIGNMENT_RULES 1
+
/* A C expression to compute the alignment for a variables in the
local store. TYPE is the data type, and ALIGN is the alignment
that the object would ordinarily have. */
#define LOCAL_ALIGNMENT(TYPE, ALIGN) \
((TARGET_ALTIVEC \
Index: gcc/gcc/varasm.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/varasm.c,v
retrieving revision 1.233
diff -c -d -c -5 -p -r1.233 varasm.c
*** varasm.c 2001/12/01 18:42:39 1.233
--- varasm.c 2001/12/05 17:39:54
*************** assemble_real (d, mode, align)
*** 2156,2174 ****
--- 2156,2176 ----
{
struct assemble_real_args args;
args.d = &d;
args.mode = mode;
+ #ifndef IRRATIONAL_ALIGNMENT_RULES
/* We cannot emit unaligned floating point constants. This is
slightly
complicated in that we don't know what "unaligned" means
exactly. */
#ifdef BIGGEST_FIELD_ALIGNMENT
if (align >= BIGGEST_FIELD_ALIGNMENT)
;
else
#endif
if (align < GET_MODE_ALIGNMENT (mode))
abort ();
+ #endif
if (do_float_handler (assemble_real_1, (PTR) &args))
return;
internal_error ("floating point trap outputting a constant");