aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorUros Bizjak <ubizjak@gmail.com>2017-10-27 20:13:14 +0200
committerUros Bizjak <uros@gcc.gnu.org>2017-10-27 20:13:14 +0200
commit3f563e0b55c78c53130d4082da6ba670ec1d9ba5 (patch)
tree5af560de442226cf7a9e26e94255a1d408a4f722 /gcc
parent68d1c4bfd74adad56b748125cd463940928e09da (diff)
downloadgcc-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/ChangeLog39
-rw-r--r--gcc/config/i386/i386-modes.def2
-rw-r--r--gcc/config/i386/i386.c76
-rw-r--r--gcc/config/i386/i386.md59
-rw-r--r--gcc/config/i386/predicates.md8
-rw-r--r--gcc/config/i386/sse.md24
-rw-r--r--gcc/config/i386/subst.md13
-rw-r--r--gcc/reg-stack.c34
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.target/i386/pr82692.c25
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);
+}