* [PATCH, i386]: Fix PR 82692, Ordered comparisons used for unordered built-ins
@ 2017-10-27 18:30 Uros Bizjak
0 siblings, 0 replies; only message in thread
From: Uros Bizjak @ 2017-10-27 18:30 UTC (permalink / raw)
To: gcc-patches; +Cc: Segher Boessenkool, Joseph S. Myers, H. J. Lu
[-- Attachment #1: Type: text/plain, Size: 2549 bytes --]
Hello!
As discussed in the PR, different modes of a FP compare RTX are not
strong enough to survive through RTL optimization passes. Attached
testcase was miscompiled due to combine changing the mode of FP
compare through SELECT_CC_MODE.
The solution, implemented in the attached patch, is to drop CCFPUmode
(which was used to distinguish unordered and ordered compares) and use
UNSPEC_NOTRAP unspec wrappers around compare RTXes for unordered
comparisons.
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.
testsuite/ChangeLog:
2017-10-27 Uros Bizjak <ubizjak@gmail.com>
PR target/82692
* gcc.dg/torture/pr82692.c: New test.
Patch was bootstrapped and regression tested on x86_64-linux-gnu {,-m32}.
Committed to mainline SVN.
Uros.
[-- Attachment #2: p.diff.txt --]
[-- Type: text/plain, Size: 18592 bytes --]
Index: config/i386/i386-modes.def
===================================================================
--- config/i386/i386-modes.def (revision 254111)
+++ config/i386/i386-modes.def (working copy)
@@ -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. */
Index: config/i386/i386.c
===================================================================
--- config/i386/i386.c (revision 254111)
+++ config/i386/i386.c (working copy)
@@ -16930,7 +16930,7 @@ put_condition_code (enum rtx_code code, machine_mo
{
const char *suffix;
- if (mode == CCFPmode || mode == CCFPUmode)
+ if (mode == CCFPmode)
{
code = ix86_fp_compare_code_to_integer (code);
mode = CCmode;
@@ -21709,14 +21709,13 @@ ix86_expand_int_compare (enum rtx_code code, rtx o
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)
{
@@ -21724,7 +21723,7 @@ ix86_expand_int_compare (enum rtx_code code, rtx o
case GE:
case LT:
case LE:
- return CCFPmode;
+ return false;
case EQ:
case NE:
@@ -21737,7 +21736,7 @@ ix86_expand_int_compare (enum rtx_code code, rtx o
case UNGT:
case UNGE:
case UNEQ:
- return CCFPUmode;
+ return true;
default:
gcc_unreachable ();
@@ -21752,7 +21751,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)
@@ -21874,7 +21873,6 @@ ix86_cc_modes_compatible (machine_mode m1, machine
}
case E_CCFPmode:
- case E_CCFPUmode:
/* These are only compatible with themselves, which we already
checked above. */
return VOIDmode;
@@ -21978,7 +21976,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);
@@ -21990,7 +21988,7 @@ ix86_prepare_fp_compare_args (enum rtx_code code,
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)
@@ -22087,10 +22085,10 @@ ix86_fp_compare_code_to_integer (enum rtx_code cod
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. */
@@ -22097,17 +22095,19 @@ ix86_expand_fp_compare (enum rtx_code code, rtx op
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);
@@ -22116,11 +22116,13 @@ ix86_expand_fp_compare (enum rtx_code code, rtx op
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.
@@ -22562,8 +22564,7 @@ ix86_expand_carry_flag_compare (enum rtx_code code
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);
@@ -22703,8 +22704,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
@@ -24744,8 +24744,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);
@@ -43208,7 +43207,7 @@ ix86_encode_section_info (tree decl, rtx rtl, int
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));
}
@@ -43823,17 +43822,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));
Index: config/i386/i386.md
===================================================================
--- config/i386/i386.md (revision 254111)
+++ config/i386/i386.md (working copy)
@@ -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,10 +1598,12 @@
(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"
"#"
@@ -1608,8 +1610,10 @@
"&& 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_insn "*cmpi<FPCMP:unord><MODEF:mode>"
- [(set (reg:FPCMP FLAGS_REG)
- (compare:FPCMP
+(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<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")
Index: config/i386/predicates.md
===================================================================
--- config/i386/predicates.md (revision 254111)
+++ config/i386/predicates.md (working copy)
@@ -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;
Index: config/i386/sse.md
===================================================================
--- config/i386/sse.md (revision 254111)
+++ config/i386/sse.md (working copy)
@@ -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,7 +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>}"
+ "%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")
@@ -2775,26 +2775,6 @@
(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>}"
- [(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_expand "vec_cmp<mode><avx512fmaskmodelower>"
[(set (match_operand:<avx512fmaskmode> 0 "register_operand")
(match_operator:<avx512fmaskmode> 1 ""
Index: config/i386/subst.md
===================================================================
--- config/i386/subst.md (revision 254111)
+++ config/i386/subst.md (working copy)
@@ -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]")
Index: reg-stack.c
===================================================================
--- reg-stack.c (revision 254111)
+++ reg-stack.c (working copy)
@@ -1560,12 +1560,6 @@ subst_stack_regs_pat (rtx_insn *insn, stack_ptr re
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,15 +1960,6 @@ subst_stack_regs_pat (rtx_insn *insn, stack_ptr re
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
@@ -1981,16 +1966,29 @@ subst_stack_regs_pat (rtx_insn *insn, stack_ptr re
up before now. */
pat_src = XVECEXP (pat_src, 0, 0);
+ if (GET_CODE (pat_src) == COMPARE)
+ goto do_compare;
+
+ /* Fall through. */
+
+ case UNSPEC_NOTRAP:
+
+ pat_src = XVECEXP (pat_src, 0, 0);
gcc_assert (GET_CODE (pat_src) == COMPARE);
+ goto do_compare;
- compare_for_stack_reg (insn, regstack, pat_src, true);
- break;
-
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. */
Index: testsuite/gcc.target/i386/pr82692.c
===================================================================
--- testsuite/gcc.target/i386/pr82692.c (nonexistent)
+++ testsuite/gcc.target/i386/pr82692.c (working copy)
@@ -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);
+}
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2017-10-27 18:22 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-10-27 18:30 [PATCH, i386]: Fix PR 82692, Ordered comparisons used for unordered built-ins Uros Bizjak
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).