aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>2005-01-13 16:33:49 -0800
committerRichard Henderson <rth@gcc.gnu.org>2005-01-13 16:33:49 -0800
commiteaa49b49418e32fc83f5b99217e6e7fc0cfeff32 (patch)
treed00bde60425ce12ced7b26a9deae38fb3e236e00
parent997e120f69b918083ac855511dd42d21b35326c6 (diff)
downloadgcc-eaa49b49418e32fc83f5b99217e6e7fc0cfeff32.zip
gcc-eaa49b49418e32fc83f5b99217e6e7fc0cfeff32.tar.gz
gcc-eaa49b49418e32fc83f5b99217e6e7fc0cfeff32.tar.bz2
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
-rw-r--r--gcc/ChangeLog35
-rw-r--r--gcc/config/i386/i386-protos.h1
-rw-r--r--gcc/config/i386/i386.c247
-rw-r--r--gcc/config/i386/i386.md983
4 files changed, 389 insertions, 877 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index a9451b2..6195716 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,38 @@
+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>
* tree-ssa-dse.c (fix_phi_uses): Use SSA operand iterators.
diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
index 33bf6fc..06c8577 100644
--- a/gcc/config/i386/i386-protos.h
+++ b/gcc/config/i386/i386-protos.h
@@ -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_int_movcc (rtx[]);
extern int ix86_expand_fp_movcc (rtx[]);
+extern void ix86_split_sse_movcc (rtx[]);
extern int ix86_expand_int_addcc (rtx[]);
extern void ix86_expand_call (rtx, rtx, rtx, rtx, rtx, int);
extern void x86_initialize_trampoline (rtx, rtx, rtx);
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index cb73a18..4bc0c75 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -9743,118 +9743,95 @@ ix86_expand_int_movcc (rtx operands[])
int
ix86_expand_fp_movcc (rtx operands[])
{
- enum rtx_code code;
- rtx tmp;
- rtx compare_op, second_test, bypass_test;
-
- /* For SF/DFmode conditional moves based on comparisons
- in same mode, we may want to use SSE min/max instructions. */
- if (((TARGET_SSE_MATH && GET_MODE (operands[0]) == SFmode)
- || (TARGET_SSE2 && TARGET_SSE_MATH && GET_MODE (operands[0]) == DFmode))
- && GET_MODE (ix86_compare_op0) == GET_MODE (operands[0])
- /* The SSE comparisons does not support the LTGT/UNEQ pair. */
- && (!TARGET_IEEE_FP
- || (GET_CODE (operands[1]) != LTGT && GET_CODE (operands[1]) != UNEQ))
- /* We may be called from the post-reload splitter. */
- && (!REG_P (operands[0])
- || SSE_REG_P (operands[0])
- || REGNO (operands[0]) >= FIRST_PSEUDO_REGISTER))
- {
- rtx op0 = ix86_compare_op0, op1 = ix86_compare_op1;
- code = GET_CODE (operands[1]);
-
- /* See if we have (cross) match between comparison operands and
- conditional move operands. */
- if (rtx_equal_p (operands[2], op1))
+ enum machine_mode mode = GET_MODE (operands[0]);
+ enum rtx_code code = GET_CODE (operands[1]);
+ rtx tmp, compare_op, second_test, bypass_test;
+
+ if (TARGET_SSE_MATH && SSE_FLOAT_MODE_P (mode))
+ {
+ rtx cmp_op0, cmp_op1, if_true, if_false;
+ rtx clob;
+ enum machine_mode vmode, cmode;
+ bool is_minmax = false;
+
+ cmp_op0 = ix86_compare_op0;
+ cmp_op1 = ix86_compare_op1;
+ if_true = operands[2];
+ if_false = operands[3];
+
+ /* Since we've no cmove for sse registers, don't force bad register
+ allocation just to gain access to it. Deny movcc when the
+ comparison mode doesn't match the move mode. */
+ cmode = GET_MODE (cmp_op0);
+ if (cmode == VOIDmode)
+ cmode = GET_MODE (cmp_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;
- op0 = op1;
- op1 = tmp;
- code = reverse_condition_maybe_unordered (code);
+ tmp = cmp_op0;
+ cmp_op0 = cmp_op1;
+ cmp_op1 = tmp;
+ 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
+ semantics. Note that this is IEEE safe, as long as we don't
+ 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 == LT || code == UNGE) && REG_P (cmp_op0) && REG_P (cmp_op1))
{
- /* Check for min operation. */
- if (code == LT || code == UNLE)
+ if (((cmp_op0 == if_true && cmp_op1 == if_false)
+ || (cmp_op0 == if_false && cmp_op1 == if_true)))
{
- if (code == UNLE)
+ is_minmax = true;
+ if (code == UNGE)
{
- rtx tmp = op0;
- op0 = op1;
- op1 = tmp;
+ code = LT;
+ tmp = if_true;
+ 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_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)
- {
- if (code == UNGE)
- {
- rtx tmp = op0;
- op0 = op1;
- 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_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
- to be first in the comparison - this helps reload to avoid extra
- moves. */
- if (!sse_comparison_operator (operands[1], VOIDmode)
- || (rtx_equal_p (operands[0], ix86_compare_op1) && !TARGET_IEEE_FP))
- {
- rtx tmp = ix86_compare_op0;
- ix86_compare_op0 = ix86_compare_op1;
- 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],
- operands[2], operands[3],
- ix86_compare_op0, ix86_compare_op1));
+
+ if (mode == SFmode)
+ vmode = V4SFmode;
+ else if (mode == DFmode)
+ vmode = V2DFmode;
else
- emit_insn (gen_sse_movdfcc (operands[0], operands[1],
- operands[2], operands[3],
- ix86_compare_op0, ix86_compare_op1));
+ 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)
+ {
+ clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (vmode));
+ tmp = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, tmp, clob));
+ }
+
+ emit_insn (tmp);
return 1;
}
/* The floating point conditional move instructions don't directly
support conditions resulting from a signed integer comparison. */
- code = GET_CODE (operands[1]);
compare_op = ix86_expand_compare (code, &second_test, &bypass_test);
/* The floating point conditional move instructions don't directly
@@ -9873,38 +9850,86 @@ ix86_expand_fp_movcc (rtx operands[])
}
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]);
operands[3] = tmp;
}
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]);
operands[2] = tmp;
}
emit_insn (gen_rtx_SET (VOIDmode, operands[0],
- gen_rtx_IF_THEN_ELSE (GET_MODE (operands[0]),
- compare_op,
- operands[2],
- operands[3])));
+ gen_rtx_IF_THEN_ELSE (mode, compare_op,
+ operands[2], operands[3])));
if (bypass_test)
emit_insn (gen_rtx_SET (VOIDmode, operands[0],
- gen_rtx_IF_THEN_ELSE (GET_MODE (operands[0]),
- bypass_test,
- operands[3],
- operands[0])));
+ gen_rtx_IF_THEN_ELSE (mode, bypass_test,
+ operands[3], operands[0])));
if (second_test)
emit_insn (gen_rtx_SET (VOIDmode, operands[0],
- gen_rtx_IF_THEN_ELSE (GET_MODE (operands[0]),
- second_test,
- operands[2],
- operands[0])));
+ gen_rtx_IF_THEN_ELSE (mode, second_test,
+ operands[2], operands[0])));
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.
The default case using setcc followed by the conditional move can be
done by generic code. */
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 194c218..674d0935 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -774,7 +774,7 @@
[(set (reg:CC FLAGS_REG)
(compare:CC (match_operand:DF 0 "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_op1 = operands[1];
@@ -785,7 +785,7 @@
[(set (reg:CC FLAGS_REG)
(compare:CC (match_operand:SF 0 "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_op1 = operands[1];
@@ -935,30 +935,11 @@
;; Pentium Pro can do steps 1 through 3 in one go.
-(define_insn "*cmpfp_i"
- [(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"
+(define_insn "*cmpfp_i_mixed"
[(set (reg:CCFP FLAGS_REG)
(compare:CCFP (match_operand 0 "register_operand" "f#x,x#f")
(match_operand 1 "nonimmediate_operand" "f#x,xm#f")))]
- "TARGET_80387
+ "TARGET_MIX_SSE_I387
&& SSE_FLOAT_MODE_P (GET_MODE (operands[0]))
&& GET_MODE (operands[0]) == GET_MODE (operands[1])"
"* return output_fp_compare (insn, operands, 1, 0);"
@@ -969,11 +950,12 @@
(const_string "DF")))
(set_attr "athlon_decode" "vector")])
-(define_insn "*cmpfp_i_sse_only"
+(define_insn "*cmpfp_i_sse"
[(set (reg:CCFP FLAGS_REG)
(compare:CCFP (match_operand 0 "register_operand" "x")
(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])"
"* return output_fp_compare (insn, operands, 1, 0);"
[(set_attr "type" "ssecomi")
@@ -983,15 +965,15 @@
(const_string "DF")))
(set_attr "athlon_decode" "vector")])
-(define_insn "*cmpfp_iu"
- [(set (reg:CCFPU FLAGS_REG)
- (compare:CCFPU (match_operand 0 "register_operand" "f")
- (match_operand 1 "register_operand" "f")))]
+(define_insn "*cmpfp_i_i387"
+ [(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]))
+ && (!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);"
+ "* return output_fp_compare (insn, operands, 1, 0);"
[(set_attr "type" "fcmp")
(set (attr "mode")
(cond [(match_operand:SF 1 "" "")
@@ -1002,11 +984,11 @@
(const_string "XF")))
(set_attr "athlon_decode" "vector")])
-(define_insn "*cmpfp_iu_sse"
+(define_insn "*cmpfp_iu_mixed"
[(set (reg:CCFPU FLAGS_REG)
(compare:CCFPU (match_operand 0 "register_operand" "f#x,x#f")
(match_operand 1 "nonimmediate_operand" "f#x,xm#f")))]
- "TARGET_80387
+ "TARGET_MIX_SSE_I387
&& SSE_FLOAT_MODE_P (GET_MODE (operands[0]))
&& GET_MODE (operands[0]) == GET_MODE (operands[1])"
"* return output_fp_compare (insn, operands, 1, 1);"
@@ -1017,11 +999,12 @@
(const_string "DF")))
(set_attr "athlon_decode" "vector")])
-(define_insn "*cmpfp_iu_sse_only"
+(define_insn "*cmpfp_iu_sse"
[(set (reg:CCFPU FLAGS_REG)
(compare:CCFPU (match_operand 0 "register_operand" "x")
(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])"
"* return output_fp_compare (insn, operands, 1, 1);"
[(set_attr "type" "ssecomi")
@@ -1030,6 +1013,25 @@
(const_string "SF")
(const_string "DF")))
(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.
@@ -12683,7 +12685,7 @@
(if_then_else (match_dup 1)
(label_ref (match_operand 0 "" ""))
(pc)))]
- "TARGET_80387 || TARGET_SSE"
+ "TARGET_80387 || TARGET_SSE_MATH"
"ix86_expand_branch (UNORDERED, operands[0]); DONE;")
(define_expand "bordered"
@@ -12691,7 +12693,7 @@
(if_then_else (match_dup 1)
(label_ref (match_operand 0 "" ""))
(pc)))]
- "TARGET_80387 || TARGET_SSE"
+ "TARGET_80387 || TARGET_SSE_MATH"
"ix86_expand_branch (ORDERED, operands[0]); DONE;")
(define_expand "buneq"
@@ -12699,7 +12701,7 @@
(if_then_else (match_dup 1)
(label_ref (match_operand 0 "" ""))
(pc)))]
- "TARGET_80387 || TARGET_SSE"
+ "TARGET_80387 || TARGET_SSE_MATH"
"ix86_expand_branch (UNEQ, operands[0]); DONE;")
(define_expand "bunge"
@@ -12707,7 +12709,7 @@
(if_then_else (match_dup 1)
(label_ref (match_operand 0 "" ""))
(pc)))]
- "TARGET_80387 || TARGET_SSE"
+ "TARGET_80387 || TARGET_SSE_MATH"
"ix86_expand_branch (UNGE, operands[0]); DONE;")
(define_expand "bungt"
@@ -12715,7 +12717,7 @@
(if_then_else (match_dup 1)
(label_ref (match_operand 0 "" ""))
(pc)))]
- "TARGET_80387 || TARGET_SSE"
+ "TARGET_80387 || TARGET_SSE_MATH"
"ix86_expand_branch (UNGT, operands[0]); DONE;")
(define_expand "bunle"
@@ -12723,7 +12725,7 @@
(if_then_else (match_dup 1)
(label_ref (match_operand 0 "" ""))
(pc)))]
- "TARGET_80387 || TARGET_SSE"
+ "TARGET_80387 || TARGET_SSE_MATH"
"ix86_expand_branch (UNLE, operands[0]); DONE;")
(define_expand "bunlt"
@@ -12731,7 +12733,7 @@
(if_then_else (match_dup 1)
(label_ref (match_operand 0 "" ""))
(pc)))]
- "TARGET_80387 || TARGET_SSE"
+ "TARGET_80387 || TARGET_SSE_MATH"
"ix86_expand_branch (UNLT, operands[0]); DONE;")
(define_expand "bltgt"
@@ -12739,7 +12741,7 @@
(if_then_else (match_dup 1)
(label_ref (match_operand 0 "" ""))
(pc)))]
- "TARGET_80387 || TARGET_SSE"
+ "TARGET_80387 || TARGET_SSE_MATH"
"ix86_expand_branch (LTGT, operands[0]); DONE;")
(define_insn "*jcc_1"
@@ -12831,18 +12833,17 @@
;; during early optimization. Splitting the operation apart early makes
;; for bad code when we want to reverse the operation.
-(define_insn "*fp_jcc_1"
+(define_insn "*fp_jcc_1_mixed"
[(set (pc)
(if_then_else (match_operator 0 "comparison_operator"
- [(match_operand 1 "register_operand" "f")
- (match_operand 2 "register_operand" "f")])
+ [(match_operand 1 "register_operand" "f#x,x#f")
+ (match_operand 2 "nonimmediate_operand" "f#x,xm#f")])
(label_ref (match_operand 3 "" ""))
(pc)))
(clobber (reg:CCFP FPSR_REG))
(clobber (reg:CCFP FLAGS_REG))]
- "TARGET_CMOVE && TARGET_80387
- && !SSE_FLOAT_MODE_P (GET_MODE (operands[1]))
- && FLOAT_MODE_P (GET_MODE (operands[1]))
+ "TARGET_MIX_SSE_I387
+ && SSE_FLOAT_MODE_P (GET_MODE (operands[1]))
&& GET_MODE (operands[1]) == GET_MODE (operands[2])
&& ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
"#")
@@ -12850,44 +12851,44 @@
(define_insn "*fp_jcc_1_sse"
[(set (pc)
(if_then_else (match_operator 0 "comparison_operator"
- [(match_operand 1 "register_operand" "f#x,x#f")
- (match_operand 2 "nonimmediate_operand" "f#x,xm#f")])
+ [(match_operand 1 "register_operand" "x")
+ (match_operand 2 "nonimmediate_operand" "xm")])
(label_ref (match_operand 3 "" ""))
(pc)))
(clobber (reg:CCFP FPSR_REG))
(clobber (reg:CCFP FLAGS_REG))]
- "TARGET_80387
+ "TARGET_SSE_MATH
&& SSE_FLOAT_MODE_P (GET_MODE (operands[1]))
&& GET_MODE (operands[1]) == GET_MODE (operands[2])
&& ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
"#")
-(define_insn "*fp_jcc_1_sse_only"
+(define_insn "*fp_jcc_1_387"
[(set (pc)
(if_then_else (match_operator 0 "comparison_operator"
- [(match_operand 1 "register_operand" "x")
- (match_operand 2 "nonimmediate_operand" "xm")])
+ [(match_operand 1 "register_operand" "f")
+ (match_operand 2 "register_operand" "f")])
(label_ref (match_operand 3 "" ""))
(pc)))
(clobber (reg:CCFP FPSR_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])
&& ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
"#")
-(define_insn "*fp_jcc_2"
+(define_insn "*fp_jcc_2_mixed"
[(set (pc)
(if_then_else (match_operator 0 "comparison_operator"
- [(match_operand 1 "register_operand" "f")
- (match_operand 2 "register_operand" "f")])
+ [(match_operand 1 "register_operand" "f#x,x#f")
+ (match_operand 2 "nonimmediate_operand" "f#x,xm#f")])
(pc)
(label_ref (match_operand 3 "" ""))))
(clobber (reg:CCFP FPSR_REG))
(clobber (reg:CCFP FLAGS_REG))]
- "TARGET_CMOVE && TARGET_80387
- && !SSE_FLOAT_MODE_P (GET_MODE (operands[1]))
- && FLOAT_MODE_P (GET_MODE (operands[1]))
+ "TARGET_MIX_SSE_I387
+ && SSE_FLOAT_MODE_P (GET_MODE (operands[1]))
&& GET_MODE (operands[1]) == GET_MODE (operands[2])
&& ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
"#")
@@ -12895,33 +12896,34 @@
(define_insn "*fp_jcc_2_sse"
[(set (pc)
(if_then_else (match_operator 0 "comparison_operator"
- [(match_operand 1 "register_operand" "f#x,x#f")
- (match_operand 2 "nonimmediate_operand" "f#x,xm#f")])
+ [(match_operand 1 "register_operand" "x")
+ (match_operand 2 "nonimmediate_operand" "xm")])
(pc)
(label_ref (match_operand 3 "" ""))))
(clobber (reg:CCFP FPSR_REG))
(clobber (reg:CCFP FLAGS_REG))]
- "TARGET_80387
+ "TARGET_SSE_MATH
&& SSE_FLOAT_MODE_P (GET_MODE (operands[1]))
&& GET_MODE (operands[1]) == GET_MODE (operands[2])
&& ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
"#")
-(define_insn "*fp_jcc_2_sse_only"
+(define_insn "*fp_jcc_2_387"
[(set (pc)
(if_then_else (match_operator 0 "comparison_operator"
- [(match_operand 1 "register_operand" "x")
- (match_operand 2 "nonimmediate_operand" "xm")])
+ [(match_operand 1 "register_operand" "f")
+ (match_operand 2 "register_operand" "f")])
(pc)
(label_ref (match_operand 3 "" ""))))
(clobber (reg:CCFP FPSR_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])
&& ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
"#")
-(define_insn "*fp_jcc_3"
+(define_insn "*fp_jcc_3_387"
[(set (pc)
(if_then_else (match_operator 0 "comparison_operator"
[(match_operand 1 "register_operand" "f")
@@ -12940,7 +12942,7 @@
&& ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
"#")
-(define_insn "*fp_jcc_4"
+(define_insn "*fp_jcc_4_387"
[(set (pc)
(if_then_else (match_operator 0 "comparison_operator"
[(match_operand 1 "register_operand" "f")
@@ -12959,7 +12961,7 @@
&& ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
"#")
-(define_insn "*fp_jcc_5"
+(define_insn "*fp_jcc_5_387"
[(set (pc)
(if_then_else (match_operator 0 "comparison_operator"
[(match_operand 1 "register_operand" "f")
@@ -12975,7 +12977,7 @@
&& ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
"#")
-(define_insn "*fp_jcc_6"
+(define_insn "*fp_jcc_6_387"
[(set (pc)
(if_then_else (match_operator 0 "comparison_operator"
[(match_operand 1 "register_operand" "f")
@@ -12991,7 +12993,7 @@
&& ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
"#")
-(define_insn "*fp_jcc_7"
+(define_insn "*fp_jcc_7_387"
[(set (pc)
(if_then_else (match_operator 0 "comparison_operator"
[(match_operand 1 "register_operand" "f")
@@ -13015,7 +13017,7 @@
;; with a precedence over other operators and is always put in the first
;; place. Swap condition and operands to match ficom instruction.
-(define_insn "*fp_jcc_8"
+(define_insn "*fp_jcc_8_387"
[(set (pc)
(if_then_else (match_operator 0 "comparison_operator"
[(match_operator 1 "float_operator"
@@ -17417,7 +17419,7 @@
(set_attr "mode" "DI")
(set_attr "length_immediate" "0")])
-(define_insn "movdicc_c_rex64"
+(define_insn "*movdicc_c_rex64"
[(set (match_operand:DI 0 "register_operand" "=r,r")
(if_then_else:DI (match_operator 1 "ix86_comparison_operator"
[(reg FLAGS_REG) (const_int 0)])
@@ -17507,7 +17509,8 @@
(define_insn_and_split "*movqicc_noc"
[(set (match_operand:QI 0 "register_operand" "=r,r")
(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 3 "register_operand" "0,r")))]
"TARGET_CMOVE && !TARGET_PARTIAL_REG_STALL"
@@ -17528,16 +17531,61 @@
(if_then_else:SF (match_operand 1 "comparison_operator" "")
(match_operand:SF 2 "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;")
-(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")
(if_then_else:SF (match_operator 1 "fcmov_comparison_operator"
[(reg FLAGS_REG) (const_int 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")))]
- "TARGET_CMOVE
+ "TARGET_80387 && TARGET_CMOVE
&& (GET_CODE (operands[2]) != MEM || GET_CODE (operands[3]) != MEM)"
"@
fcmov%F1\t{%2, %0|%0, %2}
@@ -17552,16 +17600,61 @@
(if_then_else:DF (match_operand 1 "comparison_operator" "")
(match_operand:DF 2 "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;")
+;; 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"
[(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"
[(reg FLAGS_REG) (const_int 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")))]
- "!TARGET_64BIT && TARGET_CMOVE
+ "!TARGET_64BIT && TARGET_80387 && TARGET_CMOVE
&& (GET_CODE (operands[2]) != MEM || GET_CODE (operands[3]) != MEM)"
"@
fcmov%F1\t{%2, %0|%0, %2}
@@ -17577,7 +17670,7 @@
[(reg FLAGS_REG) (const_int 0)])
(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")))]
- "TARGET_64BIT && TARGET_CMOVE
+ "TARGET_64BIT && TARGET_80387 && TARGET_CMOVE
&& (GET_CODE (operands[2]) != MEM || GET_CODE (operands[3]) != MEM)"
"@
fcmov%F1\t{%2, %0|%0, %2}
@@ -17590,7 +17683,8 @@
(define_split
[(set (match_operand:DF 0 "register_and_not_any_fp_reg_operand" "")
(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 3 "nonimmediate_operand" "")))]
"!TARGET_64BIT && reload_completed"
@@ -17611,7 +17705,7 @@
(if_then_else:XF (match_operand 1 "comparison_operator" "")
(match_operand:XF 2 "register_operand" "")
(match_operand:XF 3 "register_operand" "")))]
- "TARGET_CMOVE"
+ "TARGET_80387 && TARGET_CMOVE"
"if (! ix86_expand_fp_movcc (operands)) FAIL; DONE;")
(define_insn "*movxfcc_1"
@@ -17620,62 +17714,53 @@
[(reg FLAGS_REG) (const_int 0)])
(match_operand:XF 2 "register_operand" "f,0")
(match_operand:XF 3 "register_operand" "0,f")))]
- "TARGET_CMOVE"
+ "TARGET_80387 && TARGET_CMOVE"
"@
fcmov%F1\t{%2, %0|%0, %2}
fcmov%f1\t{%3, %0|%0, %3}"
[(set_attr "type" "fcmov")
(set_attr "mode" "XF")])
-(define_expand "minsf3"
- [(parallel [
- (set (match_operand:SF 0 "register_operand" "")
- (if_then_else:SF (lt (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"
- "")
+;; These versions of the min/max patterns are intentionally ignorant of
+;; their behaviour wrt -0.0 and NaN (via the commutative operand mark).
+;; Since both the tree-level MAX_EXPR and the rtl-level SMAX operator
+;; are undefined in this condition, we're certain this is correct.
-(define_insn "*minsf"
- [(set (match_operand:SF 0 "register_operand" "=x#f,f#x,f#x")
- (if_then_else:SF (lt (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 "sminsf3"
+ [(set (match_operand:SF 0 "register_operand" "=x")
+ (smin:SF (match_operand:SF 1 "nonimmediate_operand" "%0")
+ (match_operand:SF 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE_MATH"
+ "minss\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseadd")
+ (set_attr "mode" "SF")])
-(define_insn "*minsf_nonieee"
- [(set (match_operand:SF 0 "register_operand" "=x#f,f#x")
- (if_then_else:SF (lt (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_insn "smaxsf3"
+ [(set (match_operand:SF 0 "register_operand" "=x")
+ (smax:SF (match_operand:SF 1 "nonimmediate_operand" "%0")
+ (match_operand:SF 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE_MATH"
+ "minss\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseadd")
+ (set_attr "mode" "SF")])
-(define_split
- [(set (match_operand:SF 0 "register_operand" "")
- (if_then_else:SF (lt (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 (lt (match_dup 1)
- (match_dup 2))
- (match_dup 1)
- (match_dup 2)))])
+(define_insn "smindf3"
+ [(set (match_operand:DF 0 "register_operand" "=x")
+ (smin:DF (match_operand:DF 1 "nonimmediate_operand" "%0")
+ (match_operand:DF 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2 && TARGET_SSE_MATH"
+ "minsd\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseadd")
+ (set_attr "mode" "DF")])
+
+(define_insn "smaxdf3"
+ [(set (match_operand:DF 0 "register_operand" "=x")
+ (smax:DF (match_operand:DF 1 "nonimmediate_operand" "%0")
+ (match_operand:DF 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2 && TARGET_SSE_MATH"
+ "maxsd\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseadd")
+ (set_attr "mode" "DF")])
;; Conditional addition patterns
(define_expand "addqicc"
@@ -17710,282 +17795,6 @@
"TARGET_64BIT"
"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 (?)
@@ -18107,364 +17916,6 @@
[(set_attr "type" "alu,lea")
(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"
[(match_operand:SI 0 "register_operand" "")]
"TARGET_STACK_PROBE"