re PR target/19009 (Loading of FP constants into FP reg via SSE reg)
authorRichard Henderson <rth@redhat.com>
Fri, 14 Jan 2005 00:33:49 +0000 (16:33 -0800)
committerRichard Henderson <rth@gcc.gnu.org>
Fri, 14 Jan 2005 00:33:49 +0000 (16:33 -0800)
        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
gcc/config/i386/i386-protos.h
gcc/config/i386/i386.c
gcc/config/i386/i386.md

index a9451b2c6c0fe22577836a2d2db3f1f570091946..6195716e02a297f5d217fcb5fd1d5c6a3933cf4d 100644 (file)
@@ -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.
index 33bf6fc6c9bc73ce82be1588823542403dd0e482..06c857770a99eea4ecbfdbc58bc0620884f7c90b 100644 (file)
@@ -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);
index cb73a18e9150aa9362e8f5f7daa8e37fe94e507a..4bc0c7533b567626bbc161e49ccfeb21f82e3ffc 100644 (file)
@@ -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.  */
index 194c218c163f4ad789448aa083e939be11e762f9..674d0935740aaf47126305640318ce0e7b992605 100644 (file)
   [(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];
   [(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];
 
 ;; 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);"
         (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")
         (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 "" "")
           (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);"
         (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")
         (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")])
 \f
 ;; Move instructions.
 
        (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"
        (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"
        (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"
        (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"
        (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"
        (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"
        (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"
        (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"
 ;; 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]))"
   "#")
 (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]))"
   "#")
 (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")
    && 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")
    && 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")
    && 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")
    && 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")
 ;; 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"
    (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)])
 (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"
        (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}
        (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}
                                [(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}
 (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"
        (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"
                                [(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"
   "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")])
 \f
 ;; Misc patterns (?)
 
   [(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"