https://gcc.gnu.org/g:74feb478b0eb0b10efab7c56c0b92d77f70be793

commit 74feb478b0eb0b10efab7c56c0b92d77f70be793
Author: Michael Meissner <meiss...@linux.ibm.com>
Date:   Fri Aug 15 00:09:36 2025 -0400

    Revert changes

Diff:
---
 gcc/config/rs6000/predicates.md |  11 +++
 gcc/config/rs6000/rs6000.cc     | 109 ++++++++++++++++++++--
 gcc/config/rs6000/rs6000.md     | 197 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 309 insertions(+), 8 deletions(-)

diff --git a/gcc/config/rs6000/predicates.md b/gcc/config/rs6000/predicates.md
index 065cdb10e10f..647e89afb6a7 100644
--- a/gcc/config/rs6000/predicates.md
+++ b/gcc/config/rs6000/predicates.md
@@ -1458,6 +1458,17 @@
   (and (match_operand 0 "branch_comparison_operator")
        (match_code "ne,le,ge,leu,geu,ordered")))
 
+;; Return 1 if OP is a comparison operator suitable for floating point
+;; vector/scalar comparisons that generate a -1/0 mask.
+(define_predicate "fpmask_comparison_operator"
+  (match_code "eq,gt,ge"))
+
+;; Return 1 if OP is a comparison operator suitable for vector/scalar
+;; comparisons that generate a 0/-1 mask (i.e. the inverse of
+;; fpmask_comparison_operator).
+(define_predicate "invert_fpmask_comparison_operator"
+  (match_code "ne,unlt,unle"))
+
 ;; Return 1 if OP is a comparison operation suitable for integer vector/scalar
 ;; comparisons that generate a -1/0 mask.
 (define_predicate "vecint_comparison_operator"
diff --git a/gcc/config/rs6000/rs6000.cc b/gcc/config/rs6000/rs6000.cc
index 24f453bee659..781beb0a26a5 100644
--- a/gcc/config/rs6000/rs6000.cc
+++ b/gcc/config/rs6000/rs6000.cc
@@ -16353,11 +16353,98 @@ rs6000_maybe_emit_maxc_minc (rtx dest, rtx op, rtx 
true_cond, rtx false_cond)
   return true;
 }
 
-/* Helper function to return true if the target supports the "C" minimum and
-   maximum instructions.  */
+/* Possibly emit a floating point conditional move by generating a compare that
+   sets a mask instruction and a XXSEL select instruction.
+
+   Move TRUE_COND to DEST if OP of the operands of the last comparison is
+   nonzero/true, FALSE_COND if it is zero/false.
+
+   Return false if the operation cannot be generated, and true if we could
+   generate the instruction.  */
+
+static bool
+rs6000_maybe_emit_fp_cmove (rtx dest, rtx op, rtx true_cond, rtx false_cond)
+{
+  enum rtx_code code = GET_CODE (op);
+  rtx op0 = XEXP (op, 0);
+  rtx op1 = XEXP (op, 1);
+  machine_mode compare_mode = GET_MODE (op0);
+  machine_mode result_mode = GET_MODE (dest);
+  rtx compare_rtx;
+  rtx cmove_rtx;
+  rtx clobber_rtx;
+
+  if (!can_create_pseudo_p ())
+    return 0;
+
+  /* We allow the comparison to be either SFmode/DFmode and the true/false
+     condition to be either SFmode/DFmode.  I.e. we allow:
+
+       float a, b;
+       double c, d, r;
+
+       r = (a == b) ? c : d;
+
+    and:
+
+       double a, b;
+       float c, d, r;
+
+       r = (a == b) ? c : d;
+
+    but we don't allow intermixing the IEEE 128-bit floating point types with
+    the 32/64-bit scalar types.  */
+
+  if (!(compare_mode == result_mode
+       || (compare_mode == SFmode && result_mode == DFmode)
+       || (compare_mode == DFmode && result_mode == SFmode)))
+    return false;
+
+  switch (code)
+    {
+    case EQ:
+    case GE:
+    case GT:
+      break;
+
+    case NE:
+    case LT:
+    case LE:
+      code = swap_condition (code);
+      std::swap (op0, op1);
+      break;
+
+    default:
+      return false;
+    }
+
+  /* Generate: [(parallel [(set (dest)
+                                (if_then_else (op (cmp1) (cmp2))
+                                              (true)
+                                              (false)))
+                           (clobber (scratch))])].  */
+
+  compare_rtx = gen_rtx_fmt_ee (code, CCFPmode, op0, op1);
+  cmove_rtx = gen_rtx_SET (dest,
+                          gen_rtx_IF_THEN_ELSE (result_mode,
+                                                compare_rtx,
+                                                true_cond,
+                                                false_cond));
+
+  clobber_rtx = gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (V2DImode));
+  emit_insn (gen_rtx_PARALLEL (VOIDmode,
+                              gen_rtvec (2, cmove_rtx, clobber_rtx)));
+
+  return true;
+}
+
+/* Helper function to return true if the target has instructions to do a
+   compare and set mask instruction that can be used with XXSEL to implement a
+   conditional move.  It is also assumed that such a target also supports the
+   "C" minimum and maximum instructions. */
 
 static bool
-have_fp_cmin_cmax (machine_mode mode)
+have_compare_and_set_mask (machine_mode mode)
 {
   switch (mode)
     {
@@ -16402,11 +16489,17 @@ rs6000_emit_cmove (rtx dest, rtx op, rtx true_cond, 
rtx false_cond)
   if (GET_MODE (false_cond) != result_mode)
     return false;
 
-  /* See if we can use the "C" minimum, "C" maximum instructions.  */
-  if (have_fp_cmin_cmax (compare_mode)
-      && compare_mode == result_mode
-      && rs6000_maybe_emit_maxc_minc (dest, op, true_cond, false_cond))
-    return true;
+  /* See if we can use the "C" minimum, "C" maximum, and compare and set mask
+     instructions.  */
+  if (have_compare_and_set_mask (compare_mode)
+      && have_compare_and_set_mask (result_mode))
+    {
+      if (rs6000_maybe_emit_maxc_minc (dest, op, true_cond, false_cond))
+       return true;
+
+      if (rs6000_maybe_emit_fp_cmove (dest, op, true_cond, false_cond))
+       return true;
+    }
 
   /* Don't allow using floating point comparisons for integer results for
      now.  */
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index aa0b49d6e080..4b0467ba1b80 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -5747,6 +5747,203 @@
   "TARGET_HARD_FLOAT && TARGET_PPC_GFXOPT"
   "fsel %0,%1,%2,%3"
   [(set_attr "type" "fp")])
+
+(define_insn_and_split "*mov<SFDF:mode><SFDF2:mode>cc_p9"
+  [(set (match_operand:SFDF 0 "vsx_register_operand" "=&wa,wa")
+       (if_then_else:SFDF
+        (match_operator:CCFP 1 "fpmask_comparison_operator"
+               [(match_operand:SFDF2 2 "vsx_register_operand" "wa,wa")
+                (match_operand:SFDF2 3 "vsx_register_operand" "wa,wa")])
+        (match_operand:SFDF 4 "vsx_register_operand" "wa,wa")
+        (match_operand:SFDF 5 "vsx_register_operand" "wa,wa")))
+   (clobber (match_scratch:V2DI 6 "=0,&wa"))]
+  "TARGET_P9_MINMAX"
+  "#"
+  "&& 1"
+  [(set (match_dup 6)
+       (if_then_else:V2DI (match_dup 1)
+                          (match_dup 7)
+                          (match_dup 8)))
+   (set (match_dup 0)
+       (if_then_else:SFDF (ne (match_dup 6)
+                              (match_dup 8))
+                          (match_dup 4)
+                          (match_dup 5)))]
+{
+  if (GET_CODE (operands[6]) == SCRATCH)
+    operands[6] = gen_reg_rtx (V2DImode);
+
+  operands[7] = CONSTM1_RTX (V2DImode);
+  operands[8] = CONST0_RTX (V2DImode);
+}
+ [(set_attr "length" "8")
+  (set_attr "type" "vecperm")])
+
+;; Handle inverting the fpmask comparisons.
+(define_insn_and_split "*mov<SFDF:mode><SFDF2:mode>cc_invert_p9"
+  [(set (match_operand:SFDF 0 "vsx_register_operand" "=&wa,wa")
+       (if_then_else:SFDF
+        (match_operator:CCFP 1 "invert_fpmask_comparison_operator"
+               [(match_operand:SFDF2 2 "vsx_register_operand" "wa,wa")
+                (match_operand:SFDF2 3 "vsx_register_operand" "wa,wa")])
+        (match_operand:SFDF 4 "vsx_register_operand" "wa,wa")
+        (match_operand:SFDF 5 "vsx_register_operand" "wa,wa")))
+   (clobber (match_scratch:V2DI 6 "=0,&wa"))]
+  "TARGET_P9_MINMAX"
+  "#"
+  "&& 1"
+  [(set (match_dup 6)
+       (if_then_else:V2DI (match_dup 9)
+                          (match_dup 7)
+                          (match_dup 8)))
+   (set (match_dup 0)
+       (if_then_else:SFDF (ne (match_dup 6)
+                              (match_dup 8))
+                          (match_dup 5)
+                          (match_dup 4)))]
+{
+  rtx op1 = operands[1];
+  enum rtx_code cond = reverse_condition_maybe_unordered (GET_CODE (op1));
+
+  if (GET_CODE (operands[6]) == SCRATCH)
+    operands[6] = gen_reg_rtx (V2DImode);
+
+  operands[7] = CONSTM1_RTX (V2DImode);
+  operands[8] = CONST0_RTX (V2DImode);
+
+  operands[9] = gen_rtx_fmt_ee (cond, CCFPmode, operands[2], operands[3]);
+}
+ [(set_attr "length" "8")
+  (set_attr "type" "vecperm")])
+
+(define_insn "*fpmask<mode>"
+  [(set (match_operand:V2DI 0 "vsx_register_operand" "=wa")
+       (if_then_else:V2DI
+        (match_operator:CCFP 1 "fpmask_comparison_operator"
+               [(match_operand:SFDF 2 "vsx_register_operand" "wa")
+                (match_operand:SFDF 3 "vsx_register_operand" "wa")])
+        (match_operand:V2DI 4 "all_ones_constant" "")
+        (match_operand:V2DI 5 "zero_constant" "")))]
+  "TARGET_P9_MINMAX"
+  "xscmp%V1dp %x0,%x2,%x3"
+  [(set_attr "type" "fpcompare")])
+
+(define_insn "*xxsel<mode>"
+  [(set (match_operand:SFDF 0 "vsx_register_operand" "=wa")
+       (if_then_else:SFDF (ne (match_operand:V2DI 1 "vsx_register_operand" 
"wa")
+                              (match_operand:V2DI 2 "zero_constant" ""))
+                          (match_operand:SFDF 3 "vsx_register_operand" "wa")
+                          (match_operand:SFDF 4 "vsx_register_operand" "wa")))]
+  "TARGET_P9_MINMAX"
+  "xxsel %x0,%x4,%x3,%x1"
+  [(set_attr "type" "vecmove")])
+
+;; Support for ISA 3.1 IEEE 128-bit conditional move.  The mode used in the
+;; comparison must be the same as used in the move.
+(define_expand "mov<mode>cc"
+   [(set (match_operand:IEEE128 0 "gpc_reg_operand")
+        (if_then_else:IEEE128 (match_operand 1 "comparison_operator")
+                              (match_operand:IEEE128 2 "gpc_reg_operand")
+                              (match_operand:IEEE128 3 "gpc_reg_operand")))]
+  "TARGET_POWER10 && TARGET_FLOAT128_HW"
+{
+  if (rs6000_emit_cmove (operands[0], operands[1], operands[2], operands[3]))
+    DONE;
+  else
+    FAIL;
+})
+
+(define_insn_and_split "*mov<mode>cc_p10"
+  [(set (match_operand:IEEE128 0 "altivec_register_operand" "=&v,v")
+       (if_then_else:IEEE128
+        (match_operator:CCFP 1 "fpmask_comparison_operator"
+               [(match_operand:IEEE128 2 "altivec_register_operand" "v,v")
+                (match_operand:IEEE128 3 "altivec_register_operand" "v,v")])
+        (match_operand:IEEE128 4 "altivec_register_operand" "v,v")
+        (match_operand:IEEE128 5 "altivec_register_operand" "v,v")))
+   (clobber (match_scratch:V2DI 6 "=0,&v"))]
+  "TARGET_POWER10 && TARGET_FLOAT128_HW"
+  "#"
+  "&& 1"
+  [(set (match_dup 6)
+       (if_then_else:V2DI (match_dup 1)
+                          (match_dup 7)
+                          (match_dup 8)))
+   (set (match_dup 0)
+       (if_then_else:IEEE128 (ne (match_dup 6)
+                                 (match_dup 8))
+                             (match_dup 4)
+                             (match_dup 5)))]
+{
+  if (GET_CODE (operands[6]) == SCRATCH)
+    operands[6] = gen_reg_rtx (V2DImode);
+
+  operands[7] = CONSTM1_RTX (V2DImode);
+  operands[8] = CONST0_RTX (V2DImode);
+}
+ [(set_attr "length" "8")
+  (set_attr "type" "vecperm")])
+
+;; Handle inverting the fpmask comparisons.
+(define_insn_and_split "*mov<mode>cc_invert_p10"
+  [(set (match_operand:IEEE128 0 "altivec_register_operand" "=&v,v")
+       (if_then_else:IEEE128
+        (match_operator:CCFP 1 "invert_fpmask_comparison_operator"
+               [(match_operand:IEEE128 2 "altivec_register_operand" "v,v")
+                (match_operand:IEEE128 3 "altivec_register_operand" "v,v")])
+        (match_operand:IEEE128 4 "altivec_register_operand" "v,v")
+        (match_operand:IEEE128 5 "altivec_register_operand" "v,v")))
+   (clobber (match_scratch:V2DI 6 "=0,&v"))]
+  "TARGET_POWER10 && TARGET_FLOAT128_HW"
+  "#"
+  "&& 1"
+  [(set (match_dup 6)
+       (if_then_else:V2DI (match_dup 9)
+                          (match_dup 7)
+                          (match_dup 8)))
+   (set (match_dup 0)
+       (if_then_else:IEEE128 (ne (match_dup 6)
+                                 (match_dup 8))
+                             (match_dup 5)
+                             (match_dup 4)))]
+{
+  rtx op1 = operands[1];
+  enum rtx_code cond = reverse_condition_maybe_unordered (GET_CODE (op1));
+
+  if (GET_CODE (operands[6]) == SCRATCH)
+    operands[6] = gen_reg_rtx (V2DImode);
+
+  operands[7] = CONSTM1_RTX (V2DImode);
+  operands[8] = CONST0_RTX (V2DImode);
+
+  operands[9] = gen_rtx_fmt_ee (cond, CCFPmode, operands[2], operands[3]);
+}
+ [(set_attr "length" "8")
+  (set_attr "type" "vecperm")])
+
+(define_insn "*fpmask<mode>"
+  [(set (match_operand:V2DI 0 "altivec_register_operand" "=v")
+       (if_then_else:V2DI
+        (match_operator:CCFP 1 "fpmask_comparison_operator"
+               [(match_operand:IEEE128 2 "altivec_register_operand" "v")
+                (match_operand:IEEE128 3 "altivec_register_operand" "v")])
+        (match_operand:V2DI 4 "all_ones_constant" "")
+        (match_operand:V2DI 5 "zero_constant" "")))]
+  "TARGET_POWER10 && TARGET_FLOAT128_HW"
+  "xscmp%V1qp %0,%2,%3"
+  [(set_attr "type" "fpcompare")])
+
+(define_insn "*xxsel<mode>"
+  [(set (match_operand:IEEE128 0 "altivec_register_operand" "=v")
+       (if_then_else:IEEE128
+        (ne (match_operand:V2DI 1 "altivec_register_operand" "v")
+            (match_operand:V2DI 2 "zero_constant" ""))
+        (match_operand:IEEE128 3 "altivec_register_operand" "v")
+        (match_operand:IEEE128 4 "altivec_register_operand" "v")))]
+  "TARGET_POWER10 && TARGET_FLOAT128_HW"
+  "xxsel %x0,%x4,%x3,%x1"
+  [(set_attr "type" "vecmove")])
+
 
 ;; Conversions to and from floating-point.

Reply via email to