This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] PR/17836 (was Re: [RFA/RFT] Tree-level lowering of genericvectors, part 4)


I am worried about the places in the patch that you changed

ALTIVEC_VECTOR_MODE (MODE)

to

TREE_CODE (TYPE) == VECTOR_TYPE && int_size_in_bytes (TYPE) == 16

where it is used to determine whether the value can be passed in a vector
register. Altivec only allows specific modes and the original tests are
ensuring the modes are correct. For instance, Altivec does not support
V2DF.

This patch fixes the problem by introducing ALTIVEC_VECTOR_TYPE and using it everywhere, except in the places you said were already correct (function_arg_boundary, rs6000_return_in_memory).


Ok for mainline?

Paolo
2004-10-20  Paolo Bonzini  <bonzini@gnu.org>

	PR target/17836

	* config/rs6000/rs6000.h (ALTIVEC_VECTOR_TYPE): New.
	* config/rs6000/rs6000.c (USE_ALTIVEC_FOR_ARG_P,
	init_cumulative_args, function_arg_advance, function_arg,
	rs6000_gimplify_va_arg): Use it.
	(function_arg_boundary): Look into the type instead of using
	ALTIVEC_VECTOR_MODE.
	(rs6000_pass_by_reference): Same as above, plus warn
	for wide (>16 bytes) vector types and pass them by reference.
	(rs6000_return_in_memory): Return true for vectors
	above 16 bytes.

Index: rs6000.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000.c,v
retrieving revision 1.724
diff -u -p -r1.724 rs6000.c
--- rs6000.c	14 Oct 2004 22:30:42 -0000	1.724
+++ rs6000.c	20 Oct 2004 07:26:32 -0000
@@ -4541,7 +4541,8 @@ rs6000_emit_move (rtx dest, rtx source, 
 
 /* Nonzero if we can use an AltiVec register to pass this arg.  */
 #define USE_ALTIVEC_FOR_ARG_P(CUM,MODE,TYPE,NAMED)	\
-  (ALTIVEC_VECTOR_MODE (MODE)				\
+  ((TYPE)						\
+   && ALTIVEC_VECTOR_TYPE (TYPE)			\
    && (CUM)->vregno <= ALTIVEC_ARG_MAX_REG		\
    && TARGET_ALTIVEC_ABI				\
    && (NAMED))
@@ -4574,6 +4575,12 @@ rs6000_return_in_memory (tree type, tree
       && (TARGET_AIX_STRUCT_RET
 	  || (unsigned HOST_WIDE_INT) int_size_in_bytes (type) > 8))
     return true;
+  /* If TARGET_ALTIVEC is not set, we return 16-byte vectors in memory,
+     otherwise function.c tries to use a TImode register and we get
+     an unrecognizable insn.  */
+  if (TREE_CODE (type) == VECTOR_TYPE
+      && int_size_in_bytes (type) > (TARGET_ALTIVEC ? 16 : 8))
+    return true;
   if (DEFAULT_ABI == ABI_V4 && TYPE_MODE (type) == TFmode)
     return true;
   return false;
@@ -4636,7 +4643,7 @@ init_cumulative_args (CUMULATIVE_ARGS *c
   if (fntype
       && !TARGET_ALTIVEC
       && TARGET_ALTIVEC_ABI
-      && ALTIVEC_VECTOR_MODE (TYPE_MODE (TREE_TYPE (fntype))))
+      && ALTIVEC_VECTOR_TYPE (TREE_TYPE (fntype)))
     {
       error ("Cannot return value in vector register because"
 	     " altivec instructions are disabled, use -maltivec"
@@ -4720,14 +4727,15 @@ function_arg_padding (enum machine_mode 
    V.4 wants long longs to be double word aligned.  */
 
 int
-function_arg_boundary (enum machine_mode mode, tree type ATTRIBUTE_UNUSED)
+function_arg_boundary (enum machine_mode mode, tree type)
 {
   if (DEFAULT_ABI == ABI_V4 && GET_MODE_SIZE (mode) == 8)
     return 64;
-  else if (SPE_VECTOR_MODE (mode))
-    return 64;
-  else if (ALTIVEC_VECTOR_MODE (mode))
-    return 128;
+  else if (type
+	   && TREE_CODE (type) == VECTOR_TYPE
+	   && (int_size_in_bytes (type) == 8
+	       || int_size_in_bytes (type) == 16))
+    return 8 * int_size_in_bytes (type);
   else
     return PARM_BOUNDARY;
 }
@@ -4764,7 +4772,9 @@ function_arg_advance (CUMULATIVE_ARGS *c
 {
   cum->nargs_prototype--;
 
-  if (TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (mode))
+  if (TARGET_ALTIVEC_ABI
+      && type
+      && ALTIVEC_VECTOR_TYPE (type))
     {
       bool stack = false;
 
@@ -5067,7 +5077,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
+           && type
+           && ALTIVEC_VECTOR_TYPE (type))
     {
       if (named || abi == ABI_V4)
 	return NULL_RTX;
@@ -5306,25 +5318,64 @@ function_arg_partial_nregs (CUMULATIVE_A
    As an extension to all 32-bit ABIs, AltiVec vectors are passed by
    reference unless the AltiVec vector extension ABI is in force.
 
-   As an extension to all ABIs, variable sized types are passed by
-   reference.  */
+   As an extension to all ABIs, variable sized types and vectors
+   wider than 16 bytes are passed by reference.  */
 
 static bool
-rs6000_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED,
-			  enum machine_mode mode ATTRIBUTE_UNUSED,
-			  tree type, bool named ATTRIBUTE_UNUSED)
-{
-  if ((DEFAULT_ABI == ABI_V4
-       && ((type && AGGREGATE_TYPE_P (type))
-	   || mode == TFmode))
-      || (TARGET_32BIT && !TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (mode))
-      || (type && int_size_in_bytes (type) < 0))
+rs6000_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED, 
+			  enum machine_mode mode, tree type,
+			  bool named ATTRIBUTE_UNUSED)
+{
+  if (DEFAULT_ABI == ABI_V4 && mode == TFmode)
+    {
+      if (TARGET_DEBUG_ARG)
+	fprintf (stderr, "function_arg_pass_by_reference: V4 long double\n");
+      return 1;
+    }
+
+  if (!type)
+    return 0;
+
+  if (DEFAULT_ABI == ABI_V4 && AGGREGATE_TYPE_P (type))
+    {
+      if (TARGET_DEBUG_ARG)
+	fprintf (stderr, "function_arg_pass_by_reference: V4 aggregates\n");
+      return 1;
+    }
+
+  if (TARGET_32BIT
+      && !TARGET_ALTIVEC_ABI
+      && TREE_CODE (type) == VECTOR_TYPE
+      && int_size_in_bytes (type) == 16)
     {
       if (TARGET_DEBUG_ARG)
-	fprintf (stderr, "function_arg_pass_by_reference\n");
+	fprintf (stderr, "function_arg_pass_by_reference: AltiVec\n");
+      return 1;
+    }
+
+  if (TREE_CODE (type) == VECTOR_TYPE
+      && int_size_in_bytes (type) > 16)
+    {
+      static int warned_for_big_vectors = false;
+      if (TARGET_DEBUG_ARG)
+	fprintf (stderr, "function_arg_pass_by_reference: vectors >16 bytes\n");
+      if (!warned_for_big_vectors)
+	{
+	  warning ("vectors bigger than 16 bytes are passed by reference: "
+		   "this may change in a future version of the ABI");
+	  warned_for_big_vectors = 1;
+	}
 
       return 1;
     }
+
+  if (int_size_in_bytes (type) == -1)
+    {
+      if (TARGET_DEBUG_ARG)
+	fprintf (stderr, "function_arg_pass_by_reference: variable size\n");
+      return 1;
+    }
+
   return 0;
 }
 
@@ -5656,7 +5707,7 @@ rs6000_gimplify_va_arg (tree valist, tre
   DECL_POINTER_ALIAS_SET (addr) = get_varargs_alias_set ();
 
   /*  AltiVec vectors never go in registers when -mabi=altivec.  */
-  if (TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (TYPE_MODE (type)))
+  if (TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_TYPE (type))
     align = 16;
   else
     {
Index: rs6000.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000.h,v
retrieving revision 1.342
diff -u -p -r1.342 rs6000.h
--- rs6000.h	15 Oct 2004 18:50:55 -0000	1.342
+++ rs6000.h	20 Oct 2004 07:33:46 -0000
@@ -1019,6 +1019,11 @@ extern const char *rs6000_warn_altivec_l
     && (GET_MODE_SIZE (MODE) > 4)  \
     && INT_REGNO_P (REGNO)) ? 1 : 0)
 
+#define ALTIVEC_VECTOR_TYPE(TYPE)                \
+	 (TREE_CODE (TYPE) == VECTOR_TYPE        \
+	  && int_size_in_bytes (TYPE) == 16      \
+	  && TYPE_VECTOR_SUBPARTS (TYPE) >= 4)
+
 #define ALTIVEC_VECTOR_MODE(MODE)	\
 	 ((MODE) == V16QImode		\
 	  || (MODE) == V8HImode		\

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]