[Bug target/15106] Vector varargs failure for AltiVec on ppc32 linux

Hartmut Penner HPENNER@de.ibm.com
Wed Apr 28 14:26:00 GMT 2004





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.  */



More information about the Gcc-patches mailing list