This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [Bug target/15106] Vector varargs failure for AltiVec on ppc32 linux
- From: Hartmut Penner <HPENNER at de dot ibm dot com>
- To: Alan Modra <amodra at bigpond dot net dot au>
- Cc: Aldy Hernandez <aldyh at redhat dot com>, gcc-patches at gcc dot gnu dot org, Janis Johnson <janis187 at us dot ibm dot com>
- Date: Wed, 28 Apr 2004 14:17:55 +0200
- Subject: Re: [Bug target/15106] Vector varargs failure for AltiVec on ppc32 linux
Alan wrote:
> > I don't think, there are any libs out there having vector args and been
> > compiled with -mno-altivec -mabi=no-altivec. The ABI also states
nothing
> > about this case. That means, we would not break anything. And it does
not
> > make sense, that long longs have a higher aligment than 128 bit
vectors.
> Hmm, after looking at latest passee_1.o, I think you do need to do
> something like this for -maltivec -mabi=no-altivec. The problem is
> that in this case (va_arg access to a vector type), an altivec insn is
> used to load out of the parameter save area. That requires 16 byte
> alignment. So firstly we need to ensure the stack is 16 byte aligned,
> and secondly we need to ensure that the offset into the parm save area
> is 16 byte aligned. A 16 byte aligned offset means that we need to
> choose r5,r6,r7,r8 to pass a vector in gprs.
> If you can't guarantee stack alignment then you'd need to create an
> aligned stack temp and shuffle data through it to the vector register.
> That's horrible.
I tried hard to fix 15106, and just dump what I have done for this,
the testcase of 15106 works now for both 32 and 64 bit.
The Patch does following:
Regardless of ABI, 16 byte vectors need to be aligned to 16 byte,
and also be passed in right aligned registers or stack.
What I am not sure about ppc32, if the stack is on 16 byte boundary.
Without this, we cannot fix for the testcase for ppc32, unless doing
'horrible' stuff. Pls. take a look at this, after this, I am now sure,
that the -mabi=altivec flag was a bad invention ...
regards, Hartmut
Index: rs6000.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000.c,v
retrieving revision 1.630
diff -u -p -r1.630 rs6000.c
--- rs6000.c 24 Apr 2004 06:37:18 -0000 1.630
+++ rs6000.c 28 Apr 2004 12:00:27 -0000
@@ -4040,7 +4040,7 @@ function_arg_boundary (enum machine_mode
return 64;
else if (SPE_VECTOR_MODE (mode))
return 64;
- else if (TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (mode))
+ else if (ALTIVEC_VECTOR_MODE (mode))
return 128;
else
return PARM_BOUNDARY;
@@ -4074,7 +4074,9 @@ function_arg_advance (CUMULATIVE_ARGS *c
{
cum->nargs_prototype--;
- if (TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (mode))
+ if ((TARGET_ALTIVEC_ABI
+ || (DEFAULT_ABI == ABI_AIX && TARGET_64BIT))
+ && ALTIVEC_VECTOR_MODE (mode))
{
if (USE_ALTIVEC_FOR_ARG_P (cum, mode, type, named))
{
@@ -4146,7 +4148,7 @@ function_arg_advance (CUMULATIVE_ARGS *c
n_words = rs6000_arg_size (mode, type);
/* Long long and SPE vectors are put in odd registers. */
- if (n_words == 2 && (gregno & 1) == 0)
+ if (n_words >= 2 && (gregno & 1) == 0)
gregno += 1;
/* Long long and SPE vectors are not split between registers
@@ -4154,7 +4156,7 @@ function_arg_advance (CUMULATIVE_ARGS *c
if (gregno + n_words - 1 > GP_ARG_MAX_REG)
{
/* Long long is aligned on the stack. */
- if (n_words == 2)
+ if (n_words >= 2)
cum->words += cum->words & 1;
cum->words += n_words;
}
@@ -4419,7 +4421,9 @@ function_arg (CUMULATIVE_ARGS *cum, enum
}
else
return gen_rtx_REG (mode, cum->vregno);
- else if (TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (mode))
+ else if ((TARGET_ALTIVEC_ABI
+ || (DEFAULT_ABI == ABI_AIX && TARGET_64BIT))
+ && ALTIVEC_VECTOR_MODE (mode))
{
if (named || abi == ABI_V4)
return NULL_RTX;
@@ -4481,10 +4485,11 @@ function_arg (CUMULATIVE_ARGS *cum, enum
n_words = rs6000_arg_size (mode, type);
/* Long long and SPE vectors are put in odd registers. */
- if (n_words == 2 && (gregno & 1) == 0)
+ if (n_words >= 2 && (gregno & 1) == 0)
gregno += 1;
- /* Long long does not split between registers and stack. */
+ /* Long long does not split between registers and stack,
+ nor do vector types. */
if (gregno + n_words - 1 <= GP_ARG_MAX_REG)
return gen_rtx_REG (mode, gregno);
else
@@ -4994,8 +4999,8 @@ rs6000_va_arg (tree valist, tree type)
lab_over = gen_label_rtx ();
addr_rtx = gen_reg_rtx (Pmode);
- /* AltiVec vectors never go in registers. */
- if (!TARGET_ALTIVEC || TREE_CODE (type) != VECTOR_TYPE)
+ /* AltiVec vectors never go in registers when using the AltiVec ABI. */
+ if (!TARGET_ALTIVEC_ABI || TREE_CODE (type) != VECTOR_TYPE)
{
TREE_THIS_VOLATILE (reg) = 1;
emit_cmp_and_jump_insns
@@ -5004,7 +5009,7 @@ rs6000_va_arg (tree valist, tree type)
lab_false);
/* Long long is aligned in the registers. */
- if (n_reg > 1)
+ if (n_reg >= 2)
{
u = build (BIT_AND_EXPR, TREE_TYPE (reg), reg,
build_int_2 (n_reg - 1, 0));
@@ -5044,13 +5049,8 @@ rs6000_va_arg (tree valist, tree type)
/* ... otherwise out of the overflow area. */
- /* Make sure we don't find reg 7 for the next int arg.
-
- All AltiVec vectors go in the overflow area. So in the AltiVec
- case we need to get the vectors from the overflow area, but
- remember where the GPRs and FPRs are. */
- if (n_reg > 1 && (TREE_CODE (type) != VECTOR_TYPE
- || !TARGET_ALTIVEC))
+ /* Make sure we don't find reg 7 for the next int arg. */
+ if (n_reg == 2)
{
t = build (MODIFY_EXPR, TREE_TYPE (reg), reg, build_int_2 (8, 0));
TREE_SIDE_EFFECTS (t) = 1;
@@ -5065,7 +5065,7 @@ rs6000_va_arg (tree valist, tree type)
int align;
/* AltiVec vectors are 16 byte aligned. */
- if (TARGET_ALTIVEC && TREE_CODE (type) == VECTOR_TYPE)
+ if (ALTIVEC_VECTOR_MODE (TYPE_MODE(type)))
align = 15;
else
align = 7;
Index: rs6000.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000.h,v
retrieving revision 1.320
diff -u -p -r1.320 rs6000.h
--- rs6000.h 24 Apr 2004 06:37:19 -0000 1.320
+++ rs6000.h 28 Apr 2004 12:00:29 -0000
@@ -718,7 +718,8 @@ extern const char *rs6000_warn_altivec_l
#define PARM_BOUNDARY (TARGET_32BIT ? 32 : 64)
/* Boundary (in *bits*) on which stack pointer should be aligned. */
-#define STACK_BOUNDARY ((TARGET_32BIT && !TARGET_ALTIVEC_ABI) ? 64 : 128)
+#define STACK_BOUNDARY \
+ ((TARGET_32BIT && !TARGET_ALTIVEC && !TARGET_ALTIVEC_ABI) ? 64 : 128)
/* Allocation boundary (in *bits*) for the code of a function. */
#define FUNCTION_BOUNDARY 32
Index: sysv4.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/sysv4.h,v
retrieving revision 1.148
diff -u -p -r1.148 sysv4.h
--- sysv4.h 11 Apr 2004 06:21:05 -0000 1.148
+++ sysv4.h 28 Apr 2004 12:00:29 -0000
@@ -389,7 +389,7 @@ do { \
one set of libraries with -mno-eabi instead of eabi libraries and non-eabi
versions, just use 64 as the stack boundary. */
#undef STACK_BOUNDARY
-#define STACK_BOUNDARY (TARGET_ALTIVEC_ABI ? 128 : 64)
+#define STACK_BOUNDARY (TARGET_ALTIVEC || TARGET_ALTIVEC_ABI ? 128 : 64)
/* Define this macro if you wish to preserve a certain alignment for
the stack pointer, greater than what the hardware enforces. The
@@ -407,7 +407,8 @@ do { \
#define PREFERRED_STACK_BOUNDARY 128
/* Real stack boundary as mandated by the appropriate ABI. */
-#define ABI_STACK_BOUNDARY ((TARGET_EABI && !TARGET_ALTIVEC_ABI) ? 64 : 128)
+#define ABI_STACK_BOUNDARY \
+ ((TARGET_EABI && !TARGET_ALTIVEC && !TARGET_ALTIVEC_ABI) ? 64 : 128)
/* An expression for the alignment of a structure field FIELD if the
alignment computed in the usual way is COMPUTED. */