From 3f563e0b55c78c53130d4082da6ba670ec1d9ba5 Mon Sep 17 00:00:00 2001 From: Uros Bizjak Date: Fri, 27 Oct 2017 20:13:14 +0200 Subject: [PATCH] re PR target/82692 (Ordered comparisons used for unordered built-ins) PR target/82692 * config/i386/i386-modes.def (CCFPU): Remove definition. * config/i386/i386.c (put_condition_mode): Remove CCFPU mode handling. (ix86_cc_modes_compatible): Ditto. (ix86_expand_carry_flag_compare): Ditto. (ix86_expand_int_movcc): Ditto. (ix86_expand_int_addcc): Ditto. (ix86_reverse_condition): Ditto. (ix86_unordered_fp_compare): Rename from ix86_fp_compare_mode. Return true/false for unordered/ordered fp comparisons. (ix86_cc_mode): Always return CCFPmode for float mode comparisons. (ix86_prepare_fp_compare_args): Update for rename. (ix86_expand_fp_compare): Update for rename. Generate unordered compare RTXes wrapped with UNSPEC_NOTRAP unspec. (ix86_expand_sse_compare_and_jump): Ditto. * config/i386/predicates.md (fcmov_comparison_operator): Remove CCFPU mode handling. (ix86_comparison_operator): Ditto. (ix86_carry_flag_operator): Ditto. * config/i386/i386.md (UNSPEC_NOTRAP): New unspec. (*cmpu_i387): Wrap compare RTX with UNSPEC_NOTRAP unspec. (*cmpu_cc_i387): Ditto. (FPCMP): Remove mode iterator. (unord): Remove mode attribute. (unord_subst): New define_subst transformation (unord): New define_subst attribute. (unordered): Ditto. (*cmpi): Rewrite using unord_subst transformation. (*cmpixf_i387): Ditto. * config/i386/sse.md (_comi): Merge from _comi and _ucomi using unord_subst transformation. * config/i386/subst.md (SUBST_A): Remove CCFP and CCFPU modes. (round_saeonly): Also handle CCFP mode. * reg-stack.c (subst_stack_regs_pat): Handle UNSPEC_NOTRAP unspec. Remove UNSPEC_SAHF unspec handling. testsuite/ChangeLog: PR target/82692 * gcc.dg/torture/pr82692.c: New test. From-SVN: r254167 --- gcc/ChangeLog | 39 +++++++++++++ gcc/config/i386/i386-modes.def | 2 +- gcc/config/i386/i386.c | 76 +++++++++++++------------ gcc/config/i386/i386.md | 59 +++++++++++-------- gcc/config/i386/predicates.md | 8 +-- gcc/config/i386/sse.md | 24 +------- gcc/config/i386/subst.md | 13 ++++- gcc/reg-stack.c | 34 ++++++----- gcc/testsuite/ChangeLog | 5 ++ gcc/testsuite/gcc.target/i386/pr82692.c | 25 ++++++++ 10 files changed, 177 insertions(+), 108 deletions(-) create mode 100644 gcc/testsuite/gcc.target/i386/pr82692.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e8fa8fce70b..7c3f1e54590 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,42 @@ +2017-10-27 Uros Bizjak + + PR target/82692 + * config/i386/i386-modes.def (CCFPU): Remove definition. + * config/i386/i386.c (put_condition_mode): Remove CCFPU mode handling. + (ix86_cc_modes_compatible): Ditto. + (ix86_expand_carry_flag_compare): Ditto. + (ix86_expand_int_movcc): Ditto. + (ix86_expand_int_addcc): Ditto. + (ix86_reverse_condition): Ditto. + (ix86_unordered_fp_compare): Rename from ix86_fp_compare_mode. + Return true/false for unordered/ordered fp comparisons. + (ix86_cc_mode): Always return CCFPmode for float mode comparisons. + (ix86_prepare_fp_compare_args): Update for rename. + (ix86_expand_fp_compare): Update for rename. Generate unordered + compare RTXes wrapped with UNSPEC_NOTRAP unspec. + (ix86_expand_sse_compare_and_jump): Ditto. + * config/i386/predicates.md (fcmov_comparison_operator): + Remove CCFPU mode handling. + (ix86_comparison_operator): Ditto. + (ix86_carry_flag_operator): Ditto. + * config/i386/i386.md (UNSPEC_NOTRAP): New unspec. + (*cmpu_i387): Wrap compare RTX with UNSPEC_NOTRAP unspec. + (*cmpu_cc_i387): Ditto. + (FPCMP): Remove mode iterator. + (unord): Remove mode attribute. + (unord_subst): New define_subst transformation + (unord): New define_subst attribute. + (unordered): Ditto. + (*cmpi): Rewrite using unord_subst transformation. + (*cmpixf_i387): Ditto. + * config/i386/sse.md (_comi): Merge + from _comi and _ucomi + using unord_subst transformation. + * config/i386/subst.md (SUBST_A): Remove CCFP and CCFPU modes. + (round_saeonly): Also handle CCFP mode. + * reg-stack.c (subst_stack_regs_pat): Handle UNSPEC_NOTRAP unspec. + Remove UNSPEC_SAHF unspec handling. + 2017-10-27 Jan Hubicka * x86-tune.def (X86_TUNE_INTER_UNIT_MOVES_TO_VEC): Disable for Zen. diff --git a/gcc/config/i386/i386-modes.def b/gcc/config/i386/i386-modes.def index 16bc1d8b71a..dcf6854b57d 100644 --- a/gcc/config/i386/i386-modes.def +++ b/gcc/config/i386/i386-modes.def @@ -72,8 +72,8 @@ CC_MODE (CCO); CC_MODE (CCP); CC_MODE (CCS); CC_MODE (CCZ); + CC_MODE (CCFP); -CC_MODE (CCFPU); /* Vector modes. Note that VEC_CONCAT patterns require vector sizes twice as big as implemented in hardware. */ diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 6ee6abea258..8a2e2dac6b7 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -16930,7 +16930,7 @@ put_condition_code (enum rtx_code code, machine_mode mode, bool reverse, { const char *suffix; - if (mode == CCFPmode || mode == CCFPUmode) + if (mode == CCFPmode) { code = ix86_fp_compare_code_to_integer (code); mode = CCmode; @@ -21695,14 +21695,13 @@ ix86_expand_int_compare (enum rtx_code code, rtx op0, rtx op1) return gen_rtx_fmt_ee (code, VOIDmode, flags, const0_rtx); } -/* Figure out whether to use ordered or unordered fp comparisons. - Return the appropriate mode to use. */ +/* Figure out whether to use unordered fp comparisons. */ -machine_mode -ix86_fp_compare_mode (enum rtx_code code) +static bool +ix86_unordered_fp_compare (enum rtx_code code) { if (!TARGET_IEEE_FP) - return CCFPmode; + return false; switch (code) { @@ -21710,7 +21709,7 @@ ix86_fp_compare_mode (enum rtx_code code) case GE: case LT: case LE: - return CCFPmode; + return false; case EQ: case NE: @@ -21723,7 +21722,7 @@ ix86_fp_compare_mode (enum rtx_code code) case UNGT: case UNGE: case UNEQ: - return CCFPUmode; + return true; default: gcc_unreachable (); @@ -21738,7 +21737,7 @@ ix86_cc_mode (enum rtx_code code, rtx op0, rtx op1) if (SCALAR_FLOAT_MODE_P (mode)) { gcc_assert (!DECIMAL_FLOAT_MODE_P (mode)); - return ix86_fp_compare_mode (code); + return CCFPmode; } switch (code) @@ -21860,7 +21859,6 @@ ix86_cc_modes_compatible (machine_mode m1, machine_mode m2) } case E_CCFPmode: - case E_CCFPUmode: /* These are only compatible with themselves, which we already checked above. */ return VOIDmode; @@ -21964,7 +21962,7 @@ ix86_fp_comparison_strategy (enum rtx_code) static enum rtx_code ix86_prepare_fp_compare_args (enum rtx_code code, rtx *pop0, rtx *pop1) { - machine_mode fpcmp_mode = ix86_fp_compare_mode (code); + bool unordered_compare = ix86_unordered_fp_compare (code); rtx op0 = *pop0, op1 = *pop1; machine_mode op_mode = GET_MODE (op0); bool is_sse = TARGET_SSE_MATH && SSE_FLOAT_MODE_P (op_mode); @@ -21976,7 +21974,7 @@ ix86_prepare_fp_compare_args (enum rtx_code code, rtx *pop0, rtx *pop1) floating point. */ if (!is_sse - && (fpcmp_mode == CCFPUmode + && (unordered_compare || (op_mode == XFmode && ! (standard_80387_constant_p (op0) == 1 || standard_80387_constant_p (op1) == 1) @@ -22073,27 +22071,29 @@ ix86_fp_compare_code_to_integer (enum rtx_code code) static rtx ix86_expand_fp_compare (enum rtx_code code, rtx op0, rtx op1, rtx scratch) { - machine_mode fpcmp_mode, intcmp_mode; + bool unordered_compare = ix86_unordered_fp_compare (code); + machine_mode intcmp_mode; rtx tmp, tmp2; - fpcmp_mode = ix86_fp_compare_mode (code); code = ix86_prepare_fp_compare_args (code, &op0, &op1); /* Do fcomi/sahf based test when profitable. */ switch (ix86_fp_comparison_strategy (code)) { case IX86_FPCMP_COMI: - intcmp_mode = fpcmp_mode; - tmp = gen_rtx_COMPARE (fpcmp_mode, op0, op1); - tmp = gen_rtx_SET (gen_rtx_REG (fpcmp_mode, FLAGS_REG), tmp); - emit_insn (tmp); + intcmp_mode = CCFPmode; + tmp = gen_rtx_COMPARE (CCFPmode, op0, op1); + if (unordered_compare) + tmp = gen_rtx_UNSPEC (CCFPmode, gen_rtvec (1, tmp), UNSPEC_NOTRAP); + emit_insn (gen_rtx_SET (gen_rtx_REG (CCFPmode, FLAGS_REG), tmp)); break; case IX86_FPCMP_SAHF: - intcmp_mode = fpcmp_mode; - tmp = gen_rtx_COMPARE (fpcmp_mode, op0, op1); - tmp = gen_rtx_SET (gen_rtx_REG (fpcmp_mode, FLAGS_REG), tmp); - + intcmp_mode = CCFPmode; + tmp = gen_rtx_COMPARE (CCFPmode, op0, op1); + if (unordered_compare) + tmp = gen_rtx_UNSPEC (CCFPmode, gen_rtvec (1, tmp), UNSPEC_NOTRAP); + tmp = gen_rtx_SET (gen_rtx_REG (CCFPmode, FLAGS_REG), tmp); if (!scratch) scratch = gen_reg_rtx (HImode); tmp2 = gen_rtx_CLOBBER (VOIDmode, scratch); @@ -22102,11 +22102,13 @@ ix86_expand_fp_compare (enum rtx_code code, rtx op0, rtx op1, rtx scratch) case IX86_FPCMP_ARITH: /* Sadness wrt reg-stack pops killing fpsr -- gotta get fnstsw first. */ - tmp = gen_rtx_COMPARE (fpcmp_mode, op0, op1); - tmp2 = gen_rtx_UNSPEC (HImode, gen_rtvec (1, tmp), UNSPEC_FNSTSW); + tmp = gen_rtx_COMPARE (CCFPmode, op0, op1); + if (unordered_compare) + tmp = gen_rtx_UNSPEC (CCFPmode, gen_rtvec (1, tmp), UNSPEC_NOTRAP); + tmp = gen_rtx_UNSPEC (HImode, gen_rtvec (1, tmp), UNSPEC_FNSTSW); if (!scratch) scratch = gen_reg_rtx (HImode); - emit_insn (gen_rtx_SET (scratch, tmp2)); + emit_insn (gen_rtx_SET (scratch, tmp)); /* In the unordered case, we have to check C2 for NaN's, which doesn't happen to work out to anything nice combination-wise. @@ -22548,8 +22550,7 @@ ix86_expand_carry_flag_compare (enum rtx_code code, rtx op0, rtx op1, rtx *pop) compare_seq = get_insns (); end_sequence (); - if (GET_MODE (XEXP (compare_op, 0)) == CCFPmode - || GET_MODE (XEXP (compare_op, 0)) == CCFPUmode) + if (GET_MODE (XEXP (compare_op, 0)) == CCFPmode) code = ix86_fp_compare_code_to_integer (GET_CODE (compare_op)); else code = GET_CODE (compare_op); @@ -22689,8 +22690,7 @@ ix86_expand_int_movcc (rtx operands[]) flags = XEXP (compare_op, 0); - if (GET_MODE (flags) == CCFPmode - || GET_MODE (flags) == CCFPUmode) + if (GET_MODE (flags) == CCFPmode) { fpcmp = true; compare_code @@ -24730,8 +24730,7 @@ ix86_expand_int_addcc (rtx operands[]) flags = XEXP (compare_op, 0); - if (GET_MODE (flags) == CCFPmode - || GET_MODE (flags) == CCFPUmode) + if (GET_MODE (flags) == CCFPmode) { fpcmp = true; code = ix86_fp_compare_code_to_integer (code); @@ -43190,7 +43189,7 @@ ix86_encode_section_info (tree decl, rtx rtl, int first) enum rtx_code ix86_reverse_condition (enum rtx_code code, machine_mode mode) { - return (mode != CCFPmode && mode != CCFPUmode + return (mode != CCFPmode ? reverse_condition (code) : reverse_condition_maybe_unordered (code)); } @@ -43805,17 +43804,20 @@ static rtx_code_label * ix86_expand_sse_compare_and_jump (enum rtx_code code, rtx op0, rtx op1, bool swap_operands) { - machine_mode fpcmp_mode = ix86_fp_compare_mode (code); + bool unordered_compare = ix86_unordered_fp_compare (code); rtx_code_label *label; - rtx tmp; + rtx tmp, reg; if (swap_operands) std::swap (op0, op1); label = gen_label_rtx (); - tmp = gen_rtx_REG (fpcmp_mode, FLAGS_REG); - emit_insn (gen_rtx_SET (tmp, gen_rtx_COMPARE (fpcmp_mode, op0, op1))); - tmp = gen_rtx_fmt_ee (code, VOIDmode, tmp, const0_rtx); + tmp = gen_rtx_COMPARE (CCFPmode, op0, op1); + if (unordered_compare) + tmp = gen_rtx_UNSPEC (CCFPmode, gen_rtvec (1, tmp), UNSPEC_NOTRAP); + reg = gen_rtx_REG (CCFPmode, FLAGS_REG); + emit_insn (gen_rtx_SET (reg, tmp)); + tmp = gen_rtx_fmt_ee (code, VOIDmode, reg, const0_rtx); tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp, gen_rtx_LABEL_REF (VOIDmode, label), pc_rtx); tmp = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp)); diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 49ad0394fb5..d48decbb7d9 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -99,6 +99,7 @@ UNSPEC_SCAS UNSPEC_FNSTSW UNSPEC_SAHF + UNSPEC_NOTRAP UNSPEC_PARITY UNSPEC_FSTCW UNSPEC_FLDCW @@ -1478,9 +1479,6 @@ ;; FP compares, step 1: ;; Set the FP condition codes. -;; -;; CCFPmode compare with exceptions -;; CCFPUmode compare with no exceptions ;; We may not use "#" to split and emit these, since the REG_DEAD notes ;; used to manage the reg stack popping would not be preserved. @@ -1587,9 +1585,11 @@ (define_insn "*cmpu_i387" [(set (match_operand:HI 0 "register_operand" "=a") (unspec:HI - [(compare:CCFPU - (match_operand:X87MODEF 1 "register_operand" "f") - (match_operand:X87MODEF 2 "register_operand" "f"))] + [(unspec:CCFP + [(compare:CCFP + (match_operand:X87MODEF 1 "register_operand" "f") + (match_operand:X87MODEF 2 "register_operand" "f"))] + UNSPEC_NOTRAP)] UNSPEC_FNSTSW))] "TARGET_80387" "* return output_fp_compare (insn, operands, false, true);" @@ -1598,18 +1598,22 @@ (set_attr "mode" "")]) (define_insn_and_split "*cmpu_cc_i387" - [(set (reg:CCFPU FLAGS_REG) - (compare:CCFPU - (match_operand:X87MODEF 1 "register_operand" "f") - (match_operand:X87MODEF 2 "register_operand" "f"))) + [(set (reg:CCFP FLAGS_REG) + (unspec:CCFP + [(compare:CCFP + (match_operand:X87MODEF 1 "register_operand" "f") + (match_operand:X87MODEF 2 "register_operand" "f"))] + UNSPEC_NOTRAP)) (clobber (match_operand:HI 0 "register_operand" "=a"))] "TARGET_80387 && TARGET_SAHF && !TARGET_CMOVE" "#" "&& reload_completed" [(set (match_dup 0) (unspec:HI - [(compare:CCFPU (match_dup 1)(match_dup 2))] - UNSPEC_FNSTSW)) + [(unspec:CCFP + [(compare:CCFP (match_dup 1)(match_dup 2))] + UNSPEC_NOTRAP)] + UNSPEC_FNSTSW)) (set (reg:CC FLAGS_REG) (unspec:CC [(match_dup 0)] UNSPEC_SAHF))] "" @@ -1697,20 +1701,28 @@ ;; Pentium Pro can do steps 1 through 3 in one go. ;; (these instructions set flags directly) -(define_mode_iterator FPCMP [CCFP CCFPU]) -(define_mode_attr unord [(CCFP "") (CCFPU "u")]) +(define_subst_attr "unord" "unord_subst" "" "u") +(define_subst_attr "unordered" "unord_subst" "false" "true") + +(define_subst "unord_subst" + [(set (match_operand:CCFP 0) + (match_operand:CCFP 1))] + "" + [(set (match_dup 0) + (unspec:CCFP + [(match_dup 1)] + UNSPEC_NOTRAP))]) -(define_insn "*cmpi" - [(set (reg:FPCMP FLAGS_REG) - (compare:FPCMP +(define_insn "*cmpi" + [(set (reg:CCFP FLAGS_REG) + (compare:CCFP (match_operand:MODEF 0 "register_operand" "f,v") (match_operand:MODEF 1 "register_ssemem_operand" "f,vm")))] "(SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH) || (TARGET_80387 && TARGET_CMOVE)" "@ - * return output_fp_compare (insn, operands, true, \ - mode == CCFPUmode); - %vcomi\t{%1, %0|%0, %1}" + * return output_fp_compare (insn, operands, true, ); + %vcomi\t{%1, %0|%0, %1}" [(set_attr "type" "fcmp,ssecomi") (set_attr "prefix" "orig,maybe_vex") (set_attr "mode" "") @@ -1739,13 +1751,12 @@ (symbol_ref "false"))))]) (define_insn "*cmpixf_i387" - [(set (reg:FPCMP FLAGS_REG) - (compare:FPCMP + [(set (reg:CCFP FLAGS_REG) + (compare:CCFP (match_operand:XF 0 "register_operand" "f") (match_operand:XF 1 "register_operand" "f")))] "TARGET_80387 && TARGET_CMOVE" - "* return output_fp_compare (insn, operands, true, - mode == CCFPUmode);" + "* return output_fp_compare (insn, operands, true, );" [(set_attr "type" "fcmp") (set_attr "mode" "XF") (set_attr "athlon_decode" "vector") diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md index 89df15ac55c..be9be85a3f2 100644 --- a/gcc/config/i386/predicates.md +++ b/gcc/config/i386/predicates.md @@ -1301,7 +1301,7 @@ machine_mode inmode = GET_MODE (XEXP (op, 0)); enum rtx_code code = GET_CODE (op); - if (inmode == CCFPmode || inmode == CCFPUmode) + if (inmode == CCFPmode) { if (!ix86_trivial_fp_comparison_operator (op, mode)) return false; @@ -1311,7 +1311,7 @@ switch (code) { case LTU: case GTU: case LEU: case GEU: - if (inmode == CCmode || inmode == CCFPmode || inmode == CCFPUmode + if (inmode == CCmode || inmode == CCFPmode || inmode == CCCmode) return true; return false; @@ -1348,7 +1348,7 @@ machine_mode inmode = GET_MODE (XEXP (op, 0)); enum rtx_code code = GET_CODE (op); - if (inmode == CCFPmode || inmode == CCFPUmode) + if (inmode == CCFPmode) return ix86_trivial_fp_comparison_operator (op, mode); switch (code) @@ -1391,7 +1391,7 @@ machine_mode inmode = GET_MODE (XEXP (op, 0)); enum rtx_code code = GET_CODE (op); - if (inmode == CCFPmode || inmode == CCFPUmode) + if (inmode == CCFPmode) { if (!ix86_trivial_fp_comparison_operator (op, mode)) return false; diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md index fe3cb1791ad..56275155544 100644 --- a/gcc/config/i386/sse.md +++ b/gcc/config/i386/sse.md @@ -2755,7 +2755,7 @@ (set_attr "prefix" "evex") (set_attr "mode" "")]) -(define_insn "_comi" +(define_insn "_comi" [(set (reg:CCFP FLAGS_REG) (compare:CCFP (vec_select:MODEF @@ -2765,27 +2765,7 @@ (match_operand: 1 "" "") (parallel [(const_int 0)]))))] "SSE_FLOAT_MODE_P (mode)" - "%vcomi\t{%1, %0|%0, %1}" - [(set_attr "type" "ssecomi") - (set_attr "prefix" "maybe_vex") - (set_attr "prefix_rep" "0") - (set (attr "prefix_data16") - (if_then_else (eq_attr "mode" "DF") - (const_string "1") - (const_string "0"))) - (set_attr "mode" "")]) - -(define_insn "_ucomi" - [(set (reg:CCFPU FLAGS_REG) - (compare:CCFPU - (vec_select:MODEF - (match_operand: 0 "register_operand" "v") - (parallel [(const_int 0)])) - (vec_select:MODEF - (match_operand: 1 "" "") - (parallel [(const_int 0)]))))] - "SSE_FLOAT_MODE_P (mode)" - "%vucomi\t{%1, %0|%0, %1}" + "%vcomi\t{%1, %0|%0, %1}" [(set_attr "type" "ssecomi") (set_attr "prefix" "maybe_vex") (set_attr "prefix_rep" "0") diff --git a/gcc/config/i386/subst.md b/gcc/config/i386/subst.md index c93a5263435..d9100c8d6b0 100644 --- a/gcc/config/i386/subst.md +++ b/gcc/config/i386/subst.md @@ -37,8 +37,7 @@ V8DI V4DI V2DI V16SF V8SF V4SF V8DF V4DF V2DF - QI HI SI DI SF DF - CCFP CCFPU]) + QI HI SI DI SF DF]) (define_subst_attr "mask_name" "mask" "" "_mask") (define_subst_attr "mask_applied" "mask" "false" "true") @@ -183,6 +182,16 @@ UNSPEC_EMBEDDED_ROUNDING)) ]) +(define_subst "round_saeonly" + [(set (match_operand:CCFP 0) + (match_operand:CCFP 1))] + "TARGET_AVX512F" + [(set (match_dup 0) + (unspec:CCFP [(match_dup 1) + (match_operand:SI 2 "const48_operand")] + UNSPEC_EMBEDDED_ROUNDING)) +]) + (define_subst_attr "round_expand_name" "round_expand" "" "_round") (define_subst_attr "round_expand_nimm_predicate" "round_expand" "nonimmediate_operand" "register_operand") (define_subst_attr "round_expand_operand" "round_expand" "" ", operands[5]") diff --git a/gcc/reg-stack.c b/gcc/reg-stack.c index 62f7d7b9653..83fc4762671 100644 --- a/gcc/reg-stack.c +++ b/gcc/reg-stack.c @@ -1560,12 +1560,6 @@ subst_stack_regs_pat (rtx_insn *insn, stack_ptr regstack, rtx pat) switch (GET_CODE (pat_src)) { - case COMPARE: - /* `fcomi' insn can't pop two regs. */ - compare_for_stack_reg (insn, regstack, pat_src, - REGNO (*dest) != FLAGS_REG); - break; - case CALL: { int count; @@ -1966,31 +1960,35 @@ subst_stack_regs_pat (rtx_insn *insn, stack_ptr regstack, rtx pat) replace_reg (src2, FIRST_STACK_REG + 1); break; - case UNSPEC_SAHF: - /* (unspec [(unspec [(compare)] UNSPEC_FNSTSW)] UNSPEC_SAHF) - The combination matches the PPRO fcomi instruction. */ - - pat_src = XVECEXP (pat_src, 0, 0); - gcc_assert (GET_CODE (pat_src) == UNSPEC); - gcc_assert (XINT (pat_src, 1) == UNSPEC_FNSTSW); - /* Fall through. */ - case UNSPEC_FNSTSW: /* Combined fcomp+fnstsw generated for doing well with CSE. When optimizing this would have been broken up before now. */ pat_src = XVECEXP (pat_src, 0, 0); - gcc_assert (GET_CODE (pat_src) == COMPARE); + if (GET_CODE (pat_src) == COMPARE) + goto do_compare; - compare_for_stack_reg (insn, regstack, pat_src, true); - break; + /* Fall through. */ + + case UNSPEC_NOTRAP: + + pat_src = XVECEXP (pat_src, 0, 0); + gcc_assert (GET_CODE (pat_src) == COMPARE); + goto do_compare; default: gcc_unreachable (); } break; + case COMPARE: + do_compare: + /* `fcomi' insn can't pop two regs. */ + compare_for_stack_reg (insn, regstack, pat_src, + REGNO (*dest) != FLAGS_REG); + break; + case IF_THEN_ELSE: /* This insn requires the top of stack to be the destination. */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index b8dac7e625a..f227e7ec36f 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2017-10-27 Uros Bizjak + + PR target/82692 + * gcc.dg/torture/pr82692.c: New test. + 2017-10-27 Will Schmidt * gcc.target/powerpc/fold-vec-neg-char.c: New. diff --git a/gcc/testsuite/gcc.target/i386/pr82692.c b/gcc/testsuite/gcc.target/i386/pr82692.c new file mode 100644 index 00000000000..7f16804c196 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr82692.c @@ -0,0 +1,25 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ +/* { dg-require-effective-target fenv_exceptions } */ + +#include + +extern void abort (void); +extern void exit (int); + +double __attribute__ ((noinline, noclone)) +foo (double x) +{ + if (__builtin_islessequal (x, 0.0) || __builtin_isgreater (x, 1.0)) + return x + x; + return x * x; +} + +int +main (void) +{ + volatile double x = foo (__builtin_nan ("")); + if (fetestexcept (FE_INVALID)) + abort (); + exit (0); +} -- 2.30.2