This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Patch: IA64 HP-UX struct-layout failures in testsuite.
- From: Steve Ellcey <sje at cup dot hp dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Tue, 5 Oct 2004 14:30:41 -0700 (PDT)
- Subject: Patch: IA64 HP-UX struct-layout failures in testsuite.
- Reply-to: sje at cup dot hp dot com
This patch fixes most of the gcc.dg-struct-layout-1 failures on IA64
HP-UX. The problem is that while the 128 long double type has 8 byte
alignment in ILP32 mode it should be aligned to 16 bytes when passed as
an argument. I also found a place in ia64_function_arg_advance where
TFmode values might try to be put into FP registers which is also wrong.
Tested on IA64 HP-UX with no regressions and 25 fewer failures.
Steve Ellcey
sje@cup.hp.com
2004-10-05 Steve Ellcey <sje@cup.hp.com>
* config/ia64/ia64.h (FUNCTION_ARG_BOUNDARY): Change macro to
call ia64_function_arg_boundary.
* config/ia64/ia64-protos.h (ia64_function_arg_boundary): New.
* config/ia64/ia64.c (ia64_function_arg_boundary): New.
(ia64_function_arg_advance): Do not put 128 bit floats into
FP registers.
*** gcc.orig/gcc/config/ia64/ia64.h Tue Oct 5 14:05:41 2004
--- gcc/gcc/config/ia64/ia64.h Tue Oct 5 14:05:15 2004
*************** do { \
*** 1376,1390 ****
/* If defined, a C expression that gives the alignment boundary, in bits, of an
argument with the specified mode and type. */
! /* Arguments with alignment larger than 8 bytes start at the next even
! boundary. See ia64_function_arg. */
#define FUNCTION_ARG_BOUNDARY(MODE, TYPE) \
! (((TYPE) ? (TYPE_ALIGN (TYPE) > 8 * BITS_PER_UNIT) \
! : (((((MODE) == BLKmode \
! ? int_size_in_bytes (TYPE) : GET_MODE_SIZE (MODE)) \
! + UNITS_PER_WORD - 1) / UNITS_PER_WORD) > 1)) \
! ? 128 : PARM_BOUNDARY)
/* A C expression that is nonzero if REGNO is the number of a hard register in
which function arguments are sometimes passed. This does *not* include
--- 1376,1386 ----
/* If defined, a C expression that gives the alignment boundary, in bits, of an
argument with the specified mode and type. */
! /* Return the alignment boundary in bits for an argument with a specified
! mode and type. */
#define FUNCTION_ARG_BOUNDARY(MODE, TYPE) \
! ia64_function_arg_boundary (MODE, TYPE)
/* A C expression that is nonzero if REGNO is the number of a hard register in
which function arguments are sometimes passed. This does *not* include
*** gcc.orig/gcc/config/ia64/ia64-protos.h Tue Oct 5 14:05:56 2004
--- gcc/gcc/config/ia64/ia64-protos.h Tue Oct 5 14:05:09 2004
*************** extern int ia64_function_arg_partial_nre
*** 77,82 ****
--- 77,83 ----
enum machine_mode, tree, int);
extern void ia64_function_arg_advance (CUMULATIVE_ARGS *, enum machine_mode,
tree, int);
+ extern int ia64_function_arg_boundary (enum machine_mode, tree);
extern void ia64_asm_output_external (FILE *, tree, const char *);
#endif /* TREE_CODE */
*** gcc.orig/gcc/config/ia64/ia64.c Tue Oct 5 14:05:36 2004
--- gcc/gcc/config/ia64/ia64.c Tue Oct 5 14:05:17 2004
*************** ia64_function_arg_advance (CUMULATIVE_AR
*** 3328,3334 ****
/* Integral and aggregates go in general registers. If we have run out of
FR registers, then FP values must also go in general registers. This can
happen when we have a SFmode HFA. */
! else if (! FLOAT_MODE_P (mode) || cum->fp_regs == MAX_ARGUMENT_SLOTS)
cum->int_regs = cum->words;
/* If there is a prototype, then FP values go in a FR register when
--- 3328,3335 ----
/* Integral and aggregates go in general registers. If we have run out of
FR registers, then FP values must also go in general registers. This can
happen when we have a SFmode HFA. */
! else if (mode == TFmode || mode == TCmode
! || (! FLOAT_MODE_P (mode) || cum->fp_regs == MAX_ARGUMENT_SLOTS))
cum->int_regs = cum->words;
/* If there is a prototype, then FP values go in a FR register when
*************** ia64_function_arg_advance (CUMULATIVE_AR
*** 3349,3354 ****
--- 3350,3379 ----
cum->fp_regs += (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT ? 2 : 1);
cum->int_regs = cum->words;
}
+ }
+
+ /* Arguments with alignment larger than 8 bytes start at the next even
+ boundary. See ia64_function_arg. */
+
+ int
+ ia64_function_arg_boundary (enum machine_mode mode, tree type)
+ {
+
+ if (mode == TFmode && TARGET_HPUX && TARGET_ILP32)
+ return PARM_BOUNDARY * 2;
+
+ if (type)
+ {
+ if (TYPE_ALIGN (type) > PARM_BOUNDARY)
+ return PARM_BOUNDARY * 2;
+ else
+ return PARM_BOUNDARY;
+ }
+
+ if (GET_MODE_BITSIZE (mode) > PARM_BOUNDARY)
+ return PARM_BOUNDARY * 2;
+ else
+ return PARM_BOUNDARY;
}
/* Variable sized types are passed by reference. */