Fixes gcc.dg/torture/pr91323.c fail for MIPS. Ok for trunk? LTGT should trap for unordered operands (see discussion in bugzilla), but c.ueq does not trap for qNaN. Use c.ngl as it handles non-NaN operands like c.ueq, but traps for qNaN as we want for LTGT.
gcc/ PR target/91323 * config/mips/mips.md (sngl_<mode>_using_cc): New insn pattern for c.ngl.{f,d}. * config/mips/mips.cc (mips_emit_compare): Use c.ngl.{f,d} for LTGT. --- gcc/config/mips/mips.cc | 38 +++++++++++++++++++++++++++++++++----- gcc/config/mips/mips.md | 10 ++++++++++ 2 files changed, 43 insertions(+), 5 deletions(-) diff --git a/gcc/config/mips/mips.cc b/gcc/config/mips/mips.cc index 5010f99f761..77675a57a01 100644 --- a/gcc/config/mips/mips.cc +++ b/gcc/config/mips/mips.cc @@ -5625,6 +5625,7 @@ mips_emit_compare (enum rtx_code *code, rtx *op0, rtx *op1, bool need_eq_ne_p) } else { + bool need_ngl = false; enum rtx_code cmp_code; /* Floating-point tests use a separate C.cond.fmt or CMP.cond.fmt @@ -5643,10 +5644,20 @@ mips_emit_compare (enum rtx_code *code, rtx *op0, rtx *op1, bool need_eq_ne_p) } else { - /* Three FP conditions cannot be implemented by reversing the - operands for C.cond.fmt, instead a reversed condition code is - required and a test for false. */ - *code = mips_reversed_fp_cond (&cmp_code) ? EQ : NE; + /* We'll need a special case. LTGT is not an unordered compare + (PR 91323) so we can't simply use !UNEQ for it. MIPS has + "ngl" (Not Greater than or Less than) condition as a perfect + opposite of LTGT, but we don't have an rtx_code for it. */ + if (cmp_code == LTGT) + { + need_ngl = true; + *code = EQ; + } + else + /* Three FP conditions cannot be implemented by reversing the + operands for C.cond.fmt, instead a reversed condition code + is required and a test for false. */ + *code = mips_reversed_fp_cond (&cmp_code) ? EQ : NE; if (ISA_HAS_8CC) *op0 = mips_allocate_fcc (CCmode); else @@ -5654,7 +5665,24 @@ mips_emit_compare (enum rtx_code *code, rtx *op0, rtx *op1, bool need_eq_ne_p) } *op1 = const0_rtx; - mips_emit_binary (cmp_code, *op0, cmp_op0, cmp_op1); + if (need_ngl) + { + rtx insn; + switch (GET_MODE (cmp_op0)) + { + case SFmode: + insn = gen_sngl_sf_using_cc (*op0, cmp_op0, cmp_op1); + break; + case DFmode: + insn = gen_sngl_df_using_cc (*op0, cmp_op0, cmp_op1); + break; + default: + gcc_unreachable (); + } + emit_insn(insn); + } + else + mips_emit_binary (cmp_code, *op0, cmp_op0, cmp_op1); } } diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md index e0f0a582732..47405f03d7a 100644 --- a/gcc/config/mips/mips.md +++ b/gcc/config/mips/mips.md @@ -6293,6 +6293,16 @@ (define_insn "s<code>_<SCALARF:mode>_using_<FPCC:mode>" "<fpcmp>.<swapped_fcond>.<fmt>\t%Z0%2,%1" [(set_attr "type" "fcmp") (set_attr "mode" "FPSW")]) + +(define_insn "sngl_<SCALARF:mode>_using_cc" + [(set (match_operand:CC 0 "register_operand" "=z") + (eq:CC (const_int 0) + (ltgt:CC (match_operand:SCALARF 1 "register_operand" "f") + (match_operand:SCALARF 2 "register_operand" "f"))))] + "!ISA_HAS_CCF" + "c.ngl.<fmt>\t%Z0%1,%2" + [(set_attr "type" "fcmp") + (set_attr "mode" "FPSW")]) ;; ;; .................... -- 2.35.1