https://gcc.gnu.org/g:89a0027e79e90ac5cf8909c28d05cae569646ede

commit 89a0027e79e90ac5cf8909c28d05cae569646ede
Author: Michael Meissner <[email protected]>
Date:   Mon Dec 8 21:29:50 2025 -0500

    Revert changes

Diff:
---
 gcc/config/rs6000/linux64.h                    |   5 +-
 gcc/config/rs6000/predicates.md                |  11 +
 gcc/config/rs6000/rs6000.cc                    | 121 ++++++++--
 gcc/config/rs6000/rs6000.md                    | 305 ++++++++++++++++---------
 gcc/config/rs6000/vsx.md                       |  18 --
 gcc/testsuite/gcc.target/powerpc/builtins-1.c  |   2 +-
 gcc/testsuite/gcc.target/powerpc/p9-minmax-2.c | 175 +++++++++++++-
 gcc/testsuite/gcc.target/powerpc/pr108958.c    |  47 ----
 gcc/testsuite/gcc.target/powerpc/pr120528.c    |  91 --------
 gcc/testsuite/gcc.target/powerpc/pr120681.c    |  34 ---
 gcc/testsuite/gcc.target/powerpc/pr99293.c     |  22 --
 11 files changed, 485 insertions(+), 346 deletions(-)

diff --git a/gcc/config/rs6000/linux64.h b/gcc/config/rs6000/linux64.h
index 5a6c3e199ba8..dd4d3f1f2095 100644
--- a/gcc/config/rs6000/linux64.h
+++ b/gcc/config/rs6000/linux64.h
@@ -564,8 +564,7 @@ extern int dot_symbols;
 
 /* Enable using prefixed PC-relative addressing on POWER10 if the ABI
    supports it.  The ELF v2 ABI only supports PC-relative relocations for
-   the medium/large code models.  */
+   the medium code model.  */
 #define PCREL_SUPPORTED_BY_OS  (TARGET_POWER10 && TARGET_PREFIXED      \
                                 && ELFv2_ABI_CHECK                     \
-                                && (TARGET_CMODEL == CMODEL_MEDIUM     \
-                                    || TARGET_CMODEL == CMODEL_LARGE))
+                                && TARGET_CMODEL == CMODEL_MEDIUM)
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 3b365b9fc30a..cb087640ebcf 100644
--- a/gcc/config/rs6000/rs6000.cc
+++ b/gcc/config/rs6000/rs6000.cc
@@ -4358,15 +4358,12 @@ rs6000_option_override_internal (bool global_init_p)
       && (rs6000_isa_flags_explicit & OPTION_MASK_PCREL) == 0)
     rs6000_isa_flags |= OPTION_MASK_PCREL;
 
-  /* -mpcrel requires medium or large code models, but we can't check
-      TARGET_CMODEL until after the subtarget override options are done.  */
-  else if (TARGET_PCREL
-          && TARGET_CMODEL != CMODEL_MEDIUM
-          && TARGET_CMODEL != CMODEL_LARGE)
+  /* -mpcrel requires -mcmodel=medium, but we can't check TARGET_CMODEL until
+      after the subtarget override options are done.  */
+  else if (TARGET_PCREL && TARGET_CMODEL != CMODEL_MEDIUM)
     {
       if ((rs6000_isa_flags_explicit & OPTION_MASK_PCREL) != 0)
-       error ("%qs requires %qs or %qs", "-mpcrel", "-mcmodel=medium",
-              "-mcmodel=large");
+       error ("%qs requires %qs", "-mpcrel", "-mcmodel=medium");
 
       rs6000_isa_flags &= ~OPTION_MASK_PCREL;
     }
@@ -16338,11 +16335,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_minc_maxc (machine_mode mode)
+have_compare_and_set_mask (machine_mode mode)
 {
   switch (mode)
     {
@@ -16387,10 +16471,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_minc_maxc (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.  */
@@ -21268,7 +21359,7 @@ rs6000_elf_declare_function_name (FILE *file, const 
char *name, tree decl)
   ASM_OUTPUT_TYPE_DIRECTIVE (file, name, "function");
   ASM_DECLARE_RESULT (file, DECL_RESULT (decl));
 
-  if (TARGET_CMODEL == CMODEL_LARGE && !TARGET_PCREL
+  if (TARGET_CMODEL == CMODEL_LARGE
       && rs6000_global_entry_point_prologue_needed_p ())
     {
       char buf[256];
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index 87e42cd548fa..ff085bf9bb10 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -173,7 +173,6 @@
    UNSPEC_XXSPLTIW_CONST
    UNSPEC_FMAX
    UNSPEC_FMIN
-   UNSPEC_ZERO_EXTEND
   ])
 
 ;;
@@ -970,100 +969,6 @@
    (set_attr "dot" "yes")
    (set_attr "length" "4,8")])
 
-;; Optimize zero_extendsiti2 from a GPR to a GPR and then moving the GPR to a
-;; VSX register
-(define_peephole2
-  [(set (match_operand:DI 0 "int_reg_operand")
-       (match_operand:DI 1 "int_reg_operand"))
-   (set (match_operand:DI 2 "int_reg_operand")
-       (const_int 0))
-   (set (match_operand:TI 3 "vsx_register_operand")
-       (match_operand:TI 4 "int_reg_operand"))]
-  "TARGET_DIRECT_MOVE_64BIT
-   && (reg_or_subregno (operands[0])
-       == reg_or_subregno (operands[4]) + !!WORDS_BIG_ENDIAN)
-   && (reg_or_subregno (operands[2])
-       == reg_or_subregno (operands[4]) + !WORDS_BIG_ENDIAN)
-   && peep2_reg_dead_p (3, operands[4])"
-  [(set (match_dup 3)
-       (unspec:TI [(match_dup 1)] UNSPEC_ZERO_EXTEND))])
-
-(define_insn "*zero_extendsiti2_vsx"
-  [(set (match_operand:TI 0 "vsx_register_operand" "=wa")
-       (unspec:TI [(match_operand:DI 1 "int_reg_operand" "r")]
-                  UNSPEC_ZERO_EXTEND))]
-  "TARGET_DIRECT_MOVE_64BIT"
-  "mtvsrdd %x0,0,%1"
-  [(set_attr "type" "mtvsr")])
-
-;; On power10, optimize zero extending a QI/HI/SI/DImode value from memory that
-;; is going to a vector register target by generating a LXVR{B,H,W,D}X
-;; instruction without creating the TImode value in a GPR and using MTVSRDD to
-;; move it to the vector register.
-(define_peephole2
-  [(set (match_operand:DI 0 "int_reg_operand")
-       (match_operand:DI 1 "memory_operand"))
-   (set (match_operand:DI 2 "base_reg_operand")
-       (const_int 0))
-   (set (match_operand:TI 3 "vsx_register_operand")
-       (match_operand:TI 4 "int_reg_operand"))]
-  "TARGET_POWER10 && TARGET_POWERPC64
-   && (reg_or_subregno (operands[0])
-       == reg_or_subregno (operands[4]) + !!WORDS_BIG_ENDIAN)
-   && (reg_or_subregno (operands[2])
-       == reg_or_subregno (operands[4]) + !WORDS_BIG_ENDIAN)
-   && peep2_reg_dead_p (3, operands[4])
-   && (REG_P (XEXP (operands[1], 0))
-       || SUBREG_P (XEXP (operands[1], 0))
-       || GET_CODE (XEXP (operands[1], 0)) == PLUS)"
-  [(set (match_dup 3)
-       (zero_extend:TI (match_dup 5)))]
-{
-  rtx mem = operands[1];
-  rtx addr = XEXP (mem, 0);
-
-  if (indexed_or_indirect_address (addr, DImode))
-    operands[5] = mem;
-  else
-    {
-      rtx op2 = operands[2];
-      emit_insn (gen_rtx_SET (op2, addr));
-      operands[5] = change_address (mem, DImode, op2);
-    }
-})
-
-(define_peephole2
-  [(set (match_operand:DI 0 "int_reg_operand")
-       (zero_extend:DI
-        (match_operand:QHSI 1 "memory_operand")))
-   (set (match_operand:DI 2 "base_reg_operand")
-       (const_int 0))
-   (set (match_operand:TI 3 "vsx_register_operand")
-       (match_operand:TI 4 "int_reg_operand"))]
-  "TARGET_POWER10 && TARGET_POWERPC64
-   && (reg_or_subregno (operands[0])
-       == reg_or_subregno (operands[4]) + !!WORDS_BIG_ENDIAN)
-   && (reg_or_subregno (operands[2])
-       == reg_or_subregno (operands[4]) + !WORDS_BIG_ENDIAN)
-   && peep2_reg_dead_p (3, operands[4])
-   && (REG_P (XEXP (operands[1], 0))
-       || SUBREG_P (XEXP (operands[1], 0))
-       || GET_CODE (XEXP (operands[1], 0)) == PLUS)"
-  [(set (match_dup 3)
-       (zero_extend:TI (match_dup 5)))]
-{
-  rtx mem = operands[1];
-  rtx addr = XEXP (mem, 0);
-
-  if (indexed_or_indirect_address (addr, DImode))
-    operands[5] = mem;
-  else
-    {
-      rtx op2 = operands[2];
-      emit_insn (gen_rtx_SET (op2, addr));
-      operands[5] = change_address (mem, DImode, op2);
-    }
-})
 
 (define_insn "zero_extendsi<mode>2"
   [(set (match_operand:EXTSI 0 "gpc_reg_operand" "=r,r,d,wa,wa,r,wa")
@@ -5645,19 +5550,6 @@
     FAIL;
 })
 
-(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;
-})
-
 ;; We use the BASE_REGS for the isel input operands because, if rA is
 ;; 0, the value of 0 is placed in rD upon truth.  Similarly for rB
 ;; because we may switch the operands and rB may end up being rA.
@@ -5760,6 +5652,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.
 
diff --git a/gcc/config/rs6000/vsx.md b/gcc/config/rs6000/vsx.md
index f47c4e2f7766..0082a36831a5 100644
--- a/gcc/config/rs6000/vsx.md
+++ b/gcc/config/rs6000/vsx.md
@@ -4798,24 +4798,6 @@
   "lxvdsx %x0,%y1"
   [(set_attr "type" "vecload")])
 
-;; Optimize SPLAT of an extract from a V2DF/V2DI vector with a constant element
-(define_insn "*vsx_splat_extract_<mode>"
-  [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wa")
-       (vec_duplicate:VSX_D
-        (vec_select:<VEC_base>
-         (match_operand:VSX_D 1 "vsx_register_operand" "wa")
-         (parallel [(match_operand 2 "const_0_to_1_operand" "n")]))))]
-  "VECTOR_MEM_VSX_P (<MODE>mode)"
-{
-  int which_word = INTVAL (operands[2]);
-  if (!BYTES_BIG_ENDIAN)
-    which_word = 1 - which_word;
-
-  operands[3] = GEN_INT (which_word ? 3 : 0);
-  return "xxpermdi %x0,%x1,%x1,%3";
-}
-  [(set_attr "type" "vecperm")])
-
 ;; V4SI splat support
 (define_insn "vsx_splat_v4si"
   [(set (match_operand:V4SI 0 "vsx_register_operand" "=wa,wa")
diff --git a/gcc/testsuite/gcc.target/powerpc/builtins-1.c 
b/gcc/testsuite/gcc.target/powerpc/builtins-1.c
index 8410a5fd4319..4e7e5384675f 100644
--- a/gcc/testsuite/gcc.target/powerpc/builtins-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/builtins-1.c
@@ -1035,4 +1035,4 @@ foo156 (vector unsigned short usa)
 /* { dg-final { scan-assembler-times {\mvmrglb\M} 3 } } */
 /* { dg-final { scan-assembler-times {\mvmrgew\M} 4 } } */
 /* { dg-final { scan-assembler-times {\mvsplth|xxsplth\M} 4 } } */
-/* { dg-final { scan-assembler-times {\mxxpermdi\M} 44 } } */
+/* { dg-final { scan-assembler-times {\mxxpermdi\M} 42 } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/p9-minmax-2.c 
b/gcc/testsuite/gcc.target/powerpc/p9-minmax-2.c
index b93056f78aea..0684eb501c56 100644
--- a/gcc/testsuite/gcc.target/powerpc/p9-minmax-2.c
+++ b/gcc/testsuite/gcc.target/powerpc/p9-minmax-2.c
@@ -1,29 +1,190 @@
 /* { dg-do compile } */
-/* { dg-options "-mdejagnu-cpu=power9 -mvsx -O2" } */
+/* { dg-options "-mdejagnu-cpu=power9 -mvsx -O2 -mpower9-minmax" } */
 /* { dg-require-effective-target powerpc_vsx } */
-/* { dg-final { scan-assembler "xsmaxcdp"  } } */
-/* { dg-final { scan-assembler "xsmincdp"  } } */
+/* { dg-final { scan-assembler-not "fsel"      } } */
+/* { dg-final { scan-assembler     "xscmpeqdp" } } */
+/* { dg-final { scan-assembler     "xscmpgtdp" } } */
+/* { dg-final { scan-assembler-not "xscmpodp"  } } */
+/* { dg-final { scan-assembler-not "xscmpudp"  } } */
+/* { dg-final { scan-assembler     "xsmaxcdp"  } } */
+/* { dg-final { scan-assembler-not "xsmaxdp"   } } */
+/* { dg-final { scan-assembler     "xsmincdp"  } } */
+/* { dg-final { scan-assembler-not "xsmindp"   } } */
+/* { dg-final { scan-assembler     "xxsel"     } } */
+
+/* Due to NaN support, <= and >= are not handled presently unless -ffast-math
+   is used.  At some point this will be fixed and the xscmpgedp instruction can
+   be generated normally. The <= and >= tests are bracketed with
+   #ifdef DO_GE_LE.  */
+
+#ifdef DO_GE_LE
+double
+dbl_max1 (double a, double b)
+{
+  return (a >= b) ? a : b;
+}
+#endif
 
 double
-dbl_max (double a, double b)
+dbl_max2 (double a, double b)
 {
   return (a > b) ? a : b;
 }
 
 double
-dbl_min (double a, double b)
+dbl_min1 (double a, double b)
 {
   return (a < b) ? a : b;
 }
 
+#ifdef DO_GE_LE
+double
+dbl_min2 (double a, double b)
+{
+  return (a <= b) ? a : b;
+}
+#endif
+
+double
+dbl_cmp_eq (double a, double b, double c, double d)
+{
+  return (a == b) ? c : d;
+}
+
+double
+dbl_cmp_ne (double a, double b, double c, double d)
+{
+  return (a != b) ? c : d;
+}
+
+double
+dbl_cmp_gt (double a, double b, double c, double d)
+{
+  return (a > b) ? c : d;
+}
+
+#ifdef DO_GE_LE
+double
+dbl_cmp_ge (double a, double b, double c, double d)
+{
+  return (a >= b) ? c : d;
+}
+#endif
+
+double
+dbl_cmp_lt (double a, double b, double c, double d)
+{
+  return (a < b) ? c : d;
+}
+
+#ifdef DO_GE_LE
+double
+dbl_cmp_le (double a, double b, double c, double d)
+{
+  return (a <= b) ? c : d;
+}
+#endif
+
+#ifdef DO_GE_LE
+float
+flt_max1 (float a, float b)
+{
+  return (a >= b) ? a : b;
+}
+#endif
+
 float
-flt_max (float a, float b)
+flt_max2 (float a, float b)
 {
   return (a > b) ? a : b;
 }
 
 float
-flt_min (float a, float b)
+flt_min1 (float a, float b)
+{
+  return (a < b) ? a : b;
+}
+
+#ifdef DO_GE_LE
+float
+flt_min2 (float a, float b)
+{
+  return (a <= b) ? a : b;
+}
+#endif
+
+float
+flt_cmp_eq (float a, float b, float c, float d)
+{
+  return (a == b) ? c : d;
+}
+
+float
+flt_cmp_ne (float a, float b, float c, float d)
+{
+  return (a != b) ? c : d;
+}
+
+float
+flt_cmp_gt (float a, float b, float c, float d)
+{
+  return (a > b) ? c : d;
+}
+
+#ifdef DO_GE_LE
+float
+flt_cmp_ge (float a, float b, float c, float d)
+{
+  return (a >= b) ? c : d;
+}
+#endif
+
+float
+flt_cmp_lt (float a, float b, float c, float d)
+{
+  return (a < b) ? c : d;
+}
+
+#ifdef DO_GE_LE
+float
+flt_cmp_le (float a, float b, float c, float d)
+{
+  return (a <= b) ? c : d;
+}
+#endif
+
+double
+dbl_flt_max1 (float a, float b)
+{
+  return (a > b) ? a : b;
+}
+
+double
+dbl_flt_max2 (double a, float b)
+{
+  return (a > b) ? a : b;
+}
+
+double
+dbl_flt_max3 (float a, double b)
+{
+  return (a > b) ? a : b;
+}
+
+double
+dbl_flt_min1 (float a, float b)
+{
+  return (a < b) ? a : b;
+}
+
+double
+dbl_flt_min2 (double a, float b)
+{
+  return (a < b) ? a : b;
+}
+
+double
+dbl_flt_min3 (float a, double b)
 {
   return (a < b) ? a : b;
 }
diff --git a/gcc/testsuite/gcc.target/powerpc/pr108958.c 
b/gcc/testsuite/gcc.target/powerpc/pr108958.c
deleted file mode 100644
index 21b3f2766918..000000000000
--- a/gcc/testsuite/gcc.target/powerpc/pr108958.c
+++ /dev/null
@@ -1,47 +0,0 @@
-/* { dg-do compile } */
-/* { dg-require-effective-target int128 } */
-/* { dg-require-effective-target lp64 } */
-/* { dg-options "-mdejagnu-cpu=power9 -O2" } */
-
-#ifndef TYPE
-#define TYPE unsigned long long
-#endif
-
-/* PR target/108958, when zero extending a DImode to a TImode, and the TImode 
variable is in a VSX register, generate:
-
-       mtvsrdd vreg,0,gpr
-
-   instead of:
-
-       mr tmp,gpr
-       li tmp+1,0
-       mtvsrdd vreg,tmp+1,tmp.  */
-
-void
-gpr_to_vsx (TYPE x, __uint128_t *p)
-{
-  /* mtvsrdd 0,0,3
-     stvx 0,0(4)  */
-
-  __uint128_t y = x;
-  __asm__ (" # %x0" : "+wa" (y));
-  *p = y;
-}
-
-void
-gpr_to_gpr (TYPE x, __uint128_t *p)
-{
-  /* mr 2,3
-     li 3,0
-     std 2,0(4)
-     std 3,8(4)  */
-
-  __uint128_t y = x;
-  __asm__ (" # %0" : "+r" (y));
-  *p = y;
-}
-
-/* { dg-final { scan-assembler-times {\mli\M}              1 } } */
-/* { dg-final { scan-assembler-times {\mmtvsrdd .*,0,.*\M} 1 } } */
-/* { dg-final { scan-assembler-times {\mstd\M}             2 } } */
-/* { dg-final { scan-assembler-times {\mstxv\M}            1 } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/pr120528.c 
b/gcc/testsuite/gcc.target/powerpc/pr120528.c
deleted file mode 100644
index 476725eaa4fb..000000000000
--- a/gcc/testsuite/gcc.target/powerpc/pr120528.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/* { dg-do compile } */
-/* { dg-require-effective-target int128 } */
-/* { dg-require-effective-target lp64 } */
-/* { dg-require-effective-target power10_ok } */
-/* { dg-options "-mdejagnu-cpu=power10 -O2" } */
-
-#include <stddef.h>
-
-#ifndef TYPE
-#define TYPE unsigned long long
-#endif
-
-void
-mem_to_vsx (TYPE *p, __uint128_t *q)
-{
-  /* lxvrdx 0,0,3
-     stxv 0,0(4)  */
-
-  __uint128_t x = *p;
-  __asm__ (" # %x0" : "+wa" (x));
-  *q = x;
-}
-
-void
-memx_to_vsx (TYPE *p, size_t n, __uint128_t *q)
-{
-  /* sldi 4,4,3
-     lxvrdx 0,3,4
-     stxv 0,0(4)  */
-
-  __uint128_t x = p[n];
-  __asm__ (" # %x0" : "+wa" (x));
-  *q = x;
-}
-
-void
-mem3_to_vsx (TYPE *p, __uint128_t *q)
-{
-  /* addi 2,3,24
-     lxvrdx 0,0,2
-     stxv 0,0(4)  */
-
-  __uint128_t x = p[3];
-  __asm__ (" # %x0" : "+wa" (x));
-  *q = x;
-}
-
-void
-mem_to_gpr (TYPE *p, __uint128_t *q)
-{
-  /* ld 2,0(3)
-     li 3,0
-     std 2,0(4)
-     std 3,8(8)  */
-
-  __uint128_t x = *p;
-  __asm__ (" # %0" : "+r" (x));
-  *q = x;
-}
-
-void
-memx_to_gpr (TYPE *p, size_t n, __uint128_t *q)
-{
-  /* sldi 4,4,3
-     ldx 2,3,4
-     li 3,0
-     std 2,0(4)
-     std 3,8(8)  */
-
-  __uint128_t x = p[n];
-  __asm__ (" # %0" : "+r" (x));
-  *q = x;
-}
-
-void
-mem3_to_gpr (TYPE *p, __uint128_t *q)
-{
-  /* ld 2,24(3)
-     li 3,0
-     std 2,0(4)
-     std 3,8(8)  */
-
-  __uint128_t x = p[3];
-  __asm__ (" # %0" : "+r" (x));
-  *q = x;
-}
-
-/* { dg-final { scan-assembler-times {\maddi\M}   1 } } */
-/* { dg-final { scan-assembler-times {\mli\M}     3 } } */
-/* { dg-final { scan-assembler-times {\mlxvrdx\M} 3 } } */
-/* { dg-final { scan-assembler-times {\mstxv\M}   3 } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/pr120681.c 
b/gcc/testsuite/gcc.target/powerpc/pr120681.c
deleted file mode 100644
index d883d1c8a951..000000000000
--- a/gcc/testsuite/gcc.target/powerpc/pr120681.c
+++ /dev/null
@@ -1,34 +0,0 @@
-/* { dg-do compile } */
-/* { dg-require-effective-target powerpc_elfv2 } */
-/* { dg-require-effective-target powerpc_pcrel } */
-/* { dg-options "-mdejagnu-cpu=power10 -O2 -mcmodel=large" } */
-
-/* PR target/120681 -- verify that -mcpu=power10 -mcmodel=large uses PC
-   relative addressing instead of using TOC addressing.  */
-
-#ifndef TYPE
-#define TYPE unsigned long
-#endif
-
-extern TYPE global_var;
-
-void
-set_global (TYPE value)
-{
-  /*
-   * Generate:
-   * pld 9,global_var@got@pcrel
-   * std 3,0(9)
-   *
-   * Not:
-   * addis 9,2,.LC0@toc@ha
-   * ld    9,.LC0@toc@l(9)
-   * std   3,0(9)
-   */
-
-  global_var = value;
-}
-
-/* { dg-final { scan-assembler     {@got@pcrel} } } */
-/* { dg-final { scan-assembler-not {@toc@ha}    } } */
-/* { dg-final { scan-assembler-not {@toc@l}     } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/pr99293.c 
b/gcc/testsuite/gcc.target/powerpc/pr99293.c
deleted file mode 100644
index 20adc1f27f65..000000000000
--- a/gcc/testsuite/gcc.target/powerpc/pr99293.c
+++ /dev/null
@@ -1,22 +0,0 @@
-/* { dg-do compile { target powerpc*-*-* } } */
-/* { dg-require-effective-target powerpc_vsx_ok } */
-/* { dg-options "-O2 -mvsx" } */
-
-/* Test for PR 99263, which wants to do:
-       __builtin_vec_splats (__builtin_vec_extract (v, n))
-
-   where v is a V2DF or V2DI vector and n is either 0 or 1.  Previously the
-   compiler would do a direct move to the GPR registers to select the item and 
a
-   direct move from the GPR registers to do the splat.  */
-
-vector long long splat_dup_l_0 (vector long long v)
-{
-  return __builtin_vec_splats (__builtin_vec_extract (v, 0));
-}
-
-vector long long splat_dup_l_1 (vector long long v)
-{
-  return __builtin_vec_splats (__builtin_vec_extract (v, 1));
-}
-
-/* { dg-final { scan-assembler-times "xxpermdi" 2 } } */

Reply via email to