[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