https://gcc.gnu.org/g:1335fcb077113c83f9eb4b40b996be41bee80a74

commit 1335fcb077113c83f9eb4b40b996be41bee80a74
Author: Michael Meissner <meiss...@linux.ibm.com>
Date:   Fri Jan 24 15:06:52 2025 -0500

    Fix PR 118541, do not generate unordered fp cmoves.
    
    2025-01-24  Michael Meissner  <meiss...@linux.ibm.com>
    
    gcc/
    
            PR target/118541
            * config/rs6000/rs6000-protos.h (REVERSE_COND_ORDERED_OK): New 
macro.
            (REVERSE_COND_NO_ORDERED): Likewise.
            (rs6000_reverse_condition): Add argument.
            * config/rs6000/rs6000.cc (rs6000_reverse_condition): Do not allow
            ordered comparisons to be reversed for floating point cmoves.
            (rs6000_emit_sCOND): Adjust rs6000_reverse_condition call.
            * config/rs6000/rs6000.h (REVERSE_CONDITION): Likewise.
            * config/rs6000/rs6000.md (reverse_branch_comparison): Name insn.
            Adjust rs6000_reverse_condition call.
    
    gcc/testsuite/
    
            PR target/118541
            * gcc.target/powerpc/pr118541.c: New test.

Diff:
---
 gcc/config/rs6000/rs6000-protos.h           |  6 ++++-
 gcc/config/rs6000/rs6000.cc                 | 23 ++++++++++++----
 gcc/config/rs6000/rs6000.h                  | 10 +++++--
 gcc/config/rs6000/rs6000.md                 | 24 ++++++++++-------
 gcc/testsuite/gcc.target/powerpc/pr118541.c | 42 +++++++++++++++++++++++++++++
 5 files changed, 88 insertions(+), 17 deletions(-)

diff --git a/gcc/config/rs6000/rs6000-protos.h 
b/gcc/config/rs6000/rs6000-protos.h
index 4619142d197b..112332660d3b 100644
--- a/gcc/config/rs6000/rs6000-protos.h
+++ b/gcc/config/rs6000/rs6000-protos.h
@@ -114,8 +114,12 @@ extern const char *rs6000_sibcall_template (rtx *, 
unsigned int);
 extern const char *rs6000_indirect_call_template (rtx *, unsigned int);
 extern const char *rs6000_indirect_sibcall_template (rtx *, unsigned int);
 extern const char *rs6000_pltseq_template (rtx *, int);
+
+#define REVERSE_COND_ORDERED_OK        false
+#define REVERSE_COND_NO_ORDERED        true
+
 extern enum rtx_code rs6000_reverse_condition (machine_mode,
-                                              enum rtx_code);
+                                              enum rtx_code, bool);
 extern rtx rs6000_emit_eqne (machine_mode, rtx, rtx, rtx);
 extern rtx rs6000_emit_fp_cror (rtx_code, machine_mode, rtx);
 extern void rs6000_emit_sCOND (machine_mode, rtx[]);
diff --git a/gcc/config/rs6000/rs6000.cc b/gcc/config/rs6000/rs6000.cc
index f9f9a0b931db..eaf79435ec32 100644
--- a/gcc/config/rs6000/rs6000.cc
+++ b/gcc/config/rs6000/rs6000.cc
@@ -15360,15 +15360,25 @@ rs6000_print_patchable_function_entry (FILE *file,
 }
 
 enum rtx_code
-rs6000_reverse_condition (machine_mode mode, enum rtx_code code)
+rs6000_reverse_condition (machine_mode mode,
+                         enum rtx_code code,
+                         bool no_ordered)
 {
   /* Reversal of FP compares takes care -- an ordered compare
-     becomes an unordered compare and vice versa.  */
+     becomes an unordered compare and vice versa.
+
+     However, this is not safe for ordered comparisons (i.e. for isgreater,
+     etc.)  starting with the power9 because ifcvt.cc will want to create a fp
+     cmove, and the x{s,v}cmp{eq,gt,ge}{dp,qp} instructions will trap if one of
+     the arguments is a signalling NaN.  */
+
   if (mode == CCFPmode
       && (!flag_finite_math_only
          || code == UNLT || code == UNLE || code == UNGT || code == UNGE
          || code == UNEQ || code == LTGT))
-    return reverse_condition_maybe_unordered (code);
+    return (no_ordered
+           ? UNKNOWN
+           : reverse_condition_maybe_unordered (code));
   else
     return reverse_condition (code);
 }
@@ -15980,11 +15990,14 @@ rs6000_emit_sCOND (machine_mode mode, rtx operands[])
       rtx not_result = gen_reg_rtx (CCEQmode);
       rtx not_op, rev_cond_rtx;
       machine_mode cc_mode;
+      enum rtx_code rev;
 
       cc_mode = GET_MODE (XEXP (condition_rtx, 0));
 
-      rev_cond_rtx = gen_rtx_fmt_ee (rs6000_reverse_condition (cc_mode, 
cond_code),
-                                    SImode, XEXP (condition_rtx, 0), 
const0_rtx);
+      rev = rs6000_reverse_condition (cc_mode, cond_code,
+                                     REVERSE_COND_ORDERED_OK);
+      rev_cond_rtx = gen_rtx_fmt_ee (rev, SImode, XEXP (condition_rtx, 0),
+                                    const0_rtx);
       not_op = gen_rtx_COMPARE (CCEQmode, rev_cond_rtx, const0_rtx);
       emit_insn (gen_rtx_SET (not_result, not_op));
       condition_rtx = gen_rtx_EQ (VOIDmode, not_result, const0_rtx);
diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h
index ec08c96d0f67..c595d7138bcd 100644
--- a/gcc/config/rs6000/rs6000.h
+++ b/gcc/config/rs6000/rs6000.h
@@ -1812,11 +1812,17 @@ extern scalar_int_mode rs6000_pmode;
 
 /* Can the condition code MODE be safely reversed?  This is safe in
    all cases on this port, because at present it doesn't use the
-   trapping FP comparisons (fcmpo).  */
+   trapping FP comparisons (fcmpo).
+
+   However, this is not safe for ordered comparisons (i.e. for isgreater, etc.)
+   starting with the power9 because ifcvt.cc will want to create a fp cmove,
+   and the x{s,v}cmp{eq,gt,ge}{dp,qp} instructions will trap if one of the
+   arguments is a signalling NaN.  */
 #define REVERSIBLE_CC_MODE(MODE) 1
 
 /* Given a condition code and a mode, return the inverse condition.  */
-#define REVERSE_CONDITION(CODE, MODE) rs6000_reverse_condition (MODE, CODE)
+#define REVERSE_CONDITION(CODE, MODE) \
+  rs6000_reverse_condition (MODE, CODE, REVERSE_COND_NO_ORDERED)
 
 
 /* Target cpu costs.  */
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index 65da0c653304..5f7ff36617da 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -13497,7 +13497,7 @@
 ;; If we are comparing the result of two comparisons, this can be done
 ;; using creqv or crxor.
 
-(define_insn_and_split ""
+(define_insn_and_split "*reverse_branch_comparison"
   [(set (match_operand:CCEQ 0 "cc_reg_operand" "=y")
        (compare:CCEQ (match_operator 1 "branch_comparison_operator"
                              [(match_operand 2 "cc_reg_operand" "y")
@@ -13519,19 +13519,25 @@
                                                    GET_MODE (operands[3]));
 
   if (! positive_1)
-    operands[1] = gen_rtx_fmt_ee (rs6000_reverse_condition (GET_MODE 
(operands[2]),
-                                                           GET_CODE 
(operands[1])),
-                                 SImode,
-                                 operands[2], const0_rtx);
+    {
+      enum rtx_code rev = rs6000_reverse_condition (GET_MODE (operands[2]),
+                                                   GET_CODE (operands[1]),
+                                                   REVERSE_COND_ORDERED_OK);
+      gcc_assert (rev != UNKNOWN);
+      operands[1] = gen_rtx_fmt_ee (rev, SImode, operands[2], const0_rtx);
+    }
   else if (GET_MODE (operands[1]) != SImode)
     operands[1] = gen_rtx_fmt_ee (GET_CODE (operands[1]), SImode,
                                  operands[2], const0_rtx);
 
   if (! positive_2)
-    operands[3] = gen_rtx_fmt_ee (rs6000_reverse_condition (GET_MODE 
(operands[4]),
-                                                           GET_CODE 
(operands[3])),
-                                 SImode,
-                                 operands[4], const0_rtx);
+    {
+      enum rtx_code rev = rs6000_reverse_condition (GET_MODE (operands[4]),
+                                                   GET_CODE (operands[3]),
+                                                   REVERSE_COND_ORDERED_OK);
+      gcc_assert (rev != UNKNOWN);
+      operands[3] = gen_rtx_fmt_ee (rev, SImode, operands[4], const0_rtx);
+    }
   else if (GET_MODE (operands[3]) != SImode)
     operands[3] = gen_rtx_fmt_ee (GET_CODE (operands[3]), SImode,
                                  operands[4], const0_rtx);
diff --git a/gcc/testsuite/gcc.target/powerpc/pr118541.c 
b/gcc/testsuite/gcc.target/powerpc/pr118541.c
new file mode 100644
index 000000000000..a89224020fdb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr118541.c
@@ -0,0 +1,42 @@
+/* { dg-do compile } */
+/* { dg-options "-mdejagnu-cpu=power9 -O2" } */
+
+/* PR target/118541 says that the ordered comparison functions like isgreater
+   should not optimize floating point conditional moves to use
+   x{s,v}cmp{eq,gt,ge}{dp,qp} and xxsel since that instruction can cause traps
+   if one of the arguments is a signaling NaN.  */
+
+/* Verify isgreater does not generate xscmpgtdp.  */
+
+double
+ordered_compare (double a, double b, double c, double d)
+{
+  /*
+   * fcmpu 0,1,2
+   * fmr   1,4
+   * bnglr 0
+   * fmr   1,3
+   * blr
+   */
+
+  return __builtin_isgreater (a, b) ? c : d;
+}
+
+/* Verify normal > does generate xscmpgtdp.  */
+
+double
+normal_compare (double a, double b, double c, double d)
+{
+  /*
+   * xscmpgtdp 1,1,2
+   * xxsel     1,4,3,1
+   * blr
+   */
+
+  return a > b ? c : d;
+}
+
+/* { dg-final { scan-assembler-times {\mxscmpg[te]dp\M} }  1 } */
+/* { dg-final { scan-assembler-times {\mxxsel} }           1 } */
+/* { dg-final { scan-assembler-times {\mxscmpudp\|fcmpu\M} 1 } */
+

Reply via email to