https://gcc.gnu.org/g:9d68161c958ee4a460e450663d1f1096d37dc40a
commit 9d68161c958ee4a460e450663d1f1096d37dc40a Author: Michael Meissner <meiss...@linux.ibm.com> Date: Thu Jan 23 17:04:12 2025 -0500 Fix PR 118541, do not generate unordered fp cmoves. 2025-01-23 Michael Meissner <meiss...@linux.ibm.com> gcc/ PR target/118541 * config/rs6000/rs6000.cc (rs6000_reverse_condition): Do not allow unordered floating point comparisons to be reversed if signaling NaNs are a possibility. (rs6000_maybe_emit_fp_cmove): Likewise. (rs6000_emit_cmove): Likewise. Diff: --- gcc/config/rs6000/rs6000.cc | 54 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 49 insertions(+), 5 deletions(-) diff --git a/gcc/config/rs6000/rs6000.cc b/gcc/config/rs6000/rs6000.cc index f9f9a0b931db..6c218ac7d6f6 100644 --- a/gcc/config/rs6000/rs6000.cc +++ b/gcc/config/rs6000/rs6000.cc @@ -15362,13 +15362,20 @@ rs6000_print_patchable_function_entry (FILE *file, enum rtx_code rs6000_reverse_condition (machine_mode mode, enum rtx_code code) { - /* Reversal of FP compares takes care -- an ordered compare - becomes an unordered compare and vice versa. */ + /* Reversal of FP compares takes care -- Do not allow an ordered compare to + become an unordered compare if signaling NaNs are possible, since the + unordered compare may trap. This happens on power9 when ?: is converted + into a cmove. The xscmp{eq,gt,ge}{dp,qp} instructions will trap on a + signalling NaN. */ if (mode == CCFPmode - && (!flag_finite_math_only - || code == UNLT || code == UNLE || code == UNGT || code == UNGE + && (code == UNLT || code == UNLE || code == UNGT || code == UNGE || code == UNEQ || code == LTGT)) - return reverse_condition_maybe_unordered (code); + { + if (!flag_finite_math_only || flag_signaling_nans) + return UNKNOWN; + + return reverse_condition_maybe_unordered (code); + } else return reverse_condition (code); } @@ -16439,6 +16446,24 @@ rs6000_maybe_emit_fp_cmove (rtx dest, rtx op, rtx true_cond, rtx false_cond) if (!can_create_pseudo_p ()) return 0; + /* Don't optimize comparisons with explicit unordered support (like + isgreater), since the fpmask VSX instructions can generate an error with a + signaling NaN. */ + if (!flag_finite_math_only || flag_signaling_nans) + switch (code) + { + case LTGT: + case UNGE: + case UNGT: + case UNEQ: + case UNLE: + case UNLT: + return false; + + default: + break; + } + /* We allow the comparison to be either SFmode/DFmode and the true/false condition to be either SFmode/DFmode. I.e. we allow: @@ -16551,6 +16576,25 @@ rs6000_emit_cmove (rtx dest, rtx op, rtx true_cond, rtx false_cond) if (GET_MODE (false_cond) != result_mode) return false; + /* Don't allow optimizing comparisons with explicit unordered support (like + isgreater), since the fpmask VSX instructions can generate an error with a + signaling NaN. */ + if (FLOAT_MODE_P (compare_mode) + && (!flag_finite_math_only || flag_signaling_nans)) + switch (code) + { + case LTGT: + case UNGE: + case UNGT: + case UNEQ: + case UNLE: + case UNLT: + return false; + + default: + break; + } + /* See if we can use the "C" minimum, "C" maximum, and compare and set mask instructions. */ if (have_compare_and_set_mask (compare_mode)