[gcc(refs/users/meissner/heads/work041)] Load SFmode constants with XXSPLTIDP.
Michael Meissner
meissner@gcc.gnu.org
Sat Mar 13 03:12:33 GMT 2021
https://gcc.gnu.org/g:1662d83c637628e285d0bf5de142336a10d112a4
commit 1662d83c637628e285d0bf5de142336a10d112a4
Author: Michael Meissner <meissner@linux.ibm.com>
Date: Fri Mar 12 22:12:09 2021 -0500
Load SFmode constants with XXSPLTIDP.
Power10 adds an instruction to load SF/DFmode constants directly into a vector
register. The constant must not be a SFmode denormal value. This patch
implements loading SFmode constants. A later patch will implement loading
DFmode constants.
gcc/
2021-03-12 Michael Meissner <meissner@linux.ibm.com>
* config/rs6000/altivec.md (UNSPEC_XXSPLTID): Delete.
(xxspltiw_v2df): Use UNSPEC_XXSPLTIDP instead of UNSPEC_XXSPLTID.
(xxspltiw_v2df_inst): Use UNSPEC_XXSPLTIDP instead of
UNSPEC_XXSPLTID.
* config/rs6000/constraints.md (eF): New constraint.
* config/rs6000/predicates.md (xxspltidp_operand): New predicate.
(easy_fp_constant): If the constant can be loaded with XXSPLTIDP,
it is an easy floating point constant.
* config/rs6000/rs6000.md (UNSPEC_XXSPLTIDP): New unspec.
(SF mode define_split): Convert constants loaded via XXSPLTIDP
into a form for generating the instruction.
(xxspltidpsf): New insn.
(movsf_hardfloat): Add support for loading SFmode constants via
XXSPLTIDP.
gcc/testsuite/
2021-03-12 Michael Meissner <meissner@linux.ibm.com>
* gcc.target/powerpc/xxsplitdp-sf.c: New test.
Diff:
---
gcc/config/rs6000/altivec.md | 5 ++-
gcc/config/rs6000/constraints.md | 4 +++
gcc/config/rs6000/predicates.md | 42 +++++++++++++++++++++++++
gcc/config/rs6000/rs6000.md | 38 ++++++++++++++++++++++
gcc/testsuite/gcc.target/powerpc/xxspltidp-sf.c | 35 +++++++++++++++++++++
5 files changed, 121 insertions(+), 3 deletions(-)
diff --git a/gcc/config/rs6000/altivec.md b/gcc/config/rs6000/altivec.md
index b452aa192b8..4779ddc9641 100644
--- a/gcc/config/rs6000/altivec.md
+++ b/gcc/config/rs6000/altivec.md
@@ -176,7 +176,6 @@
UNSPEC_VSTRIL
UNSPEC_SLDB
UNSPEC_SRDB
- UNSPEC_XXSPLTID
UNSPEC_XXSPLTI32DX
UNSPEC_XXBLEND
UNSPEC_XXPERMX
@@ -853,7 +852,7 @@
(define_expand "xxspltidp_v2df"
[(set (match_operand:V2DF 0 "register_operand" )
(unspec:V2DF [(match_operand:SF 1 "const_double_operand")]
- UNSPEC_XXSPLTID))]
+ UNSPEC_XXSPLTIDP))]
"TARGET_POWER10"
{
long value = rs6000_const_f32_to_i32 (operands[1]);
@@ -864,7 +863,7 @@
(define_insn "xxspltidp_v2df_inst"
[(set (match_operand:V2DF 0 "register_operand" "=wa")
(unspec:V2DF [(match_operand:SI 1 "c32bit_cint_operand" "n")]
- UNSPEC_XXSPLTID))]
+ UNSPEC_XXSPLTIDP))]
"TARGET_POWER10"
"xxspltidp %x0,%1"
[(set_attr "type" "vecsimple")
diff --git a/gcc/config/rs6000/constraints.md b/gcc/config/rs6000/constraints.md
index 561ce9797af..2d9d0a4fb96 100644
--- a/gcc/config/rs6000/constraints.md
+++ b/gcc/config/rs6000/constraints.md
@@ -213,6 +213,10 @@
"A signed 34-bit integer constant if prefixed instructions are supported."
(match_operand 0 "cint34_operand"))
+(define_constraint "eF"
+ "A floating point constant that can be loaded with XXSPLTIDP."
+ (match_operand 0 "xxspltidp_operand"))
+
;; Floating-point constraints. These two are defined so that insn
;; length attributes can be calculated exactly.
diff --git a/gcc/config/rs6000/predicates.md b/gcc/config/rs6000/predicates.md
index 24b24e373fc..5fd8035a82a 100644
--- a/gcc/config/rs6000/predicates.md
+++ b/gcc/config/rs6000/predicates.md
@@ -565,6 +565,43 @@
(ior (match_operand 0 "vsx_register_operand")
(match_operand 0 "reg_or_logical_cint_operand")))
+;; Return 1 if operand is a CONST_DOUBLE that can be loaded via the ISA 3.1
+;; XXSPLTIDP instruction. Note, 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), the
+;; result is undefined. We handle both floating point constants and integer
+;; constants to allow this predicate to be used after the insn is split to get
+;; the integer value.
+(define_predicate "xxspltidp_operand"
+ (match_code "const_double,const_int")
+{
+ long value;
+
+ if (!TARGET_POWER10)
+ return 0;
+
+ /* For now do not handle DFmode constants that could be represented as SFmode
+ values. */
+ if (mode == SFmode && CONST_DOUBLE_P (op))
+ value = rs6000_const_f32_to_i32 (op);
+
+ else if (CONST_INT_P (op))
+ value = INTVAL (op);
+
+ else
+ return 0;
+
+ /* Do not return true for 0.0, since it can get loaded with the smaller
+ XXSPLTIB instruction. */
+ if (value == 0)
+ return 0;
+
+ /* Test for SFmode denormal. */
+ if (((value & 0x7F800000) == 0) && ((value & 0x7FFFFF) != 0))
+ return 0;
+
+ return 1;
+})
+
;; Return 1 if operand is a CONST_DOUBLE that can be set in a register
;; with no more than one instruction per word.
(define_predicate "easy_fp_constant"
@@ -601,6 +638,11 @@
if (TARGET_VSX && op == CONST0_RTX (mode))
return 1;
+ /* If we have the ISA 3.1 XXSPLTIDP instruction, see if the constant can
+ be loaded with that instruction. */
+ if (xxspltidp_operand (op, mode))
+ return 1;
+
/* Otherwise consider floating point constants hard, so that the
constant gets pushed to memory during the early RTL phases. This
has the advantage that double precision constants that can be
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index aaefce38af3..1096703f07a 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -154,6 +154,7 @@
UNSPEC_CNTTZDM
UNSPEC_PDEPD
UNSPEC_PEXTD
+ UNSPEC_XXSPLTIDP
])
;;
@@ -7528,6 +7529,27 @@
DONE;
})
+;; Load a SFmode constant via the ISA 3.1 XXSPLTIDP instruction
+(define_split
+ [(set (match_operand:SF 0 "gpc_reg_operand")
+ (match_operand:SF 1 "xxspltidp_operand"))]
+ "TARGET_POWER10"
+ [(set (match_dup 0)
+ (unspec:SF [(match_dup 2)] UNSPEC_XXSPLTIDP))]
+{
+ operands[2] = GEN_INT (rs6000_const_f32_to_i32 (operands[1]));
+})
+
+(define_insn "*xxspltidpsf"
+ [(set (match_operand:SF 0 "gpc_reg_operand" "=wa")
+ (unspec:SF [(match_operand:SI 1 "xxspltidp_operand" "n")]
+ UNSPEC_XXSPLTIDP))]
+ "TARGET_POWER10"
+ "xxspltidp %x0,%1"
+ [(set_attr "type" "vecsimple")
+ (set_attr "prefixed" "yes")
+ (set_attr "prefixed_prepend_p" "no")])
+
(define_split
[(set (match_operand:FMOVE32 0 "gpc_reg_operand")
(match_operand:FMOVE32 1 "const_double_operand"))]
@@ -7561,16 +7583,19 @@
;;
;; LWZ LFS LXSSP LXSSPX STFS STXSSP
;; STXSSPX STW XXLXOR LI FMR XSCPSGNDP
+;; XXSPLTIDP
;; MR MT<x> MF<x> NOP
(define_insn "movsf_hardfloat"
[(set (match_operand:SF 0 "nonimmediate_operand"
"=!r, f, v, wa, m, wY,
Z, m, wa, !r, f, wa,
+ wa,
!r, *c*l, !r, *h")
(match_operand:SF 1 "input_operand"
"m, m, wY, Z, f, v,
wa, r, j, j, f, wa,
+ eF,
r, r, *h, 0"))]
"(register_operand (operands[0], SFmode)
|| register_operand (operands[1], SFmode))
@@ -7590,6 +7615,7 @@
li %0,0
fmr %0,%1
xscpsgndp %x0,%x1,%x1
+ #
mr %0,%1
mt%0 %1
mf%1 %0
@@ -7597,10 +7623,22 @@
[(set_attr "type"
"load, fpload, fpload, fpload, fpstore, fpstore,
fpstore, store, veclogical, integer, fpsimple, fpsimple,
+ vecsimple,
*, mtjmpr, mfjmpr, *")
(set_attr "isa"
"*, *, p9v, p8v, *, p9v,
p8v, *, *, *, *, *,
+ p10,
+ *, *, *, *")
+ (set_attr "prefixed"
+ "*, *, *, *, *, *,
+ *, *, *, *, *, *,
+ yes,
+ *, *, *, *")
+ (set_attr "prefixed_prepend_p"
+ "*, *, *, *, *, *,
+ *, *, *, *, *, *,
+ no,
*, *, *, *")])
;; LWZ LFIWZX STW STFIWX MTVSRWZ MFVSRWZ
diff --git a/gcc/testsuite/gcc.target/powerpc/xxspltidp-sf.c b/gcc/testsuite/gcc.target/powerpc/xxspltidp-sf.c
new file mode 100644
index 00000000000..48387d9c34f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/xxspltidp-sf.c
@@ -0,0 +1,35 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target power10_ok } */
+/* { dg-options "-O2 -mdejagnu-cpu=power10" } */
+
+/* Test loading SF floating point constants. */
+
+float zero (void)
+{
+ return 0.0f; /* XXLXOR */
+}
+
+float one (void)
+{
+ return 1.0f; /* XXSPLTIDP */
+}
+
+float infinity (void)
+{
+ return __builtin_inff (); /* XXSPLTIDP */
+}
+
+float not_a_number (void)
+{
+ return __builtin_nanf (""); /* XXSPLTIDP */
+}
+
+float subnormal (void)
+{
+ return 0x1p-149f; /* PLFS */
+}
+
+/* { dg-final { scan-assembler-times {\mxxlxor\|vsplitsw\|xxspltib\M} 1 } } */
+/* { dg-final { scan-assembler-times {\mxxspltidp\M} 3 } } */
+/* { dg-final { scan-assembler-times {\mlfs\|plfs\|lxssp\|lxsspx\M} 1 } } */
+
More information about the Gcc-cvs
mailing list