Index: i386.c
===================================================================
--- i386.c	(revision 189746)
+++ i386.c	(working copy)
@@ -11576,9 +11576,18 @@ ix86_decompose_address (rtx addr, struct ix86_addr
   int retval = 1;
   enum ix86_address_seg seg = SEG_DEFAULT;
 
+  /* Allow SImode subregs of DImode addresses,
+     they will be emitted with addr32 prefix.  */
+  if (TARGET_64BIT && GET_MODE (addr) == SImode)
+    {
+      if (GET_CODE (addr) == SUBREG
+	  && GET_MODE (XEXP (addr, 0)) == DImode)
+	addr = SUBREG_REG (addr);
+    }
+
   /* Allow zero-extended SImode addresses,
      they will be emitted with addr32 prefix.  */
-  if (TARGET_64BIT && GET_MODE (addr) == DImode)
+  else if (TARGET_64BIT && GET_MODE (addr) == DImode)
     {
       if (GET_CODE (addr) == ZERO_EXTEND
 	  && GET_MODE (XEXP (addr, 0)) == SImode)
@@ -14755,10 +14764,10 @@ ix86_print_operand_address (FILE *file, rtx addr)
     }
   else
     {
-      /* Print SImode register names for zero-extended
-	 addresses to force addr32 prefix.  */
+      /* Print SImode register names to force addr32 prefix.  */
       if (TARGET_64BIT
-	  && (GET_CODE (addr) == ZERO_EXTEND
+	  && (GET_CODE (addr) == SUBREG
+	      || GET_CODE (addr) == ZERO_EXTEND
 	      || GET_CODE (addr) == AND))
 	{
 	  gcc_assert (!code);
@@ -16855,6 +16864,11 @@ ix86_avoid_lea_for_add (rtx insn, rtx operands[])
   unsigned int regno1 = true_regnum (operands[1]);
   unsigned int regno2 = true_regnum (operands[2]);
 
+  /* FIXME: Handle zero-extended addresses.  */
+  if (GET_CODE (operands[1]) == ZERO_EXTEND
+      || GET_CODE (operands[1]) == AND)
+    return false;
+
   /* Check if we need to optimize.  */
   if (!TARGET_OPT_AGU || optimize_function_for_size_p (cfun))
     return false;
Index: predicates.md
===================================================================
--- predicates.md	(revision 189746)
+++ predicates.md	(working copy)
@@ -830,11 +830,6 @@
   struct ix86_address parts;
   int ok;
 
-  /*  LEA handles zero-extend by itself.  */
-  if (GET_CODE (op) == ZERO_EXTEND
-      || GET_CODE (op) == AND)
-    return false;
-
   ok = ix86_decompose_address (op, &parts);
   gcc_assert (ok);
   return parts.seg == SEG_DEFAULT;
Index: constraints.md
===================================================================
--- constraints.md	(revision 189746)
+++ constraints.md	(working copy)
@@ -19,7 +19,7 @@
 
 ;;; Unused letters:
 ;;;     B     H           T
-;;;           h  k          v
+;;;           h jk          v
 
 ;; Integer register constraints.
 ;; It is not necessary to define 'r' here.
@@ -133,11 +133,6 @@
   (and (not (match_test "TARGET_X32"))
        (match_operand 0 "memory_operand")))
 
-(define_address_constraint "j"
-  "@internal Address operand that can be zero extended in LEA instruction."
-  (and (not (match_code "const_int"))
-       (match_operand 0 "address_operand")))
-
 ;; Integer constant constraints.
 (define_constraint "I"
   "Integer constant in the range 0 @dots{} 31, for 32-bit shifts."
Index: i386.md
===================================================================
--- i386.md	(revision 189746)
+++ i386.md	(working copy)
@@ -5508,25 +5508,21 @@
   [(set_attr "type" "alu")
    (set_attr "mode" "QI")])
 
-(define_insn_and_split "*lea_1"
-  [(set (match_operand:SI 0 "register_operand" "=r")
-	(subreg:SI (match_operand:DI 1 "lea_address_operand" "p") 0))]
-  "TARGET_64BIT"
-  "lea{l}\t{%E1, %0|%0, %E1}"
-  "&& reload_completed && ix86_avoid_lea_for_addr (insn, operands)"
-  [(const_int 0)]
-{
-  ix86_split_lea_for_addr (operands, SImode);
-  DONE;
-}
-  [(set_attr "type" "lea")
-   (set_attr "mode" "SI")])
-
-(define_insn_and_split "*lea<mode>_2"
+(define_insn_and_split "*lea<mode>"
   [(set (match_operand:SWI48 0 "register_operand" "=r")
 	(match_operand:SWI48 1 "lea_address_operand" "p"))]
   ""
-  "lea{<imodesuffix>}\t{%E1, %0|%0, %E1}"
+{
+  rtx addr = operands[1];
+
+  if (GET_CODE (addr) == SUBREG)
+    return "lea{l}\t{%E1, %0|%0, %E1}";
+  else if (GET_CODE (addr) == ZERO_EXTEND
+	   || GET_CODE (addr) == AND)
+    return "lea{l}\t{%E1, %k0|%k0, %E1}";
+  else 
+    return "lea{<imodesuffix>}\t{%E1, %0|%0, %E1}";
+}
   "reload_completed && ix86_avoid_lea_for_addr (insn, operands)"
   [(const_int 0)]
 {
@@ -5536,44 +5532,6 @@
   [(set_attr "type" "lea")
    (set_attr "mode" "<MODE>")])
 
-(define_insn "*lea_3_zext"
-  [(set (match_operand:DI 0 "register_operand" "=r")
-	(zero_extend:DI
-	  (subreg:SI (match_operand:DI 1 "lea_address_operand" "j") 0)))]
-  "TARGET_64BIT"
-  "lea{l}\t{%E1, %k0|%k0, %E1}"
-  [(set_attr "type" "lea")
-   (set_attr "mode" "SI")])
-
-(define_insn "*lea_4_zext"
-  [(set (match_operand:DI 0 "register_operand" "=r")
-	(zero_extend:DI
-	  (match_operand:SI 1 "lea_address_operand" "j")))]
-  "TARGET_64BIT"
-  "lea{l}\t{%E1, %k0|%k0, %E1}"
-  [(set_attr "type" "lea")
-   (set_attr "mode" "SI")])
-
-(define_insn "*lea_5_zext"
-  [(set (match_operand:DI 0 "register_operand" "=r")
-	(and:DI
-	  (subreg:DI (match_operand:SI 1 "lea_address_operand" "p") 0)
-	  (match_operand:DI 2 "const_32bit_mask" "n")))]
-  "TARGET_64BIT"
-  "lea{l}\t{%E1, %k0|%k0, %E1}"
-  [(set_attr "type" "lea")
-   (set_attr "mode" "SI")])
-
-(define_insn "*lea_6_zext"
-  [(set (match_operand:DI 0 "register_operand" "=r")
-	(and:DI
-	  (match_operand:DI 1 "lea_address_operand" "p")
-	  (match_operand:DI 2 "const_32bit_mask" "n")))]
-  "TARGET_64BIT"
-  "lea{l}\t{%E1, %k0|%k0, %E1}"
-  [(set_attr "type" "lea")
-   (set_attr "mode" "SI")])
-
 (define_insn "*add<mode>_1"
   [(set (match_operand:SWI48 0 "nonimmediate_operand" "=r,rm,r,r")
 	(plus:SWI48
