From eaa49b49418e32fc83f5b99217e6e7fc0cfeff32 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Thu, 13 Jan 2005 16:33:49 -0800 Subject: [PATCH] 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 --- gcc/ChangeLog | 35 ++ gcc/config/i386/i386-protos.h | 1 + gcc/config/i386/i386.c | 247 +++++---- gcc/config/i386/i386.md | 983 ++++++++-------------------------- 4 files changed, 389 insertions(+), 877 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a9451b2c6c0f..6195716e02a2 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,38 @@ +2005-01-13 Richard Henderson + + 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 * 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 33bf6fc6c9bc..06c857770a99 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 cb73a18e9150..4bc0c7533b56 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 194c218c163f..674d0935740a 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" -- 2.43.5