[gcc(refs/users/meissner/heads/work041)] Add support for XXSPLTIDP to load vector constants.
Michael Meissner
meissner@gcc.gnu.org
Wed Mar 17 19:00:14 GMT 2021
https://gcc.gnu.org/g:6bbc906717c5946a0954ceb21ee8d013f40ba509
commit 6bbc906717c5946a0954ceb21ee8d013f40ba509
Author: Michael Meissner <meissner@linux.ibm.com>
Date: Wed Mar 17 14:59:49 2021 -0400
Add support for XXSPLTIDP to load vector constants.
gcc/
2021-03-17 Michael Meissner <meissner@linux.ibm.com>
* config/rs6000/predicates.md (xxspltidp_operand): Add support for
V2DFmode.
(easy_vector_constant): Ditto.
* config/rs6000/rs6000.c (rs6000_expand_vector_init): Ditto.
* config/rs6000/rs6000.md (SF_DF_V2DF): New iterator.
(xxspltidp splitter): Add support for V2DF.
(xxspltidp<mode>): Ditto.
* config/rs6000/vsx.md (vsx_mov<mode>_64bit): Add support for
vector constants loaded with XXSPLTIDP.
(vsx_mov<mode>_32bit): Ditto.
gcc/testsuite/
2021-03-17 Michael Meissner <meissner@linux.ibm.com>
* gcc.target/powerpc/p10-v2df-const.c: New test.
Diff:
---
gcc/config/rs6000/predicates.md | 43 +++++++++++++++++-----
gcc/config/rs6000/rs6000.c | 6 ++--
gcc/config/rs6000/rs6000.md | 37 ++++++++++++++-----
gcc/config/rs6000/vsx.md | 44 +++++++++++++++--------
gcc/testsuite/gcc.target/powerpc/p10-v2df-const.c | 35 ++++++++++++++++++
5 files changed, 133 insertions(+), 32 deletions(-)
diff --git a/gcc/config/rs6000/predicates.md b/gcc/config/rs6000/predicates.md
index e0c0ecafece..42e20be7636 100644
--- a/gcc/config/rs6000/predicates.md
+++ b/gcc/config/rs6000/predicates.md
@@ -565,22 +565,47 @@
(ior (match_operand 0 "vsx_register_operand")
(match_operand 0 "reg_or_logical_cint_operand")))
-;; Return 1 if operand is a SF/DF CONST_DOUBLE that can be loaded via the ISA
-;; 3.1 XXSPLTIDP instruction. This function has to check, if the immediate
-;; specifies a single-precision denormal value (i.e., bits 1:8 equal to 0 and
-;; bits 9:31 not equal to 0), since the result is undefined in the hardware.
+;; Return 1 if operand is a SF/DF CONST_DOUBLE or V2DF CONST_VECTOR that can be
+;; loaded via the ISA 3.1 XXSPLTIDP instruction. This function has to check,
+;; if the immediate specifies a single-precision denormal value (i.e., bits 1:8
+;; equal to 0 and bits 9:31 not equal to 0), since the result is undefined in
+;; the hardware.
(define_predicate "xxspltidp_operand"
- (match_code "const_double")
+ (match_code "const_double,const_vector,vec_duplicate")
{
long value;
+ rtx element;
if (!TARGET_POWER10 || !TARGET_VSX)
return 0;
- if (mode != SFmode && mode != DFmode)
+ if (mode == V2DFmode)
+ {
+ /* Handle VEC_DUPLICATE and CONST_VECTOR. */
+ if (GET_CODE (op) == VEC_DUPLICATE)
+ element = XEXP (op, 0);
+
+ else if (GET_CODE (op) == CONST_VECTOR)
+ {
+ element = CONST_VECTOR_ELT (op, 0);
+ if (!rtx_equal_p (element, CONST_VECTOR_ELT (op, 1)))
+ return 0;
+ }
+
+ else
+ return 0;
+ }
+
+ else if (mode == SFmode || mode == DFmode)
+ element = op;
+
+ else
+ return 0;
+
+ if (!CONST_DOUBLE_P (element))
return 0;
- const struct real_value *rv = CONST_DOUBLE_REAL_VALUE (op);
+ const struct real_value *rv = CONST_DOUBLE_REAL_VALUE (element);
if (!exact_real_truncate (SFmode, rv))
return 0;
@@ -692,7 +717,9 @@
if (zero_constant (op, mode) || all_ones_constant (op, mode))
return true;
- if (TARGET_POWER10 && xxspltiw_constant_p (op, mode, &constant))
+ if (TARGET_POWER10
+ && (xxspltiw_constant_p (op, mode, &constant)
+ || xxspltidp_operand (op, mode)))
return true;
if (TARGET_P9_VECTOR
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index ec2c0dc2f7c..8ac4bc8cbdc 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -6651,9 +6651,11 @@ rs6000_expand_vector_init (rtx target, rtx vals)
if (n_var == 0)
{
- /* Generate XXSPLTIW if we can. */
+ /* Generate XXSPLTIW/XXSPLTIDP if we can. */
if (TARGET_POWER10 && all_same
- && (mode == V4SImode || mode == V4SFmode))
+ && (mode == V4SImode || mode == V4SFmode
+ || (mode == V2DFmode
+ && xxspltidp_operand (XVECEXP (vals, 0, 0), inner_mode))))
{
rtx dup = gen_rtx_VEC_DUPLICATE (mode, XVECEXP (vals, 0, 0));
emit_insn (gen_rtx_SET (target, dup));
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index f25ac1ec53a..2c6296c1f18 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -573,6 +573,9 @@
; And again, for when we need two FP modes in a pattern.
(define_mode_iterator SFDF2 [SF DF])
+; SFmode, DFmode, or V2DF.
+(define_mode_iterator SF_DF_V2DF [SF DF V2DF])
+
; Floating scalars that supports the set compare mask instruction.
(define_mode_iterator FPMASK [SF
DF
@@ -7529,24 +7532,42 @@
DONE;
})
-;; Load a SFmode/DFmode constant via the ISA 3.1 XXSPLTIDP instruction
+;; Load a SFmode/DFmode/V2DFmode constant via the ISA 3.1 XXSPLTIDP instruction
(define_split
- [(set (match_operand:SFDF 0 "vsx_register_operand")
- (match_operand:SFDF 1 "xxspltidp_operand"))]
+ [(set (match_operand:SF_DF_V2DF 0 "vsx_register_operand")
+ (match_operand:SF_DF_V2DF 1 "xxspltidp_operand"))]
"TARGET_POWER10 && TARGET_VSX"
[(set (match_dup 0)
- (unspec:SFDF [(match_dup 2)] UNSPEC_XXSPLTIDP))]
+ (unspec:SF_DF_V2DF [(match_dup 2)] UNSPEC_XXSPLTIDP))]
{
long value;
- const struct real_value *rv = CONST_DOUBLE_REAL_VALUE (operands[1]);
+ rtx op1 = operands[1];
+ rtx element;
+
+ if (<MODE>mode == V2DFmode)
+ {
+ if (GET_CODE (op1) == VEC_DUPLICATE)
+ element = XEXP (op1, 0);
+
+ else if (GET_CODE (op1) == CONST_VECTOR)
+ element = CONST_VECTOR_ELT (op1, 0);
+
+ else
+ gcc_unreachable ();
+ }
+
+ else
+ element = operands[1];
+
+ const struct real_value *rv = CONST_DOUBLE_REAL_VALUE (element);
REAL_VALUE_TO_TARGET_SINGLE (*rv, value);
operands[2] = GEN_INT (value);
})
(define_insn "*xxspltidp<mode>"
- [(set (match_operand:SFDF 0 "vsx_register_operand" "=wa")
- (unspec:SFDF [(match_operand 1 "const_int_operand" "n")]
- UNSPEC_XXSPLTIDP))]
+ [(set (match_operand:SF_DF_V2DF 0 "vsx_register_operand" "=wa")
+ (unspec:SF_DF_V2DF [(match_operand 1 "const_int_operand" "n")]
+ UNSPEC_XXSPLTIDP))]
"TARGET_POWER10 && TARGET_VSX"
"xxspltidp %x0,%1"
[(set_attr "type" "vecsimple")
diff --git a/gcc/config/rs6000/vsx.md b/gcc/config/rs6000/vsx.md
index a1fa4f94d51..c2153eb0bcf 100644
--- a/gcc/config/rs6000/vsx.md
+++ b/gcc/config/rs6000/vsx.md
@@ -1167,17 +1167,17 @@
;; VSX store VSX load VSX move VSX->GPR GPR->VSX LQ (GPR)
;; STQ (GPR) GPR load GPR store GPR move XXSPLTIB VSPLTISW
-;; VSX 0/-1 VMX const GPR const LVX (VMX) STVX (VMX)
+;; VSX 0/-1 VMX const GPR const LVX (VMX) STVX (VMX) XXSPLTIDP
(define_insn "vsx_mov<mode>_64bit"
[(set (match_operand:VSX_M 0 "nonimmediate_operand"
"=ZwO, wa, wa, r, we, ?wQ,
?&r, ??r, ??Y, <??r>, wa, v,
- ?wa, v, <??r>, wZ, v")
+ ?wa, v, <??r>, wZ, v, wa")
(match_operand:VSX_M 1 "input_operand"
"wa, ZwO, wa, we, r, r,
wQ, Y, r, r, wE, jwM,
- ?jwM, W, <nW>, v, wZ"))]
+ ?jwM, W, <nW>, v, wZ, eF"))]
"TARGET_POWERPC64 && VECTOR_MEM_VSX_P (<MODE>mode)
&& (register_operand (operands[0], <MODE>mode)
@@ -1188,36 +1188,44 @@
[(set_attr "type"
"vecstore, vecload, vecsimple, mtvsr, mfvsr, load,
store, load, store, *, vecsimple, vecsimple,
- vecsimple, *, *, vecstore, vecload")
+ vecsimple, *, *, vecstore, vecload, vecsimple")
(set_attr "num_insns"
"*, *, *, 2, *, 2,
2, 2, 2, 2, *, *,
- *, 5, 2, *, *")
+ *, 5, 2, *, *, *")
(set_attr "max_prefixed_insns"
"*, *, *, *, *, 2,
2, 2, 2, 2, *, *,
- *, *, *, *, *")
+ *, *, *, *, *, *")
(set_attr "length"
"*, *, *, 8, *, 8,
8, 8, 8, 8, *, *,
- *, 20, 8, *, *")
+ *, 20, 8, *, *, *")
(set_attr "isa"
"<VSisa>, <VSisa>, <VSisa>, *, *, *,
*, *, *, *, p9v, *,
- <VSisa>, *, *, *, *")])
+ <VSisa>, *, *, *, *, p10")
+ (set_attr "prefixed"
+ "*, *, *, *, *, *,
+ *, *, *, *, *, *,
+ *, *, *, *, *, yes")
+ (set_attr "prefixed_prepend_p"
+ "*, *, *, *, *, *,
+ *, *, *, *, *, *,
+ *, *, *, *, *, no")])
;; VSX store VSX load VSX move GPR load GPR store GPR move
-;; XXSPLTIB VSPLTISW VSX 0/-1 VMX const GPR const
+;; XXSPLTIB VSPLTISW VSX 0/-1 VMX const GPR const XXSPLTIDP
;; LVX (VMX) STVX (VMX)
(define_insn "*vsx_mov<mode>_32bit"
[(set (match_operand:VSX_M 0 "nonimmediate_operand"
"=ZwO, wa, wa, ??r, ??Y, <??r>,
- wa, v, ?wa, v, <??r>,
+ wa, v, ?wa, v, <??r>, wa,
wZ, v")
(match_operand:VSX_M 1 "input_operand"
"wa, ZwO, wa, Y, r, r,
- wE, jwM, ?jwM, W, <nW>,
+ wE, jwM, ?jwM, W, <nW>, eF,
v, wZ"))]
"!TARGET_POWERPC64 && VECTOR_MEM_VSX_P (<MODE>mode)
@@ -1228,15 +1236,23 @@
}
[(set_attr "type"
"vecstore, vecload, vecsimple, load, store, *,
- vecsimple, vecsimple, vecsimple, *, *,
+ vecsimple, vecsimple, vecsimple, *, *, vecsimple,
vecstore, vecload")
(set_attr "length"
"*, *, *, 16, 16, 16,
- *, *, *, 20, 16,
+ *, *, *, 20, 16, *,
*, *")
(set_attr "isa"
"<VSisa>, <VSisa>, <VSisa>, *, *, *,
- p9v, *, <VSisa>, *, *,
+ p9v, *, <VSisa>, *, *, p10,
+ *, *")
+ (set_attr "prefixed"
+ "*, *, *, *, *, *,
+ *, *, *, *, *, yes,
+ *, *")
+ (set_attr "prefixed_prepend_p"
+ "*, *, *, *, *, *,
+ *, *, *, *, *, no,
*, *")])
;; Explicit load/store expanders for the builtin functions
diff --git a/gcc/testsuite/gcc.target/powerpc/p10-v2df-const.c b/gcc/testsuite/gcc.target/powerpc/p10-v2df-const.c
new file mode 100644
index 00000000000..e82f2f5c59a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/p10-v2df-const.c
@@ -0,0 +1,35 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target power10_ok } */
+/* { dg-options "-O2 -mdejagnu-cpu=power10" } */
+
+/* Test generating XXSPLTIDP on power10 for V2DF vectors. */
+
+#include <altivec.h>
+
+vector double
+init_zero (void)
+{
+ return (vector double) { 0.0, 0.0 }; /* XXSPLTIB */
+}
+
+vector double
+init_one (void)
+{
+ return (vector double) { 1.0, 1.0 }; /* XXSPLTIDP */
+}
+
+vector double
+splat_zero (void)
+{
+ return vec_splats (0.0); /* XXSPLTIB */
+}
+
+vector double
+splat_one (void)
+{
+ return vec_splats (1.0); /* XXSPLTIDP */
+}
+
+/* { dg-final { scan-assembler-times {\mxxlxor|vspltiw|xxspltib\M} 2 } } */
+/* { dg-final { scan-assembler-times {\mxxspltidp\M} 2 } } */
+/* { dg-final { scan-assembler-not {\mp?lxvx?\M} } } */
More information about the Gcc-cvs
mailing list