Commit eaa49b49 by Richard Henderson Committed by Richard Henderson

re PR target/19009 (Loading of FP constants into FP reg via SSE reg)

        PR target/19099
        PR target/19250
        PR target/19252
        * config/i386/i386.md (cmpdf, cmpsf, bunordered, bordered, buneq,
        bunge, bungt, bunle, bunlt, bltgt): Enable for TARGET_SSE_MATH,
        not just TARGET_SSE.
        (cmpfp_i_387): Rename from cmpfp_i.  Move after sse patterns.
        (cmpfp_i_mixed): Rename from cmpfp_i_sse; use for TARGET_MIX_SSE_I387.
        (cmpfp_i_sse): Rename from cmpfp_i_sse_only; use for TARGET_SSE_MATH.
        (cmpfp_iu_mixed, cmpfp_iu_sse, cmpfp_iu_387): Similarly.
        (fp_jcc_1_mixed, fp_jcc_1_sse, fp_jcc_1_387): Similarly.
        (fp_jcc_2_mixed, fp_jcc_2_sse, fp_jcc_2_387): Similarly.
        (fp_jcc_3_387, fp_jcc_4_387, fp_jcc_5_387, fp_jcc_6_387,
        fp_jcc_7_387, fp_jcc_8_387): Rename from fp_jcc_N.
        (movdicc_c_rex64): Rename with '*'.
        (movsfcc, movdfcc): Add checks for 387 and sse math to condition.
        (movsfcc_1_sse_min, movsfcc_1_sse_max, movsfcc_1_sse): New.
        (movsfcc_1_387): Rename from movsfcc_1.
        (movdfcc_1_sse_min, movdfcc_1_sse_max, movdfcc_1_sse): New.
        (movdfcc_1, movdfcc_1_rex64): Add check for 387.
        (sminsf3, smaxsf3, smindf3, smaxdf3): New.
        (minsf3, minsf, minsf_nonieee, minsf_sse, mindf3, mindf,
        mindf_nonieee, mindf_sse, maxsf3, maxsf, maxsf_nonieee, maxsf_sse,
        maxdf3, maxdf, maxdf_nonieee, maxdf_sse, sse_movsfcc, sse_movsfcc_eq,
        sse_movdfcc, sse_movdfcc_eq, sse_movsfcc_const0_1,
        sse_movsfcc_const0_2, sse_movsfcc_const0_3, sse_movsfcc_const0_4,
        sse_movdfcc_const0_1, sse_movdfcc_const0_2, sse_movdfcc_const0_3,
        sse_movdfcc_const0_4): Remove.
        * config/i386/i386.c (ix86_expand_fp_movcc): For TARGET_SSE_MATH,
        recognize min/max early.  Update for changed sse cmove patterns.
        (ix86_split_sse_movcc): New.
        * config/i386/i386-protos.h: Update.

From-SVN: r93620
parent 997e120f
2005-01-13 Richard Henderson <rth@redhat.com>
PR target/19099
PR target/19250
PR target/19252
* config/i386/i386.md (cmpdf, cmpsf, bunordered, bordered, buneq,
bunge, bungt, bunle, bunlt, bltgt): Enable for TARGET_SSE_MATH,
not just TARGET_SSE.
(cmpfp_i_387): Rename from cmpfp_i. Move after sse patterns.
(cmpfp_i_mixed): Rename from cmpfp_i_sse; use for TARGET_MIX_SSE_I387.
(cmpfp_i_sse): Rename from cmpfp_i_sse_only; use for TARGET_SSE_MATH.
(cmpfp_iu_mixed, cmpfp_iu_sse, cmpfp_iu_387): Similarly.
(fp_jcc_1_mixed, fp_jcc_1_sse, fp_jcc_1_387): Similarly.
(fp_jcc_2_mixed, fp_jcc_2_sse, fp_jcc_2_387): Similarly.
(fp_jcc_3_387, fp_jcc_4_387, fp_jcc_5_387, fp_jcc_6_387,
fp_jcc_7_387, fp_jcc_8_387): Rename from fp_jcc_N.
(movdicc_c_rex64): Rename with '*'.
(movsfcc, movdfcc): Add checks for 387 and sse math to condition.
(movsfcc_1_sse_min, movsfcc_1_sse_max, movsfcc_1_sse): New.
(movsfcc_1_387): Rename from movsfcc_1.
(movdfcc_1_sse_min, movdfcc_1_sse_max, movdfcc_1_sse): New.
(movdfcc_1, movdfcc_1_rex64): Add check for 387.
(sminsf3, smaxsf3, smindf3, smaxdf3): New.
(minsf3, minsf, minsf_nonieee, minsf_sse, mindf3, mindf,
mindf_nonieee, mindf_sse, maxsf3, maxsf, maxsf_nonieee, maxsf_sse,
maxdf3, maxdf, maxdf_nonieee, maxdf_sse, sse_movsfcc, sse_movsfcc_eq,
sse_movdfcc, sse_movdfcc_eq, sse_movsfcc_const0_1,
sse_movsfcc_const0_2, sse_movsfcc_const0_3, sse_movsfcc_const0_4,
sse_movdfcc_const0_1, sse_movdfcc_const0_2, sse_movdfcc_const0_3,
sse_movdfcc_const0_4): Remove.
* config/i386/i386.c (ix86_expand_fp_movcc): For TARGET_SSE_MATH,
recognize min/max early. Update for changed sse cmove patterns.
(ix86_split_sse_movcc): New.
* config/i386/i386-protos.h: Update.
2005-01-13 Steven Bosscher <stevenb@suse.de> 2005-01-13 Steven Bosscher <stevenb@suse.de>
* tree-ssa-dse.c (fix_phi_uses): Use SSA operand iterators. * tree-ssa-dse.c (fix_phi_uses): Use SSA operand iterators.
......
...@@ -145,6 +145,7 @@ extern void ix86_expand_branch (enum rtx_code, rtx); ...@@ -145,6 +145,7 @@ extern void ix86_expand_branch (enum rtx_code, rtx);
extern int ix86_expand_setcc (enum rtx_code, rtx); extern int ix86_expand_setcc (enum rtx_code, rtx);
extern int ix86_expand_int_movcc (rtx[]); extern int ix86_expand_int_movcc (rtx[]);
extern int ix86_expand_fp_movcc (rtx[]); extern int ix86_expand_fp_movcc (rtx[]);
extern void ix86_split_sse_movcc (rtx[]);
extern int ix86_expand_int_addcc (rtx[]); extern int ix86_expand_int_addcc (rtx[]);
extern void ix86_expand_call (rtx, rtx, rtx, rtx, rtx, int); extern void ix86_expand_call (rtx, rtx, rtx, rtx, rtx, int);
extern void x86_initialize_trampoline (rtx, rtx, rtx); extern void x86_initialize_trampoline (rtx, rtx, rtx);
......
...@@ -9743,118 +9743,95 @@ ix86_expand_int_movcc (rtx operands[]) ...@@ -9743,118 +9743,95 @@ ix86_expand_int_movcc (rtx operands[])
int int
ix86_expand_fp_movcc (rtx operands[]) ix86_expand_fp_movcc (rtx operands[])
{ {
enum rtx_code code; enum machine_mode mode = GET_MODE (operands[0]);
rtx tmp; enum rtx_code code = GET_CODE (operands[1]);
rtx compare_op, second_test, bypass_test; rtx tmp, compare_op, second_test, bypass_test;
/* For SF/DFmode conditional moves based on comparisons if (TARGET_SSE_MATH && SSE_FLOAT_MODE_P (mode))
in same mode, we may want to use SSE min/max instructions. */ {
if (((TARGET_SSE_MATH && GET_MODE (operands[0]) == SFmode) rtx cmp_op0, cmp_op1, if_true, if_false;
|| (TARGET_SSE2 && TARGET_SSE_MATH && GET_MODE (operands[0]) == DFmode)) rtx clob;
&& GET_MODE (ix86_compare_op0) == GET_MODE (operands[0]) enum machine_mode vmode, cmode;
/* The SSE comparisons does not support the LTGT/UNEQ pair. */ bool is_minmax = false;
&& (!TARGET_IEEE_FP
|| (GET_CODE (operands[1]) != LTGT && GET_CODE (operands[1]) != UNEQ)) cmp_op0 = ix86_compare_op0;
/* We may be called from the post-reload splitter. */ cmp_op1 = ix86_compare_op1;
&& (!REG_P (operands[0]) if_true = operands[2];
|| SSE_REG_P (operands[0]) if_false = operands[3];
|| REGNO (operands[0]) >= FIRST_PSEUDO_REGISTER))
{ /* Since we've no cmove for sse registers, don't force bad register
rtx op0 = ix86_compare_op0, op1 = ix86_compare_op1; allocation just to gain access to it. Deny movcc when the
code = GET_CODE (operands[1]); comparison mode doesn't match the move mode. */
cmode = GET_MODE (cmp_op0);
/* See if we have (cross) match between comparison operands and if (cmode == VOIDmode)
conditional move operands. */ cmode = GET_MODE (cmp_op1);
if (rtx_equal_p (operands[2], op1)) if (cmode != mode)
return 0;
/* Massage condition to satisfy sse_comparison_operator. In case we
are in non-ieee mode, try to canonicalize the destination operand
to be first in the comparison - this helps reload to avoid extra
moves. */
if (!sse_comparison_operator (operands[1], VOIDmode)
|| ((COMMUTATIVE_P (operands[1]) || !TARGET_IEEE_FP)
&& rtx_equal_p (operands[0], cmp_op1)))
{ {
rtx tmp = op0; tmp = cmp_op0;
op0 = op1; cmp_op0 = cmp_op1;
op1 = tmp; cmp_op1 = tmp;
code = reverse_condition_maybe_unordered (code); code = swap_condition (code);
} }
if (rtx_equal_p (operands[2], op0) && rtx_equal_p (operands[3], op1))
{ /* Detect conditional moves that exactly match min/max operational
/* Check for min operation. */ semantics. Note that this is IEEE safe, as long as we don't
if (code == LT || code == UNLE) interchange the operands. Which is why we keep this in the form
{ if an IF_THEN_ELSE instead of reducing to SMIN/SMAX. */
if (code == UNLE) if ((code == LT || code == UNGE) && REG_P (cmp_op0) && REG_P (cmp_op1))
{ {
rtx tmp = op0; if (((cmp_op0 == if_true && cmp_op1 == if_false)
op0 = op1; || (cmp_op0 == if_false && cmp_op1 == if_true)))
op1 = tmp;
}
operands[0] = force_reg (GET_MODE (operands[0]), operands[0]);
if (memory_operand (op0, VOIDmode))
op0 = force_reg (GET_MODE (operands[0]), op0);
if (GET_MODE (operands[0]) == SFmode)
emit_insn (gen_minsf3 (operands[0], op0, op1));
else
emit_insn (gen_mindf3 (operands[0], op0, op1));
return 1;
}
/* Check for max operation. */
if (code == GT || code == UNGE)
{ {
is_minmax = true;
if (code == UNGE) if (code == UNGE)
{ {
rtx tmp = op0; code = LT;
op0 = op1; tmp = if_true;
op1 = tmp; if_true = if_false;
if_false = tmp;
} }
operands[0] = force_reg (GET_MODE (operands[0]), operands[0]);
if (memory_operand (op0, VOIDmode))
op0 = force_reg (GET_MODE (operands[0]), op0);
if (GET_MODE (operands[0]) == SFmode)
emit_insn (gen_maxsf3 (operands[0], op0, op1));
else
emit_insn (gen_maxdf3 (operands[0], op0, op1));
return 1;
} }
} }
/* Manage condition to be sse_comparison_operator. In case we are
in non-ieee mode, try to canonicalize the destination operand if (mode == SFmode)
to be first in the comparison - this helps reload to avoid extra vmode = V4SFmode;
moves. */ else if (mode == DFmode)
if (!sse_comparison_operator (operands[1], VOIDmode) vmode = V2DFmode;
|| (rtx_equal_p (operands[0], ix86_compare_op1) && !TARGET_IEEE_FP)) else
gcc_unreachable ();
cmp_op0 = force_reg (mode, cmp_op0);
if (!nonimmediate_operand (cmp_op1, mode))
cmp_op1 = force_reg (mode, cmp_op1);
tmp = gen_rtx_fmt_ee (code, mode, cmp_op0, cmp_op1);
gcc_assert (sse_comparison_operator (tmp, VOIDmode));
tmp = gen_rtx_IF_THEN_ELSE (mode, tmp, if_true, if_false);
tmp = gen_rtx_SET (VOIDmode, operands[0], tmp);
if (!is_minmax)
{ {
rtx tmp = ix86_compare_op0; clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (vmode));
ix86_compare_op0 = ix86_compare_op1; tmp = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, tmp, clob));
ix86_compare_op1 = tmp;
operands[1] = gen_rtx_fmt_ee (swap_condition (GET_CODE (operands[1])),
VOIDmode, ix86_compare_op0,
ix86_compare_op1);
}
/* Similarly try to manage result to be first operand of conditional
move. We also don't support the NE comparison on SSE, so try to
avoid it. */
if ((rtx_equal_p (operands[0], operands[3])
&& (!TARGET_IEEE_FP || GET_CODE (operands[1]) != EQ))
|| (GET_CODE (operands[1]) == NE && TARGET_IEEE_FP))
{
rtx tmp = operands[2];
operands[2] = operands[3];
operands[3] = tmp;
operands[1] = gen_rtx_fmt_ee (reverse_condition_maybe_unordered
(GET_CODE (operands[1])),
VOIDmode, ix86_compare_op0,
ix86_compare_op1);
} }
if (GET_MODE (operands[0]) == SFmode)
emit_insn (gen_sse_movsfcc (operands[0], operands[1], emit_insn (tmp);
operands[2], operands[3],
ix86_compare_op0, ix86_compare_op1));
else
emit_insn (gen_sse_movdfcc (operands[0], operands[1],
operands[2], operands[3],
ix86_compare_op0, ix86_compare_op1));
return 1; return 1;
} }
/* The floating point conditional move instructions don't directly /* The floating point conditional move instructions don't directly
support conditions resulting from a signed integer comparison. */ support conditions resulting from a signed integer comparison. */
code = GET_CODE (operands[1]);
compare_op = ix86_expand_compare (code, &second_test, &bypass_test); compare_op = ix86_expand_compare (code, &second_test, &bypass_test);
/* The floating point conditional move instructions don't directly /* The floating point conditional move instructions don't directly
...@@ -9873,38 +9850,86 @@ ix86_expand_fp_movcc (rtx operands[]) ...@@ -9873,38 +9850,86 @@ ix86_expand_fp_movcc (rtx operands[])
} }
if (bypass_test && reg_overlap_mentioned_p (operands[0], operands[3])) if (bypass_test && reg_overlap_mentioned_p (operands[0], operands[3]))
{ {
tmp = gen_reg_rtx (GET_MODE (operands[0])); tmp = gen_reg_rtx (mode);
emit_move_insn (tmp, operands[3]); emit_move_insn (tmp, operands[3]);
operands[3] = tmp; operands[3] = tmp;
} }
if (second_test && reg_overlap_mentioned_p (operands[0], operands[2])) if (second_test && reg_overlap_mentioned_p (operands[0], operands[2]))
{ {
tmp = gen_reg_rtx (GET_MODE (operands[0])); tmp = gen_reg_rtx (mode);
emit_move_insn (tmp, operands[2]); emit_move_insn (tmp, operands[2]);
operands[2] = tmp; operands[2] = tmp;
} }
emit_insn (gen_rtx_SET (VOIDmode, operands[0], emit_insn (gen_rtx_SET (VOIDmode, operands[0],
gen_rtx_IF_THEN_ELSE (GET_MODE (operands[0]), gen_rtx_IF_THEN_ELSE (mode, compare_op,
compare_op, operands[2], operands[3])));
operands[2],
operands[3])));
if (bypass_test) if (bypass_test)
emit_insn (gen_rtx_SET (VOIDmode, operands[0], emit_insn (gen_rtx_SET (VOIDmode, operands[0],
gen_rtx_IF_THEN_ELSE (GET_MODE (operands[0]), gen_rtx_IF_THEN_ELSE (mode, bypass_test,
bypass_test, operands[3], operands[0])));
operands[3],
operands[0])));
if (second_test) if (second_test)
emit_insn (gen_rtx_SET (VOIDmode, operands[0], emit_insn (gen_rtx_SET (VOIDmode, operands[0],
gen_rtx_IF_THEN_ELSE (GET_MODE (operands[0]), gen_rtx_IF_THEN_ELSE (mode, second_test,
second_test, operands[2], operands[0])));
operands[2],
operands[0])));
return 1; return 1;
} }
void
ix86_split_sse_movcc (rtx operands[])
{
rtx dest, scratch, cmp, op_true, op_false, x;
enum machine_mode mode, vmode;
/* Note that the operator CMP has been set up with matching constraints
such that dest is valid for the comparison. Unless one of the true
or false operands are zero, the true operand has already been placed
in SCRATCH. */
dest = operands[0];
scratch = operands[1];
op_true = operands[2];
op_false = operands[3];
cmp = operands[4];
mode = GET_MODE (dest);
vmode = GET_MODE (scratch);
emit_insn (gen_rtx_SET (VOIDmode, dest, cmp));
dest = simplify_gen_subreg (vmode, dest, mode, 0);
if (op_false == CONST0_RTX (mode))
{
op_true = simplify_gen_subreg (vmode, op_true, mode, 0);
x = gen_rtx_AND (vmode, dest, op_true);
emit_insn (gen_rtx_SET (VOIDmode, dest, x));
}
else
{
op_false = simplify_gen_subreg (vmode, op_false, mode, 0);
if (op_true == CONST0_RTX (mode))
{
x = gen_rtx_NOT (vmode, dest);
x = gen_rtx_AND (vmode, x, op_false);
emit_insn (gen_rtx_SET (VOIDmode, dest, x));
}
else
{
x = gen_rtx_AND (vmode, scratch, dest);
emit_insn (gen_rtx_SET (VOIDmode, scratch, x));
x = gen_rtx_NOT (vmode, dest);
x = gen_rtx_AND (vmode, x, op_false);
emit_insn (gen_rtx_SET (VOIDmode, dest, x));
x = gen_rtx_IOR (vmode, dest, scratch);
emit_insn (gen_rtx_SET (VOIDmode, dest, x));
}
}
}
/* Expand conditional increment or decrement using adb/sbb instructions. /* Expand conditional increment or decrement using adb/sbb instructions.
The default case using setcc followed by the conditional move can be The default case using setcc followed by the conditional move can be
done by generic code. */ done by generic code. */
......
...@@ -774,7 +774,7 @@ ...@@ -774,7 +774,7 @@
[(set (reg:CC FLAGS_REG) [(set (reg:CC FLAGS_REG)
(compare:CC (match_operand:DF 0 "cmp_fp_expander_operand" "") (compare:CC (match_operand:DF 0 "cmp_fp_expander_operand" "")
(match_operand:DF 1 "cmp_fp_expander_operand" "")))] (match_operand:DF 1 "cmp_fp_expander_operand" "")))]
"TARGET_80387 || TARGET_SSE2" "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)"
{ {
ix86_compare_op0 = operands[0]; ix86_compare_op0 = operands[0];
ix86_compare_op1 = operands[1]; ix86_compare_op1 = operands[1];
...@@ -785,7 +785,7 @@ ...@@ -785,7 +785,7 @@
[(set (reg:CC FLAGS_REG) [(set (reg:CC FLAGS_REG)
(compare:CC (match_operand:SF 0 "cmp_fp_expander_operand" "") (compare:CC (match_operand:SF 0 "cmp_fp_expander_operand" "")
(match_operand:SF 1 "cmp_fp_expander_operand" "")))] (match_operand:SF 1 "cmp_fp_expander_operand" "")))]
"TARGET_80387 || TARGET_SSE" "TARGET_80387 || TARGET_SSE_MATH"
{ {
ix86_compare_op0 = operands[0]; ix86_compare_op0 = operands[0];
ix86_compare_op1 = operands[1]; ix86_compare_op1 = operands[1];
...@@ -935,30 +935,11 @@ ...@@ -935,30 +935,11 @@
;; Pentium Pro can do steps 1 through 3 in one go. ;; Pentium Pro can do steps 1 through 3 in one go.
(define_insn "*cmpfp_i" (define_insn "*cmpfp_i_mixed"
[(set (reg:CCFP FLAGS_REG)
(compare:CCFP (match_operand 0 "register_operand" "f")
(match_operand 1 "register_operand" "f")))]
"TARGET_80387 && TARGET_CMOVE
&& !SSE_FLOAT_MODE_P (GET_MODE (operands[0]))
&& FLOAT_MODE_P (GET_MODE (operands[0]))
&& GET_MODE (operands[0]) == GET_MODE (operands[1])"
"* return output_fp_compare (insn, operands, 1, 0);"
[(set_attr "type" "fcmp")
(set (attr "mode")
(cond [(match_operand:SF 1 "" "")
(const_string "SF")
(match_operand:DF 1 "" "")
(const_string "DF")
]
(const_string "XF")))
(set_attr "athlon_decode" "vector")])
(define_insn "*cmpfp_i_sse"
[(set (reg:CCFP FLAGS_REG) [(set (reg:CCFP FLAGS_REG)
(compare:CCFP (match_operand 0 "register_operand" "f#x,x#f") (compare:CCFP (match_operand 0 "register_operand" "f#x,x#f")
(match_operand 1 "nonimmediate_operand" "f#x,xm#f")))] (match_operand 1 "nonimmediate_operand" "f#x,xm#f")))]
"TARGET_80387 "TARGET_MIX_SSE_I387
&& SSE_FLOAT_MODE_P (GET_MODE (operands[0])) && SSE_FLOAT_MODE_P (GET_MODE (operands[0]))
&& GET_MODE (operands[0]) == GET_MODE (operands[1])" && GET_MODE (operands[0]) == GET_MODE (operands[1])"
"* return output_fp_compare (insn, operands, 1, 0);" "* return output_fp_compare (insn, operands, 1, 0);"
...@@ -969,11 +950,12 @@ ...@@ -969,11 +950,12 @@
(const_string "DF"))) (const_string "DF")))
(set_attr "athlon_decode" "vector")]) (set_attr "athlon_decode" "vector")])
(define_insn "*cmpfp_i_sse_only" (define_insn "*cmpfp_i_sse"
[(set (reg:CCFP FLAGS_REG) [(set (reg:CCFP FLAGS_REG)
(compare:CCFP (match_operand 0 "register_operand" "x") (compare:CCFP (match_operand 0 "register_operand" "x")
(match_operand 1 "nonimmediate_operand" "xm")))] (match_operand 1 "nonimmediate_operand" "xm")))]
"SSE_FLOAT_MODE_P (GET_MODE (operands[0])) "TARGET_SSE_MATH
&& SSE_FLOAT_MODE_P (GET_MODE (operands[0]))
&& GET_MODE (operands[0]) == GET_MODE (operands[1])" && GET_MODE (operands[0]) == GET_MODE (operands[1])"
"* return output_fp_compare (insn, operands, 1, 0);" "* return output_fp_compare (insn, operands, 1, 0);"
[(set_attr "type" "ssecomi") [(set_attr "type" "ssecomi")
...@@ -983,15 +965,15 @@ ...@@ -983,15 +965,15 @@
(const_string "DF"))) (const_string "DF")))
(set_attr "athlon_decode" "vector")]) (set_attr "athlon_decode" "vector")])
(define_insn "*cmpfp_iu" (define_insn "*cmpfp_i_i387"
[(set (reg:CCFPU FLAGS_REG) [(set (reg:CCFP FLAGS_REG)
(compare:CCFPU (match_operand 0 "register_operand" "f") (compare:CCFP (match_operand 0 "register_operand" "f")
(match_operand 1 "register_operand" "f")))] (match_operand 1 "register_operand" "f")))]
"TARGET_80387 && TARGET_CMOVE "TARGET_80387 && TARGET_CMOVE
&& !SSE_FLOAT_MODE_P (GET_MODE (operands[0])) && (!TARGET_SSE_MATH || !SSE_FLOAT_MODE_P (GET_MODE (operands[0])))
&& FLOAT_MODE_P (GET_MODE (operands[0])) && FLOAT_MODE_P (GET_MODE (operands[0]))
&& GET_MODE (operands[0]) == GET_MODE (operands[1])" && GET_MODE (operands[0]) == GET_MODE (operands[1])"
"* return output_fp_compare (insn, operands, 1, 1);" "* return output_fp_compare (insn, operands, 1, 0);"
[(set_attr "type" "fcmp") [(set_attr "type" "fcmp")
(set (attr "mode") (set (attr "mode")
(cond [(match_operand:SF 1 "" "") (cond [(match_operand:SF 1 "" "")
...@@ -1002,11 +984,11 @@ ...@@ -1002,11 +984,11 @@
(const_string "XF"))) (const_string "XF")))
(set_attr "athlon_decode" "vector")]) (set_attr "athlon_decode" "vector")])
(define_insn "*cmpfp_iu_sse" (define_insn "*cmpfp_iu_mixed"
[(set (reg:CCFPU FLAGS_REG) [(set (reg:CCFPU FLAGS_REG)
(compare:CCFPU (match_operand 0 "register_operand" "f#x,x#f") (compare:CCFPU (match_operand 0 "register_operand" "f#x,x#f")
(match_operand 1 "nonimmediate_operand" "f#x,xm#f")))] (match_operand 1 "nonimmediate_operand" "f#x,xm#f")))]
"TARGET_80387 "TARGET_MIX_SSE_I387
&& SSE_FLOAT_MODE_P (GET_MODE (operands[0])) && SSE_FLOAT_MODE_P (GET_MODE (operands[0]))
&& GET_MODE (operands[0]) == GET_MODE (operands[1])" && GET_MODE (operands[0]) == GET_MODE (operands[1])"
"* return output_fp_compare (insn, operands, 1, 1);" "* return output_fp_compare (insn, operands, 1, 1);"
...@@ -1017,11 +999,12 @@ ...@@ -1017,11 +999,12 @@
(const_string "DF"))) (const_string "DF")))
(set_attr "athlon_decode" "vector")]) (set_attr "athlon_decode" "vector")])
(define_insn "*cmpfp_iu_sse_only" (define_insn "*cmpfp_iu_sse"
[(set (reg:CCFPU FLAGS_REG) [(set (reg:CCFPU FLAGS_REG)
(compare:CCFPU (match_operand 0 "register_operand" "x") (compare:CCFPU (match_operand 0 "register_operand" "x")
(match_operand 1 "nonimmediate_operand" "xm")))] (match_operand 1 "nonimmediate_operand" "xm")))]
"SSE_FLOAT_MODE_P (GET_MODE (operands[0])) "TARGET_SSE_MATH
&& SSE_FLOAT_MODE_P (GET_MODE (operands[0]))
&& GET_MODE (operands[0]) == GET_MODE (operands[1])" && GET_MODE (operands[0]) == GET_MODE (operands[1])"
"* return output_fp_compare (insn, operands, 1, 1);" "* return output_fp_compare (insn, operands, 1, 1);"
[(set_attr "type" "ssecomi") [(set_attr "type" "ssecomi")
...@@ -1031,6 +1014,25 @@ ...@@ -1031,6 +1014,25 @@
(const_string "DF"))) (const_string "DF")))
(set_attr "athlon_decode" "vector")]) (set_attr "athlon_decode" "vector")])
(define_insn "*cmpfp_iu_387"
[(set (reg:CCFPU FLAGS_REG)
(compare:CCFPU (match_operand 0 "register_operand" "f")
(match_operand 1 "register_operand" "f")))]
"TARGET_80387 && TARGET_CMOVE
&& (!TARGET_SSE_MATH || !SSE_FLOAT_MODE_P (GET_MODE (operands[0])))
&& FLOAT_MODE_P (GET_MODE (operands[0]))
&& GET_MODE (operands[0]) == GET_MODE (operands[1])"
"* return output_fp_compare (insn, operands, 1, 1);"
[(set_attr "type" "fcmp")
(set (attr "mode")
(cond [(match_operand:SF 1 "" "")
(const_string "SF")
(match_operand:DF 1 "" "")
(const_string "DF")
]
(const_string "XF")))
(set_attr "athlon_decode" "vector")])
;; Move instructions. ;; Move instructions.
;; General case of fullword move. ;; General case of fullword move.
...@@ -12683,7 +12685,7 @@ ...@@ -12683,7 +12685,7 @@
(if_then_else (match_dup 1) (if_then_else (match_dup 1)
(label_ref (match_operand 0 "" "")) (label_ref (match_operand 0 "" ""))
(pc)))] (pc)))]
"TARGET_80387 || TARGET_SSE" "TARGET_80387 || TARGET_SSE_MATH"
"ix86_expand_branch (UNORDERED, operands[0]); DONE;") "ix86_expand_branch (UNORDERED, operands[0]); DONE;")
(define_expand "bordered" (define_expand "bordered"
...@@ -12691,7 +12693,7 @@ ...@@ -12691,7 +12693,7 @@
(if_then_else (match_dup 1) (if_then_else (match_dup 1)
(label_ref (match_operand 0 "" "")) (label_ref (match_operand 0 "" ""))
(pc)))] (pc)))]
"TARGET_80387 || TARGET_SSE" "TARGET_80387 || TARGET_SSE_MATH"
"ix86_expand_branch (ORDERED, operands[0]); DONE;") "ix86_expand_branch (ORDERED, operands[0]); DONE;")
(define_expand "buneq" (define_expand "buneq"
...@@ -12699,7 +12701,7 @@ ...@@ -12699,7 +12701,7 @@
(if_then_else (match_dup 1) (if_then_else (match_dup 1)
(label_ref (match_operand 0 "" "")) (label_ref (match_operand 0 "" ""))
(pc)))] (pc)))]
"TARGET_80387 || TARGET_SSE" "TARGET_80387 || TARGET_SSE_MATH"
"ix86_expand_branch (UNEQ, operands[0]); DONE;") "ix86_expand_branch (UNEQ, operands[0]); DONE;")
(define_expand "bunge" (define_expand "bunge"
...@@ -12707,7 +12709,7 @@ ...@@ -12707,7 +12709,7 @@
(if_then_else (match_dup 1) (if_then_else (match_dup 1)
(label_ref (match_operand 0 "" "")) (label_ref (match_operand 0 "" ""))
(pc)))] (pc)))]
"TARGET_80387 || TARGET_SSE" "TARGET_80387 || TARGET_SSE_MATH"
"ix86_expand_branch (UNGE, operands[0]); DONE;") "ix86_expand_branch (UNGE, operands[0]); DONE;")
(define_expand "bungt" (define_expand "bungt"
...@@ -12715,7 +12717,7 @@ ...@@ -12715,7 +12717,7 @@
(if_then_else (match_dup 1) (if_then_else (match_dup 1)
(label_ref (match_operand 0 "" "")) (label_ref (match_operand 0 "" ""))
(pc)))] (pc)))]
"TARGET_80387 || TARGET_SSE" "TARGET_80387 || TARGET_SSE_MATH"
"ix86_expand_branch (UNGT, operands[0]); DONE;") "ix86_expand_branch (UNGT, operands[0]); DONE;")
(define_expand "bunle" (define_expand "bunle"
...@@ -12723,7 +12725,7 @@ ...@@ -12723,7 +12725,7 @@
(if_then_else (match_dup 1) (if_then_else (match_dup 1)
(label_ref (match_operand 0 "" "")) (label_ref (match_operand 0 "" ""))
(pc)))] (pc)))]
"TARGET_80387 || TARGET_SSE" "TARGET_80387 || TARGET_SSE_MATH"
"ix86_expand_branch (UNLE, operands[0]); DONE;") "ix86_expand_branch (UNLE, operands[0]); DONE;")
(define_expand "bunlt" (define_expand "bunlt"
...@@ -12731,7 +12733,7 @@ ...@@ -12731,7 +12733,7 @@
(if_then_else (match_dup 1) (if_then_else (match_dup 1)
(label_ref (match_operand 0 "" "")) (label_ref (match_operand 0 "" ""))
(pc)))] (pc)))]
"TARGET_80387 || TARGET_SSE" "TARGET_80387 || TARGET_SSE_MATH"
"ix86_expand_branch (UNLT, operands[0]); DONE;") "ix86_expand_branch (UNLT, operands[0]); DONE;")
(define_expand "bltgt" (define_expand "bltgt"
...@@ -12739,7 +12741,7 @@ ...@@ -12739,7 +12741,7 @@
(if_then_else (match_dup 1) (if_then_else (match_dup 1)
(label_ref (match_operand 0 "" "")) (label_ref (match_operand 0 "" ""))
(pc)))] (pc)))]
"TARGET_80387 || TARGET_SSE" "TARGET_80387 || TARGET_SSE_MATH"
"ix86_expand_branch (LTGT, operands[0]); DONE;") "ix86_expand_branch (LTGT, operands[0]); DONE;")
(define_insn "*jcc_1" (define_insn "*jcc_1"
...@@ -12831,18 +12833,17 @@ ...@@ -12831,18 +12833,17 @@
;; during early optimization. Splitting the operation apart early makes ;; during early optimization. Splitting the operation apart early makes
;; for bad code when we want to reverse the operation. ;; for bad code when we want to reverse the operation.
(define_insn "*fp_jcc_1" (define_insn "*fp_jcc_1_mixed"
[(set (pc) [(set (pc)
(if_then_else (match_operator 0 "comparison_operator" (if_then_else (match_operator 0 "comparison_operator"
[(match_operand 1 "register_operand" "f") [(match_operand 1 "register_operand" "f#x,x#f")
(match_operand 2 "register_operand" "f")]) (match_operand 2 "nonimmediate_operand" "f#x,xm#f")])
(label_ref (match_operand 3 "" "")) (label_ref (match_operand 3 "" ""))
(pc))) (pc)))
(clobber (reg:CCFP FPSR_REG)) (clobber (reg:CCFP FPSR_REG))
(clobber (reg:CCFP FLAGS_REG))] (clobber (reg:CCFP FLAGS_REG))]
"TARGET_CMOVE && TARGET_80387 "TARGET_MIX_SSE_I387
&& !SSE_FLOAT_MODE_P (GET_MODE (operands[1])) && SSE_FLOAT_MODE_P (GET_MODE (operands[1]))
&& FLOAT_MODE_P (GET_MODE (operands[1]))
&& GET_MODE (operands[1]) == GET_MODE (operands[2]) && GET_MODE (operands[1]) == GET_MODE (operands[2])
&& ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))" && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
"#") "#")
...@@ -12850,44 +12851,44 @@ ...@@ -12850,44 +12851,44 @@
(define_insn "*fp_jcc_1_sse" (define_insn "*fp_jcc_1_sse"
[(set (pc) [(set (pc)
(if_then_else (match_operator 0 "comparison_operator" (if_then_else (match_operator 0 "comparison_operator"
[(match_operand 1 "register_operand" "f#x,x#f") [(match_operand 1 "register_operand" "x")
(match_operand 2 "nonimmediate_operand" "f#x,xm#f")]) (match_operand 2 "nonimmediate_operand" "xm")])
(label_ref (match_operand 3 "" "")) (label_ref (match_operand 3 "" ""))
(pc))) (pc)))
(clobber (reg:CCFP FPSR_REG)) (clobber (reg:CCFP FPSR_REG))
(clobber (reg:CCFP FLAGS_REG))] (clobber (reg:CCFP FLAGS_REG))]
"TARGET_80387 "TARGET_SSE_MATH
&& SSE_FLOAT_MODE_P (GET_MODE (operands[1])) && SSE_FLOAT_MODE_P (GET_MODE (operands[1]))
&& GET_MODE (operands[1]) == GET_MODE (operands[2]) && GET_MODE (operands[1]) == GET_MODE (operands[2])
&& ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))" && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
"#") "#")
(define_insn "*fp_jcc_1_sse_only" (define_insn "*fp_jcc_1_387"
[(set (pc) [(set (pc)
(if_then_else (match_operator 0 "comparison_operator" (if_then_else (match_operator 0 "comparison_operator"
[(match_operand 1 "register_operand" "x") [(match_operand 1 "register_operand" "f")
(match_operand 2 "nonimmediate_operand" "xm")]) (match_operand 2 "register_operand" "f")])
(label_ref (match_operand 3 "" "")) (label_ref (match_operand 3 "" ""))
(pc))) (pc)))
(clobber (reg:CCFP FPSR_REG)) (clobber (reg:CCFP FPSR_REG))
(clobber (reg:CCFP FLAGS_REG))] (clobber (reg:CCFP FLAGS_REG))]
"SSE_FLOAT_MODE_P (GET_MODE (operands[1])) "TARGET_CMOVE && TARGET_80387
&& FLOAT_MODE_P (GET_MODE (operands[1]))
&& GET_MODE (operands[1]) == GET_MODE (operands[2]) && GET_MODE (operands[1]) == GET_MODE (operands[2])
&& ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))" && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
"#") "#")
(define_insn "*fp_jcc_2" (define_insn "*fp_jcc_2_mixed"
[(set (pc) [(set (pc)
(if_then_else (match_operator 0 "comparison_operator" (if_then_else (match_operator 0 "comparison_operator"
[(match_operand 1 "register_operand" "f") [(match_operand 1 "register_operand" "f#x,x#f")
(match_operand 2 "register_operand" "f")]) (match_operand 2 "nonimmediate_operand" "f#x,xm#f")])
(pc) (pc)
(label_ref (match_operand 3 "" "")))) (label_ref (match_operand 3 "" ""))))
(clobber (reg:CCFP FPSR_REG)) (clobber (reg:CCFP FPSR_REG))
(clobber (reg:CCFP FLAGS_REG))] (clobber (reg:CCFP FLAGS_REG))]
"TARGET_CMOVE && TARGET_80387 "TARGET_MIX_SSE_I387
&& !SSE_FLOAT_MODE_P (GET_MODE (operands[1])) && SSE_FLOAT_MODE_P (GET_MODE (operands[1]))
&& FLOAT_MODE_P (GET_MODE (operands[1]))
&& GET_MODE (operands[1]) == GET_MODE (operands[2]) && GET_MODE (operands[1]) == GET_MODE (operands[2])
&& ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))" && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
"#") "#")
...@@ -12895,33 +12896,34 @@ ...@@ -12895,33 +12896,34 @@
(define_insn "*fp_jcc_2_sse" (define_insn "*fp_jcc_2_sse"
[(set (pc) [(set (pc)
(if_then_else (match_operator 0 "comparison_operator" (if_then_else (match_operator 0 "comparison_operator"
[(match_operand 1 "register_operand" "f#x,x#f") [(match_operand 1 "register_operand" "x")
(match_operand 2 "nonimmediate_operand" "f#x,xm#f")]) (match_operand 2 "nonimmediate_operand" "xm")])
(pc) (pc)
(label_ref (match_operand 3 "" "")))) (label_ref (match_operand 3 "" ""))))
(clobber (reg:CCFP FPSR_REG)) (clobber (reg:CCFP FPSR_REG))
(clobber (reg:CCFP FLAGS_REG))] (clobber (reg:CCFP FLAGS_REG))]
"TARGET_80387 "TARGET_SSE_MATH
&& SSE_FLOAT_MODE_P (GET_MODE (operands[1])) && SSE_FLOAT_MODE_P (GET_MODE (operands[1]))
&& GET_MODE (operands[1]) == GET_MODE (operands[2]) && GET_MODE (operands[1]) == GET_MODE (operands[2])
&& ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))" && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
"#") "#")
(define_insn "*fp_jcc_2_sse_only" (define_insn "*fp_jcc_2_387"
[(set (pc) [(set (pc)
(if_then_else (match_operator 0 "comparison_operator" (if_then_else (match_operator 0 "comparison_operator"
[(match_operand 1 "register_operand" "x") [(match_operand 1 "register_operand" "f")
(match_operand 2 "nonimmediate_operand" "xm")]) (match_operand 2 "register_operand" "f")])
(pc) (pc)
(label_ref (match_operand 3 "" "")))) (label_ref (match_operand 3 "" ""))))
(clobber (reg:CCFP FPSR_REG)) (clobber (reg:CCFP FPSR_REG))
(clobber (reg:CCFP FLAGS_REG))] (clobber (reg:CCFP FLAGS_REG))]
"SSE_FLOAT_MODE_P (GET_MODE (operands[1])) "TARGET_CMOVE && TARGET_80387
&& FLOAT_MODE_P (GET_MODE (operands[1]))
&& GET_MODE (operands[1]) == GET_MODE (operands[2]) && GET_MODE (operands[1]) == GET_MODE (operands[2])
&& ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))" && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
"#") "#")
(define_insn "*fp_jcc_3" (define_insn "*fp_jcc_3_387"
[(set (pc) [(set (pc)
(if_then_else (match_operator 0 "comparison_operator" (if_then_else (match_operator 0 "comparison_operator"
[(match_operand 1 "register_operand" "f") [(match_operand 1 "register_operand" "f")
...@@ -12940,7 +12942,7 @@ ...@@ -12940,7 +12942,7 @@
&& ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))" && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
"#") "#")
(define_insn "*fp_jcc_4" (define_insn "*fp_jcc_4_387"
[(set (pc) [(set (pc)
(if_then_else (match_operator 0 "comparison_operator" (if_then_else (match_operator 0 "comparison_operator"
[(match_operand 1 "register_operand" "f") [(match_operand 1 "register_operand" "f")
...@@ -12959,7 +12961,7 @@ ...@@ -12959,7 +12961,7 @@
&& ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))" && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
"#") "#")
(define_insn "*fp_jcc_5" (define_insn "*fp_jcc_5_387"
[(set (pc) [(set (pc)
(if_then_else (match_operator 0 "comparison_operator" (if_then_else (match_operator 0 "comparison_operator"
[(match_operand 1 "register_operand" "f") [(match_operand 1 "register_operand" "f")
...@@ -12975,7 +12977,7 @@ ...@@ -12975,7 +12977,7 @@
&& ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))" && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
"#") "#")
(define_insn "*fp_jcc_6" (define_insn "*fp_jcc_6_387"
[(set (pc) [(set (pc)
(if_then_else (match_operator 0 "comparison_operator" (if_then_else (match_operator 0 "comparison_operator"
[(match_operand 1 "register_operand" "f") [(match_operand 1 "register_operand" "f")
...@@ -12991,7 +12993,7 @@ ...@@ -12991,7 +12993,7 @@
&& ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))" && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
"#") "#")
(define_insn "*fp_jcc_7" (define_insn "*fp_jcc_7_387"
[(set (pc) [(set (pc)
(if_then_else (match_operator 0 "comparison_operator" (if_then_else (match_operator 0 "comparison_operator"
[(match_operand 1 "register_operand" "f") [(match_operand 1 "register_operand" "f")
...@@ -13015,7 +13017,7 @@ ...@@ -13015,7 +13017,7 @@
;; with a precedence over other operators and is always put in the first ;; with a precedence over other operators and is always put in the first
;; place. Swap condition and operands to match ficom instruction. ;; place. Swap condition and operands to match ficom instruction.
(define_insn "*fp_jcc_8" (define_insn "*fp_jcc_8_387"
[(set (pc) [(set (pc)
(if_then_else (match_operator 0 "comparison_operator" (if_then_else (match_operator 0 "comparison_operator"
[(match_operator 1 "float_operator" [(match_operator 1 "float_operator"
...@@ -17417,7 +17419,7 @@ ...@@ -17417,7 +17419,7 @@
(set_attr "mode" "DI") (set_attr "mode" "DI")
(set_attr "length_immediate" "0")]) (set_attr "length_immediate" "0")])
(define_insn "movdicc_c_rex64" (define_insn "*movdicc_c_rex64"
[(set (match_operand:DI 0 "register_operand" "=r,r") [(set (match_operand:DI 0 "register_operand" "=r,r")
(if_then_else:DI (match_operator 1 "ix86_comparison_operator" (if_then_else:DI (match_operator 1 "ix86_comparison_operator"
[(reg FLAGS_REG) (const_int 0)]) [(reg FLAGS_REG) (const_int 0)])
...@@ -17507,7 +17509,8 @@ ...@@ -17507,7 +17509,8 @@
(define_insn_and_split "*movqicc_noc" (define_insn_and_split "*movqicc_noc"
[(set (match_operand:QI 0 "register_operand" "=r,r") [(set (match_operand:QI 0 "register_operand" "=r,r")
(if_then_else:QI (match_operator 1 "ix86_comparison_operator" (if_then_else:QI (match_operator 1 "ix86_comparison_operator"
[(match_operand 4 "flags_reg_operand" "") (const_int 0)]) [(match_operand 4 "flags_reg_operand" "")
(const_int 0)])
(match_operand:QI 2 "register_operand" "r,0") (match_operand:QI 2 "register_operand" "r,0")
(match_operand:QI 3 "register_operand" "0,r")))] (match_operand:QI 3 "register_operand" "0,r")))]
"TARGET_CMOVE && !TARGET_PARTIAL_REG_STALL" "TARGET_CMOVE && !TARGET_PARTIAL_REG_STALL"
...@@ -17528,16 +17531,61 @@ ...@@ -17528,16 +17531,61 @@
(if_then_else:SF (match_operand 1 "comparison_operator" "") (if_then_else:SF (match_operand 1 "comparison_operator" "")
(match_operand:SF 2 "register_operand" "") (match_operand:SF 2 "register_operand" "")
(match_operand:SF 3 "register_operand" "")))] (match_operand:SF 3 "register_operand" "")))]
"TARGET_CMOVE" "(TARGET_80387 && TARGET_CMOVE) || TARGET_SSE_MATH"
"if (! ix86_expand_fp_movcc (operands)) FAIL; DONE;") "if (! ix86_expand_fp_movcc (operands)) FAIL; DONE;")
(define_insn "*movsfcc_1" ;; These versions of min/max are aware of the instruction's behaviour
;; wrt -0.0 and NaN inputs. If we don't care about either, then we
;; should have used the smin/smax expanders in the first place.
(define_insn "*movsfcc_1_sse_min"
[(set (match_operand:SF 0 "register_operand" "=x")
(if_then_else:SF
(lt:SF (match_operand:SF 1 "register_operand" "0")
(match_operand:SF 2 "nonimmediate_operand" "xm"))
(match_dup 1)
(match_dup 2)))]
"TARGET_SSE_MATH"
"minss\t{%2, %0|%0, %2}"
[(set_attr "type" "sseadd")
(set_attr "mode" "SF")])
(define_insn "*movsfcc_1_sse_max"
[(set (match_operand:SF 0 "register_operand" "=x")
(if_then_else:SF
(lt:SF (match_operand:SF 2 "nonimmediate_operand" "xm")
(match_operand:SF 1 "register_operand" "0"))
(match_dup 1)
(match_dup 2)))]
"TARGET_SSE_MATH"
"maxss\t{%2, %0|%0, %2}"
[(set_attr "type" "sseadd")
(set_attr "mode" "SF")])
(define_insn_and_split "*movsfcc_1_sse"
[(set (match_operand:SF 0 "register_operand" "=x,x,x")
(if_then_else:SF
(match_operator:SF 4 "sse_comparison_operator"
[(match_operand:SF 5 "register_operand" "0,0,0")
(match_operand:SF 6 "nonimmediate_operand" "xm,xm,xm")])
(match_operand:SF 2 "reg_or_0_operand" "C,x,1")
(match_operand:SF 3 "reg_or_0_operand" "x,C,x")))
(clobber (match_scratch:V4SF 1 "=X,X,x"))]
"TARGET_SSE_MATH"
"#"
"&& reload_completed"
[(const_int 0)]
{
ix86_split_sse_movcc (operands);
DONE;
})
(define_insn "*movsfcc_1_387"
[(set (match_operand:SF 0 "register_operand" "=f#r,f#r,r#f,r#f") [(set (match_operand:SF 0 "register_operand" "=f#r,f#r,r#f,r#f")
(if_then_else:SF (match_operator 1 "fcmov_comparison_operator" (if_then_else:SF (match_operator 1 "fcmov_comparison_operator"
[(reg FLAGS_REG) (const_int 0)]) [(reg FLAGS_REG) (const_int 0)])
(match_operand:SF 2 "nonimmediate_operand" "f#r,0,rm#f,0") (match_operand:SF 2 "nonimmediate_operand" "f#r,0,rm#f,0")
(match_operand:SF 3 "nonimmediate_operand" "0,f#r,0,rm#f")))] (match_operand:SF 3 "nonimmediate_operand" "0,f#r,0,rm#f")))]
"TARGET_CMOVE "TARGET_80387 && TARGET_CMOVE
&& (GET_CODE (operands[2]) != MEM || GET_CODE (operands[3]) != MEM)" && (GET_CODE (operands[2]) != MEM || GET_CODE (operands[3]) != MEM)"
"@ "@
fcmov%F1\t{%2, %0|%0, %2} fcmov%F1\t{%2, %0|%0, %2}
...@@ -17552,16 +17600,61 @@ ...@@ -17552,16 +17600,61 @@
(if_then_else:DF (match_operand 1 "comparison_operator" "") (if_then_else:DF (match_operand 1 "comparison_operator" "")
(match_operand:DF 2 "register_operand" "") (match_operand:DF 2 "register_operand" "")
(match_operand:DF 3 "register_operand" "")))] (match_operand:DF 3 "register_operand" "")))]
"TARGET_CMOVE" "(TARGET_80387 && TARGET_CMOVE) || (TARGET_SSE2 && TARGET_SSE_MATH)"
"if (! ix86_expand_fp_movcc (operands)) FAIL; DONE;") "if (! ix86_expand_fp_movcc (operands)) FAIL; DONE;")
;; These versions of min/max are aware of the instruction's behaviour
;; wrt -0.0 and NaN inputs. If we don't care about either, then we
;; should have used the smin/smax expanders in the first place.
(define_insn "*movdfcc_1_sse_min"
[(set (match_operand:DF 0 "register_operand" "=x")
(if_then_else:DF
(lt:DF (match_operand:DF 1 "register_operand" "0")
(match_operand:DF 2 "nonimmediate_operand" "xm"))
(match_dup 1)
(match_dup 2)))]
"TARGET_SSE2 && TARGET_SSE_MATH"
"minsd\t{%2, %0|%0, %2}"
[(set_attr "type" "sseadd")
(set_attr "mode" "DF")])
(define_insn "*movdfcc_1_sse_max"
[(set (match_operand:DF 0 "register_operand" "=x")
(if_then_else:DF
(lt:DF (match_operand:DF 2 "nonimmediate_operand" "xm")
(match_operand:DF 1 "register_operand" "0"))
(match_dup 1)
(match_dup 2)))]
"TARGET_SSE2 && TARGET_SSE_MATH"
"maxsd\t{%2, %0|%0, %2}"
[(set_attr "type" "sseadd")
(set_attr "mode" "DF")])
(define_insn_and_split "*movdfcc_1_sse"
[(set (match_operand:DF 0 "register_operand" "=x,x,x")
(if_then_else:DF
(match_operator:DF 4 "sse_comparison_operator"
[(match_operand:DF 5 "register_operand" "0,0,0")
(match_operand:DF 6 "nonimmediate_operand" "xm,xm,xm")])
(match_operand:DF 2 "reg_or_0_operand" "C,x,1")
(match_operand:DF 3 "reg_or_0_operand" "x,C,x")))
(clobber (match_scratch:V2DF 1 "=X,X,x"))]
"TARGET_SSE2 && TARGET_SSE_MATH"
"#"
"&& reload_completed"
[(const_int 0)]
{
ix86_split_sse_movcc (operands);
DONE;
})
(define_insn "*movdfcc_1" (define_insn "*movdfcc_1"
[(set (match_operand:DF 0 "register_operand" "=f#r,f#r,&r#f,&r#f") [(set (match_operand:DF 0 "register_operand" "=f#r,f#r,&r#f,&r#f")
(if_then_else:DF (match_operator 1 "fcmov_comparison_operator" (if_then_else:DF (match_operator 1 "fcmov_comparison_operator"
[(reg FLAGS_REG) (const_int 0)]) [(reg FLAGS_REG) (const_int 0)])
(match_operand:DF 2 "nonimmediate_operand" "f#r,0,rm#f,0") (match_operand:DF 2 "nonimmediate_operand" "f#r,0,rm#f,0")
(match_operand:DF 3 "nonimmediate_operand" "0,f#r,0,rm#f")))] (match_operand:DF 3 "nonimmediate_operand" "0,f#r,0,rm#f")))]
"!TARGET_64BIT && TARGET_CMOVE "!TARGET_64BIT && TARGET_80387 && TARGET_CMOVE
&& (GET_CODE (operands[2]) != MEM || GET_CODE (operands[3]) != MEM)" && (GET_CODE (operands[2]) != MEM || GET_CODE (operands[3]) != MEM)"
"@ "@
fcmov%F1\t{%2, %0|%0, %2} fcmov%F1\t{%2, %0|%0, %2}
...@@ -17577,7 +17670,7 @@ ...@@ -17577,7 +17670,7 @@
[(reg FLAGS_REG) (const_int 0)]) [(reg FLAGS_REG) (const_int 0)])
(match_operand:DF 2 "nonimmediate_operand" "f#r,0#r,rm#f,0#f") (match_operand:DF 2 "nonimmediate_operand" "f#r,0#r,rm#f,0#f")
(match_operand:DF 3 "nonimmediate_operand" "0#r,f#r,0#f,rm#f")))] (match_operand:DF 3 "nonimmediate_operand" "0#r,f#r,0#f,rm#f")))]
"TARGET_64BIT && TARGET_CMOVE "TARGET_64BIT && TARGET_80387 && TARGET_CMOVE
&& (GET_CODE (operands[2]) != MEM || GET_CODE (operands[3]) != MEM)" && (GET_CODE (operands[2]) != MEM || GET_CODE (operands[3]) != MEM)"
"@ "@
fcmov%F1\t{%2, %0|%0, %2} fcmov%F1\t{%2, %0|%0, %2}
...@@ -17590,7 +17683,8 @@ ...@@ -17590,7 +17683,8 @@
(define_split (define_split
[(set (match_operand:DF 0 "register_and_not_any_fp_reg_operand" "") [(set (match_operand:DF 0 "register_and_not_any_fp_reg_operand" "")
(if_then_else:DF (match_operator 1 "fcmov_comparison_operator" (if_then_else:DF (match_operator 1 "fcmov_comparison_operator"
[(match_operand 4 "flags_reg_operand" "") (const_int 0)]) [(match_operand 4 "flags_reg_operand" "")
(const_int 0)])
(match_operand:DF 2 "nonimmediate_operand" "") (match_operand:DF 2 "nonimmediate_operand" "")
(match_operand:DF 3 "nonimmediate_operand" "")))] (match_operand:DF 3 "nonimmediate_operand" "")))]
"!TARGET_64BIT && reload_completed" "!TARGET_64BIT && reload_completed"
...@@ -17611,7 +17705,7 @@ ...@@ -17611,7 +17705,7 @@
(if_then_else:XF (match_operand 1 "comparison_operator" "") (if_then_else:XF (match_operand 1 "comparison_operator" "")
(match_operand:XF 2 "register_operand" "") (match_operand:XF 2 "register_operand" "")
(match_operand:XF 3 "register_operand" "")))] (match_operand:XF 3 "register_operand" "")))]
"TARGET_CMOVE" "TARGET_80387 && TARGET_CMOVE"
"if (! ix86_expand_fp_movcc (operands)) FAIL; DONE;") "if (! ix86_expand_fp_movcc (operands)) FAIL; DONE;")
(define_insn "*movxfcc_1" (define_insn "*movxfcc_1"
...@@ -17620,62 +17714,53 @@ ...@@ -17620,62 +17714,53 @@
[(reg FLAGS_REG) (const_int 0)]) [(reg FLAGS_REG) (const_int 0)])
(match_operand:XF 2 "register_operand" "f,0") (match_operand:XF 2 "register_operand" "f,0")
(match_operand:XF 3 "register_operand" "0,f")))] (match_operand:XF 3 "register_operand" "0,f")))]
"TARGET_CMOVE" "TARGET_80387 && TARGET_CMOVE"
"@ "@
fcmov%F1\t{%2, %0|%0, %2} fcmov%F1\t{%2, %0|%0, %2}
fcmov%f1\t{%3, %0|%0, %3}" fcmov%f1\t{%3, %0|%0, %3}"
[(set_attr "type" "fcmov") [(set_attr "type" "fcmov")
(set_attr "mode" "XF")]) (set_attr "mode" "XF")])
(define_expand "minsf3" ;; These versions of the min/max patterns are intentionally ignorant of
[(parallel [ ;; their behaviour wrt -0.0 and NaN (via the commutative operand mark).
(set (match_operand:SF 0 "register_operand" "") ;; Since both the tree-level MAX_EXPR and the rtl-level SMAX operator
(if_then_else:SF (lt (match_operand:SF 1 "register_operand" "") ;; are undefined in this condition, we're certain this is correct.
(match_operand:SF 2 "nonimmediate_operand" ""))
(match_dup 1)
(match_dup 2)))
(clobber (reg:CC FLAGS_REG))])]
"TARGET_SSE"
"")
(define_insn "*minsf" (define_insn "sminsf3"
[(set (match_operand:SF 0 "register_operand" "=x#f,f#x,f#x") [(set (match_operand:SF 0 "register_operand" "=x")
(if_then_else:SF (lt (match_operand:SF 1 "register_operand" "0,0,f#x") (smin:SF (match_operand:SF 1 "nonimmediate_operand" "%0")
(match_operand:SF 2 "nonimmediate_operand" "xm#f,f#x,0")) (match_operand:SF 2 "nonimmediate_operand" "xm")))]
(match_dup 1) "TARGET_SSE_MATH"
(match_dup 2))) "minss\t{%2, %0|%0, %2}"
(clobber (reg:CC FLAGS_REG))] [(set_attr "type" "sseadd")
"TARGET_SSE && TARGET_IEEE_FP" (set_attr "mode" "SF")])
"#")
(define_insn "*minsf_nonieee" (define_insn "smaxsf3"
[(set (match_operand:SF 0 "register_operand" "=x#f,f#x") [(set (match_operand:SF 0 "register_operand" "=x")
(if_then_else:SF (lt (match_operand:SF 1 "nonimmediate_operand" "%0,0") (smax:SF (match_operand:SF 1 "nonimmediate_operand" "%0")
(match_operand:SF 2 "nonimmediate_operand" "xm#f,f#x")) (match_operand:SF 2 "nonimmediate_operand" "xm")))]
(match_dup 1) "TARGET_SSE_MATH"
(match_dup 2))) "minss\t{%2, %0|%0, %2}"
(clobber (reg:CC FLAGS_REG))] [(set_attr "type" "sseadd")
"TARGET_SSE && !TARGET_IEEE_FP (set_attr "mode" "SF")])
&& (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
"#")
(define_split (define_insn "smindf3"
[(set (match_operand:SF 0 "register_operand" "") [(set (match_operand:DF 0 "register_operand" "=x")
(if_then_else:SF (lt (match_operand:SF 1 "register_operand" "") (smin:DF (match_operand:DF 1 "nonimmediate_operand" "%0")
(match_operand:SF 2 "nonimmediate_operand" "")) (match_operand:DF 2 "nonimmediate_operand" "xm")))]
(match_operand:SF 3 "register_operand" "") "TARGET_SSE2 && TARGET_SSE_MATH"
(match_operand:SF 4 "nonimmediate_operand" ""))) "minsd\t{%2, %0|%0, %2}"
(clobber (reg:CC FLAGS_REG))] [(set_attr "type" "sseadd")
"SSE_REG_P (operands[0]) && reload_completed (set_attr "mode" "DF")])
&& ((operands_match_p (operands[1], operands[3])
&& operands_match_p (operands[2], operands[4])) (define_insn "smaxdf3"
|| (operands_match_p (operands[1], operands[4]) [(set (match_operand:DF 0 "register_operand" "=x")
&& operands_match_p (operands[2], operands[3])))" (smax:DF (match_operand:DF 1 "nonimmediate_operand" "%0")
[(set (match_dup 0) (match_operand:DF 2 "nonimmediate_operand" "xm")))]
(if_then_else:SF (lt (match_dup 1) "TARGET_SSE2 && TARGET_SSE_MATH"
(match_dup 2)) "maxsd\t{%2, %0|%0, %2}"
(match_dup 1) [(set_attr "type" "sseadd")
(match_dup 2)))]) (set_attr "mode" "DF")])
;; Conditional addition patterns ;; Conditional addition patterns
(define_expand "addqicc" (define_expand "addqicc"
...@@ -17710,282 +17795,6 @@ ...@@ -17710,282 +17795,6 @@
"TARGET_64BIT" "TARGET_64BIT"
"if (!ix86_expand_int_addcc (operands)) FAIL; DONE;") "if (!ix86_expand_int_addcc (operands)) FAIL; DONE;")
;; We can't represent the LT test directly. Do this by swapping the operands.
(define_split
[(set (match_operand:SF 0 "fp_register_operand" "")
(if_then_else:SF (lt (match_operand:SF 1 "register_operand" "")
(match_operand:SF 2 "register_operand" ""))
(match_operand:SF 3 "register_operand" "")
(match_operand:SF 4 "register_operand" "")))
(clobber (reg:CC FLAGS_REG))]
"reload_completed
&& ((operands_match_p (operands[1], operands[3])
&& operands_match_p (operands[2], operands[4]))
|| (operands_match_p (operands[1], operands[4])
&& operands_match_p (operands[2], operands[3])))"
[(set (reg:CCFP FLAGS_REG)
(compare:CCFP (match_dup 2)
(match_dup 1)))
(set (match_dup 0)
(if_then_else:SF (ge (reg:CCFP FLAGS_REG) (const_int 0))
(match_dup 1)
(match_dup 2)))])
(define_insn "*minsf_sse"
[(set (match_operand:SF 0 "register_operand" "=x")
(if_then_else:SF (lt (match_operand:SF 1 "register_operand" "0")
(match_operand:SF 2 "nonimmediate_operand" "xm"))
(match_dup 1)
(match_dup 2)))]
"TARGET_SSE && reload_completed"
"minss\t{%2, %0|%0, %2}"
[(set_attr "type" "sse")
(set_attr "mode" "SF")])
(define_expand "mindf3"
[(parallel [
(set (match_operand:DF 0 "register_operand" "")
(if_then_else:DF (lt (match_operand:DF 1 "register_operand" "")
(match_operand:DF 2 "nonimmediate_operand" ""))
(match_dup 1)
(match_dup 2)))
(clobber (reg:CC FLAGS_REG))])]
"TARGET_SSE2 && TARGET_SSE_MATH"
"#")
(define_insn "*mindf"
[(set (match_operand:DF 0 "register_operand" "=Y#f,f#Y,f#Y")
(if_then_else:DF (lt (match_operand:DF 1 "register_operand" "0,0,f#Y")
(match_operand:DF 2 "nonimmediate_operand" "Ym#f,f#Y,0"))
(match_dup 1)
(match_dup 2)))
(clobber (reg:CC FLAGS_REG))]
"TARGET_SSE2 && TARGET_IEEE_FP && TARGET_SSE_MATH"
"#")
(define_insn "*mindf_nonieee"
[(set (match_operand:DF 0 "register_operand" "=Y#f,f#Y")
(if_then_else:DF (lt (match_operand:DF 1 "nonimmediate_operand" "%0,0")
(match_operand:DF 2 "nonimmediate_operand" "Ym#f,f#Y"))
(match_dup 1)
(match_dup 2)))
(clobber (reg:CC FLAGS_REG))]
"TARGET_SSE2 && TARGET_SSE_MATH && !TARGET_IEEE_FP
&& (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
"#")
(define_split
[(set (match_operand:DF 0 "register_operand" "")
(if_then_else:DF (lt (match_operand:DF 1 "register_operand" "")
(match_operand:DF 2 "nonimmediate_operand" ""))
(match_operand:DF 3 "register_operand" "")
(match_operand:DF 4 "nonimmediate_operand" "")))
(clobber (reg:CC FLAGS_REG))]
"SSE_REG_P (operands[0]) && reload_completed
&& ((operands_match_p (operands[1], operands[3])
&& operands_match_p (operands[2], operands[4]))
|| (operands_match_p (operands[1], operands[4])
&& operands_match_p (operands[2], operands[3])))"
[(set (match_dup 0)
(if_then_else:DF (lt (match_dup 1)
(match_dup 2))
(match_dup 1)
(match_dup 2)))])
;; We can't represent the LT test directly. Do this by swapping the operands.
(define_split
[(set (match_operand:DF 0 "fp_register_operand" "")
(if_then_else:DF (lt (match_operand:DF 1 "register_operand" "")
(match_operand:DF 2 "register_operand" ""))
(match_operand:DF 3 "register_operand" "")
(match_operand:DF 4 "register_operand" "")))
(clobber (reg:CC FLAGS_REG))]
"reload_completed
&& ((operands_match_p (operands[1], operands[3])
&& operands_match_p (operands[2], operands[4]))
|| (operands_match_p (operands[1], operands[4])
&& operands_match_p (operands[2], operands[3])))"
[(set (reg:CCFP FLAGS_REG)
(compare:CCFP (match_dup 2)
(match_dup 1)))
(set (match_dup 0)
(if_then_else:DF (ge (reg:CCFP FLAGS_REG) (const_int 0))
(match_dup 1)
(match_dup 2)))])
(define_insn "*mindf_sse"
[(set (match_operand:DF 0 "register_operand" "=Y")
(if_then_else:DF (lt (match_operand:DF 1 "register_operand" "0")
(match_operand:DF 2 "nonimmediate_operand" "Ym"))
(match_dup 1)
(match_dup 2)))]
"TARGET_SSE2 && TARGET_SSE_MATH && reload_completed"
"minsd\t{%2, %0|%0, %2}"
[(set_attr "type" "sse")
(set_attr "mode" "DF")])
(define_expand "maxsf3"
[(parallel [
(set (match_operand:SF 0 "register_operand" "")
(if_then_else:SF (gt (match_operand:SF 1 "register_operand" "")
(match_operand:SF 2 "nonimmediate_operand" ""))
(match_dup 1)
(match_dup 2)))
(clobber (reg:CC FLAGS_REG))])]
"TARGET_SSE"
"#")
(define_insn "*maxsf"
[(set (match_operand:SF 0 "register_operand" "=x#f,f#x,f#x")
(if_then_else:SF (gt (match_operand:SF 1 "register_operand" "0,0,f#x")
(match_operand:SF 2 "nonimmediate_operand" "xm#f,f#x,0"))
(match_dup 1)
(match_dup 2)))
(clobber (reg:CC FLAGS_REG))]
"TARGET_SSE && TARGET_IEEE_FP"
"#")
(define_insn "*maxsf_nonieee"
[(set (match_operand:SF 0 "register_operand" "=x#f,f#x")
(if_then_else:SF (gt (match_operand:SF 1 "nonimmediate_operand" "%0,0")
(match_operand:SF 2 "nonimmediate_operand" "xm#f,f#x"))
(match_dup 1)
(match_dup 2)))
(clobber (reg:CC FLAGS_REG))]
"TARGET_SSE && !TARGET_IEEE_FP
&& (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
"#")
(define_split
[(set (match_operand:SF 0 "register_operand" "")
(if_then_else:SF (gt (match_operand:SF 1 "register_operand" "")
(match_operand:SF 2 "nonimmediate_operand" ""))
(match_operand:SF 3 "register_operand" "")
(match_operand:SF 4 "nonimmediate_operand" "")))
(clobber (reg:CC FLAGS_REG))]
"SSE_REG_P (operands[0]) && reload_completed
&& ((operands_match_p (operands[1], operands[3])
&& operands_match_p (operands[2], operands[4]))
|| (operands_match_p (operands[1], operands[4])
&& operands_match_p (operands[2], operands[3])))"
[(set (match_dup 0)
(if_then_else:SF (gt (match_dup 1)
(match_dup 2))
(match_dup 1)
(match_dup 2)))])
(define_split
[(set (match_operand:SF 0 "fp_register_operand" "")
(if_then_else:SF (gt (match_operand:SF 1 "register_operand" "")
(match_operand:SF 2 "register_operand" ""))
(match_operand:SF 3 "register_operand" "")
(match_operand:SF 4 "register_operand" "")))
(clobber (reg:CC FLAGS_REG))]
"reload_completed
&& ((operands_match_p (operands[1], operands[3])
&& operands_match_p (operands[2], operands[4]))
|| (operands_match_p (operands[1], operands[4])
&& operands_match_p (operands[2], operands[3])))"
[(set (reg:CCFP FLAGS_REG)
(compare:CCFP (match_dup 1)
(match_dup 2)))
(set (match_dup 0)
(if_then_else:SF (gt (reg:CCFP FLAGS_REG) (const_int 0))
(match_dup 1)
(match_dup 2)))])
(define_insn "*maxsf_sse"
[(set (match_operand:SF 0 "register_operand" "=x")
(if_then_else:SF (gt (match_operand:SF 1 "register_operand" "0")
(match_operand:SF 2 "nonimmediate_operand" "xm"))
(match_dup 1)
(match_dup 2)))]
"TARGET_SSE && reload_completed"
"maxss\t{%2, %0|%0, %2}"
[(set_attr "type" "sse")
(set_attr "mode" "SF")])
(define_expand "maxdf3"
[(parallel [
(set (match_operand:DF 0 "register_operand" "")
(if_then_else:DF (gt (match_operand:DF 1 "register_operand" "")
(match_operand:DF 2 "nonimmediate_operand" ""))
(match_dup 1)
(match_dup 2)))
(clobber (reg:CC FLAGS_REG))])]
"TARGET_SSE2 && TARGET_SSE_MATH"
"#")
(define_insn "*maxdf"
[(set (match_operand:DF 0 "register_operand" "=Y#f,f#Y,f#Y")
(if_then_else:DF (gt (match_operand:DF 1 "register_operand" "0,0,f#Y")
(match_operand:DF 2 "nonimmediate_operand" "Ym#f,f#Y,0"))
(match_dup 1)
(match_dup 2)))
(clobber (reg:CC FLAGS_REG))]
"TARGET_SSE2 && TARGET_SSE_MATH && TARGET_IEEE_FP"
"#")
(define_insn "*maxdf_nonieee"
[(set (match_operand:DF 0 "register_operand" "=Y#f,f#Y")
(if_then_else:DF (gt (match_operand:DF 1 "nonimmediate_operand" "%0,0")
(match_operand:DF 2 "nonimmediate_operand" "Ym#f,f#Y"))
(match_dup 1)
(match_dup 2)))
(clobber (reg:CC FLAGS_REG))]
"TARGET_SSE2 && TARGET_SSE_MATH && !TARGET_IEEE_FP
&& (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
"#")
(define_split
[(set (match_operand:DF 0 "register_operand" "")
(if_then_else:DF (gt (match_operand:DF 1 "register_operand" "")
(match_operand:DF 2 "nonimmediate_operand" ""))
(match_operand:DF 3 "register_operand" "")
(match_operand:DF 4 "nonimmediate_operand" "")))
(clobber (reg:CC FLAGS_REG))]
"SSE_REG_P (operands[0]) && reload_completed
&& ((operands_match_p (operands[1], operands[3])
&& operands_match_p (operands[2], operands[4]))
|| (operands_match_p (operands[1], operands[4])
&& operands_match_p (operands[2], operands[3])))"
[(set (match_dup 0)
(if_then_else:DF (gt (match_dup 1)
(match_dup 2))
(match_dup 1)
(match_dup 2)))])
(define_split
[(set (match_operand:DF 0 "fp_register_operand" "")
(if_then_else:DF (gt (match_operand:DF 1 "register_operand" "")
(match_operand:DF 2 "register_operand" ""))
(match_operand:DF 3 "register_operand" "")
(match_operand:DF 4 "register_operand" "")))
(clobber (reg:CC FLAGS_REG))]
"reload_completed
&& ((operands_match_p (operands[1], operands[3])
&& operands_match_p (operands[2], operands[4]))
|| (operands_match_p (operands[1], operands[4])
&& operands_match_p (operands[2], operands[3])))"
[(set (reg:CCFP FLAGS_REG)
(compare:CCFP (match_dup 1)
(match_dup 2)))
(set (match_dup 0)
(if_then_else:DF (gt (reg:CCFP FLAGS_REG) (const_int 0))
(match_dup 1)
(match_dup 2)))])
(define_insn "*maxdf_sse"
[(set (match_operand:DF 0 "register_operand" "=Y")
(if_then_else:DF (gt (match_operand:DF 1 "register_operand" "0")
(match_operand:DF 2 "nonimmediate_operand" "Ym"))
(match_dup 1)
(match_dup 2)))]
"TARGET_SSE2 && TARGET_SSE_MATH && reload_completed"
"maxsd\t{%2, %0|%0, %2}"
[(set_attr "type" "sse")
(set_attr "mode" "DF")])
;; Misc patterns (?) ;; Misc patterns (?)
...@@ -18107,364 +17916,6 @@ ...@@ -18107,364 +17916,6 @@
[(set_attr "type" "alu,lea") [(set_attr "type" "alu,lea")
(set_attr "mode" "DI")]) (set_attr "mode" "DI")])
;; Placeholder for the conditional moves. This one is split either to SSE
;; based moves emulation or to usual cmove sequence. Little bit unfortunate
;; fact is that compares supported by the cmp??ss instructions are exactly
;; swapped of those supported by cmove sequence.
;; The EQ/NE comparisons also needs bit care, since they are not directly
;; supported by i387 comparisons and we do need to emit two conditional moves
;; in tandem.
(define_insn "sse_movsfcc"
[(set (match_operand:SF 0 "register_operand" "=&x#rf,x#rf,?f#xr,?f#xr,?f#xr,?f#xr,?r#xf,?r#xf,?r#xf,?r#xf")
(if_then_else:SF (match_operator 1 "sse_comparison_operator"
[(match_operand:SF 4 "nonimmediate_operand" "0#fx,x#fx,f#x,f#x,xm#f,xm#f,f#x,f#x,xm#f,xm#f")
(match_operand:SF 5 "nonimmediate_operand" "xm#f,xm#f,f#x,f#x,x#f,x#f,f#x,f#x,x#f,x#f")])
(match_operand:SF 2 "nonimmediate_operand" "x#fr,0#fr,f#fx,0#fx,f#fx,0#fx,rm#rx,0#rx,rm#rx,0#rx")
(match_operand:SF 3 "nonimmediate_operand" "x#fr,x#fr,0#fx,f#fx,0#fx,f#fx,0#fx,rm#rx,0#rx,rm#rx")))
(clobber (match_scratch:SF 6 "=2,&4,X,X,X,X,X,X,X,X"))
(clobber (reg:CC FLAGS_REG))]
"TARGET_SSE
&& (GET_CODE (operands[2]) != MEM || GET_CODE (operands[3]) != MEM)
/* Avoid combine from being smart and converting min/max
instruction patterns into conditional moves. */
&& ((GET_CODE (operands[1]) != LT && GET_CODE (operands[1]) != GT
&& GET_CODE (operands[1]) != UNLE && GET_CODE (operands[1]) != UNGE)
|| !rtx_equal_p (operands[4], operands[2])
|| !rtx_equal_p (operands[5], operands[3]))
&& (!TARGET_IEEE_FP
|| (GET_CODE (operands[1]) != EQ && GET_CODE (operands[1]) != NE))"
"#")
(define_insn "sse_movsfcc_eq"
[(set (match_operand:SF 0 "register_operand" "=&x#rf,x#rf,?f#xr,?f#xr,?r#xf,?r#xf")
(if_then_else:SF (eq (match_operand:SF 3 "nonimmediate_operand" "%0#fx,x#fx,f#x,xm#f,f#x,xm#f")
(match_operand:SF 4 "nonimmediate_operand" "xm#f,xm#f,f#x,x#f,f#x,x#f"))
(match_operand:SF 1 "nonimmediate_operand" "x#fr,0#fr,0#fx,0#fx,0#rx,0#rx")
(match_operand:SF 2 "nonimmediate_operand" "x#fr,x#fr,f#fx,f#fx,rm#rx,rm#rx")))
(clobber (match_scratch:SF 5 "=1,&3,X,X,X,X"))
(clobber (reg:CC FLAGS_REG))]
"TARGET_SSE
&& (GET_CODE (operands[2]) != MEM || GET_CODE (operands[3]) != MEM)"
"#")
(define_insn "sse_movdfcc"
[(set (match_operand:DF 0 "register_operand" "=&Y#rf,Y#rf,?f#Yr,?f#Yr,?f#Yr,?f#Yr,?r#Yf,?r#Yf,?r#Yf,?r#Yf")
(if_then_else:DF (match_operator 1 "sse_comparison_operator"
[(match_operand:DF 4 "nonimmediate_operand" "0#fY,Y#fY,f#Y,f#Y,Ym#f,Ym#f,f#Y,f#Y,Ym#f,Ym#f")
(match_operand:DF 5 "nonimmediate_operand" "Ym#f,Ym#f,f#Y,f#Y,Y#f,Y#f,f#Y,f#Y,Y#f,Y#f")])
(match_operand:DF 2 "nonimmediate_operand" "Y#fr,0#fr,f#fY,0#fY,f#fY,0#fY,rm#rY,0#rY,rm#rY,0#rY")
(match_operand:DF 3 "nonimmediate_operand" "Y#fr,Y#fr,0#fY,f#fY,0#fY,f#fY,0#fY,rm#rY,0#rY,rm#rY")))
(clobber (match_scratch:DF 6 "=2,&4,X,X,X,X,X,X,X,X"))
(clobber (reg:CC FLAGS_REG))]
"TARGET_SSE2
&& (GET_CODE (operands[2]) != MEM || GET_CODE (operands[3]) != MEM)
/* Avoid combine from being smart and converting min/max
instruction patterns into conditional moves. */
&& ((GET_CODE (operands[1]) != LT && GET_CODE (operands[1]) != GT
&& GET_CODE (operands[1]) != UNLE && GET_CODE (operands[1]) != UNGE)
|| !rtx_equal_p (operands[4], operands[2])
|| !rtx_equal_p (operands[5], operands[3]))
&& (!TARGET_IEEE_FP
|| (GET_CODE (operands[1]) != EQ && GET_CODE (operands[1]) != NE))"
"#")
(define_insn "sse_movdfcc_eq"
[(set (match_operand:DF 0 "register_operand" "=&Y#rf,Y#rf,?f#Yr,?f#Yr,?r#Yf,?r#Yf")
(if_then_else:DF (eq (match_operand:DF 3 "nonimmediate_operand" "%0#fY,Y#fY,f#Y,Ym#f,f#Y,Ym#f")
(match_operand:DF 4 "nonimmediate_operand" "Ym#f,Ym#f,f#Y,Y#f,f#Y,Y#f"))
(match_operand:DF 1 "nonimmediate_operand" "Y#fr,0#fr,0#fY,0#fY,0#rY,0#rY")
(match_operand:DF 2 "nonimmediate_operand" "Y#fr,Y#fr,f#fY,f#fY,rm#rY,rm#rY")))
(clobber (match_scratch:DF 5 "=1,&3,X,X,X,X"))
(clobber (reg:CC FLAGS_REG))]
"TARGET_SSE
&& (GET_CODE (operands[2]) != MEM || GET_CODE (operands[3]) != MEM)"
"#")
;; For non-sse moves just expand the usual cmove sequence.
(define_split
[(set (match_operand 0 "register_operand" "")
(if_then_else (match_operator 1 "comparison_operator"
[(match_operand 4 "nonimmediate_operand" "")
(match_operand 5 "register_operand" "")])
(match_operand 2 "nonimmediate_operand" "")
(match_operand 3 "nonimmediate_operand" "")))
(clobber (match_operand 6 "" ""))
(clobber (reg:CC FLAGS_REG))]
"!SSE_REG_P (operands[0]) && reload_completed
&& (GET_MODE (operands[0]) == SFmode
|| (TARGET_SSE2 && GET_MODE (operands[0]) == DFmode))"
[(const_int 0)]
{
ix86_compare_op0 = operands[5];
ix86_compare_op1 = operands[4];
operands[1] = gen_rtx_fmt_ee (swap_condition (GET_CODE (operands[1])),
VOIDmode, operands[5], operands[4]);
ix86_expand_fp_movcc (operands);
DONE;
})
;; Split SSE based conditional move into sequence:
;; cmpCC op0, op4 - set op0 to 0 or ffffffff depending on the comparison
;; and op2, op0 - zero op2 if comparison was false
;; nand op0, op3 - load op3 to op0 if comparison was false
;; or op2, op0 - get the nonzero one into the result.
(define_split
[(set (match_operand:SF 0 "register_operand" "")
(if_then_else:SF (match_operator:SF 1 "sse_comparison_operator"
[(match_operand:SF 4 "register_operand" "")
(match_operand:SF 5 "nonimmediate_operand" "")])
(match_operand:SF 2 "register_operand" "")
(match_operand:SF 3 "register_operand" "")))
(clobber (match_operand 6 "" ""))
(clobber (reg:CC FLAGS_REG))]
"SSE_REG_P (operands[0]) && reload_completed"
[(set (match_dup 4) (match_op_dup 1 [(match_dup 4) (match_dup 5)]))
(set (match_dup 2) (and:V4SF (match_dup 2)
(match_dup 8)))
(set (match_dup 8) (and:V4SF (not:V4SF (match_dup 8))
(match_dup 3)))
(set (match_dup 0) (ior:V4SF (match_dup 6)
(match_dup 7)))]
{
/* If op2 == op3, op3 would be clobbered before it is used. */
if (operands_match_p (operands[2], operands[3]))
{
emit_move_insn (operands[0], operands[2]);
DONE;
}
PUT_MODE (operands[1], GET_MODE (operands[0]));
if (operands_match_p (operands[0], operands[4]))
operands[6] = operands[4], operands[7] = operands[2];
else
operands[6] = operands[2], operands[7] = operands[4];
operands[0] = simplify_gen_subreg (V4SFmode, operands[0], SFmode, 0);
operands[2] = simplify_gen_subreg (V4SFmode, operands[2], SFmode, 0);
operands[3] = simplify_gen_subreg (V4SFmode, operands[3], SFmode, 0);
operands[8] = simplify_gen_subreg (V4SFmode, operands[4], SFmode, 0);
operands[6] = simplify_gen_subreg (V4SFmode, operands[6], SFmode, 0);
operands[7] = simplify_gen_subreg (V4SFmode, operands[7], SFmode, 0);
})
(define_split
[(set (match_operand:DF 0 "register_operand" "")
(if_then_else:DF (match_operator:DF 1 "sse_comparison_operator"
[(match_operand:DF 4 "register_operand" "")
(match_operand:DF 5 "nonimmediate_operand" "")])
(match_operand:DF 2 "register_operand" "")
(match_operand:DF 3 "register_operand" "")))
(clobber (match_operand 6 "" ""))
(clobber (reg:CC FLAGS_REG))]
"SSE_REG_P (operands[0]) && reload_completed"
[(set (match_dup 4) (match_op_dup 1 [(match_dup 4) (match_dup 5)]))
(set (match_dup 2) (and:V2DF (match_dup 2)
(match_dup 8)))
(set (match_dup 8) (and:V2DF (not:V2DF (match_dup 8))
(match_dup 3)))
(set (match_dup 0) (ior:V2DF (match_dup 6)
(match_dup 7)))]
{
if (TARGET_SSE_SPLIT_REGS && !optimize_size)
{
rtx op = simplify_gen_subreg (V2DFmode, operands[2], DFmode, 0);
emit_insn (gen_sse2_unpcklpd (op, op, op));
op = simplify_gen_subreg (V2DFmode, operands[3], DFmode, 0);
emit_insn (gen_sse2_unpcklpd (op, op, op));
}
/* If op2 == op3, op3 would be clobbered before it is used. */
if (operands_match_p (operands[2], operands[3]))
{
emit_move_insn (operands[0], operands[2]);
DONE;
}
PUT_MODE (operands[1], GET_MODE (operands[0]));
if (operands_match_p (operands[0], operands[4]))
operands[6] = operands[4], operands[7] = operands[2];
else
operands[6] = operands[2], operands[7] = operands[4];
operands[0] = simplify_gen_subreg (V2DFmode, operands[0], DFmode, 0);
operands[2] = simplify_gen_subreg (V2DFmode, operands[2], DFmode, 0);
operands[3] = simplify_gen_subreg (V2DFmode, operands[3], DFmode, 0);
operands[8] = simplify_gen_subreg (V2DFmode, operands[4], DFmode, 0);
operands[6] = simplify_gen_subreg (V2DFmode, operands[6], DFmode, 0);
operands[7] = simplify_gen_subreg (V2DFmode, operands[7], DFmode, 0);
})
;; Special case of conditional move we can handle effectively.
;; Do not brother with the integer/floating point case, since these are
;; bot considerably slower, unlike in the generic case.
(define_insn "*sse_movsfcc_const0_1"
[(set (match_operand:SF 0 "register_operand" "=&x")
(if_then_else:SF (match_operator 1 "sse_comparison_operator"
[(match_operand:SF 4 "register_operand" "0")
(match_operand:SF 5 "nonimmediate_operand" "xm")])
(match_operand:SF 2 "register_operand" "x")
(match_operand:SF 3 "const0_operand" "X")))]
"TARGET_SSE"
"#")
(define_insn "*sse_movsfcc_const0_2"
[(set (match_operand:SF 0 "register_operand" "=&x")
(if_then_else:SF (match_operator 1 "sse_comparison_operator"
[(match_operand:SF 4 "register_operand" "0")
(match_operand:SF 5 "nonimmediate_operand" "xm")])
(match_operand:SF 2 "const0_operand" "X")
(match_operand:SF 3 "register_operand" "x")))]
"TARGET_SSE"
"#")
(define_insn "*sse_movsfcc_const0_3"
[(set (match_operand:SF 0 "register_operand" "=&x")
(if_then_else:SF (match_operator 1 "fcmov_comparison_operator"
[(match_operand:SF 4 "nonimmediate_operand" "xm")
(match_operand:SF 5 "register_operand" "0")])
(match_operand:SF 2 "register_operand" "x")
(match_operand:SF 3 "const0_operand" "X")))]
"TARGET_SSE"
"#")
(define_insn "*sse_movsfcc_const0_4"
[(set (match_operand:SF 0 "register_operand" "=&x")
(if_then_else:SF (match_operator 1 "fcmov_comparison_operator"
[(match_operand:SF 4 "nonimmediate_operand" "xm")
(match_operand:SF 5 "register_operand" "0")])
(match_operand:SF 2 "const0_operand" "X")
(match_operand:SF 3 "register_operand" "x")))]
"TARGET_SSE"
"#")
(define_insn "*sse_movdfcc_const0_1"
[(set (match_operand:DF 0 "register_operand" "=&Y")
(if_then_else:DF (match_operator 1 "sse_comparison_operator"
[(match_operand:DF 4 "register_operand" "0")
(match_operand:DF 5 "nonimmediate_operand" "Ym")])
(match_operand:DF 2 "register_operand" "Y")
(match_operand:DF 3 "const0_operand" "X")))]
"TARGET_SSE2"
"#")
(define_insn "*sse_movdfcc_const0_2"
[(set (match_operand:DF 0 "register_operand" "=&Y")
(if_then_else:DF (match_operator 1 "sse_comparison_operator"
[(match_operand:DF 4 "register_operand" "0")
(match_operand:DF 5 "nonimmediate_operand" "Ym")])
(match_operand:DF 2 "const0_operand" "X")
(match_operand:DF 3 "register_operand" "Y")))]
"TARGET_SSE2"
"#")
(define_insn "*sse_movdfcc_const0_3"
[(set (match_operand:DF 0 "register_operand" "=&Y")
(if_then_else:DF (match_operator 1 "fcmov_comparison_operator"
[(match_operand:DF 4 "nonimmediate_operand" "Ym")
(match_operand:DF 5 "register_operand" "0")])
(match_operand:DF 2 "register_operand" "Y")
(match_operand:DF 3 "const0_operand" "X")))]
"TARGET_SSE2"
"#")
(define_insn "*sse_movdfcc_const0_4"
[(set (match_operand:DF 0 "register_operand" "=&Y")
(if_then_else:DF (match_operator 1 "fcmov_comparison_operator"
[(match_operand:DF 4 "nonimmediate_operand" "Ym")
(match_operand:DF 5 "register_operand" "0")])
(match_operand:DF 2 "const0_operand" "X")
(match_operand:DF 3 "register_operand" "Y")))]
"TARGET_SSE2"
"#")
(define_split
[(set (match_operand:SF 0 "register_operand" "")
(if_then_else:SF (match_operator 1 "comparison_operator"
[(match_operand:SF 4 "nonimmediate_operand" "")
(match_operand:SF 5 "nonimmediate_operand" "")])
(match_operand:SF 2 "nonmemory_operand" "")
(match_operand:SF 3 "nonmemory_operand" "")))]
"SSE_REG_P (operands[0]) && reload_completed
&& (const0_operand (operands[2], GET_MODE (operands[0]))
|| const0_operand (operands[3], GET_MODE (operands[0])))"
[(set (match_dup 0) (match_op_dup 1 [(match_dup 0) (match_dup 5)]))
(set (match_dup 8) (and:V4SF (match_dup 6) (match_dup 7)))]
{
PUT_MODE (operands[1], GET_MODE (operands[0]));
if (!sse_comparison_operator (operands[1], VOIDmode)
|| !rtx_equal_p (operands[0], operands[4]))
{
rtx tmp = operands[5];
operands[5] = operands[4];
operands[4] = tmp;
PUT_CODE (operands[1], swap_condition (GET_CODE (operands[1])));
}
if (!rtx_equal_p (operands[0], operands[4]))
abort ();
operands[8] = simplify_gen_subreg (V4SFmode, operands[0], SFmode, 0);
if (const0_operand (operands[2], GET_MODE (operands[2])))
{
operands[7] = operands[3];
operands[6] = gen_rtx_NOT (V4SFmode, operands[8]);
}
else
{
operands[7] = operands[2];
operands[6] = operands[8];
}
operands[7] = simplify_gen_subreg (V4SFmode, operands[7], SFmode, 0);
})
(define_split
[(set (match_operand:DF 0 "register_operand" "")
(if_then_else:DF (match_operator 1 "comparison_operator"
[(match_operand:DF 4 "nonimmediate_operand" "")
(match_operand:DF 5 "nonimmediate_operand" "")])
(match_operand:DF 2 "nonmemory_operand" "")
(match_operand:DF 3 "nonmemory_operand" "")))]
"SSE_REG_P (operands[0]) && reload_completed
&& (const0_operand (operands[2], GET_MODE (operands[0]))
|| const0_operand (operands[3], GET_MODE (operands[0])))"
[(set (match_dup 0) (match_op_dup 1 [(match_dup 0) (match_dup 5)]))
(set (match_dup 8) (and:V2DF (match_dup 6) (match_dup 7)))]
{
if (TARGET_SSE_SPLIT_REGS && !optimize_size)
{
if (REG_P (operands[2]))
{
rtx op = simplify_gen_subreg (V2DFmode, operands[2], DFmode, 0);
emit_insn (gen_sse2_unpcklpd (op, op, op));
}
if (REG_P (operands[3]))
{
rtx op = simplify_gen_subreg (V2DFmode, operands[3], DFmode, 0);
emit_insn (gen_sse2_unpcklpd (op, op, op));
}
}
PUT_MODE (operands[1], GET_MODE (operands[0]));
if (!sse_comparison_operator (operands[1], VOIDmode)
|| !rtx_equal_p (operands[0], operands[4]))
{
rtx tmp = operands[5];
operands[5] = operands[4];
operands[4] = tmp;
PUT_CODE (operands[1], swap_condition (GET_CODE (operands[1])));
}
if (!rtx_equal_p (operands[0], operands[4]))
abort ();
operands[8] = simplify_gen_subreg (V2DFmode, operands[0], DFmode, 0);
if (const0_operand (operands[2], GET_MODE (operands[2])))
{
operands[7] = operands[3];
operands[6] = gen_rtx_NOT (V2DFmode, operands[8]);
}
else
{
operands[7] = operands[2];
operands[6] = operands[8];
}
operands[7] = simplify_gen_subreg (V2DFmode, operands[7], DFmode, 0);
})
(define_expand "allocate_stack_worker" (define_expand "allocate_stack_worker"
[(match_operand:SI 0 "register_operand" "")] [(match_operand:SI 0 "register_operand" "")]
"TARGET_STACK_PROBE" "TARGET_STACK_PROBE"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment