This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH] PR/17836 (was Re: [RFA/RFT] Tree-level lowering of genericvectors, part 4)
I understand the alignment change. Sorry for not making that
clear. What I do not understand is the need for the alternate way for
testing how to pass parameters. It seems most safe, clean, and clear to
use the existing implementation: explicitly specify modes that correspond
to Altivec vector registers, as opposed to testing for types that have the
right size and number of elements.
Is the attached patch ok? It converts the type to a vector mode
unconditionally (independent of TARGET_ALTIVEC) and then uses
ALTIVEC_VECTOR_MODE.
Paolo
2004-10-20 Paolo Bonzini <bonzini@gnu.org>
PR target/17836
* config/rs6000/rs6000.c (USE_ALTIVEC_FOR_ARG_P,
init_cumulative_args, function_arg_advance, function_arg,
rs6000_gimplify_va_arg): Use rs6000_is_altivec_vector_type.
(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.
(rs6000_is_altivec_vector_type, rs6000_vector_mode_for_type): New.
Index: rs6000.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000.c,v
retrieving revision 1.732
diff -u -r1.732 rs6000.c
--- rs6000.c 28 Oct 2004 22:32:41 -0000 1.732
+++ rs6000.c 29 Oct 2004 07:42:21 -0000
@@ -753,6 +753,9 @@
int *, int);
static bool rs6000_pass_by_reference (CUMULATIVE_ARGS *, enum machine_mode,
tree, bool);
+static enum machine_mode rs6000_mode_for_vector_type (tree) ATTRIBUTE_PURE;
+static enum machine_mode rs6000_is_altivec_vector_type (tree) ATTRIBUTE_PURE;
+
#if TARGET_MACHO
static void macho_branch_islands (void);
static void add_compiler_branch_island (tree, tree, int);
@@ -4581,7 +4584,8 @@
/* 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) \
+ && rs6000_is_altivec_vector_type ((TYPE)) \
&& (CUM)->vregno <= ALTIVEC_ARG_MAX_REG \
&& TARGET_ALTIVEC_ABI \
&& (NAMED))
@@ -4614,6 +4618,12 @@
&& (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;
@@ -4676,7 +4686,7 @@
if (fntype
&& !TARGET_ALTIVEC
&& TARGET_ALTIVEC_ABI
- && ALTIVEC_VECTOR_MODE (TYPE_MODE (TREE_TYPE (fntype))))
+ && rs6000_is_altivec_vector_type (TREE_TYPE (fntype)))
{
error ("Cannot return value in vector register because"
" altivec instructions are disabled, use -maltivec"
@@ -4760,14 +4770,15 @@
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;
}
@@ -4804,7 +4815,9 @@
{
cum->nargs_prototype--;
- if (TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (mode))
+ if (TARGET_ALTIVEC_ABI
+ && type
+ && rs6000_is_altivec_vector_type (type))
{
bool stack = false;
@@ -5142,7 +5155,9 @@
}
else
return gen_rtx_REG (mode, cum->vregno);
- else if (TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (mode))
+ else if (TARGET_ALTIVEC_ABI
+ && type
+ && rs6000_is_altivec_vector_type (type))
{
if (named || abi == ABI_V4)
return NULL_RTX;
@@ -5383,25 +5398,64 @@
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\n");
+ 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: 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;
}
@@ -5734,7 +5788,7 @@
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 && rs6000_is_altivec_vector_type (type))
align = 16;
else
{
@@ -18290,4 +18345,53 @@
return false;
}
+/* Return a vector mode that represents the vector type TYPE. Always
+ return an AltiVec or SPE mode, even if those ISAs are disabled for
+ the current compilation. */
+enum machine_mode
+rs6000_mode_for_vector_type (tree type) ATTRIBUTE_PURE
+{
+ enum machine_mode element_mode = TYPE_MODE (TREE_TYPE (type));
+ int type_size = int_size_in_bytes (type);
+ gcc_assert (TREE_CODE (type) == VECTOR_TYPE);
+
+ if (type_size == 8)
+ switch (element_mode)
+ {
+ case DImode: return V1DImode;
+ case SImode: return V2SImode;
+ case HImode: return V4HImode;
+ case QImode: return V8QImode;
+ case SFmode: return V2SFmode;
+ default: return TYPE_MODE (type);
+ }
+
+ else if (type_size == 16)
+ switch (element_mode)
+ {
+ case SImode: return V4SImode;
+ case HImode: return V8HImode;
+ case QImode: return V16QImode;
+ case SFmode: return V4SFmode;
+ default: return TYPE_MODE (type);
+ }
+
+ return TYPE_MODE (type);
+}
+
+/* Return whether the vector type TYPE could be held in an AltiVec
+ register. Don't care about whether AltiVec is effectively enabled
+ the current compilation. */
+bool
+rs6000_is_altivec_vector_type (tree type) ATTRIBUTE_PURE
+{
+ if (TREE_CODE (type) != VECTOR_TYPE)
+ return 0;
+ else
+ {
+ enum machine_mode mode = rs6000_mode_for_vector_type (type);
+ return ALTIVEC_VECTOR_MODE (mode);
+ }
+}
+
#include "gt-rs6000.h"