diff options
author | Uros Bizjak <ubizjak@gmail.com> | 2017-10-27 20:13:14 +0200 |
---|---|---|
committer | Uros Bizjak <uros@gcc.gnu.org> | 2017-10-27 20:13:14 +0200 |
commit | 3f563e0b55c78c53130d4082da6ba670ec1d9ba5 (patch) | |
tree | 5af560de442226cf7a9e26e94255a1d408a4f722 /gcc | |
parent | 68d1c4bfd74adad56b748125cd463940928e09da (diff) | |
download | gcc-3f563e0b55c78c53130d4082da6ba670ec1d9ba5.zip gcc-3f563e0b55c78c53130d4082da6ba670ec1d9ba5.tar.gz gcc-3f563e0b55c78c53130d4082da6ba670ec1d9ba5.tar.bz2 |
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<mode>_i387): Wrap compare RTX with UNSPEC_NOTRAP unspec.
(*cmpu<mode>_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<unord><MODEF:mode>): Rewrite using unord_subst transformation.
(*cmpi<unord>xf_i387): Ditto.
* config/i386/sse.md (<sse>_<unord>comi<round_saeonly_name>): Merge
from <sse>_comi<round_saeonly_name> and <sse>_ucomi<round_saeonly_name>
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 39 | ||||
-rw-r--r-- | gcc/config/i386/i386-modes.def | 2 | ||||
-rw-r--r-- | gcc/config/i386/i386.c | 76 | ||||
-rw-r--r-- | gcc/config/i386/i386.md | 59 | ||||
-rw-r--r-- | gcc/config/i386/predicates.md | 8 | ||||
-rw-r--r-- | gcc/config/i386/sse.md | 24 | ||||
-rw-r--r-- | gcc/config/i386/subst.md | 13 | ||||
-rw-r--r-- | gcc/reg-stack.c | 34 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/pr82692.c | 25 |
10 files changed, 177 insertions, 108 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e8fa8fc..7c3f1e5 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,42 @@ +2017-10-27 Uros Bizjak <ubizjak@gmail.com> + + 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<mode>_i387): Wrap compare RTX with UNSPEC_NOTRAP unspec. + (*cmpu<mode>_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<unord><MODEF:mode>): Rewrite using unord_subst transformation. + (*cmpi<unord>xf_i387): Ditto. + * config/i386/sse.md (<sse>_<unord>comi<round_saeonly_name>): Merge + from <sse>_comi<round_saeonly_name> and <sse>_ucomi<round_saeonly_name> + 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 <hubicka@ucw.cz> * 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 16bc1d8..dcf6854 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 6ee6abe..8a2e2da 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 49ad039..d48decb 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<mode>_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" "<MODE>")]) (define_insn_and_split "*cmpu<mode>_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<FPCMP:unord><MODEF:mode>" - [(set (reg:FPCMP FLAGS_REG) - (compare:FPCMP +(define_insn "*cmpi<unord><MODEF:mode>" + [(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 (<MODEF:MODE>mode) && TARGET_SSE_MATH) || (TARGET_80387 && TARGET_CMOVE)" "@ - * return output_fp_compare (insn, operands, true, \ - <FPCMP:MODE>mode == CCFPUmode); - %v<FPCMP:unord>comi<MODEF:ssemodesuffix>\t{%1, %0|%0, %1}" + * return output_fp_compare (insn, operands, true, <unordered>); + %v<unord>comi<MODEF:ssemodesuffix>\t{%1, %0|%0, %1}" [(set_attr "type" "fcmp,ssecomi") (set_attr "prefix" "orig,maybe_vex") (set_attr "mode" "<MODEF:MODE>") @@ -1739,13 +1751,12 @@ (symbol_ref "false"))))]) (define_insn "*cmpi<unord>xf_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>mode == CCFPUmode);" + "* return output_fp_compare (insn, operands, true, <unordered>);" [(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 89df15a..be9be85 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 fe3cb17..5627515 100644 --- a/gcc/config/i386/sse.md +++ b/gcc/config/i386/sse.md @@ -2755,7 +2755,7 @@ (set_attr "prefix" "evex") (set_attr "mode" "<sseinsnmode>")]) -(define_insn "<sse>_comi<round_saeonly_name>" +(define_insn "<sse>_<unord>comi<round_saeonly_name>" [(set (reg:CCFP FLAGS_REG) (compare:CCFP (vec_select:MODEF @@ -2765,27 +2765,7 @@ (match_operand:<ssevecmode> 1 "<round_saeonly_nimm_scalar_predicate>" "<round_saeonly_constraint>") (parallel [(const_int 0)]))))] "SSE_FLOAT_MODE_P (<MODE>mode)" - "%vcomi<ssemodesuffix>\t{<round_saeonly_op2>%1, %0|%0, %<iptr>1<round_saeonly_op2>}" - [(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" "<MODE>")]) - -(define_insn "<sse>_ucomi<round_saeonly_name>" - [(set (reg:CCFPU FLAGS_REG) - (compare:CCFPU - (vec_select:MODEF - (match_operand:<ssevecmode> 0 "register_operand" "v") - (parallel [(const_int 0)])) - (vec_select:MODEF - (match_operand:<ssevecmode> 1 "<round_saeonly_nimm_scalar_predicate>" "<round_saeonly_constraint>") - (parallel [(const_int 0)]))))] - "SSE_FLOAT_MODE_P (<MODE>mode)" - "%vucomi<ssemodesuffix>\t{<round_saeonly_op2>%1, %0|%0, %<iptr>1<round_saeonly_op2>}" + "%v<unord>comi<ssemodesuffix>\t{<round_saeonly_op2>%1, %0|%0, %<iptr>1<round_saeonly_op2>}" [(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 c93a526..d9100c8 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 62f7d7b..83fc476 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 b8dac7e..f227e7e 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2017-10-27 Uros Bizjak <ubizjak@gmail.com> + + PR target/82692 + * gcc.dg/torture/pr82692.c: New test. + 2017-10-27 Will Schmidt <will_schmidt@vnet.ibm.com> * 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 0000000..7f16804 --- /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 <fenv.h> + +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); +} |