diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 7bebe8258219794ef423bb8eb7a44f6e4700b109..dc35a49316b7d81d65fc624f0c23e03fd27fc591 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,13 @@
+2007-06-30  Uros Bizjak  <ubizjak@gmail.com>
+
+	PR target/32433
+	* config/i386/i386.md (ffssi2): Expand as ffs_cmove for TARGET_CMOVE.
+	(ffs_cmove): New expander to expand using ctz pattern.
+	(*ffs_cmove): Remove pattern.
+	(*ffs_no_cmove): Enable only for !TARGET_CMOVE.
+	(ffsdi2): Expand using ctz pattern.
+	(*ffs_rex64): Remove pattern.
+
 2007-06-30  John David Anglin  <dave.anglin@nrc-cnrc.gc.ca>
 
 	PR rtl-optimization/32296
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index c8bff3e00620c913a0bedb69b1e044d8e1a44bf3..a57d4d65ea78b7e7088a95c71d6b87b1d5f63c5a 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -14586,36 +14586,40 @@
       (clobber (match_scratch:SI 2 ""))
       (clobber (reg:CC FLAGS_REG))])]
   ""
-  "")
+{
+  if (TARGET_CMOVE)
+    {
+      emit_insn (gen_ffs_cmove (operands[0], operands[1]));
+      DONE;
+    }
+})
 
-(define_insn_and_split "*ffs_cmove"
-  [(set (match_operand:SI 0 "register_operand" "=r")
-	(ffs:SI (match_operand:SI 1 "nonimmediate_operand" "rm")))
-   (clobber (match_scratch:SI 2 "=&r"))
-   (clobber (reg:CC FLAGS_REG))]
-  "TARGET_CMOVE"
-  "#"
-  "&& reload_completed"
+(define_expand "ffs_cmove"
   [(set (match_dup 2) (const_int -1))
-   (parallel [(set (reg:CCZ FLAGS_REG) (compare:CCZ (match_dup 1) (const_int 0)))
-	      (set (match_dup 0) (ctz:SI (match_dup 1)))])
+   (parallel [(set (reg:CCZ FLAGS_REG)
+		   (compare:CCZ (match_operand:SI 1 "register_operand" "")
+				(const_int 0)))
+	      (set (match_operand:SI 0 "nonimmediate_operand" "")
+		   (ctz:SI (match_dup 1)))])
    (set (match_dup 0) (if_then_else:SI
 			(eq (reg:CCZ FLAGS_REG) (const_int 0))
 			(match_dup 2)
 			(match_dup 0)))
    (parallel [(set (match_dup 0) (plus:SI (match_dup 0) (const_int 1)))
 	      (clobber (reg:CC FLAGS_REG))])]
-  "")
+  "TARGET_CMOVE"
+  "operands[2] = gen_reg_rtx (SImode);")
 
 (define_insn_and_split "*ffs_no_cmove"
   [(set (match_operand:SI 0 "nonimmediate_operand" "=r")
 	(ffs:SI (match_operand:SI 1 "nonimmediate_operand" "rm")))
    (clobber (match_scratch:SI 2 "=&q"))
    (clobber (reg:CC FLAGS_REG))]
-  ""
+  "!TARGET_CMOVE"
   "#"
-  "reload_completed"
-  [(parallel [(set (reg:CCZ FLAGS_REG) (compare:CCZ (match_dup 1) (const_int 0)))
+  "&& reload_completed"
+  [(parallel [(set (reg:CCZ FLAGS_REG)
+		   (compare:CCZ (match_dup 1) (const_int 0)))
 	      (set (match_dup 0) (ctz:SI (match_dup 1)))])
    (set (strict_low_part (match_dup 3))
 	(eq:QI (reg:CCZ FLAGS_REG) (const_int 0)))
@@ -14641,33 +14645,20 @@
   [(set_attr "prefix_0f" "1")])
 
 (define_expand "ffsdi2"
-  [(parallel
-     [(set (match_operand:DI 0 "register_operand" "")
-	   (ffs:DI (match_operand:DI 1 "nonimmediate_operand" "")))
-      (clobber (match_scratch:DI 2 ""))
-      (clobber (reg:CC FLAGS_REG))])]
-  "TARGET_64BIT && TARGET_CMOVE"
-  "")
-
-(define_insn_and_split "*ffs_rex64"
-  [(set (match_operand:DI 0 "register_operand" "=r")
-	(ffs:DI (match_operand:DI 1 "nonimmediate_operand" "rm")))
-   (clobber (match_scratch:DI 2 "=&r"))
-   (clobber (reg:CC FLAGS_REG))]
-  "TARGET_64BIT && TARGET_CMOVE"
-  "#"
-  "&& reload_completed"
   [(set (match_dup 2) (const_int -1))
    (parallel [(set (reg:CCZ FLAGS_REG)
-		   (compare:CCZ (match_dup 1) (const_int 0)))
-	      (set (match_dup 0) (ctz:DI (match_dup 1)))])
+		   (compare:CCZ (match_operand:DI 1 "register_operand" "")
+				(const_int 0)))
+	      (set (match_operand:DI 0 "nonimmediate_operand" "")
+		   (ctz:DI (match_dup 1)))])
    (set (match_dup 0) (if_then_else:DI
 			(eq (reg:CCZ FLAGS_REG) (const_int 0))
 			(match_dup 2)
 			(match_dup 0)))
    (parallel [(set (match_dup 0) (plus:DI (match_dup 0) (const_int 1)))
 	      (clobber (reg:CC FLAGS_REG))])]
-  "")
+  "TARGET_64BIT"
+  "operands[2] = gen_reg_rtx (DImode);")
 
 (define_insn "*ffsdi_1"
   [(set (reg:CCZ FLAGS_REG)