Patchwork [4.7,RFT,i386] : Backport recent LEA improvements to 4.7 branch

login
register
mail settings
Submitter Uros Bizjak
Date July 24, 2012, 7:32 p.m.
Message ID <CAFULd4ZSP6ex6YqucQyms9mXA5Fr_uXWrQ4SrSXvF=Nw8=r9vg@mail.gmail.com>
Download mbox | patch
Permalink /patch/173038/
State New
Headers show

Comments

Uros Bizjak - July 24, 2012, 7:32 p.m.
Hello!

Attached patch backports recent LEA improvements to 4.7 branch. The
patch unifies handling of LEA addresses with generic address handling,
allowing some more zero-extended addresses for both cases.

2012-XX-XX  Uros Bizjak  <ubizjak@gmail.com>

	Backport from mainline
	2012-07-24  Uros Bizjak  <ubizjak@gmail.com>

	PR target/53961
	* config/i386/i386.c (ix86_legitimate_address_p): Move check for
	negative constant address for TARGET_X32 ...
	(ix86_decompose_address): ... here.  Reject constant addresses
	that don't satisfy x86_64_immediate_operand predicate.

	2012-07-23  Uros Bizjak  <ubizjak@gmail.com>

	PR target/53961
	* config/i386/i386.md (*lea): Add asserts to detect invalid addresses.
	* config/i386/i386.c (ix86_print_operand_address): Ditto.
	(ix86_decompose_address): Allow (zero_extend:DI (subreg:SI (...)))
	addresses.  Prevent zero extensions of CONST_INT operands.

	2012-07-22  Uros Bizjak  <ubizjak@gmail.com>

	PR target/53961
	* config/i386/i386.md (*lea): New insn pattern.
	(*lea_1): Remove.
	(*lea<mode>_2): Ditto.
	(*lea_{3,4,5,6}_zext): Ditto.
	* config/i386/predicates.md (lea_address_operand): Do not reject
	zero-extended address operands.
	* config/i386/constraints.md (j): Remove address constraint.
	* config/i386/i386.c (ix86_decompose_address): Allow SImode subreg
	of an address.
	(ix86_print_operand_address): Handle SImode subreg of an address.
	(ix86_avoid_lea_for_addr): Reject zero-extended addresses for now.

	2012-03-09  Uros Bizjak  <ubizjak@gmail.com>

	PR target/52530
	* config/i386/i386.c (ix86_print_operand): Handle 'E' operand modifier.
	(ix86_print_operand_address): Handle UNSPEC_LEA_ADDR. Do not fallback
	to set code to 'q'.
	* config/i386/i386.md (UNSPEC_LEA_ADDR): New unspec.
	(*movdi_internal_rex64): Use %E operand modifier for lea.
	(*movsi_internal): Ditto.
	(*lea_1): Ditto.
	(*lea<mode>_2): Ditto.
	(*lea_{3,4,5,6}_zext): Ditto.
	(*tls_global_dynamic_32_gnu): Ditto.
	(*tls_global_dynamic_64): Ditto.
	(*tls_dynamic_gnu2_lea_32): Ditto.
	(*tls_dynamic_gnu2_lea_64): Ditto.
	(pro_epilogue_adjust_stack_<mode>_add): Ditto.

testsuite/ChangeLog:

2012-XX-XX  Uros Bizjak  <ubizjak@gmail.com>

	Backport from mainline
	2012-03-11  Uros Bizjak  <ubizjak@gmail.com>

	PR target/52530
	* gcc.dg/torture/pr52530.c: New test.

Patch was bootstrapped and regression tested on x86_64-pc-linux-gnu
{,-m32} and various x32 compile tests. However, this patch needs
further testing on a real x32 target and maybe SPEC 2000/2006
benchmark for x86_64, i686 and x32 target. On mainline, this patch
works OK everywhere.

Uros.
Richard Guenther - July 25, 2012, 11:45 a.m.
On Tue, Jul 24, 2012 at 9:32 PM, Uros Bizjak <ubizjak@gmail.com> wrote:
> Hello!
>
> Attached patch backports recent LEA improvements to 4.7 branch.

As in regression fixes, or wrong-code fixes?  This looks suspiciously not
appropriate for 4.7 ...

Richard.

> The
> patch unifies handling of LEA addresses with generic address handling,
> allowing some more zero-extended addresses for both cases.
>
> 2012-XX-XX  Uros Bizjak  <ubizjak@gmail.com>
>
>         Backport from mainline
>         2012-07-24  Uros Bizjak  <ubizjak@gmail.com>
>
>         PR target/53961
>         * config/i386/i386.c (ix86_legitimate_address_p): Move check for
>         negative constant address for TARGET_X32 ...
>         (ix86_decompose_address): ... here.  Reject constant addresses
>         that don't satisfy x86_64_immediate_operand predicate.
>
>         2012-07-23  Uros Bizjak  <ubizjak@gmail.com>
>
>         PR target/53961
>         * config/i386/i386.md (*lea): Add asserts to detect invalid addresses.
>         * config/i386/i386.c (ix86_print_operand_address): Ditto.
>         (ix86_decompose_address): Allow (zero_extend:DI (subreg:SI (...)))
>         addresses.  Prevent zero extensions of CONST_INT operands.
>
>         2012-07-22  Uros Bizjak  <ubizjak@gmail.com>
>
>         PR target/53961
>         * config/i386/i386.md (*lea): New insn pattern.
>         (*lea_1): Remove.
>         (*lea<mode>_2): Ditto.
>         (*lea_{3,4,5,6}_zext): Ditto.
>         * config/i386/predicates.md (lea_address_operand): Do not reject
>         zero-extended address operands.
>         * config/i386/constraints.md (j): Remove address constraint.
>         * config/i386/i386.c (ix86_decompose_address): Allow SImode subreg
>         of an address.
>         (ix86_print_operand_address): Handle SImode subreg of an address.
>         (ix86_avoid_lea_for_addr): Reject zero-extended addresses for now.
>
>         2012-03-09  Uros Bizjak  <ubizjak@gmail.com>
>
>         PR target/52530
>         * config/i386/i386.c (ix86_print_operand): Handle 'E' operand modifier.
>         (ix86_print_operand_address): Handle UNSPEC_LEA_ADDR. Do not fallback
>         to set code to 'q'.
>         * config/i386/i386.md (UNSPEC_LEA_ADDR): New unspec.
>         (*movdi_internal_rex64): Use %E operand modifier for lea.
>         (*movsi_internal): Ditto.
>         (*lea_1): Ditto.
>         (*lea<mode>_2): Ditto.
>         (*lea_{3,4,5,6}_zext): Ditto.
>         (*tls_global_dynamic_32_gnu): Ditto.
>         (*tls_global_dynamic_64): Ditto.
>         (*tls_dynamic_gnu2_lea_32): Ditto.
>         (*tls_dynamic_gnu2_lea_64): Ditto.
>         (pro_epilogue_adjust_stack_<mode>_add): Ditto.
>
> testsuite/ChangeLog:
>
> 2012-XX-XX  Uros Bizjak  <ubizjak@gmail.com>
>
>         Backport from mainline
>         2012-03-11  Uros Bizjak  <ubizjak@gmail.com>
>
>         PR target/52530
>         * gcc.dg/torture/pr52530.c: New test.
>
> Patch was bootstrapped and regression tested on x86_64-pc-linux-gnu
> {,-m32} and various x32 compile tests. However, this patch needs
> further testing on a real x32 target and maybe SPEC 2000/2006
> benchmark for x86_64, i686 and x32 target. On mainline, this patch
> works OK everywhere.
>
> Uros.
Uros Bizjak - July 25, 2012, 12:33 p.m.
On Wed, Jul 25, 2012 at 1:45 PM, Richard Guenther
<richard.guenther@gmail.com> wrote:
> On Tue, Jul 24, 2012 at 9:32 PM, Uros Bizjak <ubizjak@gmail.com> wrote:
>> Hello!
>>
>> Attached patch backports recent LEA improvements to 4.7 branch.
>
> As in regression fixes, or wrong-code fixes?  This looks suspiciously not
> appropriate for 4.7 ...

I consider this patch a real fix for PR target/53961. Current "fix"
just papers over the problem by changing addresses, zero-extended with
AND, with real ZERO_EXTEND addresses in expand. But, there remain
other similar problems.

Uros.
Uros Bizjak - Aug. 2, 2012, 4:29 p.m.
On Wed, Jul 25, 2012 at 2:33 PM, Uros Bizjak <ubizjak@gmail.com> wrote:

> On Wed, Jul 25, 2012 at 1:45 PM, Richard Guenther
> <richard.guenther@gmail.com> wrote:
>> On Tue, Jul 24, 2012 at 9:32 PM, Uros Bizjak <ubizjak@gmail.com> wrote:
>>> Hello!
>>>
>>> Attached patch backports recent LEA improvements to 4.7 branch.
>>
>> As in regression fixes, or wrong-code fixes?  This looks suspiciously not
>> appropriate for 4.7 ...
>
> I consider this patch a real fix for PR target/53961. Current "fix"
> just papers over the problem by changing addresses, zero-extended with
> AND, with real ZERO_EXTEND addresses in expand. But, there remain
> other similar problems.

The patch was also tested on spec2000/spec2006 for i686/x86_64/x32 by
H.J. (thanks!).

Re-bootstrapped, re-tested on x86_64-pc-linux-gnu {-m32}, also with
-mx32, by H.J.

Committed to 4.7 branch.

Uros.

Patch

Index: config/i386/i386.c
===================================================================
--- config/i386/i386.c	(revision 189815)
+++ config/i386/i386.c	(working copy)
@@ -11421,19 +11421,44 @@  ix86_decompose_address (rtx addr, struct ix86_addr
     {
       if (GET_CODE (addr) == ZERO_EXTEND
 	  && GET_MODE (XEXP (addr, 0)) == SImode)
-	addr = XEXP (addr, 0);
+	{
+	  addr = XEXP (addr, 0);
+	  if (CONST_INT_P (addr))
+	    return 0;
+	}	      
       else if (GET_CODE (addr) == AND
 	       && const_32bit_mask (XEXP (addr, 1), DImode))
 	{
 	  addr = XEXP (addr, 0);
 
-	  /* Strip subreg.  */
+	  /* Adjust SUBREGs.  */
 	  if (GET_CODE (addr) == SUBREG
 	      && GET_MODE (SUBREG_REG (addr)) == SImode)
-	    addr = SUBREG_REG (addr);
+	    {
+	      addr = SUBREG_REG (addr);
+	      if (CONST_INT_P (addr))
+		return 0;
+	    }
+	  else if (GET_MODE (addr) == DImode)
+	    addr = gen_rtx_SUBREG (SImode, addr, 0);
+	  else if (GET_MODE (addr) != VOIDmode)
+	    return 0;
 	}
     }
 
+  /* 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 (SUBREG_REG (addr)) == DImode)
+	{
+	  addr = SUBREG_REG (addr);
+	  if (CONST_INT_P (addr))
+	    return 0;
+	}
+    }
+
   if (REG_P (addr))
     base = addr;
   else if (GET_CODE (addr) == SUBREG)
@@ -11541,6 +11566,19 @@  ix86_decompose_address (rtx addr, struct ix86_addr
       scale = 1 << scale;
       retval = -1;
     }
+  else if (CONST_INT_P (addr))
+    {
+      if (!x86_64_immediate_operand (addr, VOIDmode))
+	return 0;
+
+      /* Constant addresses are sign extended to 64bit, we have to
+	 prevent addresses from 0x80000000 to 0xffffffff in x32 mode.  */
+      if (TARGET_X32
+	  && val_signbit_known_set_p (SImode, INTVAL (addr)))
+	return 0;
+
+      disp = addr;
+    }
   else
     disp = addr;			/* displacement */
 
@@ -12044,13 +12082,6 @@  ix86_legitimate_address_p (enum machine_mode mode
   rtx base, index, disp;
   HOST_WIDE_INT scale;
 
-  /* Since constant address in x32 is signed extended to 64bit,
-     we have to prevent addresses from 0x80000000 to 0xffffffff.  */
-  if (TARGET_X32
-      && CONST_INT_P (addr)
-      && INTVAL (addr) < 0)
-    return false;
-
   if (ix86_decompose_address (addr, &parts) <= 0)
     /* Decomposition failed.  */
     return false;
@@ -13883,7 +13914,14 @@  ix86_print_operand (FILE *file, rtx x, int code)
 	  ix86_print_operand (file, x, 0);
 	  return;
 
+	case 'E':
+	  /* Wrap address in an UNSPEC to declare special handling.  */
+	  if (TARGET_64BIT)
+	    x = gen_rtx_UNSPEC (DImode, gen_rtvec (1, x), UNSPEC_LEA_ADDR);
 
+	  output_address (x);
+	  return;
+
 	case 'L':
 	  if (ASSEMBLER_DIALECT == ASM_ATT)
 	    putc ('l', file);
@@ -14488,6 +14526,7 @@  ix86_print_operand_address (FILE *file, rtx addr)
   int scale;
   int ok;
   bool vsib = false;
+  int code = 0;
 
   if (GET_CODE (addr) == UNSPEC && XINT (addr, 1) == UNSPEC_VSIBADDR)
     {
@@ -14498,6 +14537,12 @@  ix86_print_operand_address (FILE *file, rtx addr)
       addr = XVECEXP (addr, 0, 0);
       vsib = true;
     }
+  else if (GET_CODE (addr) == UNSPEC && XINT (addr, 1) == UNSPEC_LEA_ADDR)
+    {
+      gcc_assert (TARGET_64BIT);
+      ok = ix86_decompose_address (XVECEXP (addr, 0, 0), &parts);
+      code = 'q';
+    }
   else
     ok = ix86_decompose_address (addr, &parts);
 
@@ -14568,16 +14613,24 @@  ix86_print_operand_address (FILE *file, rtx addr)
     }
   else
     {
-      int code = 0;
+      /* Print SImode register names to force addr32 prefix.  */
+      if (GET_CODE (addr) == SUBREG)
+	{
+	  gcc_assert (TARGET_64BIT);
+	  gcc_assert (GET_MODE (addr) == SImode);
+	  gcc_assert (GET_MODE (SUBREG_REG (addr)) == DImode);
+	  gcc_assert (!code);
+	  code = 'l';
+	}
+      else if (GET_CODE (addr) == ZERO_EXTEND
+	       || GET_CODE (addr) == AND)
+	{
+	  gcc_assert (TARGET_64BIT);
+	  gcc_assert (GET_MODE (addr) == DImode);
+	  gcc_assert (!code);
+	  code = 'l';
+	}
 
-      /* Print SImode registers for zero-extended addresses to force
-	 addr32 prefix.  Otherwise print DImode registers to avoid it.  */
-      if (TARGET_64BIT)
-	code = ((GET_CODE (addr) == ZERO_EXTEND
-		 || GET_CODE (addr) == AND)
-		? 'l'
-		: 'q');
-
       if (ASSEMBLER_DIALECT == ASM_ATT)
 	{
 	  if (disp)
@@ -16781,6 +16834,11 @@  ix86_avoid_lea_for_addr (rtx insn, rtx operands[])
   struct ix86_address parts;
   int ok;
 
+  /* FIXME: Handle zero-extended addresses.  */
+  if (GET_CODE (operands[1]) == ZERO_EXTEND
+      || GET_CODE (operands[1]) == AND)
+    return false;
+
   /* Check we need to optimize.  */
   if (!TARGET_OPT_AGU || optimize_function_for_size_p (cfun))
     return false;
Index: config/i386/predicates.md
===================================================================
--- config/i386/predicates.md	(revision 189815)
+++ config/i386/predicates.md	(working copy)
@@ -817,11 +817,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: config/i386/i386.md
===================================================================
--- config/i386/i386.md	(revision 189815)
+++ config/i386/i386.md	(working copy)
@@ -107,6 +107,7 @@ 
   UNSPEC_MS_TO_SYSV_CALL
   UNSPEC_CALL_NEEDS_VZEROUPPER
   UNSPEC_PAUSE
+  UNSPEC_LEA_ADDR
 
   ;; For SSE/MMX support:
   UNSPEC_FIX_NOTRUNC
@@ -1956,7 +1957,7 @@ 
       return "#";
 
     case TYPE_LEA:
-      return "lea{q}\t{%a1, %0|%0, %a1}";
+      return "lea{q}\t{%E1, %0|%0, %E1}";
 
     default:
       gcc_assert (!flag_pic || LEGITIMATE_PIC_OPERAND_P (operands[1]));
@@ -1965,7 +1966,7 @@ 
       else if (which_alternative == 2)
 	return "movabs{q}\t{%1, %0|%0, %1}";
       else if (ix86_use_lea_for_mov (insn, operands))
-	return "lea{q}\t{%a1, %0|%0, %a1}";
+	return "lea{q}\t{%E1, %0|%0, %E1}";
       else
 	return "mov{q}\t{%1, %0|%0, %1}";
     }
@@ -2197,12 +2198,12 @@ 
       return "movd\t{%1, %0|%0, %1}";
 
     case TYPE_LEA:
-      return "lea{l}\t{%a1, %0|%0, %a1}";
+      return "lea{l}\t{%E1, %0|%0, %E1}";
 
     default:
       gcc_assert (!flag_pic || LEGITIMATE_PIC_OPERAND_P (operands[1]));
       if (ix86_use_lea_for_mov (insn, operands))
-	return "lea{l}\t{%a1, %0|%0, %a1}";
+	return "lea{l}\t{%E1, %0|%0, %E1}";
       else
 	return "mov{l}\t{%1, %0|%0, %1}";
     }
@@ -5373,6 +5374,41 @@ 
   DONE;
 })
 
+;; Load effective address instructions
+
+(define_insn_and_split "*lea<mode>"
+  [(set (match_operand:SWI48 0 "register_operand" "=r")
+	(match_operand:SWI48 1 "lea_address_operand" "p"))]
+  ""
+{
+  rtx addr = operands[1];
+
+  if (GET_CODE (addr) == SUBREG)
+    {
+      gcc_assert (TARGET_64BIT);
+      gcc_assert (<MODE>mode == SImode);
+      gcc_assert (GET_MODE (SUBREG_REG (addr)) == DImode);
+      return "lea{l}\t{%E1, %0|%0, %E1}";
+    }
+  else if (GET_CODE (addr) == ZERO_EXTEND
+	   || GET_CODE (addr) == AND)
+    {
+      gcc_assert (TARGET_64BIT);
+      gcc_assert (<MODE>mode == DImode);
+      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)]
+{
+  ix86_split_lea_for_addr (operands, <MODE>mode);
+  DONE;
+}
+  [(set_attr "type" "lea")
+   (set_attr "mode" "<MODE>")])
+
 ;; Add instructions
 
 (define_expand "add<mode>3"
@@ -5431,72 +5467,6 @@ 
   [(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{%a1, %0|%0, %a1}"
-  "&& 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"
-  [(set (match_operand:SWI48 0 "register_operand" "=r")
-	(match_operand:SWI48 1 "lea_address_operand" "p"))]
-  ""
-  "lea{<imodesuffix>}\t{%a1, %0|%0, %a1}"
-  "reload_completed && ix86_avoid_lea_for_addr (insn, operands)"
-  [(const_int 0)]
-{
-  ix86_split_lea_for_addr (operands, <MODE>mode);
-  DONE;
-}
-  [(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{%a1, %k0|%k0, %a1}"
-  [(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{%a1, %k0|%k0, %a1}"
-  [(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{%a1, %k0|%k0, %a1}"
-  [(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{%a1, %k0|%k0, %a1}"
-  [(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
@@ -12597,7 +12567,7 @@ 
   "!TARGET_64BIT && TARGET_GNU_TLS"
 {
   output_asm_insn
-    ("lea{l}\t{%a2@tlsgd(,%1,1), %0|%0, %a2@tlsgd[%1*1]}", operands);
+    ("lea{l}\t{%E2@tlsgd(,%1,1), %0|%0, %E2@tlsgd[%1*1]}", operands);
   if (TARGET_SUN_TLS)
 #ifdef HAVE_AS_IX86_TLSGDPLT
     return "call\t%a2@tlsgdplt";
@@ -12632,7 +12602,7 @@ 
   if (!TARGET_X32)
     fputs (ASM_BYTE "0x66\n", asm_out_file);
   output_asm_insn
-    ("lea{q}\t{%a1@tlsgd(%%rip), %%rdi|rdi, %a1@tlsgd[rip]}", operands);
+    ("lea{q}\t{%E1@tlsgd(%%rip), %%rdi|rdi, %E1@tlsgd[rip]}", operands);
   fputs (ASM_SHORT "0x6666\n", asm_out_file);
   fputs ("\trex64\n", asm_out_file);
   if (TARGET_SUN_TLS)
@@ -12858,7 +12828,7 @@ 
 		  (unspec:SI [(match_operand:SI 2 "tls_symbolic_operand" "")]
 			      UNSPEC_TLSDESC))))]
   "!TARGET_64BIT && TARGET_GNU2_TLS"
-  "lea{l}\t{%a2@TLSDESC(%1), %0|%0, %a2@TLSDESC[%1]}"
+  "lea{l}\t{%E2@TLSDESC(%1), %0|%0, %E2@TLSDESC[%1]}"
   [(set_attr "type" "lea")
    (set_attr "mode" "SI")
    (set_attr "length" "6")
@@ -12920,7 +12890,7 @@ 
 	(unspec:DI [(match_operand 1 "tls_symbolic_operand" "")]
 		   UNSPEC_TLSDESC))]
   "TARGET_64BIT && TARGET_GNU2_TLS"
-  "lea{q}\t{%a1@TLSDESC(%%rip), %0|%0, %a1@TLSDESC[rip]}"
+  "lea{q}\t{%E1@TLSDESC(%%rip), %0|%0, %E1@TLSDESC[rip]}"
   [(set_attr "type" "lea")
    (set_attr "mode" "DI")
    (set_attr "length" "7")
@@ -16675,7 +16645,7 @@ 
 
     default:
       operands[2] = SET_SRC (XVECEXP (PATTERN (insn), 0, 0));
-      return "lea{<imodesuffix>}\t{%a2, %0|%0, %a2}";
+      return "lea{<imodesuffix>}\t{%E2, %0|%0, %E2}";
     }
 }
   [(set (attr "type")
Index: config/i386/constraints.md
===================================================================
--- config/i386/constraints.md	(revision 189815)
+++ config/i386/constraints.md	(working copy)
@@ -19,7 +19,7 @@ 
 
 ;;; Unused letters:
 ;;;     B     H           T  W
-;;;           h  k          v
+;;;           h jk          v
 
 ;; Integer register constraints.
 ;; It is not necessary to define 'r' here.
@@ -127,11 +127,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: testsuite/gcc.dg/pr52530.c
===================================================================
--- testsuite/gcc.dg/pr52530.c	(revision 0)
+++ testsuite/gcc.dg/pr52530.c	(working copy)
@@ -0,0 +1,40 @@ 
+/* { dg-do run } */
+
+extern void abort (void);
+
+#if __SIZEOF_INT__ > 2
+struct foo
+{
+ int *f;
+ int i;
+};
+
+int baz;
+#else
+struct foo
+{
+ long *f;
+ long i;
+};
+
+long baz;
+#endif
+
+void __attribute__ ((noinline))
+bar (struct foo x)
+{
+ *(x.f) = x.i;
+}
+
+int
+main ()
+{
+  struct foo x = { &baz, 0xdeadbeef };
+
+  bar (x);
+
+  if (baz != 0xdeadbeef)
+    abort ();
+
+  return 0;
+}