https://gcc.gnu.org/g:bba9b39a793faf48f2e6cf04289b1e48190b127f
commit bba9b39a793faf48f2e6cf04289b1e48190b127f Author: Michael Meissner <meiss...@linux.ibm.com> Date: Fri Jan 24 10:50:35 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 (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): Likewise. Diff: --- gcc/config/rs6000/rs6000-protos.h | 2 +- gcc/config/rs6000/rs6000.cc | 19 +++++++++++++++---- gcc/config/rs6000/rs6000.h | 10 ++++++++-- gcc/config/rs6000/rs6000.md | 24 +++++++++++++++--------- 4 files changed, 39 insertions(+), 16 deletions(-) diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h index 4619142d197b..8f790d261d9a 100644 --- a/gcc/config/rs6000/rs6000-protos.h +++ b/gcc/config/rs6000/rs6000-protos.h @@ -115,7 +115,7 @@ 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); 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..276e2f886acc 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); } @@ -15983,7 +15993,8 @@ rs6000_emit_sCOND (machine_mode mode, rtx operands[]) cc_mode = GET_MODE (XEXP (condition_rtx, 0)); - rev_cond_rtx = gen_rtx_fmt_ee (rs6000_reverse_condition (cc_mode, cond_code), + rev_cond_rtx = gen_rtx_fmt_ee (rs6000_reverse_condition (cc_mode, cond_code, + false), 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)); diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h index ec08c96d0f67..98228ee5ac16 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, true) /* Target cpu costs. */ diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index 65da0c653304..cf4b10257903 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]), + false); + 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]), + false); + 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);