]> gcc.gnu.org Git - gcc.git/commitdiff
Add LXVKQ support.
authorMichael Meissner <meissner@linux.ibm.com>
Tue, 24 Aug 2021 19:24:20 +0000 (15:24 -0400)
committerMichael Meissner <meissner@linux.ibm.com>
Tue, 24 Aug 2021 19:24:20 +0000 (15:24 -0400)
This patch adds support to generate the LXVKQ instruction to load specific
IEEE-128 floating point constants.

2021-08-24  Michael Meissner  <meissner@linux.ibm.com>

gcc/

* config/rs6000/constraints.md (eQ): New constraint.
* config/rs6000/predicates.md (easy_fp_constant): If we can use
LXVKQ, it is an easy floating point constant.
(lxvkq_operand): New predicate.
* config/rs6000/rs6000-protos.h (lxvkq_constant_p): New
declaration.
* config/rs6000/rs6000.c (lxvkq_constant_p): New function.
(output_vec_const_move): Add support for LXVKQ.
(rs6000_output_move_128bit): Likewise.
* config/rs6000/rs6000.opt (-mlxvkq): New debug option.
* config/rs6000/vsx.md (vsx_mov<mode>_64bit): Add support for
LXVKQ.
(vsx_mov<mode>_32bit): Likewise.

gcc/testsuite/

* gcc.target/powerpc/float128-constant.c: New test.

gcc/config/rs6000/constraints.md
gcc/config/rs6000/predicates.md
gcc/config/rs6000/rs6000-protos.h
gcc/config/rs6000/rs6000.c
gcc/config/rs6000/rs6000.opt
gcc/config/rs6000/vsx.md
gcc/testsuite/gcc.target/powerpc/float128-constant.c [new file with mode: 0644]

index ea2e4a267c36138023cd93df1bbadfc165d82f3d..4637345f84ba29d1c8cdfba3e4127f491f6decd5 100644 (file)
   "A signed 34-bit integer constant if prefixed instructions are supported."
   (match_operand 0 "cint34_operand"))
 
+;; KF/TF scalar than can be loaded with LXVKQ
+(define_constraint "eQ"
+  "An IEEE 128-bit constant that can be loaded with the LXVKQ instruction."
+  (match_operand 0 "lxvkq_operand"))
+
 ;; Floating-point constraints.  These two are defined so that insn
 ;; length attributes can be calculated exactly.
 
index 134243e404bb62d36d51efe3f23bc126909dab62..1a87272604becd4fbce2543cc44f02ef4bc0435a 100644 (file)
   if (xxspltidp_operand (op, mode))
     return 1;
 
+  /* If we have the ISA 3.1 LXVKQ instruction, see if the constant can be loaded
+     with that instruction.  */
+  if (lxvkq_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
   return xxspltidp_constant_p (op, mode, &value);
 })
 
+;; Return 1 if the operand is an IEEE 128-bit special constant that can be
+;; loaded with the LXVKQ instruction.
+(define_predicate "lxvkq_operand"
+  (match_code "const_double")
+{
+  int immediate = 0;
+  return lxvkq_constant_p (op, mode, &immediate);
+})
+
 ;; Return 1 if the operand is a CONST_VECTOR and can be loaded into a
 ;; vector register without using memory.
 (define_predicate "easy_vector_constant"
index 9bba57c22f2eccbd749c65fc68d54e3a5a3cb3b5..de1c1ee9a8b97da7672db3a2cc79b4b1da213edd 100644 (file)
@@ -33,6 +33,7 @@ extern void init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, int, int, int,
 extern int easy_altivec_constant (rtx, machine_mode);
 extern bool xxspltib_constant_p (rtx, machine_mode, int *, int *);
 extern bool xxspltidp_constant_p (rtx, machine_mode, HOST_WIDE_INT *);
+extern bool lxvkq_constant_p (rtx, machine_mode, int *);
 extern int vspltis_shifted (rtx);
 extern HOST_WIDE_INT const_vector_elt_as_int (rtx, unsigned int);
 extern bool macho_lo_sum_memory_operand (rtx, machine_mode);
index 322b3c839258d84557d5a3daa266deb8ca86127c..4f12f9eb968c3b7c6144ce5ac867b62a6e8fb016 100644 (file)
@@ -6601,6 +6601,112 @@ xxspltidp_constant_p (rtx op,
   return true;
 }
 
+/* Return true if OP is of the given MODE is one of the 18 special values that
+   can be generated with the LXVKQ instruction.
+
+   Return the constant that will go in the LXVKQ instruction.  */
+
+/* LXVKQ immediates.  */
+enum {
+  LXVKQ_ONE            = 1,
+  LXVKQ_TWO            = 2,
+  LXVKQ_THREE          = 3,
+  LXVKQ_FOUR           = 4,
+  LXVKQ_FIVE           = 5,
+  LXVKQ_SIX            = 6,
+  LXVKQ_SEVEN          = 7,
+  LXVKQ_INF            = 8,
+  LXVKQ_NAN            = 9,
+  LXVKQ_NEG_ZERO       = 16,
+  LXVKQ_NEG_ONE                = 17,
+  LXVKQ_NEG_TWO                = 18,
+  LXVKQ_NEG_THREE      = 19,
+  LXVKQ_NEG_FOUR       = 20,
+  LXVKQ_NEG_FIVE       = 21,
+  LXVKQ_NEG_SIX                = 22,
+  LXVKQ_NEG_SEVEN      = 23,
+  LXVKQ_NEG_INF                = 24
+};
+
+bool
+lxvkq_constant_p (rtx op,
+                 machine_mode mode,
+                 int *imm_p)
+{
+  *imm_p = -1;
+
+  if (!TARGET_LXVKQ || !TARGET_POWER10 || !TARGET_VSX || !TARGET_FLOAT128_HW)
+    return false;
+
+  if (mode == VOIDmode)
+    mode = GET_MODE (op);
+
+  if (!FLOAT128_IEEE_P (mode))
+    return false;
+
+  if (!CONST_DOUBLE_P (op))
+    return false;
+
+  /* All of the values generated can be expressed as SFmode values, so if it
+     doesn't fit in SFmode, exit.  */
+  const struct real_value *rv = CONST_DOUBLE_REAL_VALUE (op);
+  if (!exact_real_truncate (SFmode, rv))
+    return 0;
+
+  /* Special values (infinity, nan, -0.0.  */
+  if (real_isinf (rv))
+    {
+      *imm_p = real_isneg (rv) ? LXVKQ_NEG_INF : LXVKQ_INF;
+      return true;
+    }
+
+  if (real_isnan (rv) && !real_isneg (rv))
+    {
+      *imm_p = LXVKQ_NAN;
+      return true;
+    }
+
+  if (real_isnegzero (rv))
+    {
+      *imm_p = LXVKQ_NEG_ZERO;
+      return true;
+    }
+
+  /* The other values are all integers 1..7, and -1..-7.  */
+  if (!real_isinteger (rv, mode))
+    return false;
+
+  HOST_WIDE_INT value = real_to_integer (rv);
+  switch (value)
+    {
+    default:
+      break;
+
+    case 1:
+    case 2:
+    case 3:
+    case 4:
+    case 5:
+    case 6:
+    case 7:
+      *imm_p = LXVKQ_ONE + (value - 1);
+      return true;
+
+    case -1:
+    case -2:
+    case -3:
+    case -4:
+    case -5:
+    case -6:
+    case -7:
+      *imm_p = LXVKQ_NEG_ONE + (-value - 1);
+      return true;
+    }
+
+  /* We can't load the value with LXVKQ.  */
+  return false;
+}
+
 const char *
 output_vec_const_move (rtx *operands)
 {
@@ -6618,6 +6724,7 @@ output_vec_const_move (rtx *operands)
       int xxspltib_value = 256;
       HOST_WIDE_INT xxspltidp_value = 0;
       int num_insns = -1;
+      int lxvkq_immediate = 0;
 
       if (zero_constant (vec, mode))
        {
@@ -6652,6 +6759,12 @@ output_vec_const_move (rtx *operands)
          return "xxspltidp %x0,%2";
        }
 
+      if (lxvkq_constant_p (vec, mode, &lxvkq_immediate))
+       {
+         operands[2] = GEN_INT (lxvkq_immediate);
+         return "lxvkq %x0,%2";
+       }
+
       if (TARGET_P9_VECTOR
          && xxspltib_constant_p (vec, mode, &num_insns, &xxspltib_value))
        {
@@ -13350,6 +13463,7 @@ rs6000_output_move_128bit (rtx operands[])
   int src_regno;
   bool dest_gpr_p, dest_fp_p, dest_vmx_p, dest_vsx_p;
   bool src_gpr_p, src_fp_p, src_vmx_p, src_vsx_p;
+  int lxvkq_immediate = 0;
 
   if (REG_P (dest))
     {
@@ -13494,6 +13608,14 @@ rs6000_output_move_128bit (rtx operands[])
     }
 
   /* Constants.  */
+  else if (dest_vmx_p
+          && CONST_DOUBLE_P (src)
+          && lxvkq_constant_p (src, mode, &lxvkq_immediate))
+    {
+      operands[2] = GEN_INT (lxvkq_immediate);
+      return "lxvkq %x0,%2";
+    }
+
   else if (dest_regno >= 0
           && (CONST_INT_P (src)
               || CONST_WIDE_INT_P (src)
index 928c4fafe079271d5d38a5082dd1e787ea822f1e..016b19e5d2d19080dff6885fcb378bc768fb4a5c 100644 (file)
@@ -643,3 +643,7 @@ Generate code that will run in privileged state.
 mxxspltidp
 Target Undocumented Var(TARGET_XXSPLTIDP) Init(1) Save
 Generate (do not generate) XXSPLTIDP instructions.
+
+mlxvkq
+Target Undocumented Var(TARGET_LXVKQ) Init(1) Save
+Generate (do not generate) LXVKQ instructions.
index af9a04870d44e95c3161a50339e545e76a546846..00f6d0eda14e894d90295443e0ad6e96d0c93950 100644 (file)
 ;; instruction). But generate XXLXOR/XXLORC if it will avoid a register move.
 
 ;;              VSX store  VSX load   VSX move  VSX->GPR   GPR->VSX    LQ (GPR)
-;;             XXSPLTIDP
+;;             XXSPLTIDP  LXVKQ
 ;;              STQ (GPR)  GPR load   GPR store GPR move   XXSPLTIB    VSPLTISW
 ;;              VSX 0/-1   VMX const  GPR const LVX (VMX)  STVX (VMX)
 (define_insn "vsx_mov<mode>_64bit"
   [(set (match_operand:VSX_M 0 "nonimmediate_operand"
                "=ZwO,      wa,        wa,        r,         we,        ?wQ,
-                wa,
+                wa,        wa,
                 ?&r,       ??r,       ??Y,       <??r>,     wa,        v,
                 ?wa,       v,         <??r>,     wZ,        v")
 
        (match_operand:VSX_M 1 "input_operand" 
                "wa,        ZwO,       wa,        we,        r,         r,
-                eF,
+                eF,        eQ,
                 wQ,        Y,         r,         r,         wE,        jwM,
                 ?jwM,      W,         <nW>,      v,         wZ"))]
 
 }
   [(set_attr "type"
                "vecstore,  vecload,   vecsimple, mtvsr,     mfvsr,     load,
-                vecperm,
+                vecperm,   vecperm,
                 store,     load,      store,     *,         vecsimple, vecsimple,
                 vecsimple, *,         *,         vecstore,  vecload")
    (set_attr "num_insns"
                "*,         *,         *,         2,         *,         2,
-                *,
+                *,         *,
                 2,         2,         2,         2,         *,         *,
                 *,         5,         2,         *,         *")
    (set_attr "max_prefixed_insns"
                "*,         *,         *,         *,         *,         2,
-                *,
+                *,         *,
                 2,         2,         2,         2,         *,         *,
                 *,         *,         *,         *,         *")
    (set_attr "length"
                "*,         *,         *,         8,         *,         8,
-                *,
+                *,         *,
                 8,         8,         8,         8,         *,         *,
                 *,         20,        8,         *,         *")
    (set_attr "isa"
                "<VSisa>,   <VSisa>,   <VSisa>,   *,         *,         *,
-                p10,
+                p10,       p10,
                 *,         *,         *,         *,         p9v,       *,
                 <VSisa>,   *,         *,         *,         *")])
 
 ;;              VSX store  VSX load   VSX move   GPR load   GPR store  GPR move
-;;             XXSPLTIDP
+;;             XXSPLTIDP  LXVKQ
 ;;              XXSPLTIB   VSPLTISW   VSX 0/-1   VMX const  GPR const
 ;;              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,
+                wa,        wa,
                 wa,        v,         ?wa,       v,         <??r>,
                 wZ,        v")
 
        (match_operand:VSX_M 1 "input_operand" 
                "wa,        ZwO,       wa,        Y,         r,         r,
-                eF,
+                eF,        eQ,
                 wE,        jwM,       ?jwM,      W,         <nW>,
                 v,         wZ"))]
 
 }
   [(set_attr "type"
                "vecstore,  vecload,   vecsimple, load,      store,    *,
-                vecperm,
+                vecperm,   vecperm,
                 vecsimple, vecsimple, vecsimple, *,         *,
                 vecstore,  vecload")
    (set_attr "length"
                "*,         *,         *,         16,        16,        16,
-                *,
+                *,         *,
                 *,         *,         *,         20,        16,
                 *,         *")
    (set_attr "isa"
                "<VSisa>,   <VSisa>,   <VSisa>,   *,         *,         *,
-                p10,
+                p10,       p10,
                 p9v,       *,         <VSisa>,   *,         *,
                 *,         *")])
 
diff --git a/gcc/testsuite/gcc.target/powerpc/float128-constant.c b/gcc/testsuite/gcc.target/powerpc/float128-constant.c
new file mode 100644 (file)
index 0000000..a5cbe0b
--- /dev/null
@@ -0,0 +1,144 @@
+/* { dg-require-effective-target ppc_float128_hw } */
+/* { dg-require-effective-target power10_ok } */
+/* { dg-options "-mdejagnu-cpu=power10 -O2" } */
+
+/* Test whether the LXVKQ instruction is generated to load special IEEE 128-bit
+   constants.  */
+
+_Float128
+return_0 (void)
+{
+  return 0.0f128;                      /* XXSPLTIB 34,0.  */
+}
+
+_Float128
+return_1 (void)
+{
+  return 1.0f128;                      /* LXVKQ 34,1.  */
+}
+
+_Float128
+return_2 (void)
+{
+  return 2.0f128;                      /* LXVKQ 34,2.  */
+}
+
+_Float128
+return_3 (void)
+{
+  return 3.0f128;                      /* LXVKQ 34,3.  */
+}
+
+_Float128
+return_4 (void)
+{
+  return 4.0f128;                      /* LXVKQ 34,4.  */
+}
+
+_Float128
+return_5 (void)
+{
+  return 5.0f128;                      /* LXVKQ 34,5.  */
+}
+
+_Float128
+return_6 (void)
+{
+  return 6.0f128;                      /* LXVKQ 34,6.  */
+}
+
+_Float128
+return_7 (void)
+{
+  return 7.0f128;                      /* LXVKQ 34,7.  */
+}
+
+_Float128
+return_m0 (void)
+{
+  return -0.0f128;                     /* LXVKQ 34,16.  */
+}
+
+_Float128
+return_m1 (void)
+{
+  return -1.0f128;                     /* LXVKQ 34,17.  */
+}
+
+_Float128
+return_m2 (void)
+{
+  return -2.0f128;                     /* LXVKQ 34,18.  */
+}
+
+_Float128
+return_m3 (void)
+{
+  return -3.0f128;                     /* LXVKQ 34,19.  */
+}
+
+_Float128
+return_m4 (void)
+{
+  return -4.0f128;                     /* LXVKQ 34,20.  */
+}
+
+_Float128
+return_m5 (void)
+{
+  return -5.0f128;                     /* LXVKQ 34,21.  */
+}
+
+_Float128
+return_m6 (void)
+{
+  return -6.0f128;                     /* LXVKQ 34,22.  */
+}
+
+_Float128
+return_m7 (void)
+{
+  return -7.0f128;                     /* LXVKQ 34,23.  */
+}
+
+_Float128
+return_inf (void)
+{
+  return __builtin_inff128 ();         /* LXVKQ 34,8.  */
+}
+
+_Float128
+return_minf (void)
+{
+  return - __builtin_inff128 ();       /* LXVKQ 34,24.  */
+}
+
+_Float128
+return_nan (void)
+{
+  return __builtin_nanf128 ("");       /* LXVKQ 34,9.  */
+}
+
+/* Note, the following NaNs should not generate a LXVKQ instruction.  */
+_Float128
+return_mnan (void)
+{
+  return - __builtin_nanf128 ("");     /* PLXV 34,... */
+}
+
+_Float128
+return_nan2 (void)
+{
+  return __builtin_nanf128 ("1");      /* PLXV 34,... */
+}
+
+_Float128
+return_nans (void)
+{
+  return __builtin_nansf128 ("");      /* PLXV 34,... */
+}
+
+/* { dg-final { scan-assembler-times {\mlxvkq\M}    18 } } */
+/* { dg-final { scan-assembler-times {\mplxv\M}      3 } } */
+/* { dg-final { scan-assembler-times {\mxxspltib\M}  1 } } */
+
This page took 0.097973 seconds and 5 git commands to generate.