When I added VSX support to the powerpc, I overlooked passing and return
V2DImode arguments, since the only machine operation that supports V2DI is
vector floating point conversion. Consequentally, V2DI types were passed and
returned in GPRs instead of the vector registers on power7.
This patch fixes that so that V2DImode values are passed and returned like
other vector types.
I did a bootstrap and make check with no regressions, comparing it to a build
without the patch. I also wrote a program that passed and returned every
single type, and I compared the assembly ouptut. With the exception of
functions that return or are passed V2DI arguments, the code is identical. I
tested:
-m64 (implies -mabi=altivec)
-m32 -mabi=altivec
-m32 -mabi=no-altivec (no difference here)
Is this patch ok to install? I will also want to install it in the 4.6 and
possibly 4.5 trees as well.
[gcc]
2011-05-03 Michael Meissner <[email protected]>
PR target/48857
* config/rs6000/rs6000.h (VSX_SCALAR_MODE): Delete.
(VSX_MODE): Ditto.
(VSX_MOVE_MODE): Ditto.
(ALTIVEC_OR_VSX_VECTOR_MODE): New macro, combine all Altivec and
VSX vector types. Add V2DImode.
(HARD_REGNO_CALLER_SAVE_MODE): Use it instead of
ALTIVEC_VECTOR_MODE and VSX_VECTOR_MODE calls.
(MODES_TIEABLE_P): Ditto.
* config/rs6000/rs6000.c (rs6000_emit_move): Use
ALTIVEC_OR_VSX_MODE instead of ALTIVEC_VECTOR_MODE and
VSX_VECTOR_MODE.
(init_cumulative_args): Ditto.
(rs6000_function_arg_boundary): Ditto.
(rs6000_function_arg_advance_1): Ditto.
(rs6000_function_arg): Ditto.
(rs6000_function_ok_for_sibcall): Ditto.
(emit_frame_save): Ditto.
(rs6000_function_value): Ditto.
(rs6000_libcall_value): Ditto.
[gcc/testsuite]
2011-05-03 Michael Meissner <[email protected]>
PR target/48857
* gcc.target/powerpc/pr48857.c: New file, make sure V2DI arguments
are passed and returned in vector registers.
--
Michael Meissner, IBM
5 Technology Place Drive, M/S 2757, Westford, MA 01886-3141, USA
[email protected] fax +1 (978) 399-6899
[gcc]
2011-05-03 Michael Meissner <[email protected]>
PR target/48857
* config/rs6000/rs6000.h (VSX_SCALAR_MODE): Delete.
(VSX_MODE): Ditto.
(VSX_MOVE_MODE): Ditto.
(ALTIVEC_OR_VSX_VECTOR_MODE): New macro, combine all Altivec and
VSX vector types. Add V2DImode.
(HARD_REGNO_CALLER_SAVE_MODE): Use it instead of
ALTIVEC_VECTOR_MODE and VSX_VECTOR_MODE calls.
(MODES_TIEABLE_P): Ditto.
* config/rs6000/rs6000.c (rs6000_emit_move): Use
ALTIVEC_OR_VSX_MODE instead of ALTIVEC_VECTOR_MODE and
VSX_VECTOR_MODE.
(init_cumulative_args): Ditto.
(rs6000_function_arg_boundary): Ditto.
(rs6000_function_arg_advance_1): Ditto.
(rs6000_function_arg): Ditto.
(rs6000_function_ok_for_sibcall): Ditto.
(emit_frame_save): Ditto.
(rs6000_function_value): Ditto.
(rs6000_libcall_value): Ditto.
[gcc/testsuite]
2011-05-03 Michael Meissner <[email protected]>
PR target/48857
* gcc.target/powerpc/pr48857.c: New file, make sure V2DI arguments
are passed and returned in vector registers.
Index: gcc/config/rs6000/rs6000.h
===================================================================
--- gcc/config/rs6000/rs6000.h (revision 173266)
+++ gcc/config/rs6000/rs6000.h (working copy)
@@ -1007,10 +1007,9 @@ extern unsigned rs6000_pointer_size;
/* When setting up caller-save slots (MODE == VOIDmode) ensure we allocate
enough space to account for vectors in FP regs. */
-#define HARD_REGNO_CALLER_SAVE_MODE(REGNO, NREGS, MODE) \
- (TARGET_VSX \
- && ((MODE) == VOIDmode || VSX_VECTOR_MODE (MODE) \
- || ALTIVEC_VECTOR_MODE (MODE)) \
+#define HARD_REGNO_CALLER_SAVE_MODE(REGNO, NREGS, MODE)
\
+ (TARGET_VSX \
+ && ((MODE) == VOIDmode || ALTIVEC_OR_VSX_VECTOR_MODE (MODE))
\
&& FP_REGNO_P (REGNO) \
? V2DFmode \
: choose_hard_reg_mode ((REGNO), (NREGS), false))
@@ -1026,25 +1025,16 @@ extern unsigned rs6000_pointer_size;
((MODE) == V4SFmode \
|| (MODE) == V2DFmode) \
-#define VSX_SCALAR_MODE(MODE) \
- ((MODE) == DFmode)
-
-#define VSX_MODE(MODE) \
- (VSX_VECTOR_MODE (MODE) \
- || VSX_SCALAR_MODE (MODE))
-
-#define VSX_MOVE_MODE(MODE) \
- (VSX_VECTOR_MODE (MODE) \
- || VSX_SCALAR_MODE (MODE) \
- || ALTIVEC_VECTOR_MODE (MODE) \
- || (MODE) == TImode)
-
#define ALTIVEC_VECTOR_MODE(MODE) \
((MODE) == V16QImode \
|| (MODE) == V8HImode \
|| (MODE) == V4SFmode \
|| (MODE) == V4SImode)
+#define ALTIVEC_OR_VSX_VECTOR_MODE(MODE) \
+ (ALTIVEC_VECTOR_MODE (MODE) || VSX_VECTOR_MODE (MODE)
\
+ || (MODE) == V2DImode)
+
#define SPE_VECTOR_MODE(MODE) \
((MODE) == V4HImode \
|| (MODE) == V2SFmode \
@@ -1080,10 +1070,10 @@ extern unsigned rs6000_pointer_size;
? ALTIVEC_VECTOR_MODE (MODE2) \
: ALTIVEC_VECTOR_MODE (MODE2) \
? ALTIVEC_VECTOR_MODE (MODE1) \
- : VSX_VECTOR_MODE (MODE1) \
- ? VSX_VECTOR_MODE (MODE2) \
- : VSX_VECTOR_MODE (MODE2) \
- ? VSX_VECTOR_MODE (MODE1) \
+ : ALTIVEC_OR_VSX_VECTOR_MODE (MODE1) \
+ ? ALTIVEC_OR_VSX_VECTOR_MODE (MODE2) \
+ : ALTIVEC_OR_VSX_VECTOR_MODE (MODE2) \
+ ? ALTIVEC_OR_VSX_VECTOR_MODE (MODE1) \
: 1)
/* Post-reload, we can't use any new AltiVec registers, as we already
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c (revision 173266)
+++ gcc/config/rs6000/rs6000.c (working copy)
@@ -7902,7 +7902,7 @@ 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) || VSX_VECTOR_MODE (MODE)) \
+ (ALTIVEC_OR_VSX_VECTOR_MODE (MODE) \
&& (CUM)->vregno <= ALTIVEC_ARG_MAX_REG \
&& TARGET_ALTIVEC_ABI \
&& (NAMED))
@@ -8102,8 +8102,7 @@ init_cumulative_args (CUMULATIVE_ARGS *c
}
if (SCALAR_FLOAT_MODE_P (return_mode))
rs6000_passes_float = true;
- else if (ALTIVEC_VECTOR_MODE (return_mode)
- || VSX_VECTOR_MODE (return_mode)
+ else if (ALTIVEC_OR_VSX_VECTOR_MODE (return_mode)
|| SPE_VECTOR_MODE (return_mode))
rs6000_passes_vector = true;
}
@@ -8218,7 +8217,7 @@ rs6000_function_arg_boundary (enum machi
&& int_size_in_bytes (type) >= 8
&& int_size_in_bytes (type) < 16))
return 64;
- else if ((ALTIVEC_VECTOR_MODE (mode) || VSX_VECTOR_MODE (mode))
+ else if (ALTIVEC_OR_VSX_VECTOR_MODE (mode)
|| (type && TREE_CODE (type) == VECTOR_TYPE
&& int_size_in_bytes (type) >= 16))
return 128;
@@ -8438,7 +8437,7 @@ rs6000_function_arg_advance_1 (CUMULATIV
{
if (SCALAR_FLOAT_MODE_P (mode))
rs6000_passes_float = true;
- else if (named && (ALTIVEC_VECTOR_MODE (mode) || VSX_VECTOR_MODE (mode)))
+ else if (named && ALTIVEC_OR_VSX_VECTOR_MODE (mode))
rs6000_passes_vector = true;
else if (SPE_VECTOR_MODE (mode)
&& !cum->stdarg
@@ -8448,8 +8447,7 @@ rs6000_function_arg_advance_1 (CUMULATIV
#endif
if (TARGET_ALTIVEC_ABI
- && (ALTIVEC_VECTOR_MODE (mode)
- || VSX_VECTOR_MODE (mode)
+ && (ALTIVEC_OR_VSX_VECTOR_MODE (mode)
|| (type && TREE_CODE (type) == VECTOR_TYPE
&& int_size_in_bytes (type) == 16)))
{
@@ -9067,8 +9065,7 @@ rs6000_function_arg (CUMULATIVE_ARGS *cu
else
return gen_rtx_REG (mode, cum->vregno);
else if (TARGET_ALTIVEC_ABI
- && (ALTIVEC_VECTOR_MODE (mode)
- || VSX_VECTOR_MODE (mode)
+ && (ALTIVEC_OR_VSX_VECTOR_MODE (mode)
|| (type && TREE_CODE (type) == VECTOR_TYPE
&& int_size_in_bytes (type) == 16)))
{
@@ -19355,14 +19352,12 @@ rs6000_function_ok_for_sibcall (tree dec
here. */
FOREACH_FUNCTION_ARGS(fntype, type, args_iter)
if (TREE_CODE (type) == VECTOR_TYPE
- && (ALTIVEC_VECTOR_MODE (TYPE_MODE (type))
- || VSX_VECTOR_MODE (TYPE_MODE (type))))
+ && ALTIVEC_OR_VSX_VECTOR_MODE (TYPE_MODE (type)))
nvreg++;
FOREACH_FUNCTION_ARGS(TREE_TYPE (current_function_decl), type, args_iter)
if (TREE_CODE (type) == VECTOR_TYPE
- && (ALTIVEC_VECTOR_MODE (TYPE_MODE (type))
- || VSX_VECTOR_MODE (TYPE_MODE (type))))
+ && ALTIVEC_OR_VSX_VECTOR_MODE (TYPE_MODE (type)))
nvreg--;
if (nvreg > 0)
@@ -20075,7 +20070,7 @@ emit_frame_save (rtx frame_reg, rtx fram
/* Some cases that need register indexed addressing. */
if ((TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (mode))
- || (TARGET_VSX && VSX_VECTOR_MODE (mode))
+ || (TARGET_VSX && ALTIVEC_OR_VSX_VECTOR_MODE (mode))
|| (TARGET_E500_DOUBLE && mode == DFmode)
|| (TARGET_SPE_ABI
&& SPE_VECTOR_MODE (mode)
@@ -27361,11 +27356,7 @@ rs6000_function_value (const_tree valtyp
return rs6000_complex_function_value (mode);
else if (TREE_CODE (valtype) == VECTOR_TYPE
&& TARGET_ALTIVEC && TARGET_ALTIVEC_ABI
- && ALTIVEC_VECTOR_MODE (mode))
- regno = ALTIVEC_ARG_RETURN;
- else if (TREE_CODE (valtype) == VECTOR_TYPE
- && TARGET_VSX && TARGET_ALTIVEC_ABI
- && VSX_VECTOR_MODE (mode))
+ && ALTIVEC_OR_VSX_VECTOR_MODE (mode))
regno = ALTIVEC_ARG_RETURN;
else if (TARGET_E500_DOUBLE && TARGET_HARD_FLOAT
&& (mode == DFmode || mode == DCmode
@@ -27405,12 +27396,9 @@ rs6000_libcall_value (enum machine_mode
&& TARGET_HARD_FLOAT && TARGET_FPRS
&& ((TARGET_SINGLE_FLOAT && mode == SFmode) || TARGET_DOUBLE_FLOAT))
regno = FP_ARG_RETURN;
- else if (ALTIVEC_VECTOR_MODE (mode)
+ else if (ALTIVEC_OR_VSX_VECTOR_MODE (mode)
&& TARGET_ALTIVEC && TARGET_ALTIVEC_ABI)
regno = ALTIVEC_ARG_RETURN;
- else if (VSX_VECTOR_MODE (mode)
- && TARGET_VSX && TARGET_ALTIVEC_ABI)
- regno = ALTIVEC_ARG_RETURN;
else if (COMPLEX_MODE_P (mode) && targetm.calls.split_complex_arg)
return rs6000_complex_function_value (mode);
else if (TARGET_E500_DOUBLE && TARGET_HARD_FLOAT
Index: gcc/testsuite/gcc.target/powerpc/pr48857.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/pr48857.c (revision 0)
+++ gcc/testsuite/gcc.target/powerpc/pr48857.c (revision 0)
@@ -0,0 +1,25 @@
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_vsx_ok } */
+/* { dg-options "-O2 -mcpu=power7 -mabi=altivec" } */
+/* { dg-final { scan-assembler-times "lxvd2x" 1 } } */
+/* { dg-final { scan-assembler-times "stxvd2x" 1 } } */
+/* { dg-final { scan-assembler-not "ld" } } */
+/* { dg-final { scan-assembler-not "lwz" } } */
+/* { dg-final { scan-assembler-not "stw" } } */
+/* { dg-final { scan-assembler-not "addi" } } */
+
+typedef vector long long v2di_type;
+
+v2di_type
+return_v2di (v2di_type *ptr)
+{
+ return *ptr; /* should generate lxvd2x 34,0,3. */
+}
+
+void
+pass_v2di (v2di_type arg, v2di_type *ptr)
+{
+ *ptr = arg; /* should generate stxvd2x 34,0,{3,5}. */
+}
+