https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100736
HaoChen Gui <guihaoc at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |guihaoc at gcc dot gnu.org --- Comment #2 from HaoChen Gui <guihaoc at gcc dot gnu.org> --- The root cause of the issue is condition rtx can't be recognized when finite-math-only is set. I drafted a patch to modify expand of "bcd<bcd_add_sub>_<code>_<mode>". It expands as before when finite-math-only is not set. While it expands with a reverse comparison(le -> ungt, ge -> unlt) when finite-math-only is set. "rs6000_reverse_compare" is a helper method. The code is extracted from "rs6000_emit_sCOND". Any comments? Thanks a lot. diff --git a/gcc/config/rs6000/altivec.md b/gcc/config/rs6000/altivec.md index 93d237156d5..e91a1af6805 100644 --- a/gcc/config/rs6000/altivec.md +++ b/gcc/config/rs6000/altivec.md @@ -4415,7 +4415,7 @@ (define_insn "bcd<bcd_add_sub>_<mode>" ;; UNORDERED test on an integer type (like V1TImode) is not defined. The type ;; probably should be one that can go in the VMX (Altivec) registers, so we ;; can't use DDmode or DFmode. -(define_insn "*bcd<bcd_add_sub>_test_<mode>" +(define_insn "bcd<bcd_add_sub>_test_<mode>" [(set (reg:CCFP CR6_REGNO) (compare:CCFP (unspec:V2DF [(match_operand:VBCD 1 "register_operand" "v") @@ -4542,6 +4542,18 @@ (define_expand "bcd<bcd_add_sub>_<code>_<mode>" "TARGET_P8_VECTOR" { operands[4] = CONST0_RTX (V2DFmode); + emit_insn (gen_bcd<bcd_add_sub>_test_<mode> (operands[0], operands[1], + operands[2], operands[3], + operands[4])); + rtx cr6 = gen_rtx_REG (CCFPmode, CR6_REGNO); + rtx condition_rtx = gen_rtx_<CODE> (SImode, cr6, const0_rtx); + if (flag_finite_math_only) + { + condition_rtx = rs6000_reverse_compare (condition_rtx); + PUT_MODE (condition_rtx, SImode); + } + emit_insn (gen_rtx_SET (operands[0], condition_rtx)); + DONE; }) (define_insn "*bcdinvalid_<mode>" diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h index 14f6b313105..9b93e26bec2 100644 --- a/gcc/config/rs6000/rs6000-protos.h +++ b/gcc/config/rs6000/rs6000-protos.h @@ -114,6 +114,7 @@ extern enum rtx_code rs6000_reverse_condition (machine_mode, 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[]); +extern rtx rs6000_reverse_compare (rtx); extern void rs6000_emit_cbranch (machine_mode, rtx[]); extern char * output_cbranch (rtx, const char *, int, rtx_insn *); extern const char * output_probe_stack_range (rtx, rtx, rtx); diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index ad860728169..39a36add08f 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -15690,19 +15690,14 @@ rs6000_emit_fp_cror (rtx_code code, machine_mode mode, rtx x) return cc; } -void -rs6000_emit_sCOND (machine_mode mode, rtx operands[]) +rtx +rs6000_reverse_compare (rtx condition_rtx) { - rtx condition_rtx = rs6000_generate_compare (operands[1], mode); rtx_code cond_code = GET_CODE (condition_rtx); - - if (FLOAT_MODE_P (mode) && HONOR_NANS (mode) - && !(FLOAT128_VECTOR_P (mode) && !TARGET_FLOAT128_HW)) - ; - else if (cond_code == NE - || cond_code == GE || cond_code == LE - || cond_code == GEU || cond_code == LEU - || cond_code == ORDERED || cond_code == UNGE || cond_code == UNLE) + if (cond_code == NE + || cond_code == GE || cond_code == LE + || cond_code == GEU || cond_code == LEU + || cond_code == ORDERED || cond_code == UNGE || cond_code == UNLE) { rtx not_result = gen_reg_rtx (CCEQmode); rtx not_op, rev_cond_rtx; @@ -15716,6 +15711,19 @@ rs6000_emit_sCOND (machine_mode mode, rtx operands[]) emit_insn (gen_rtx_SET (not_result, not_op)); condition_rtx = gen_rtx_EQ (VOIDmode, not_result, const0_rtx); } + return condition_rtx; +} + +void +rs6000_emit_sCOND (machine_mode mode, rtx operands[]) +{ + rtx condition_rtx = rs6000_generate_compare (operands[1], mode); + + if (FLOAT_MODE_P (mode) && HONOR_NANS (mode) + && !(FLOAT128_VECTOR_P (mode) && !TARGET_FLOAT128_HW)) + ; + else + condition_rtx = rs6000_reverse_compare (condition_rtx); machine_mode op_mode = GET_MODE (XEXP (operands[1], 0)); if (op_mode == VOIDmode)