[2/8] x86: optimize LEA

Message ID 912075c3-0440-ee98-8464-b714db41e35c@suse.com
State New
Headers show
Series
  • x86: assorted relocation handling related adjustments (part II)
Related show

Commit Message

Claudiu Zissulescu via Binutils April 23, 2021, 8:35 a.m.
Over the years I've seen a number of instances where people used

    lea     (%reg1), %reg2

or

    lea     symbol, %reg

despite the same thing being expressable via MOV. Since additionally
LEA often has restrictions towards the ports it can be issued to, while
MOV typically gets dealt with simply by register renaming, transform to
MOV when possible (without growing opcode size and without altering
involved relocation types).

Note that for Mach-O the new 64-bit testcases would fail (for
BFD_RELOC_X86_64_32S not having a representation), and hence get skipped
there.

gas/
2021-04-XX  Jan Beulich  <jbeulich@suse.com>

	* config/tc-i386.c (want_disp32): Also check for SIZE32.
	(optimize_encoding): Handle LEA.
	* testsuite/gas/i386/lea.s, testsuite/gas/i386/lea.d,
	testsuite/gas/i386/lea.e, testsuite/gas/i386/lea-optimize.d:
	Add many more forms.
	* testsuite/gas/i386/lea16.s, testsuite/gas/i386/lea16-optimize.d,
	testsuite/gas/i386/lea64.s, testsuite/gas/i386/lea64.d,
	testsuite/gas/i386/lea64.e, testsuite/gas/i386/lea64-optimize.d:
	New.
	* testsuite/gas/i386/i386.exp: Run new tests.

opcodes/
2021-04-XX  Jan Beulich  <jbeulich@suse.com>

	* i386-opc.tbl (lea): Add Optimize.
	* opcodes/i386-tbl.h: Re-generate.

---
For now, %eiz/%riz used as index will prevent the optimization. This
could be changed such that these get treated like an absent index.

Comments

Claudiu Zissulescu via Binutils April 23, 2021, 1:13 p.m. | #1
On Fri, Apr 23, 2021 at 1:35 AM Jan Beulich <jbeulich@suse.com> wrote:
>

> Over the years I've seen a number of instances where people used

>

>     lea     (%reg1), %reg2

>

> or

>

>     lea     symbol, %reg

>

> despite the same thing being expressable via MOV. Since additionally

> LEA often has restrictions towards the ports it can be issued to, while

> MOV typically gets dealt with simply by register renaming, transform to

> MOV when possible (without growing opcode size and without altering

> involved relocation types).

>

> Note that for Mach-O the new 64-bit testcases would fail (for

> BFD_RELOC_X86_64_32S not having a representation), and hence get skipped

> there.

>

> gas/

> 2021-04-XX  Jan Beulich  <jbeulich@suse.com>

>

>         * config/tc-i386.c (want_disp32): Also check for SIZE32.

>         (optimize_encoding): Handle LEA.

>         * testsuite/gas/i386/lea.s, testsuite/gas/i386/lea.d,

>         testsuite/gas/i386/lea.e, testsuite/gas/i386/lea-optimize.d:

>         Add many more forms.

>         * testsuite/gas/i386/lea16.s, testsuite/gas/i386/lea16-optimize.d,

>         testsuite/gas/i386/lea64.s, testsuite/gas/i386/lea64.d,

>         testsuite/gas/i386/lea64.e, testsuite/gas/i386/lea64-optimize.d:

>         New.

>         * testsuite/gas/i386/i386.exp: Run new tests.

>

> opcodes/

> 2021-04-XX  Jan Beulich  <jbeulich@suse.com>

>

>         * i386-opc.tbl (lea): Add Optimize.

>         * opcodes/i386-tbl.h: Re-generate.

>

> ---

> For now, %eiz/%riz used as index will prevent the optimization. This

> could be changed such that these get treated like an absent index.

>

> --- a/gas/config/tc-i386.c

> +++ b/gas/config/tc-i386.c

> @@ -3562,7 +3562,8 @@ want_disp32 (const insn_template *t)

>          || i.prefix[ADDR_PREFIX]

>          || (t->base_opcode == 0x8d

>              && t->opcode_modifier.opcodespace == SPACE_BASE

> -            && !i.types[1].bitfield.qword);

> +            && (!i.types[1].bitfield.qword

> +               || t->opcode_modifier.size == SIZE32));

>  }

>

>  static int

> @@ -4069,6 +4070,145 @@ optimize_encoding (void)

>  {

>    unsigned int j;

>

> +  if (i.tm.opcode_modifier.opcodespace == SPACE_BASE

> +      && i.tm.base_opcode == 0x8d)

> +    {

> +      /* Optimize: -O:

> +          lea symbol, %rN    -> mov $symbol, %rN

> +          lea (%rM), %rN     -> mov %rM, %rN

> +          lea (,%rM,1), %rN  -> mov %rM, %rN

> +

> +          and in 32-bit mode for 16-bit addressing

> +

> +          lea (%rM), %rN     -> movzx %rM, %rN

> +

> +          and in 64-bit mode zap 32-bit addressing in favor of using a

> +          32-bit (or less) destination.

> +       */

> +      if (flag_code == CODE_64BIT && i.prefix[ADDR_PREFIX])

> +       {

> +         if (!i.op[1].regs->reg_type.bitfield.word)

> +           i.tm.opcode_modifier.size = SIZE32;

> +         i.prefix[ADDR_PREFIX] = 0;

> +       }

> +

> +      if (!i.index_reg && !i.base_reg)

> +       {

> +         /* Handle:

> +              lea symbol, %rN    -> mov $symbol, %rN

> +          */

> +         if (flag_code == CODE_64BIT)

> +           {

> +             /* Don't transform a relocation to a 16-bit one.  */

> +             if (i.op[0].disps

> +                 && i.op[0].disps->X_op != O_constant

> +                 && i.op[1].regs->reg_type.bitfield.word)

> +               return;

> +

> +             if (!i.op[1].regs->reg_type.bitfield.qword

> +                 || i.tm.opcode_modifier.size == SIZE32)

> +               {

> +                 i.tm.base_opcode = 0xb8;

> +                 i.tm.opcode_modifier.modrm = 0;

> +                 if (!i.op[1].regs->reg_type.bitfield.word)

> +                   i.types[0].bitfield.imm32 = 1;

> +                 else

> +                   {

> +                     i.tm.opcode_modifier.size = SIZE16;

> +                     i.types[0].bitfield.imm16 = 1;

> +                   }

> +               }

> +             else

> +               {

> +                 /* Subject to further optimization below.  */

> +                 i.tm.base_opcode = 0xc7;

> +                 i.tm.extension_opcode = 0;

> +                 i.types[0].bitfield.imm32s = 1;

> +                 i.types[0].bitfield.baseindex = 0;

> +               }

> +           }

> +         /* Outside of 64-bit mode address and operand sizes have to match if

> +            a relocation is involved, as otherwise we wouldn't (currently) or

> +            even couldn't express the relocation correctly.  */

> +         else if (i.op[0].disps

> +                  && i.op[0].disps->X_op != O_constant

> +                  && ((!i.prefix[ADDR_PREFIX])

> +                      != (flag_code == CODE_32BIT

> +                          ? i.op[1].regs->reg_type.bitfield.dword

> +                          : i.op[1].regs->reg_type.bitfield.word)))

> +           return;

> +         else

> +           {

> +             i.tm.base_opcode = 0xb8;

> +             i.tm.opcode_modifier.modrm = 0;

> +             if (i.op[1].regs->reg_type.bitfield.dword)

> +               i.types[0].bitfield.imm32 = 1;

> +             else

> +               i.types[0].bitfield.imm16 = 1;

> +

> +             if (i.op[0].disps

> +                 && i.op[0].disps->X_op == O_constant

> +                 && i.op[1].regs->reg_type.bitfield.dword

> +                 && !i.prefix[ADDR_PREFIX] != (flag_code == CODE_32BIT))

> +               i.op[0].disps->X_add_number &= 0xffff;

> +           }

> +

> +         i.tm.operand_types[0] = i.types[0];

> +         i.imm_operands = 1;

> +         if (!i.op[0].imms)

> +           {

> +             i.op[0].imms = &im_expressions[0];

> +             i.op[0].imms->X_op = O_absent;

> +           }

> +       }

> +      else if (i.op[0].disps

> +                 && (i.op[0].disps->X_op != O_constant

> +                     || i.op[0].disps->X_add_number))

> +       return;

> +      else

> +       {

> +         /* Handle:

> +              lea (%rM), %rN     -> mov %rM, %rN

> +              lea (,%rM,1), %rN  -> mov %rM, %rN

> +              lea (%rM), %rN     -> movzx %rM, %rN

> +          */

> +         const reg_entry *addr_reg;

> +

> +         if (!i.index_reg && i.base_reg->reg_num != RegIP)

> +           addr_reg = i.base_reg;

> +         else if (!i.base_reg

> +                  && i.index_reg->reg_num != RegIZ

> +                  && !i.log2_scale_factor)

> +           addr_reg = i.index_reg;

> +         else

> +           return;

> +

> +         if (addr_reg->reg_type.bitfield.word

> +             && i.op[1].regs->reg_type.bitfield.dword)

> +           {

> +             if (flag_code != CODE_32BIT)

> +               return;

> +             i.tm.opcode_modifier.opcodespace = SPACE_0F;

> +             i.tm.base_opcode = 0xb7;

> +           }

> +         else

> +           i.tm.base_opcode = 0x8b;

> +

> +         if (addr_reg->reg_type.bitfield.dword

> +             && i.op[1].regs->reg_type.bitfield.qword)

> +           i.tm.opcode_modifier.size = SIZE32;

> +

> +         i.op[0].regs = addr_reg;

> +         i.reg_operands = 2;

> +       }

> +

> +      i.mem_operands = 0;

> +      i.disp_operands = 0;

> +      i.prefix[ADDR_PREFIX] = 0;

> +      i.prefix[SEG_PREFIX] = 0;

> +      i.seg[0] = NULL;

> +    }

> +

>    if (optimize_for_space

>        && i.tm.opcode_modifier.opcodespace == SPACE_BASE

>        && i.reg_operands == 1

> --- a/gas/testsuite/gas/i386/i386.exp

> +++ b/gas/testsuite/gas/i386/i386.exp

> @@ -538,6 +538,7 @@ if [gas_32_check] then {

>      run_dump_test "optimize-6b"

>      run_list_test "optimize-7" "-I${srcdir}/$subdir -march=+noavx2 -al"

>      run_dump_test "lea-optimize"

> +    run_dump_test "lea16-optimize"

>      run_dump_test "align-branch-1a"

>      run_dump_test "align-branch-1b"

>      run_dump_test "align-branch-1c"

> @@ -1194,6 +1195,8 @@ if [gas_64_check] then {

>         run_dump_test "x86-64-align-branch-2a"

>         run_dump_test "x86-64-align-branch-2b"

>         run_dump_test "x86-64-align-branch-2c"

> +       run_dump_test "lea64"

> +       run_dump_test "lea64-optimize"

>      }

>      run_dump_test "x86-64-align-branch-4a"

>      run_dump_test "x86-64-align-branch-4b"

> --- a/gas/testsuite/gas/i386/lea-optimize.d

> +++ b/gas/testsuite/gas/i386/lea-optimize.d

> @@ -1,6 +1,6 @@

>  #as: -O -q

>  #objdump: -dw

> -#name: i386 LEA-like segment overrride dropping

> +#name: i386 LEA optimizations

>  #source: lea.s

>

>  .*: +file format .*

> @@ -8,6 +8,41 @@

>  Disassembly of section .text:

>

>  0+ <start>:

> -[      ]*[0-9a-f]+:[   ]+8d 00[        ]+lea[  ]+\(%eax\),%eax

> -[      ]*[0-9a-f]+:[   ]+8d 00[        ]+lea[  ]+\(%eax\),%eax

> +[      ]*[0-9a-f]+:[   ]+8d 04 08[     ]+lea[  ]+\(%eax,%ecx(,1)?\),%eax

> +[      ]*[0-9a-f]+:[   ]+8d 04 08[     ]+lea[  ]+\(%eax,%ecx(,1)?\),%eax

> +[      ]*[0-9a-f]+:[   ]+8d 48 01[     ]+lea[  ]+0x1\(%eax\),%ecx

> +[      ]*[0-9a-f]+:[   ]+8d 88 00 00 00 00[    ]+lea[  ]+0x0\(%eax\),%ecx

> +[      ]*[0-9a-f]+:[   ]+8d 0c 25 00 00 00 00[         ]+lea[  ]+0x0\(,(%eiz)?(,1)?\),%ecx

> +[      ]*[0-9a-f]+:[   ]+8d 04 00[     ]+lea[  ]+\(%eax,%eax(,1)?\),%eax

> +[      ]*[0-9a-f]+:[   ]+8d 04 45 00 00 00 00[         ]+lea[  ]+0x0\(,%eax,2\),%eax

> +[      ]*[0-9a-f]+:[   ]+8d 04 25 00 00 00 00[         ]+lea[  ]+0x0\(,(%eiz)?(,1)?\),%eax

> +[      ]*[0-9a-f]+:[   ]+67 8d 00[     ]+lea[  ]+\(%bx,%si\),%eax

> +[      ]*[0-9a-f]+:[   ]+8b c0[        ]+mov[  ]+%eax,%eax

> +[      ]*[0-9a-f]+:[   ]+8b c8[        ]+mov[  ]+%eax,%ecx

> +[      ]*[0-9a-f]+:[   ]+8b c8[        ]+mov[  ]+%eax,%ecx

> +[      ]*[0-9a-f]+:[   ]+8b c8[        ]+mov[  ]+%eax,%ecx

> +[      ]*[0-9a-f]+:[   ]+0f b7 c6[     ]+movzwl[       ]+%si,%eax

> +[      ]*[0-9a-f]+:[   ]+0f b7 f6[     ]+movzwl[       ]+%si,%esi

> +[      ]*[0-9a-f]+:[   ]+0f b7 c6[     ]+movzwl[       ]+%si,%eax

> +[      ]*[0-9a-f]+:[   ]+66 8b c0[     ]+mov[  ]+%ax,%ax

> +[      ]*[0-9a-f]+:[   ]+66 8b c8[     ]+mov[  ]+%ax,%cx

> +[      ]*[0-9a-f]+:[   ]+66 8b c8[     ]+mov[  ]+%ax,%cx

> +[      ]*[0-9a-f]+:[   ]+66 8b c6[     ]+mov[  ]+%si,%ax

> +[      ]*[0-9a-f]+:[   ]+66 8b f6[     ]+mov[  ]+%si,%si

> +[      ]*[0-9a-f]+:[   ]+8b c9[        ]+mov[  ]+%ecx,%ecx

> +[      ]*[0-9a-f]+:[   ]+8b c1[        ]+mov[  ]+%ecx,%eax

> +[      ]*[0-9a-f]+:[   ]+b8 01 00 00 00[       ]+mov[  ]+\$0x1,%eax

> +[      ]*[0-9a-f]+:[   ]+66 b8 02 00[  ]+mov[  ]+\$0x2,%ax

> +[      ]*[0-9a-f]+:[   ]+b8 ff ff ff ff[       ]+mov[  ]+\$0xffffffff,%eax

> +[      ]*[0-9a-f]+:[   ]+66 b8 fe ff[  ]+mov[  ]+\$0xfffe,%ax

> +[      ]*[0-9a-f]+:[   ]+b8 01 00 00 00[       ]+mov[  ]+\$0x1,%eax

> +[      ]*[0-9a-f]+:[   ]+66 b8 02 00[  ]+mov[  ]+\$0x2,%ax

> +[      ]*[0-9a-f]+:[   ]+b8 ff ff 00 00[       ]+mov[  ]+\$0xffff,%eax

> +[      ]*[0-9a-f]+:[   ]+66 b8 fe ff[  ]+mov[  ]+\$0xfffe,%ax

> +[      ]*[0-9a-f]+:[   ]+b8 00 00 00 00[       ]+mov[  ]+\$0x0,%eax

> +[      ]*[0-9a-f]+:[   ]+66 8d 05 00 00 00 00[         ]+lea[  ]+0x0,%ax

> +[      ]*[0-9a-f]+:[   ]+67 8d 06 00 00[       ]+lea[  ]+0x0,%eax

> +[      ]*[0-9a-f]+:[   ]+66 b8 00 00[  ]+mov[  ]+\$0x0,%ax

> +[      ]*[0-9a-f]+:[   ]+b8 00 00 00 00[       ]+mov[  ]+\$0x0,%eax

> +[      ]*[0-9a-f]+:[   ]+66 b8 00 00[  ]+mov[  ]+\$0x0,%ax

>  #pass

> --- a/gas/testsuite/gas/i386/lea.d

> +++ b/gas/testsuite/gas/i386/lea.d

> @@ -7,6 +7,41 @@

>  Disassembly of section .text:

>

>  0+ <start>:

> -[      ]*[0-9a-f]+:[   ]+36 8d 00[     ]+lea[  ]+%ss:\(%eax\),%eax

> -[      ]*[0-9a-f]+:[   ]+36 8d 00[     ]+lea[  ]+%ss:\(%eax\),%eax

> +[      ]*[0-9a-f]+:[   ]+36 8d 04 08[  ]+lea[  ]+%ss:\(%eax,%ecx(,1)?\),%eax

> +[      ]*[0-9a-f]+:[   ]+36 8d 04 08[  ]+lea[  ]+%ss:\(%eax,%ecx(,1)?\),%eax

> +[      ]*[0-9a-f]+:[   ]+8d 48 01[     ]+lea[  ]+0x1\(%eax\),%ecx

> +[      ]*[0-9a-f]+:[   ]+8d 88 00 00 00 00[    ]+lea[  ]+0x0\(%eax\),%ecx

> +[      ]*[0-9a-f]+:[   ]+8d 0c 25 00 00 00 00[         ]+lea[  ]+0x0\(,(%eiz)?(,1)?\),%ecx

> +[      ]*[0-9a-f]+:[   ]+8d 04 00[     ]+lea[  ]+\(%eax,%eax(,1)?\),%eax

> +[      ]*[0-9a-f]+:[   ]+8d 04 45 00 00 00 00[         ]+lea[  ]+0x0\(,%eax,2\),%eax

> +[      ]*[0-9a-f]+:[   ]+8d 04 25 00 00 00 00[         ]+lea[  ]+0x0\(,(%eiz)?(,1)?\),%eax

> +[      ]*[0-9a-f]+:[   ]+67 8d 00[     ]+lea[  ]+\(%bx,%si\),%eax

> +[      ]*[0-9a-f]+:[   ]+8d 00[        ]+lea[  ]+\(%eax\),%eax

> +[      ]*[0-9a-f]+:[   ]+8d 08[        ]+lea[  ]+\(%eax\),%ecx

> +[      ]*[0-9a-f]+:[   ]+8d 08[        ]+lea[  ]+\(%eax\),%ecx

> +[      ]*[0-9a-f]+:[   ]+65 8d 08[     ]+lea[  ]+%gs:\(%eax\),%ecx

> +[      ]*[0-9a-f]+:[   ]+67 8d 04[     ]+lea[  ]+\(%si\),%eax

> +[      ]*[0-9a-f]+:[   ]+67 8d 34[     ]+lea[  ]+\(%si\),%esi

> +[      ]*[0-9a-f]+:[   ]+67 8d 04[     ]+lea[  ]+\(%si\),%eax

> +[      ]*[0-9a-f]+:[   ]+66 8d 00[     ]+lea[  ]+\(%eax\),%ax

> +[      ]*[0-9a-f]+:[   ]+66 8d 08[     ]+lea[  ]+\(%eax\),%cx

> +[      ]*[0-9a-f]+:[   ]+66 8d 08[     ]+lea[  ]+\(%eax\),%cx

> +[      ]*[0-9a-f]+:[   ]+67 66 8d 04[  ]+lea[  ]+\(%si\),%ax

> +[      ]*[0-9a-f]+:[   ]+67 66 8d 34[  ]+lea[  ]+\(%si\),%si

> +[      ]*[0-9a-f]+:[   ]+8d 0c 0d 00 00 00 00[         ]+lea[  ]+0x0\(,%ecx(,1)?\),%ecx

> +[      ]*[0-9a-f]+:[   ]+8d 04 0d 00 00 00 00[         ]+lea[  ]+0x0\(,%ecx(,1)?\),%eax

> +[      ]*[0-9a-f]+:[   ]+8d 05 01 00 00 00[    ]+lea[  ]+0x1,%eax

> +[      ]*[0-9a-f]+:[   ]+66 8d 05 02 00 00 00[         ]+lea[  ]+0x2,%ax

> +[      ]*[0-9a-f]+:[   ]+8d 05 ff ff ff ff[    ]+lea[  ]+0xffffffff,%eax

> +[      ]*[0-9a-f]+:[   ]+66 8d 05 fe ff ff ff[         ]+lea[  ]+0xfffffffe,%ax

> +[      ]*[0-9a-f]+:[   ]+67 8d 06 01 00[       ]+lea[  ]+0x1,%eax

> +[      ]*[0-9a-f]+:[   ]+67 66 8d 06 02 00[    ]+lea[  ]+0x2,%ax

> +[      ]*[0-9a-f]+:[   ]+67 8d 06 ff ff[       ]+lea[  ]+-0x1,%eax

> +[      ]*[0-9a-f]+:[   ]+67 66 8d 06 fe ff[    ]+lea[  ]+-0x2,%ax

> +[      ]*[0-9a-f]+:[   ]+8d 05 00 00 00 00[    ]+lea[  ]+0x0,%eax

> +[      ]*[0-9a-f]+:[   ]+66 8d 05 00 00 00 00[         ]+lea[  ]+0x0,%ax

> +[      ]*[0-9a-f]+:[   ]+67 8d 06 00 00[       ]+lea[  ]+0x0,%eax

> +[      ]*[0-9a-f]+:[   ]+67 66 8d 06 00 00[    ]+lea[  ]+0x0,%ax

> +[      ]*[0-9a-f]+:[   ]+8d 05 00 00 00 00[    ]+lea[  ]+0x0,%eax

> +[      ]*[0-9a-f]+:[   ]+66 8d 05 00 00 00 00[         ]+lea[  ]+0x0,%ax

>  #pass

> --- a/gas/testsuite/gas/i386/lea.e

> +++ b/gas/testsuite/gas/i386/lea.e

> @@ -1,3 +1,4 @@

>  .*: Assembler messages:

>  .*:3: Warning: .* `lea' .*

>  .*:4: Warning: .* `lea' .*

> +.*:19: Warning: .* `lea' .*

> --- a/gas/testsuite/gas/i386/lea.s

> +++ b/gas/testsuite/gas/i386/lea.s

> @@ -1,4 +1,54 @@

>         .text

>  start:

> -       lea     %ss:(%eax), %eax

> -       ss lea  (%eax), %eax

> +       lea     %ss:(%eax,%ecx), %eax

> +       ss lea  (%eax,%ecx), %eax

> +

> +       .allow_index_reg

> +       lea     1(%eax), %ecx

> +       lea     sym(%eax), %ecx

> +       lea     sym(,%eiz), %ecx

> +

> +       lea     (%eax,%eax), %eax

> +       lea     (,%eax,2), %eax

> +       lea     (,%eiz), %eax

> +       lea     (%bx,%si), %eax

> +

> +       lea     (%eax), %eax

> +       lea     (%eax), %ecx

> +       lea     1-1(%eax), %ecx

> +       lea     %gs:(%eax), %ecx

> +

> +       lea     (%si), %eax

> +       lea     (%si), %esi

> +       leal    (%si), %eax

> +

> +       lea     (%eax), %ax

> +       lea     (%eax), %cx

> +       leaw    (%eax), %cx

> +

> +       lea     (%si), %ax

> +       lea     (%si), %si

> +

> +       lea     (,%ecx,1), %ecx

> +       lea     (,%ecx,1), %eax

> +

> +       lea     1, %eax

> +       lea     2, %ax

> +

> +       lea     -1, %eax

> +       lea     -2, %ax

> +

> +       addr16 lea 1, %eax

> +       addr16 lea 2, %ax

> +

> +       addr16 lea -1, %eax

> +       addr16 lea -2, %ax

> +

> +       lea     sym, %eax

> +       lea     sym, %ax

> +

> +       addr16 lea sym, %eax

> +       addr16 lea sym, %ax

> +

> +       lea     (,1), %eax

> +       lea     (,1), %ax

> --- /dev/null

> +++ b/gas/testsuite/gas/i386/lea16-optimize.d

> @@ -0,0 +1,48 @@

> +#as: -O -q -I${srcdir}/$subdir

> +#objdump: -dw -Mi8086

> +#name: i386 16-bit LEA optimizations

> +#source: lea16.s

> +

> +.*: +file format .*

> +

> +Disassembly of section .text:

> +

> +0+ <start>:

> +[      ]*[0-9a-f]+:[   ]+67 66 8d 04 08[       ]+lea[  ]+\(%eax,%ecx(,1)?\),%eax

> +[      ]*[0-9a-f]+:[   ]+67 66 8d 04 08[       ]+lea[  ]+\(%eax,%ecx(,1)?\),%eax

> +[      ]*[0-9a-f]+:[   ]+67 66 8d 48 01[       ]+lea[  ]+0x1\(%eax\),%ecx

> +[      ]*[0-9a-f]+:[   ]+67 66 8d 88 00 00 00 00[      ]+lea[  ]+0x0\(%eax\),%ecx

> +[      ]*[0-9a-f]+:[   ]+67 66 8d 0c 25 00 00 00 00[   ]+addr32 lea[   ]+0x0,%ecx

> +[      ]*[0-9a-f]+:[   ]+67 66 8d 04 00[       ]+lea[  ]+\(%eax,%eax(,1)?\),%eax

> +[      ]*[0-9a-f]+:[   ]+67 66 8d 04 45 00 00 00 00[   ]+lea[  ]+0x0\(,%eax,2\),%eax

> +[      ]*[0-9a-f]+:[   ]+67 66 8d 04 25 00 00 00 00[   ]+addr32 lea[   ]+0x0,%eax

> +[      ]*[0-9a-f]+:[   ]+66 8d 00[     ]+lea[  ]+\(%bx,%si\),%eax

> +[      ]*[0-9a-f]+:[   ]+66 8b c0[     ]+mov[  ]+%eax,%eax

> +[      ]*[0-9a-f]+:[   ]+66 8b c8[     ]+mov[  ]+%eax,%ecx

> +[      ]*[0-9a-f]+:[   ]+66 8b c8[     ]+mov[  ]+%eax,%ecx

> +[      ]*[0-9a-f]+:[   ]+66 8b c8[     ]+mov[  ]+%eax,%ecx

> +[      ]*[0-9a-f]+:[   ]+66 8d 04[     ]+lea[  ]+\(%si\),%eax

> +[      ]*[0-9a-f]+:[   ]+66 8d 34[     ]+lea[  ]+\(%si\),%esi

> +[      ]*[0-9a-f]+:[   ]+66 8d 04[     ]+lea[  ]+\(%si\),%eax

> +[      ]*[0-9a-f]+:[   ]+8b c0[        ]+mov[  ]+%ax,%ax

> +[      ]*[0-9a-f]+:[   ]+8b c8[        ]+mov[  ]+%ax,%cx

> +[      ]*[0-9a-f]+:[   ]+8b c8[        ]+mov[  ]+%ax,%cx

> +[      ]*[0-9a-f]+:[   ]+8b c6[        ]+mov[  ]+%si,%ax

> +[      ]*[0-9a-f]+:[   ]+8b f6[        ]+mov[  ]+%si,%si

> +[      ]*[0-9a-f]+:[   ]+66 8b c9[     ]+mov[  ]+%ecx,%ecx

> +[      ]*[0-9a-f]+:[   ]+66 8b c1[     ]+mov[  ]+%ecx,%eax

> +[      ]*[0-9a-f]+:[   ]+66 b8 01 00 00 00[    ]+mov[  ]+\$0x1,%eax

> +[      ]*[0-9a-f]+:[   ]+b8 02 00[     ]+mov[  ]+\$0x2,%ax

> +[      ]*[0-9a-f]+:[   ]+66 b8 ff ff 00 00[    ]+mov[  ]+\$0xffff,%eax

> +[      ]*[0-9a-f]+:[   ]+b8 fe ff[     ]+mov[  ]+\$0xfffe,%ax

> +[      ]*[0-9a-f]+:[   ]+66 b8 01 00 00 00[    ]+mov[  ]+\$0x1,%eax

> +[      ]*[0-9a-f]+:[   ]+b8 02 00[     ]+mov[  ]+\$0x2,%ax

> +[      ]*[0-9a-f]+:[   ]+66 b8 ff ff ff ff[    ]+mov[  ]+\$0xffffffff,%eax

> +[      ]*[0-9a-f]+:[   ]+b8 fe ff[     ]+mov[  ]+\$0xfffe,%ax

> +[      ]*[0-9a-f]+:[   ]+66 8d 06 00 00[       ]+lea[  ]+0x0,%eax

> +[      ]*[0-9a-f]+:[   ]+b8 00 00[     ]+mov[  ]+\$0x0,%ax

> +[      ]*[0-9a-f]+:[   ]+66 b8 00 00 00 00[    ]+mov[  ]+\$0x0,%eax

> +[      ]*[0-9a-f]+:[   ]+67 8d 05 00 00 00 00[         ]+addr32 lea[   ]+0x0,%ax

> +[      ]*[0-9a-f]+:[   ]+66 b8 00 00 00 00[    ]+mov[  ]+\$0x0,%eax

> +[      ]*[0-9a-f]+:[   ]+b8 00 00[     ]+mov[  ]+\$0x0,%ax

> +#pass

> --- /dev/null

> +++ b/gas/testsuite/gas/i386/lea16.s

> @@ -0,0 +1,7 @@

> +       .code16

> +

> +       .macro addr16 mnem:req opnds:vararg

> +       addr32 \mnem \opnds

> +       .endm

> +

> +       .include "lea.s"

> --- /dev/null

> +++ b/gas/testsuite/gas/i386/lea64-optimize.d

> @@ -0,0 +1,71 @@

> +#as: -O -q

> +#objdump: -drw

> +#name: x86-64 LEA optimizations

> +#source: lea64.s

> +

> +.*: +file format .*

> +

> +Disassembly of section .text:

> +

> +0+ <start>:

> +[      ]*[0-9a-f]+:[   ]+8d 04 08[     ]+lea[  ]+\(%rax,%rcx(,1)?\),%eax

> +[      ]*[0-9a-f]+:[   ]+8d 04 08[     ]+lea[  ]+\(%rax,%rcx(,1)?\),%eax

> +[      ]*[0-9a-f]+:[   ]+8d 48 01[     ]+lea[  ]+0x1\(%rax\),%ecx

> +[      ]*[0-9a-f]+:[   ]+8d 88 00 00 00 00[    ]+lea[  ]+0x0\(%rax\),%ecx[     ]+[0-9a-f]+: R_X86_64_32[       ]+sym

> +[      ]*[0-9a-f]+:[   ]+8d 0c 25 00 00 00 00[         ]+lea[  ]+0x0,%ecx[     ]+[0-9a-f]+: R_X86_64_32[       ]+sym

> +[      ]*[0-9a-f]+:[   ]+8d 04 00[     ]+lea[  ]+\(%rax,%rax(,1)?\),%eax

> +[      ]*[0-9a-f]+:[   ]+8d 04 45 00 00 00 00[         ]+lea[  ]+0x0\(,%rax,2\),%eax

> +[      ]*[0-9a-f]+:[   ]+8d 05 00 00 00 00[    ]+lea[  ]+0x0\(%rip\),%eax($| *#.*)

> +[      ]*[0-9a-f]+:[   ]+8d 04 25 00 00 00 00[         ]+lea[  ]+0x0,%eax

> +[      ]*[0-9a-f]+:[   ]+48 8b c0[     ]+mov[  ]+%rax,%rax

> +[      ]*[0-9a-f]+:[   ]+48 8b c8[     ]+mov[  ]+%rax,%rcx

> +[      ]*[0-9a-f]+:[   ]+48 8b c8[     ]+mov[  ]+%rax,%rcx

> +[      ]*[0-9a-f]+:[   ]+48 8b c8[     ]+mov[  ]+%rax,%rcx

> +[      ]*[0-9a-f]+:[   ]+8b c6[        ]+mov[  ]+%esi,%eax

> +[      ]*[0-9a-f]+:[   ]+8b f6[        ]+mov[  ]+%esi,%esi

> +[      ]*[0-9a-f]+:[   ]+8b c6[        ]+mov[  ]+%esi,%eax

> +[      ]*[0-9a-f]+:[   ]+66 8b c6[     ]+mov[  ]+%si,%ax

> +[      ]*[0-9a-f]+:[   ]+66 8b f6[     ]+mov[  ]+%si,%si

> +[      ]*[0-9a-f]+:[   ]+66 8b c6[     ]+mov[  ]+%si,%ax

> +[      ]*[0-9a-f]+:[   ]+8b c0[        ]+mov[  ]+%eax,%eax

> +[      ]*[0-9a-f]+:[   ]+8b c8[        ]+mov[  ]+%eax,%ecx

> +[      ]*[0-9a-f]+:[   ]+8b c8[        ]+mov[  ]+%eax,%ecx

> +[      ]*[0-9a-f]+:[   ]+8b c0[        ]+mov[  ]+%eax,%eax

> +[      ]*[0-9a-f]+:[   ]+8b c8[        ]+mov[  ]+%eax,%ecx

> +[      ]*[0-9a-f]+:[   ]+66 8b c6[     ]+mov[  ]+%si,%ax

> +[      ]*[0-9a-f]+:[   ]+66 8b f6[     ]+mov[  ]+%si,%si

> +[      ]*[0-9a-f]+:[   ]+66 8b c6[     ]+mov[  ]+%si,%ax

> +[      ]*[0-9a-f]+:[   ]+48 8b c9[     ]+mov[  ]+%rcx,%rcx

> +[      ]*[0-9a-f]+:[   ]+48 8b c1[     ]+mov[  ]+%rcx,%rax

> +[      ]*[0-9a-f]+:[   ]+8b c9[        ]+mov[  ]+%ecx,%ecx

> +[      ]*[0-9a-f]+:[   ]+8b c1[        ]+mov[  ]+%ecx,%eax

> +[      ]*[0-9a-f]+:[   ]+66 8b c9[     ]+mov[  ]+%cx,%cx

> +[      ]*[0-9a-f]+:[   ]+66 8b c1[     ]+mov[  ]+%cx,%ax

> +[      ]*[0-9a-f]+:[   ]+8b c9[        ]+mov[  ]+%ecx,%ecx

> +[      ]*[0-9a-f]+:[   ]+8b c1[        ]+mov[  ]+%ecx,%eax

> +[      ]*[0-9a-f]+:[   ]+8b c9[        ]+mov[  ]+%ecx,%ecx

> +[      ]*[0-9a-f]+:[   ]+8b c1[        ]+mov[  ]+%ecx,%eax

> +[      ]*[0-9a-f]+:[   ]+66 8b c9[     ]+mov[  ]+%cx,%cx

> +[      ]*[0-9a-f]+:[   ]+66 8b c1[     ]+mov[  ]+%cx,%ax

> +[      ]*[0-9a-f]+:[   ]+b8 01 00 00 00[       ]+mov[  ]+\$0x1,%eax

> +[      ]*[0-9a-f]+:[   ]+b8 02 00 00 00[       ]+mov[  ]+\$0x2,%eax

> +[      ]*[0-9a-f]+:[   ]+66 b8 03 00[  ]+mov[  ]+\$0x3,%ax

> +[      ]*[0-9a-f]+:[   ]+48 c7 c0 ff ff ff ff[         ]+mov[  ]+\$0xffffffffffffffff,%rax

> +[      ]*[0-9a-f]+:[   ]+b8 fe ff ff ff[       ]+mov[  ]+\$0xfffffffe,%eax

> +[      ]*[0-9a-f]+:[   ]+66 b8 fd ff[  ]+mov[  ]+\$0xfffd,%ax

> +[      ]*[0-9a-f]+:[   ]+b8 01 00 00 00[       ]+mov[  ]+\$0x1,%eax

> +[      ]*[0-9a-f]+:[   ]+b8 02 00 00 00[       ]+mov[  ]+\$0x2,%eax

> +[      ]*[0-9a-f]+:[   ]+66 b8 03 00[  ]+mov[  ]+\$0x3,%ax

> +[      ]*[0-9a-f]+:[   ]+b8 ff ff ff ff[       ]+mov[  ]+\$0xffffffff,%eax

> +[      ]*[0-9a-f]+:[   ]+b8 fe ff ff ff[       ]+mov[  ]+\$0xfffffffe,%eax

> +[      ]*[0-9a-f]+:[   ]+66 b8 fd ff[  ]+mov[  ]+\$0xfffd,%ax

> +[      ]*[0-9a-f]+:[   ]+48 c7 c0 00 00 00 00[         ]+mov[  ]+\$0x0,%rax[   ]+[0-9a-f]+: R_X86_64_32S[      ]+sym

> +[      ]*[0-9a-f]+:[   ]+b8 00 00 00 00[       ]+mov[  ]+\$0x0,%eax[   ]+[0-9a-f]+: R_X86_64_32[       ]+sym

> +[      ]*[0-9a-f]+:[   ]+66 8d 04 25 00 00 00 00[      ]+lea[  ]+0x0,%ax[      ]+[0-9a-f]+: R_X86_64_32[       ]+sym

> +[      ]*[0-9a-f]+:[   ]+b8 00 00 00 00[       ]+mov[  ]+\$0x0,%eax[   ]+[0-9a-f]+: R_X86_64_32[       ]+sym

> +[      ]*[0-9a-f]+:[   ]+b8 00 00 00 00[       ]+mov[  ]+\$0x0,%eax[   ]+[0-9a-f]+: R_X86_64_32[       ]+sym

> +[      ]*[0-9a-f]+:[   ]+66 8d 04 25 00 00 00 00[      ]+lea[  ]+0x0,%ax[      ]+[0-9a-f]+: R_X86_64_32[       ]+sym

> +[      ]*[0-9a-f]+:[   ]+48 c7 c0 00 00 00 00[         ]+mov[  ]+\$0x0,%rax

> +[      ]*[0-9a-f]+:[   ]+b8 00 00 00 00[       ]+mov[  ]+\$0x0,%eax

> +[      ]*[0-9a-f]+:[   ]+66 b8 00 00[  ]+mov[  ]+\$0x0,%ax

> +#pass

> --- /dev/null

> +++ b/gas/testsuite/gas/i386/lea64.d

> @@ -0,0 +1,70 @@

> +#objdump: -drw

> +#name: x86-64 LEA

> +#warning_output: lea64.e

> +

> +.*: +file format .*

> +

> +Disassembly of section .text:

> +

> +0+ <start>:

> +[      ]*[0-9a-f]+:[   ]+64 8d 04 08[  ]+lea[  ]+%fs:\(%rax,%rcx(,1)?\),%eax

> +[      ]*[0-9a-f]+:[   ]+65 8d 04 08[  ]+lea[  ]+%gs:\(%rax,%rcx(,1)?\),%eax

> +[      ]*[0-9a-f]+:[   ]+8d 48 01[     ]+lea[  ]+0x1\(%rax\),%ecx

> +[      ]*[0-9a-f]+:[   ]+8d 88 00 00 00 00[    ]+lea[  ]+0x0\(%rax\),%ecx[     ]+[0-9a-f]+: R_X86_64_32[       ]+sym

> +[      ]*[0-9a-f]+:[   ]+8d 0c 25 00 00 00 00[         ]+lea[  ]+0x0,%ecx[     ]+[0-9a-f]+: R_X86_64_32[       ]+sym

> +[      ]*[0-9a-f]+:[   ]+8d 04 00[     ]+lea[  ]+\(%rax,%rax(,1)?\),%eax

> +[      ]*[0-9a-f]+:[   ]+8d 04 45 00 00 00 00[         ]+lea[  ]+0x0\(,%rax,2\),%eax

> +[      ]*[0-9a-f]+:[   ]+8d 05 00 00 00 00[    ]+lea[  ]+0x0\(%rip\),%eax($| *#.*)

> +[      ]*[0-9a-f]+:[   ]+8d 04 25 00 00 00 00[         ]+lea[  ]+0x0,%eax

> +[      ]*[0-9a-f]+:[   ]+48 8d 00[     ]+lea[  ]+\(%rax\),%rax

> +[      ]*[0-9a-f]+:[   ]+48 8d 08[     ]+lea[  ]+\(%rax\),%rcx

> +[      ]*[0-9a-f]+:[   ]+48 8d 08[     ]+lea[  ]+\(%rax\),%rcx

> +[      ]*[0-9a-f]+:[   ]+65 48 8d 08[  ]+lea[  ]+%gs:\(%rax\),%rcx

> +[      ]*[0-9a-f]+:[   ]+8d 06[        ]+lea[  ]+\(%rsi\),%eax

> +[      ]*[0-9a-f]+:[   ]+8d 36[        ]+lea[  ]+\(%rsi\),%esi

> +[      ]*[0-9a-f]+:[   ]+8d 06[        ]+lea[  ]+\(%rsi\),%eax

> +[      ]*[0-9a-f]+:[   ]+66 8d 06[     ]+lea[  ]+\(%rsi\),%ax

> +[      ]*[0-9a-f]+:[   ]+66 8d 36[     ]+lea[  ]+\(%rsi\),%si

> +[      ]*[0-9a-f]+:[   ]+66 8d 06[     ]+lea[  ]+\(%rsi\),%ax

> +[      ]*[0-9a-f]+:[   ]+67 48 8d 00[  ]+lea[  ]+\(%eax\),%rax

> +[      ]*[0-9a-f]+:[   ]+67 48 8d 08[  ]+lea[  ]+\(%eax\),%rcx

> +[      ]*[0-9a-f]+:[   ]+67 48 8d 08[  ]+lea[  ]+\(%eax\),%rcx

> +[      ]*[0-9a-f]+:[   ]+67 8d 00[     ]+lea[  ]+\(%eax\),%eax

> +[      ]*[0-9a-f]+:[   ]+67 8d 08[     ]+lea[  ]+\(%eax\),%ecx

> +[      ]*[0-9a-f]+:[   ]+67 66 8d 06[  ]+lea[  ]+\(%esi\),%ax

> +[      ]*[0-9a-f]+:[   ]+67 66 8d 36[  ]+lea[  ]+\(%esi\),%si

> +[      ]*[0-9a-f]+:[   ]+67 66 8d 06[  ]+lea[  ]+\(%esi\),%ax

> +[      ]*[0-9a-f]+:[   ]+48 8d 0c 0d 00 00 00 00[      ]+lea[  ]+0x0\(,%rcx(,1)?\),%rcx

> +[      ]*[0-9a-f]+:[   ]+48 8d 04 0d 00 00 00 00[      ]+lea[  ]+0x0\(,%rcx(,1)?\),%rax

> +[      ]*[0-9a-f]+:[   ]+8d 0c 0d 00 00 00 00[         ]+lea[  ]+0x0\(,%rcx(,1)?\),%ecx

> +[      ]*[0-9a-f]+:[   ]+8d 04 0d 00 00 00 00[         ]+lea[  ]+0x0\(,%rcx(,1)?\),%eax

> +[      ]*[0-9a-f]+:[   ]+66 8d 0c 0d 00 00 00 00[      ]+lea[  ]+0x0\(,%rcx(,1)?\),%cx

> +[      ]*[0-9a-f]+:[   ]+66 8d 04 0d 00 00 00 00[      ]+lea[  ]+0x0\(,%rcx(,1)?\),%ax

> +[      ]*[0-9a-f]+:[   ]+67 48 8d 0c 0d 00 00 00 00[   ]+lea[  ]+0x0\(,%ecx(,1)?\),%rcx

> +[      ]*[0-9a-f]+:[   ]+67 48 8d 04 0d 00 00 00 00[   ]+lea[  ]+0x0\(,%ecx(,1)?\),%rax

> +[      ]*[0-9a-f]+:[   ]+67 8d 0c 0d 00 00 00 00[      ]+lea[  ]+0x0\(,%ecx(,1)?\),%ecx

> +[      ]*[0-9a-f]+:[   ]+67 8d 04 0d 00 00 00 00[      ]+lea[  ]+0x0\(,%ecx(,1)?\),%eax

> +[      ]*[0-9a-f]+:[   ]+67 66 8d 0c 0d 00 00 00 00[   ]+lea[  ]+0x0\(,%ecx(,1)?\),%cx

> +[      ]*[0-9a-f]+:[   ]+67 66 8d 04 0d 00 00 00 00[   ]+lea[  ]+0x0\(,%ecx(,1)?\),%ax

> +[      ]*[0-9a-f]+:[   ]+48 8d 04 25 01 00 00 00[      ]+lea[  ]+0x1,%rax

> +[      ]*[0-9a-f]+:[   ]+8d 04 25 02 00 00 00[         ]+lea[  ]+0x2,%eax

> +[      ]*[0-9a-f]+:[   ]+66 8d 04 25 03 00 00 00[      ]+lea[  ]+0x3,%ax

> +[      ]*[0-9a-f]+:[   ]+48 8d 04 25 ff ff ff ff[      ]+lea[  ]+0xffffffffffffffff,%rax

> +[      ]*[0-9a-f]+:[   ]+8d 04 25 fe ff ff ff[         ]+lea[  ]+0xfffffffffffffffe,%eax

> +[      ]*[0-9a-f]+:[   ]+66 8d 04 25 fd ff ff ff[      ]+lea[  ]+0xfffffffffffffffd,%ax

> +[      ]*[0-9a-f]+:[   ]+67 48 8d 04 25 01 00 00 00[   ]+lea[  ]+0x1\(,%eiz,1\),%rax

> +[      ]*[0-9a-f]+:[   ]+67 8d 04 25 02 00 00 00[      ]+lea[  ]+0x2\(,%eiz,1\),%eax

> +[      ]*[0-9a-f]+:[   ]+67 66 8d 04 25 03 00 00 00[   ]+lea[  ]+0x3\(,%eiz,1\),%ax

> +[      ]*[0-9a-f]+:[   ]+67 48 8d 04 25 ff ff ff ff[   ]+lea[  ]+0xffffffff\(,%eiz,1\),%rax

> +[      ]*[0-9a-f]+:[   ]+67 8d 04 25 fe ff ff ff[      ]+lea[  ]+0xfffffffe\(,%eiz,1\),%eax

> +[      ]*[0-9a-f]+:[   ]+67 66 8d 04 25 fd ff ff ff[   ]+lea[  ]+0xfffffffd\(,%eiz,1\),%ax

> +[      ]*[0-9a-f]+:[   ]+48 8d 04 25 00 00 00 00[      ]+lea[  ]+0x0,%rax[     ]+[0-9a-f]+: R_X86_64_32S[      ]+sym

> +[      ]*[0-9a-f]+:[   ]+8d 04 25 00 00 00 00[         ]+lea[  ]+0x0,%eax[     ]+[0-9a-f]+: R_X86_64_32[       ]+sym

> +[      ]*[0-9a-f]+:[   ]+66 8d 04 25 00 00 00 00[      ]+lea[  ]+0x0,%ax[      ]+[0-9a-f]+: R_X86_64_32[       ]+sym

> +[      ]*[0-9a-f]+:[   ]+67 48 8d 04 25 00 00 00 00[   ]+lea[  ]+0x0\(,%eiz,1\),%rax[  ]+[0-9a-f]+: R_X86_64_32[       ]+sym

> +[      ]*[0-9a-f]+:[   ]+67 8d 04 25 00 00 00 00[      ]+lea[  ]+0x0\(,%eiz,1\),%eax[  ]+[0-9a-f]+: R_X86_64_32[       ]+sym

> +[      ]*[0-9a-f]+:[   ]+67 66 8d 04 25 00 00 00 00[   ]+lea[  ]+0x0\(,%eiz,1\),%ax[   ]+[0-9a-f]+: R_X86_64_32[       ]+sym

> +[      ]*[0-9a-f]+:[   ]+48 8d 04 25 00 00 00 00[      ]+lea[  ]+0x0,%rax

> +[      ]*[0-9a-f]+:[   ]+8d 04 25 00 00 00 00[         ]+lea[  ]+0x0,%eax

> +[      ]*[0-9a-f]+:[   ]+66 8d 04 25 00 00 00 00[      ]+lea[  ]+0x0,%ax

> +#pass

> --- /dev/null

> +++ b/gas/testsuite/gas/i386/lea64.e

> @@ -0,0 +1,4 @@

> +.*: Assembler messages:

> +.*:3: Warning: .* `lea' .*

> +.*:4: Warning: .* `lea' .*

> +.*:19: Warning: .* `lea' .*

> --- /dev/null

> +++ b/gas/testsuite/gas/i386/lea64.s

> @@ -0,0 +1,84 @@

> +       .text

> +start:

> +       lea     %fs:(%rax,%rcx), %eax

> +       gs lea  (%rax,%rcx), %eax

> +

> +       .allow_index_reg

> +       lea     1(%rax), %ecx

> +       lea     sym(%rax), %ecx

> +       lea     sym(,%riz), %ecx

> +

> +       lea     (%rax,%rax), %eax

> +       lea     (,%rax,2), %eax

> +       lea     (%rip), %eax

> +       lea     (,%riz), %eax

> +

> +       lea     (%rax), %rax

> +       lea     (%rax), %rcx

> +       lea     1-1(%rax), %rcx

> +       lea     %gs:(%rax), %rcx

> +

> +       lea     (%rsi), %eax

> +       lea     (%rsi), %esi

> +       leal    (%rsi), %eax

> +

> +       lea     (%rsi), %ax

> +       lea     (%rsi), %si

> +       leaw    (%rsi), %ax

> +

> +       lea     (%eax), %rax

> +       lea     (%eax), %rcx

> +       leaq    (%eax), %rcx

> +

> +       lea     (%eax), %eax

> +       lea     (%eax), %ecx

> +

> +       lea     (%esi), %ax

> +       lea     (%esi), %si

> +       leaw    (%esi), %ax

> +

> +       lea     (,%rcx,1), %rcx

> +       lea     (,%rcx,1), %rax

> +

> +       lea     (,%rcx,1), %ecx

> +       lea     (,%rcx,1), %eax

> +

> +       lea     (,%rcx,1), %cx

> +       lea     (,%rcx,1), %ax

> +

> +       lea     (,%ecx,1), %rcx

> +       lea     (,%ecx,1), %rax

> +

> +       lea     (,%ecx,1), %ecx

> +       lea     (,%ecx,1), %eax

> +

> +       lea     (,%ecx,1), %cx

> +       lea     (,%ecx,1), %ax

> +

> +       lea     1, %rax

> +       lea     2, %eax

> +       lea     3, %ax

> +

> +       lea     -1, %rax

> +       lea     -2, %eax

> +       lea     -3, %ax

> +

> +       addr32 lea 1, %rax

> +       addr32 lea 2, %eax

> +       addr32 lea 3, %ax

> +

> +       addr32 lea -1, %rax

> +       addr32 lea -2, %eax

> +       addr32 lea -3, %ax

> +

> +       lea     sym, %rax

> +       lea     sym, %eax

> +       lea     sym, %ax

> +

> +       addr32 lea sym, %rax

> +       addr32 lea sym, %eax

> +       addr32 lea sym, %ax

> +

> +       lea     (,1), %rax

> +       lea     (,1), %eax

> +       lea     (,1), %ax

> --- a/opcodes/i386-opc.tbl

> +++ b/opcodes/i386-opc.tbl

> @@ -228,7 +228,7 @@ out, 0xe6, None, 0, W|No_sSuf|No_qSuf|No

>  out, 0xee, None, 0, W|No_sSuf|No_qSuf|No_ldSuf, { InOutPortReg }

>

>  // Load effective address.

> -lea, 0x8d, None, 0, Modrm|Anysize|No_bSuf|No_sSuf|No_ldSuf, { BaseIndex, Reg16|Reg32|Reg64 }

> +lea, 0x8d, None, 0, Modrm|Anysize|No_bSuf|No_sSuf|No_ldSuf|Optimize, { BaseIndex, Reg16|Reg32|Reg64 }

>

>  // Load segment registers from memory.

>  lds, 0xc5, None, CpuNo64, Modrm|No_bSuf|No_sSuf|No_qSuf|No_ldSuf, { DWord|Fword|Unspecified|BaseIndex, Reg16|Reg32 }

>


OK.

Thanks.

-- 
H.J.
Joseph Myers April 26, 2021, 5:08 p.m. | #2
On Fri, 23 Apr 2021, Jan Beulich via Binutils wrote:

> +		  && !i.prefix[ADDR_PREFIX] != (flag_code == CODE_32BIT))


I'm seeing a -Werror build failure (with GCC 5):

/scratch/jmyers/glibc-bot/src/binutils/gas/config/tc-i386.c: In function 'optimize_encoding':
/scratch/jmyers/glibc-bot/src/binutils/gas/config/tc-i386.c:4152:31: error: logical not is only applied to the left hand side of comparison [-Werror=logical-not-parentheses]
     && !i.prefix[ADDR_PREFIX] != (flag_code == CODE_32BIT))
                               ^

-- 
Joseph S. Myers
joseph@codesourcery.com
Claudiu Zissulescu via Binutils April 27, 2021, 6:31 a.m. | #3
On 26.04.2021 19:08, Joseph Myers wrote:
> On Fri, 23 Apr 2021, Jan Beulich via Binutils wrote:

> 

>> +		  && !i.prefix[ADDR_PREFIX] != (flag_code == CODE_32BIT))

> 

> I'm seeing a -Werror build failure (with GCC 5):

> 

> /scratch/jmyers/glibc-bot/src/binutils/gas/config/tc-i386.c: In function 'optimize_encoding':

> /scratch/jmyers/glibc-bot/src/binutils/gas/config/tc-i386.c:4152:31: error: logical not is only applied to the left hand side of comparison [-Werror=logical-not-parentheses]

>      && !i.prefix[ADDR_PREFIX] != (flag_code == CODE_32BIT))


Well, not sure what to say. For one I consider the warning bogus. It
should be up to the programmer how booleans on either side of
relational operators get expressed. ! is no worse or better than ==
or any other relational operator. For example, personally I consider

     && !i.prefix[ADDR_PREFIX] == !(flag_code == CODE_32BIT))

worse.

And then, if you think this is worthwhile fixing (which probably it
is, as we're unlikely to want to state that binutils don't build
with gcc 5), how about you submit a patch, since you've noticed the
issue and hence you are in a position to check whether whatever
possible change doesn't again trigger some kind of (bogus or not)
warning?

Jan
Andreas Schwab April 27, 2021, 4:29 p.m. | #4
On Apr 27 2021, Jan Beulich via Binutils wrote:

> Well, not sure what to say. For one I consider the warning bogus.


Those parenthesis warnings are always bogus, as they ask for adding
redundant parens.  But they help detecting common logic errors, which
makes them useful.

Andreas.

-- 
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 7578 EB47 D4E5 4D69 2510  2552 DF73 E780 A9DA AEC1
"And now for something completely different."

Patch

--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -3562,7 +3562,8 @@  want_disp32 (const insn_template *t)
 	 || i.prefix[ADDR_PREFIX]
 	 || (t->base_opcode == 0x8d
 	     && t->opcode_modifier.opcodespace == SPACE_BASE
-	     && !i.types[1].bitfield.qword);
+	     && (!i.types[1].bitfield.qword
+		|| t->opcode_modifier.size == SIZE32));
 }
 
 static int
@@ -4069,6 +4070,145 @@  optimize_encoding (void)
 {
   unsigned int j;
 
+  if (i.tm.opcode_modifier.opcodespace == SPACE_BASE
+      && i.tm.base_opcode == 0x8d)
+    {
+      /* Optimize: -O:
+	   lea symbol, %rN    -> mov $symbol, %rN
+	   lea (%rM), %rN     -> mov %rM, %rN
+	   lea (,%rM,1), %rN  -> mov %rM, %rN
+
+	   and in 32-bit mode for 16-bit addressing
+
+	   lea (%rM), %rN     -> movzx %rM, %rN
+
+	   and in 64-bit mode zap 32-bit addressing in favor of using a
+	   32-bit (or less) destination.
+       */
+      if (flag_code == CODE_64BIT && i.prefix[ADDR_PREFIX])
+	{
+	  if (!i.op[1].regs->reg_type.bitfield.word)
+	    i.tm.opcode_modifier.size = SIZE32;
+	  i.prefix[ADDR_PREFIX] = 0;
+	}
+
+      if (!i.index_reg && !i.base_reg)
+	{
+	  /* Handle:
+	       lea symbol, %rN    -> mov $symbol, %rN
+	   */
+	  if (flag_code == CODE_64BIT)
+	    {
+	      /* Don't transform a relocation to a 16-bit one.  */
+	      if (i.op[0].disps
+		  && i.op[0].disps->X_op != O_constant
+		  && i.op[1].regs->reg_type.bitfield.word)
+		return;
+
+	      if (!i.op[1].regs->reg_type.bitfield.qword
+		  || i.tm.opcode_modifier.size == SIZE32)
+		{
+		  i.tm.base_opcode = 0xb8;
+		  i.tm.opcode_modifier.modrm = 0;
+		  if (!i.op[1].regs->reg_type.bitfield.word)
+		    i.types[0].bitfield.imm32 = 1;
+		  else
+		    {
+		      i.tm.opcode_modifier.size = SIZE16;
+		      i.types[0].bitfield.imm16 = 1;
+		    }
+		}
+	      else
+		{
+		  /* Subject to further optimization below.  */
+		  i.tm.base_opcode = 0xc7;
+		  i.tm.extension_opcode = 0;
+		  i.types[0].bitfield.imm32s = 1;
+		  i.types[0].bitfield.baseindex = 0;
+		}
+	    }
+	  /* Outside of 64-bit mode address and operand sizes have to match if
+	     a relocation is involved, as otherwise we wouldn't (currently) or
+	     even couldn't express the relocation correctly.  */
+	  else if (i.op[0].disps
+		   && i.op[0].disps->X_op != O_constant
+		   && ((!i.prefix[ADDR_PREFIX])
+		       != (flag_code == CODE_32BIT
+			   ? i.op[1].regs->reg_type.bitfield.dword
+			   : i.op[1].regs->reg_type.bitfield.word)))
+	    return;
+	  else
+	    {
+	      i.tm.base_opcode = 0xb8;
+	      i.tm.opcode_modifier.modrm = 0;
+	      if (i.op[1].regs->reg_type.bitfield.dword)
+		i.types[0].bitfield.imm32 = 1;
+	      else
+		i.types[0].bitfield.imm16 = 1;
+
+	      if (i.op[0].disps
+		  && i.op[0].disps->X_op == O_constant
+		  && i.op[1].regs->reg_type.bitfield.dword
+		  && !i.prefix[ADDR_PREFIX] != (flag_code == CODE_32BIT))
+		i.op[0].disps->X_add_number &= 0xffff;
+	    }
+
+	  i.tm.operand_types[0] = i.types[0];
+	  i.imm_operands = 1;
+	  if (!i.op[0].imms)
+	    {
+	      i.op[0].imms = &im_expressions[0];
+	      i.op[0].imms->X_op = O_absent;
+	    }
+	}
+      else if (i.op[0].disps
+		  && (i.op[0].disps->X_op != O_constant
+		      || i.op[0].disps->X_add_number))
+	return;
+      else
+	{
+	  /* Handle:
+	       lea (%rM), %rN     -> mov %rM, %rN
+	       lea (,%rM,1), %rN  -> mov %rM, %rN
+	       lea (%rM), %rN     -> movzx %rM, %rN
+	   */
+	  const reg_entry *addr_reg;
+
+	  if (!i.index_reg && i.base_reg->reg_num != RegIP)
+	    addr_reg = i.base_reg;
+	  else if (!i.base_reg
+		   && i.index_reg->reg_num != RegIZ
+		   && !i.log2_scale_factor)
+	    addr_reg = i.index_reg;
+	  else
+	    return;
+
+	  if (addr_reg->reg_type.bitfield.word
+	      && i.op[1].regs->reg_type.bitfield.dword)
+	    {
+	      if (flag_code != CODE_32BIT)
+		return;
+	      i.tm.opcode_modifier.opcodespace = SPACE_0F;
+	      i.tm.base_opcode = 0xb7;
+	    }
+	  else
+	    i.tm.base_opcode = 0x8b;
+
+	  if (addr_reg->reg_type.bitfield.dword
+	      && i.op[1].regs->reg_type.bitfield.qword)
+	    i.tm.opcode_modifier.size = SIZE32;
+
+	  i.op[0].regs = addr_reg;
+	  i.reg_operands = 2;
+	}
+
+      i.mem_operands = 0;
+      i.disp_operands = 0;
+      i.prefix[ADDR_PREFIX] = 0;
+      i.prefix[SEG_PREFIX] = 0;
+      i.seg[0] = NULL;
+    }
+
   if (optimize_for_space
       && i.tm.opcode_modifier.opcodespace == SPACE_BASE
       && i.reg_operands == 1
--- a/gas/testsuite/gas/i386/i386.exp
+++ b/gas/testsuite/gas/i386/i386.exp
@@ -538,6 +538,7 @@  if [gas_32_check] then {
     run_dump_test "optimize-6b"
     run_list_test "optimize-7" "-I${srcdir}/$subdir -march=+noavx2 -al"
     run_dump_test "lea-optimize"
+    run_dump_test "lea16-optimize"
     run_dump_test "align-branch-1a"
     run_dump_test "align-branch-1b"
     run_dump_test "align-branch-1c"
@@ -1194,6 +1195,8 @@  if [gas_64_check] then {
 	run_dump_test "x86-64-align-branch-2a"
 	run_dump_test "x86-64-align-branch-2b"
 	run_dump_test "x86-64-align-branch-2c"
+	run_dump_test "lea64"
+	run_dump_test "lea64-optimize"
     }
     run_dump_test "x86-64-align-branch-4a"
     run_dump_test "x86-64-align-branch-4b"
--- a/gas/testsuite/gas/i386/lea-optimize.d
+++ b/gas/testsuite/gas/i386/lea-optimize.d
@@ -1,6 +1,6 @@ 
 #as: -O -q
 #objdump: -dw
-#name: i386 LEA-like segment overrride dropping
+#name: i386 LEA optimizations
 #source: lea.s
 
 .*: +file format .*
@@ -8,6 +8,41 @@ 
 Disassembly of section .text:
 
 0+ <start>:
-[ 	]*[0-9a-f]+:[ 	]+8d 00[ 	]+lea[ 	]+\(%eax\),%eax
-[ 	]*[0-9a-f]+:[ 	]+8d 00[ 	]+lea[ 	]+\(%eax\),%eax
+[ 	]*[0-9a-f]+:[ 	]+8d 04 08[ 	]+lea[ 	]+\(%eax,%ecx(,1)?\),%eax
+[ 	]*[0-9a-f]+:[ 	]+8d 04 08[ 	]+lea[ 	]+\(%eax,%ecx(,1)?\),%eax
+[ 	]*[0-9a-f]+:[ 	]+8d 48 01[ 	]+lea[ 	]+0x1\(%eax\),%ecx
+[ 	]*[0-9a-f]+:[ 	]+8d 88 00 00 00 00[ 	]+lea[ 	]+0x0\(%eax\),%ecx
+[ 	]*[0-9a-f]+:[ 	]+8d 0c 25 00 00 00 00[ 	]+lea[ 	]+0x0\(,(%eiz)?(,1)?\),%ecx
+[ 	]*[0-9a-f]+:[ 	]+8d 04 00[ 	]+lea[ 	]+\(%eax,%eax(,1)?\),%eax
+[ 	]*[0-9a-f]+:[ 	]+8d 04 45 00 00 00 00[ 	]+lea[ 	]+0x0\(,%eax,2\),%eax
+[ 	]*[0-9a-f]+:[ 	]+8d 04 25 00 00 00 00[ 	]+lea[ 	]+0x0\(,(%eiz)?(,1)?\),%eax
+[ 	]*[0-9a-f]+:[ 	]+67 8d 00[ 	]+lea[ 	]+\(%bx,%si\),%eax
+[ 	]*[0-9a-f]+:[ 	]+8b c0[ 	]+mov[ 	]+%eax,%eax
+[ 	]*[0-9a-f]+:[ 	]+8b c8[ 	]+mov[ 	]+%eax,%ecx
+[ 	]*[0-9a-f]+:[ 	]+8b c8[ 	]+mov[ 	]+%eax,%ecx
+[ 	]*[0-9a-f]+:[ 	]+8b c8[ 	]+mov[ 	]+%eax,%ecx
+[ 	]*[0-9a-f]+:[ 	]+0f b7 c6[ 	]+movzwl[ 	]+%si,%eax
+[ 	]*[0-9a-f]+:[ 	]+0f b7 f6[ 	]+movzwl[ 	]+%si,%esi
+[ 	]*[0-9a-f]+:[ 	]+0f b7 c6[ 	]+movzwl[ 	]+%si,%eax
+[ 	]*[0-9a-f]+:[ 	]+66 8b c0[ 	]+mov[ 	]+%ax,%ax
+[ 	]*[0-9a-f]+:[ 	]+66 8b c8[ 	]+mov[ 	]+%ax,%cx
+[ 	]*[0-9a-f]+:[ 	]+66 8b c8[ 	]+mov[ 	]+%ax,%cx
+[ 	]*[0-9a-f]+:[ 	]+66 8b c6[ 	]+mov[ 	]+%si,%ax
+[ 	]*[0-9a-f]+:[ 	]+66 8b f6[ 	]+mov[ 	]+%si,%si
+[ 	]*[0-9a-f]+:[ 	]+8b c9[ 	]+mov[ 	]+%ecx,%ecx
+[ 	]*[0-9a-f]+:[ 	]+8b c1[ 	]+mov[ 	]+%ecx,%eax
+[ 	]*[0-9a-f]+:[ 	]+b8 01 00 00 00[ 	]+mov[ 	]+\$0x1,%eax
+[ 	]*[0-9a-f]+:[ 	]+66 b8 02 00[ 	]+mov[ 	]+\$0x2,%ax
+[ 	]*[0-9a-f]+:[ 	]+b8 ff ff ff ff[ 	]+mov[ 	]+\$0xffffffff,%eax
+[ 	]*[0-9a-f]+:[ 	]+66 b8 fe ff[ 	]+mov[ 	]+\$0xfffe,%ax
+[ 	]*[0-9a-f]+:[ 	]+b8 01 00 00 00[ 	]+mov[ 	]+\$0x1,%eax
+[ 	]*[0-9a-f]+:[ 	]+66 b8 02 00[ 	]+mov[ 	]+\$0x2,%ax
+[ 	]*[0-9a-f]+:[ 	]+b8 ff ff 00 00[ 	]+mov[ 	]+\$0xffff,%eax
+[ 	]*[0-9a-f]+:[ 	]+66 b8 fe ff[ 	]+mov[ 	]+\$0xfffe,%ax
+[ 	]*[0-9a-f]+:[ 	]+b8 00 00 00 00[ 	]+mov[ 	]+\$0x0,%eax
+[ 	]*[0-9a-f]+:[ 	]+66 8d 05 00 00 00 00[ 	]+lea[ 	]+0x0,%ax
+[ 	]*[0-9a-f]+:[ 	]+67 8d 06 00 00[ 	]+lea[ 	]+0x0,%eax
+[ 	]*[0-9a-f]+:[ 	]+66 b8 00 00[ 	]+mov[ 	]+\$0x0,%ax
+[ 	]*[0-9a-f]+:[ 	]+b8 00 00 00 00[ 	]+mov[ 	]+\$0x0,%eax
+[ 	]*[0-9a-f]+:[ 	]+66 b8 00 00[ 	]+mov[ 	]+\$0x0,%ax
 #pass
--- a/gas/testsuite/gas/i386/lea.d
+++ b/gas/testsuite/gas/i386/lea.d
@@ -7,6 +7,41 @@ 
 Disassembly of section .text:
 
 0+ <start>:
-[ 	]*[0-9a-f]+:[ 	]+36 8d 00[ 	]+lea[ 	]+%ss:\(%eax\),%eax
-[ 	]*[0-9a-f]+:[ 	]+36 8d 00[ 	]+lea[ 	]+%ss:\(%eax\),%eax
+[ 	]*[0-9a-f]+:[ 	]+36 8d 04 08[ 	]+lea[ 	]+%ss:\(%eax,%ecx(,1)?\),%eax
+[ 	]*[0-9a-f]+:[ 	]+36 8d 04 08[ 	]+lea[ 	]+%ss:\(%eax,%ecx(,1)?\),%eax
+[ 	]*[0-9a-f]+:[ 	]+8d 48 01[ 	]+lea[ 	]+0x1\(%eax\),%ecx
+[ 	]*[0-9a-f]+:[ 	]+8d 88 00 00 00 00[ 	]+lea[ 	]+0x0\(%eax\),%ecx
+[ 	]*[0-9a-f]+:[ 	]+8d 0c 25 00 00 00 00[ 	]+lea[ 	]+0x0\(,(%eiz)?(,1)?\),%ecx
+[ 	]*[0-9a-f]+:[ 	]+8d 04 00[ 	]+lea[ 	]+\(%eax,%eax(,1)?\),%eax
+[ 	]*[0-9a-f]+:[ 	]+8d 04 45 00 00 00 00[ 	]+lea[ 	]+0x0\(,%eax,2\),%eax
+[ 	]*[0-9a-f]+:[ 	]+8d 04 25 00 00 00 00[ 	]+lea[ 	]+0x0\(,(%eiz)?(,1)?\),%eax
+[ 	]*[0-9a-f]+:[ 	]+67 8d 00[ 	]+lea[ 	]+\(%bx,%si\),%eax
+[ 	]*[0-9a-f]+:[ 	]+8d 00[ 	]+lea[ 	]+\(%eax\),%eax
+[ 	]*[0-9a-f]+:[ 	]+8d 08[ 	]+lea[ 	]+\(%eax\),%ecx
+[ 	]*[0-9a-f]+:[ 	]+8d 08[ 	]+lea[ 	]+\(%eax\),%ecx
+[ 	]*[0-9a-f]+:[ 	]+65 8d 08[ 	]+lea[ 	]+%gs:\(%eax\),%ecx
+[ 	]*[0-9a-f]+:[ 	]+67 8d 04[ 	]+lea[ 	]+\(%si\),%eax
+[ 	]*[0-9a-f]+:[ 	]+67 8d 34[ 	]+lea[ 	]+\(%si\),%esi
+[ 	]*[0-9a-f]+:[ 	]+67 8d 04[ 	]+lea[ 	]+\(%si\),%eax
+[ 	]*[0-9a-f]+:[ 	]+66 8d 00[ 	]+lea[ 	]+\(%eax\),%ax
+[ 	]*[0-9a-f]+:[ 	]+66 8d 08[ 	]+lea[ 	]+\(%eax\),%cx
+[ 	]*[0-9a-f]+:[ 	]+66 8d 08[ 	]+lea[ 	]+\(%eax\),%cx
+[ 	]*[0-9a-f]+:[ 	]+67 66 8d 04[ 	]+lea[ 	]+\(%si\),%ax
+[ 	]*[0-9a-f]+:[ 	]+67 66 8d 34[ 	]+lea[ 	]+\(%si\),%si
+[ 	]*[0-9a-f]+:[ 	]+8d 0c 0d 00 00 00 00[ 	]+lea[ 	]+0x0\(,%ecx(,1)?\),%ecx
+[ 	]*[0-9a-f]+:[ 	]+8d 04 0d 00 00 00 00[ 	]+lea[ 	]+0x0\(,%ecx(,1)?\),%eax
+[ 	]*[0-9a-f]+:[ 	]+8d 05 01 00 00 00[ 	]+lea[ 	]+0x1,%eax
+[ 	]*[0-9a-f]+:[ 	]+66 8d 05 02 00 00 00[ 	]+lea[ 	]+0x2,%ax
+[ 	]*[0-9a-f]+:[ 	]+8d 05 ff ff ff ff[ 	]+lea[ 	]+0xffffffff,%eax
+[ 	]*[0-9a-f]+:[ 	]+66 8d 05 fe ff ff ff[ 	]+lea[ 	]+0xfffffffe,%ax
+[ 	]*[0-9a-f]+:[ 	]+67 8d 06 01 00[ 	]+lea[ 	]+0x1,%eax
+[ 	]*[0-9a-f]+:[ 	]+67 66 8d 06 02 00[ 	]+lea[ 	]+0x2,%ax
+[ 	]*[0-9a-f]+:[ 	]+67 8d 06 ff ff[ 	]+lea[ 	]+-0x1,%eax
+[ 	]*[0-9a-f]+:[ 	]+67 66 8d 06 fe ff[ 	]+lea[ 	]+-0x2,%ax
+[ 	]*[0-9a-f]+:[ 	]+8d 05 00 00 00 00[ 	]+lea[ 	]+0x0,%eax
+[ 	]*[0-9a-f]+:[ 	]+66 8d 05 00 00 00 00[ 	]+lea[ 	]+0x0,%ax
+[ 	]*[0-9a-f]+:[ 	]+67 8d 06 00 00[ 	]+lea[ 	]+0x0,%eax
+[ 	]*[0-9a-f]+:[ 	]+67 66 8d 06 00 00[ 	]+lea[ 	]+0x0,%ax
+[ 	]*[0-9a-f]+:[ 	]+8d 05 00 00 00 00[ 	]+lea[ 	]+0x0,%eax
+[ 	]*[0-9a-f]+:[ 	]+66 8d 05 00 00 00 00[ 	]+lea[ 	]+0x0,%ax
 #pass
--- a/gas/testsuite/gas/i386/lea.e
+++ b/gas/testsuite/gas/i386/lea.e
@@ -1,3 +1,4 @@ 
 .*: Assembler messages:
 .*:3: Warning: .* `lea' .*
 .*:4: Warning: .* `lea' .*
+.*:19: Warning: .* `lea' .*
--- a/gas/testsuite/gas/i386/lea.s
+++ b/gas/testsuite/gas/i386/lea.s
@@ -1,4 +1,54 @@ 
 	.text
 start:
-	lea	%ss:(%eax), %eax
-	ss lea	(%eax), %eax
+	lea	%ss:(%eax,%ecx), %eax
+	ss lea	(%eax,%ecx), %eax
+
+	.allow_index_reg
+	lea	1(%eax), %ecx
+	lea	sym(%eax), %ecx
+	lea	sym(,%eiz), %ecx
+
+	lea	(%eax,%eax), %eax
+	lea	(,%eax,2), %eax
+	lea	(,%eiz), %eax
+	lea	(%bx,%si), %eax
+
+	lea	(%eax), %eax
+	lea	(%eax), %ecx
+	lea	1-1(%eax), %ecx
+	lea	%gs:(%eax), %ecx
+
+	lea	(%si), %eax
+	lea	(%si), %esi
+	leal	(%si), %eax
+
+	lea	(%eax), %ax
+	lea	(%eax), %cx
+	leaw	(%eax), %cx
+
+	lea	(%si), %ax
+	lea	(%si), %si
+
+	lea	(,%ecx,1), %ecx
+	lea	(,%ecx,1), %eax
+
+	lea	1, %eax
+	lea	2, %ax
+
+	lea	-1, %eax
+	lea	-2, %ax
+
+	addr16 lea 1, %eax
+	addr16 lea 2, %ax
+
+	addr16 lea -1, %eax
+	addr16 lea -2, %ax
+
+	lea	sym, %eax
+	lea	sym, %ax
+
+	addr16 lea sym, %eax
+	addr16 lea sym, %ax
+
+	lea	(,1), %eax
+	lea	(,1), %ax
--- /dev/null
+++ b/gas/testsuite/gas/i386/lea16-optimize.d
@@ -0,0 +1,48 @@ 
+#as: -O -q -I${srcdir}/$subdir
+#objdump: -dw -Mi8086
+#name: i386 16-bit LEA optimizations
+#source: lea16.s
+
+.*: +file format .*
+
+Disassembly of section .text:
+
+0+ <start>:
+[ 	]*[0-9a-f]+:[ 	]+67 66 8d 04 08[ 	]+lea[ 	]+\(%eax,%ecx(,1)?\),%eax
+[ 	]*[0-9a-f]+:[ 	]+67 66 8d 04 08[ 	]+lea[ 	]+\(%eax,%ecx(,1)?\),%eax
+[ 	]*[0-9a-f]+:[ 	]+67 66 8d 48 01[ 	]+lea[ 	]+0x1\(%eax\),%ecx
+[ 	]*[0-9a-f]+:[ 	]+67 66 8d 88 00 00 00 00[ 	]+lea[ 	]+0x0\(%eax\),%ecx
+[ 	]*[0-9a-f]+:[ 	]+67 66 8d 0c 25 00 00 00 00[ 	]+addr32 lea[ 	]+0x0,%ecx
+[ 	]*[0-9a-f]+:[ 	]+67 66 8d 04 00[ 	]+lea[ 	]+\(%eax,%eax(,1)?\),%eax
+[ 	]*[0-9a-f]+:[ 	]+67 66 8d 04 45 00 00 00 00[ 	]+lea[ 	]+0x0\(,%eax,2\),%eax
+[ 	]*[0-9a-f]+:[ 	]+67 66 8d 04 25 00 00 00 00[ 	]+addr32 lea[ 	]+0x0,%eax
+[ 	]*[0-9a-f]+:[ 	]+66 8d 00[ 	]+lea[ 	]+\(%bx,%si\),%eax
+[ 	]*[0-9a-f]+:[ 	]+66 8b c0[ 	]+mov[ 	]+%eax,%eax
+[ 	]*[0-9a-f]+:[ 	]+66 8b c8[ 	]+mov[ 	]+%eax,%ecx
+[ 	]*[0-9a-f]+:[ 	]+66 8b c8[ 	]+mov[ 	]+%eax,%ecx
+[ 	]*[0-9a-f]+:[ 	]+66 8b c8[ 	]+mov[ 	]+%eax,%ecx
+[ 	]*[0-9a-f]+:[ 	]+66 8d 04[ 	]+lea[ 	]+\(%si\),%eax
+[ 	]*[0-9a-f]+:[ 	]+66 8d 34[ 	]+lea[ 	]+\(%si\),%esi
+[ 	]*[0-9a-f]+:[ 	]+66 8d 04[ 	]+lea[ 	]+\(%si\),%eax
+[ 	]*[0-9a-f]+:[ 	]+8b c0[ 	]+mov[ 	]+%ax,%ax
+[ 	]*[0-9a-f]+:[ 	]+8b c8[ 	]+mov[ 	]+%ax,%cx
+[ 	]*[0-9a-f]+:[ 	]+8b c8[ 	]+mov[ 	]+%ax,%cx
+[ 	]*[0-9a-f]+:[ 	]+8b c6[ 	]+mov[ 	]+%si,%ax
+[ 	]*[0-9a-f]+:[ 	]+8b f6[ 	]+mov[ 	]+%si,%si
+[ 	]*[0-9a-f]+:[ 	]+66 8b c9[ 	]+mov[ 	]+%ecx,%ecx
+[ 	]*[0-9a-f]+:[ 	]+66 8b c1[ 	]+mov[ 	]+%ecx,%eax
+[ 	]*[0-9a-f]+:[ 	]+66 b8 01 00 00 00[ 	]+mov[ 	]+\$0x1,%eax
+[ 	]*[0-9a-f]+:[ 	]+b8 02 00[ 	]+mov[ 	]+\$0x2,%ax
+[ 	]*[0-9a-f]+:[ 	]+66 b8 ff ff 00 00[ 	]+mov[ 	]+\$0xffff,%eax
+[ 	]*[0-9a-f]+:[ 	]+b8 fe ff[ 	]+mov[ 	]+\$0xfffe,%ax
+[ 	]*[0-9a-f]+:[ 	]+66 b8 01 00 00 00[ 	]+mov[ 	]+\$0x1,%eax
+[ 	]*[0-9a-f]+:[ 	]+b8 02 00[ 	]+mov[ 	]+\$0x2,%ax
+[ 	]*[0-9a-f]+:[ 	]+66 b8 ff ff ff ff[ 	]+mov[ 	]+\$0xffffffff,%eax
+[ 	]*[0-9a-f]+:[ 	]+b8 fe ff[ 	]+mov[ 	]+\$0xfffe,%ax
+[ 	]*[0-9a-f]+:[ 	]+66 8d 06 00 00[ 	]+lea[ 	]+0x0,%eax
+[ 	]*[0-9a-f]+:[ 	]+b8 00 00[ 	]+mov[ 	]+\$0x0,%ax
+[ 	]*[0-9a-f]+:[ 	]+66 b8 00 00 00 00[ 	]+mov[ 	]+\$0x0,%eax
+[ 	]*[0-9a-f]+:[ 	]+67 8d 05 00 00 00 00[ 	]+addr32 lea[ 	]+0x0,%ax
+[ 	]*[0-9a-f]+:[ 	]+66 b8 00 00 00 00[ 	]+mov[ 	]+\$0x0,%eax
+[ 	]*[0-9a-f]+:[ 	]+b8 00 00[ 	]+mov[ 	]+\$0x0,%ax
+#pass
--- /dev/null
+++ b/gas/testsuite/gas/i386/lea16.s
@@ -0,0 +1,7 @@ 
+	.code16
+
+	.macro addr16 mnem:req opnds:vararg
+	addr32 \mnem \opnds
+	.endm
+
+	.include "lea.s"
--- /dev/null
+++ b/gas/testsuite/gas/i386/lea64-optimize.d
@@ -0,0 +1,71 @@ 
+#as: -O -q
+#objdump: -drw
+#name: x86-64 LEA optimizations
+#source: lea64.s
+
+.*: +file format .*
+
+Disassembly of section .text:
+
+0+ <start>:
+[ 	]*[0-9a-f]+:[ 	]+8d 04 08[ 	]+lea[ 	]+\(%rax,%rcx(,1)?\),%eax
+[ 	]*[0-9a-f]+:[ 	]+8d 04 08[ 	]+lea[ 	]+\(%rax,%rcx(,1)?\),%eax
+[ 	]*[0-9a-f]+:[ 	]+8d 48 01[ 	]+lea[ 	]+0x1\(%rax\),%ecx
+[ 	]*[0-9a-f]+:[ 	]+8d 88 00 00 00 00[ 	]+lea[ 	]+0x0\(%rax\),%ecx[ 	]+[0-9a-f]+: R_X86_64_32[ 	]+sym
+[ 	]*[0-9a-f]+:[ 	]+8d 0c 25 00 00 00 00[ 	]+lea[ 	]+0x0,%ecx[ 	]+[0-9a-f]+: R_X86_64_32[ 	]+sym
+[ 	]*[0-9a-f]+:[ 	]+8d 04 00[ 	]+lea[ 	]+\(%rax,%rax(,1)?\),%eax
+[ 	]*[0-9a-f]+:[ 	]+8d 04 45 00 00 00 00[ 	]+lea[ 	]+0x0\(,%rax,2\),%eax
+[ 	]*[0-9a-f]+:[ 	]+8d 05 00 00 00 00[ 	]+lea[ 	]+0x0\(%rip\),%eax($| *#.*)
+[ 	]*[0-9a-f]+:[ 	]+8d 04 25 00 00 00 00[ 	]+lea[ 	]+0x0,%eax
+[ 	]*[0-9a-f]+:[ 	]+48 8b c0[ 	]+mov[ 	]+%rax,%rax
+[ 	]*[0-9a-f]+:[ 	]+48 8b c8[ 	]+mov[ 	]+%rax,%rcx
+[ 	]*[0-9a-f]+:[ 	]+48 8b c8[ 	]+mov[ 	]+%rax,%rcx
+[ 	]*[0-9a-f]+:[ 	]+48 8b c8[ 	]+mov[ 	]+%rax,%rcx
+[ 	]*[0-9a-f]+:[ 	]+8b c6[ 	]+mov[ 	]+%esi,%eax
+[ 	]*[0-9a-f]+:[ 	]+8b f6[ 	]+mov[ 	]+%esi,%esi
+[ 	]*[0-9a-f]+:[ 	]+8b c6[ 	]+mov[ 	]+%esi,%eax
+[ 	]*[0-9a-f]+:[ 	]+66 8b c6[ 	]+mov[ 	]+%si,%ax
+[ 	]*[0-9a-f]+:[ 	]+66 8b f6[ 	]+mov[ 	]+%si,%si
+[ 	]*[0-9a-f]+:[ 	]+66 8b c6[ 	]+mov[ 	]+%si,%ax
+[ 	]*[0-9a-f]+:[ 	]+8b c0[ 	]+mov[ 	]+%eax,%eax
+[ 	]*[0-9a-f]+:[ 	]+8b c8[ 	]+mov[ 	]+%eax,%ecx
+[ 	]*[0-9a-f]+:[ 	]+8b c8[ 	]+mov[ 	]+%eax,%ecx
+[ 	]*[0-9a-f]+:[ 	]+8b c0[ 	]+mov[ 	]+%eax,%eax
+[ 	]*[0-9a-f]+:[ 	]+8b c8[ 	]+mov[ 	]+%eax,%ecx
+[ 	]*[0-9a-f]+:[ 	]+66 8b c6[ 	]+mov[ 	]+%si,%ax
+[ 	]*[0-9a-f]+:[ 	]+66 8b f6[ 	]+mov[ 	]+%si,%si
+[ 	]*[0-9a-f]+:[ 	]+66 8b c6[ 	]+mov[ 	]+%si,%ax
+[ 	]*[0-9a-f]+:[ 	]+48 8b c9[ 	]+mov[ 	]+%rcx,%rcx
+[ 	]*[0-9a-f]+:[ 	]+48 8b c1[ 	]+mov[ 	]+%rcx,%rax
+[ 	]*[0-9a-f]+:[ 	]+8b c9[ 	]+mov[ 	]+%ecx,%ecx
+[ 	]*[0-9a-f]+:[ 	]+8b c1[ 	]+mov[ 	]+%ecx,%eax
+[ 	]*[0-9a-f]+:[ 	]+66 8b c9[ 	]+mov[ 	]+%cx,%cx
+[ 	]*[0-9a-f]+:[ 	]+66 8b c1[ 	]+mov[ 	]+%cx,%ax
+[ 	]*[0-9a-f]+:[ 	]+8b c9[ 	]+mov[ 	]+%ecx,%ecx
+[ 	]*[0-9a-f]+:[ 	]+8b c1[ 	]+mov[ 	]+%ecx,%eax
+[ 	]*[0-9a-f]+:[ 	]+8b c9[ 	]+mov[ 	]+%ecx,%ecx
+[ 	]*[0-9a-f]+:[ 	]+8b c1[ 	]+mov[ 	]+%ecx,%eax
+[ 	]*[0-9a-f]+:[ 	]+66 8b c9[ 	]+mov[ 	]+%cx,%cx
+[ 	]*[0-9a-f]+:[ 	]+66 8b c1[ 	]+mov[ 	]+%cx,%ax
+[ 	]*[0-9a-f]+:[ 	]+b8 01 00 00 00[ 	]+mov[ 	]+\$0x1,%eax
+[ 	]*[0-9a-f]+:[ 	]+b8 02 00 00 00[ 	]+mov[ 	]+\$0x2,%eax
+[ 	]*[0-9a-f]+:[ 	]+66 b8 03 00[ 	]+mov[ 	]+\$0x3,%ax
+[ 	]*[0-9a-f]+:[ 	]+48 c7 c0 ff ff ff ff[ 	]+mov[ 	]+\$0xffffffffffffffff,%rax
+[ 	]*[0-9a-f]+:[ 	]+b8 fe ff ff ff[ 	]+mov[ 	]+\$0xfffffffe,%eax
+[ 	]*[0-9a-f]+:[ 	]+66 b8 fd ff[ 	]+mov[ 	]+\$0xfffd,%ax
+[ 	]*[0-9a-f]+:[ 	]+b8 01 00 00 00[ 	]+mov[ 	]+\$0x1,%eax
+[ 	]*[0-9a-f]+:[ 	]+b8 02 00 00 00[ 	]+mov[ 	]+\$0x2,%eax
+[ 	]*[0-9a-f]+:[ 	]+66 b8 03 00[ 	]+mov[ 	]+\$0x3,%ax
+[ 	]*[0-9a-f]+:[ 	]+b8 ff ff ff ff[ 	]+mov[ 	]+\$0xffffffff,%eax
+[ 	]*[0-9a-f]+:[ 	]+b8 fe ff ff ff[ 	]+mov[ 	]+\$0xfffffffe,%eax
+[ 	]*[0-9a-f]+:[ 	]+66 b8 fd ff[ 	]+mov[ 	]+\$0xfffd,%ax
+[ 	]*[0-9a-f]+:[ 	]+48 c7 c0 00 00 00 00[ 	]+mov[ 	]+\$0x0,%rax[ 	]+[0-9a-f]+: R_X86_64_32S[ 	]+sym
+[ 	]*[0-9a-f]+:[ 	]+b8 00 00 00 00[ 	]+mov[ 	]+\$0x0,%eax[ 	]+[0-9a-f]+: R_X86_64_32[ 	]+sym
+[ 	]*[0-9a-f]+:[ 	]+66 8d 04 25 00 00 00 00[ 	]+lea[ 	]+0x0,%ax[ 	]+[0-9a-f]+: R_X86_64_32[ 	]+sym
+[ 	]*[0-9a-f]+:[ 	]+b8 00 00 00 00[ 	]+mov[ 	]+\$0x0,%eax[ 	]+[0-9a-f]+: R_X86_64_32[ 	]+sym
+[ 	]*[0-9a-f]+:[ 	]+b8 00 00 00 00[ 	]+mov[ 	]+\$0x0,%eax[ 	]+[0-9a-f]+: R_X86_64_32[ 	]+sym
+[ 	]*[0-9a-f]+:[ 	]+66 8d 04 25 00 00 00 00[ 	]+lea[ 	]+0x0,%ax[ 	]+[0-9a-f]+: R_X86_64_32[ 	]+sym
+[ 	]*[0-9a-f]+:[ 	]+48 c7 c0 00 00 00 00[ 	]+mov[ 	]+\$0x0,%rax
+[ 	]*[0-9a-f]+:[ 	]+b8 00 00 00 00[ 	]+mov[ 	]+\$0x0,%eax
+[ 	]*[0-9a-f]+:[ 	]+66 b8 00 00[ 	]+mov[ 	]+\$0x0,%ax
+#pass
--- /dev/null
+++ b/gas/testsuite/gas/i386/lea64.d
@@ -0,0 +1,70 @@ 
+#objdump: -drw
+#name: x86-64 LEA
+#warning_output: lea64.e
+
+.*: +file format .*
+
+Disassembly of section .text:
+
+0+ <start>:
+[ 	]*[0-9a-f]+:[ 	]+64 8d 04 08[ 	]+lea[ 	]+%fs:\(%rax,%rcx(,1)?\),%eax
+[ 	]*[0-9a-f]+:[ 	]+65 8d 04 08[ 	]+lea[ 	]+%gs:\(%rax,%rcx(,1)?\),%eax
+[ 	]*[0-9a-f]+:[ 	]+8d 48 01[ 	]+lea[ 	]+0x1\(%rax\),%ecx
+[ 	]*[0-9a-f]+:[ 	]+8d 88 00 00 00 00[ 	]+lea[ 	]+0x0\(%rax\),%ecx[ 	]+[0-9a-f]+: R_X86_64_32[ 	]+sym
+[ 	]*[0-9a-f]+:[ 	]+8d 0c 25 00 00 00 00[ 	]+lea[ 	]+0x0,%ecx[ 	]+[0-9a-f]+: R_X86_64_32[ 	]+sym
+[ 	]*[0-9a-f]+:[ 	]+8d 04 00[ 	]+lea[ 	]+\(%rax,%rax(,1)?\),%eax
+[ 	]*[0-9a-f]+:[ 	]+8d 04 45 00 00 00 00[ 	]+lea[ 	]+0x0\(,%rax,2\),%eax
+[ 	]*[0-9a-f]+:[ 	]+8d 05 00 00 00 00[ 	]+lea[ 	]+0x0\(%rip\),%eax($| *#.*)
+[ 	]*[0-9a-f]+:[ 	]+8d 04 25 00 00 00 00[ 	]+lea[ 	]+0x0,%eax
+[ 	]*[0-9a-f]+:[ 	]+48 8d 00[ 	]+lea[ 	]+\(%rax\),%rax
+[ 	]*[0-9a-f]+:[ 	]+48 8d 08[ 	]+lea[ 	]+\(%rax\),%rcx
+[ 	]*[0-9a-f]+:[ 	]+48 8d 08[ 	]+lea[ 	]+\(%rax\),%rcx
+[ 	]*[0-9a-f]+:[ 	]+65 48 8d 08[ 	]+lea[ 	]+%gs:\(%rax\),%rcx
+[ 	]*[0-9a-f]+:[ 	]+8d 06[ 	]+lea[ 	]+\(%rsi\),%eax
+[ 	]*[0-9a-f]+:[ 	]+8d 36[ 	]+lea[ 	]+\(%rsi\),%esi
+[ 	]*[0-9a-f]+:[ 	]+8d 06[ 	]+lea[ 	]+\(%rsi\),%eax
+[ 	]*[0-9a-f]+:[ 	]+66 8d 06[ 	]+lea[ 	]+\(%rsi\),%ax
+[ 	]*[0-9a-f]+:[ 	]+66 8d 36[ 	]+lea[ 	]+\(%rsi\),%si
+[ 	]*[0-9a-f]+:[ 	]+66 8d 06[ 	]+lea[ 	]+\(%rsi\),%ax
+[ 	]*[0-9a-f]+:[ 	]+67 48 8d 00[ 	]+lea[ 	]+\(%eax\),%rax
+[ 	]*[0-9a-f]+:[ 	]+67 48 8d 08[ 	]+lea[ 	]+\(%eax\),%rcx
+[ 	]*[0-9a-f]+:[ 	]+67 48 8d 08[ 	]+lea[ 	]+\(%eax\),%rcx
+[ 	]*[0-9a-f]+:[ 	]+67 8d 00[ 	]+lea[ 	]+\(%eax\),%eax
+[ 	]*[0-9a-f]+:[ 	]+67 8d 08[ 	]+lea[ 	]+\(%eax\),%ecx
+[ 	]*[0-9a-f]+:[ 	]+67 66 8d 06[ 	]+lea[ 	]+\(%esi\),%ax
+[ 	]*[0-9a-f]+:[ 	]+67 66 8d 36[ 	]+lea[ 	]+\(%esi\),%si
+[ 	]*[0-9a-f]+:[ 	]+67 66 8d 06[ 	]+lea[ 	]+\(%esi\),%ax
+[ 	]*[0-9a-f]+:[ 	]+48 8d 0c 0d 00 00 00 00[ 	]+lea[ 	]+0x0\(,%rcx(,1)?\),%rcx
+[ 	]*[0-9a-f]+:[ 	]+48 8d 04 0d 00 00 00 00[ 	]+lea[ 	]+0x0\(,%rcx(,1)?\),%rax
+[ 	]*[0-9a-f]+:[ 	]+8d 0c 0d 00 00 00 00[ 	]+lea[ 	]+0x0\(,%rcx(,1)?\),%ecx
+[ 	]*[0-9a-f]+:[ 	]+8d 04 0d 00 00 00 00[ 	]+lea[ 	]+0x0\(,%rcx(,1)?\),%eax
+[ 	]*[0-9a-f]+:[ 	]+66 8d 0c 0d 00 00 00 00[ 	]+lea[ 	]+0x0\(,%rcx(,1)?\),%cx
+[ 	]*[0-9a-f]+:[ 	]+66 8d 04 0d 00 00 00 00[ 	]+lea[ 	]+0x0\(,%rcx(,1)?\),%ax
+[ 	]*[0-9a-f]+:[ 	]+67 48 8d 0c 0d 00 00 00 00[ 	]+lea[ 	]+0x0\(,%ecx(,1)?\),%rcx
+[ 	]*[0-9a-f]+:[ 	]+67 48 8d 04 0d 00 00 00 00[ 	]+lea[ 	]+0x0\(,%ecx(,1)?\),%rax
+[ 	]*[0-9a-f]+:[ 	]+67 8d 0c 0d 00 00 00 00[ 	]+lea[ 	]+0x0\(,%ecx(,1)?\),%ecx
+[ 	]*[0-9a-f]+:[ 	]+67 8d 04 0d 00 00 00 00[ 	]+lea[ 	]+0x0\(,%ecx(,1)?\),%eax
+[ 	]*[0-9a-f]+:[ 	]+67 66 8d 0c 0d 00 00 00 00[ 	]+lea[ 	]+0x0\(,%ecx(,1)?\),%cx
+[ 	]*[0-9a-f]+:[ 	]+67 66 8d 04 0d 00 00 00 00[ 	]+lea[ 	]+0x0\(,%ecx(,1)?\),%ax
+[ 	]*[0-9a-f]+:[ 	]+48 8d 04 25 01 00 00 00[ 	]+lea[ 	]+0x1,%rax
+[ 	]*[0-9a-f]+:[ 	]+8d 04 25 02 00 00 00[ 	]+lea[ 	]+0x2,%eax
+[ 	]*[0-9a-f]+:[ 	]+66 8d 04 25 03 00 00 00[ 	]+lea[ 	]+0x3,%ax
+[ 	]*[0-9a-f]+:[ 	]+48 8d 04 25 ff ff ff ff[ 	]+lea[ 	]+0xffffffffffffffff,%rax
+[ 	]*[0-9a-f]+:[ 	]+8d 04 25 fe ff ff ff[ 	]+lea[ 	]+0xfffffffffffffffe,%eax
+[ 	]*[0-9a-f]+:[ 	]+66 8d 04 25 fd ff ff ff[ 	]+lea[ 	]+0xfffffffffffffffd,%ax
+[ 	]*[0-9a-f]+:[ 	]+67 48 8d 04 25 01 00 00 00[ 	]+lea[ 	]+0x1\(,%eiz,1\),%rax
+[ 	]*[0-9a-f]+:[ 	]+67 8d 04 25 02 00 00 00[ 	]+lea[ 	]+0x2\(,%eiz,1\),%eax
+[ 	]*[0-9a-f]+:[ 	]+67 66 8d 04 25 03 00 00 00[ 	]+lea[ 	]+0x3\(,%eiz,1\),%ax
+[ 	]*[0-9a-f]+:[ 	]+67 48 8d 04 25 ff ff ff ff[ 	]+lea[ 	]+0xffffffff\(,%eiz,1\),%rax
+[ 	]*[0-9a-f]+:[ 	]+67 8d 04 25 fe ff ff ff[ 	]+lea[ 	]+0xfffffffe\(,%eiz,1\),%eax
+[ 	]*[0-9a-f]+:[ 	]+67 66 8d 04 25 fd ff ff ff[ 	]+lea[ 	]+0xfffffffd\(,%eiz,1\),%ax
+[ 	]*[0-9a-f]+:[ 	]+48 8d 04 25 00 00 00 00[ 	]+lea[ 	]+0x0,%rax[ 	]+[0-9a-f]+: R_X86_64_32S[ 	]+sym
+[ 	]*[0-9a-f]+:[ 	]+8d 04 25 00 00 00 00[ 	]+lea[ 	]+0x0,%eax[ 	]+[0-9a-f]+: R_X86_64_32[ 	]+sym
+[ 	]*[0-9a-f]+:[ 	]+66 8d 04 25 00 00 00 00[ 	]+lea[ 	]+0x0,%ax[ 	]+[0-9a-f]+: R_X86_64_32[ 	]+sym
+[ 	]*[0-9a-f]+:[ 	]+67 48 8d 04 25 00 00 00 00[ 	]+lea[ 	]+0x0\(,%eiz,1\),%rax[ 	]+[0-9a-f]+: R_X86_64_32[ 	]+sym
+[ 	]*[0-9a-f]+:[ 	]+67 8d 04 25 00 00 00 00[ 	]+lea[ 	]+0x0\(,%eiz,1\),%eax[ 	]+[0-9a-f]+: R_X86_64_32[ 	]+sym
+[ 	]*[0-9a-f]+:[ 	]+67 66 8d 04 25 00 00 00 00[ 	]+lea[ 	]+0x0\(,%eiz,1\),%ax[ 	]+[0-9a-f]+: R_X86_64_32[ 	]+sym
+[ 	]*[0-9a-f]+:[ 	]+48 8d 04 25 00 00 00 00[ 	]+lea[ 	]+0x0,%rax
+[ 	]*[0-9a-f]+:[ 	]+8d 04 25 00 00 00 00[ 	]+lea[ 	]+0x0,%eax
+[ 	]*[0-9a-f]+:[ 	]+66 8d 04 25 00 00 00 00[ 	]+lea[ 	]+0x0,%ax
+#pass
--- /dev/null
+++ b/gas/testsuite/gas/i386/lea64.e
@@ -0,0 +1,4 @@ 
+.*: Assembler messages:
+.*:3: Warning: .* `lea' .*
+.*:4: Warning: .* `lea' .*
+.*:19: Warning: .* `lea' .*
--- /dev/null
+++ b/gas/testsuite/gas/i386/lea64.s
@@ -0,0 +1,84 @@ 
+	.text
+start:
+	lea	%fs:(%rax,%rcx), %eax
+	gs lea	(%rax,%rcx), %eax
+
+	.allow_index_reg
+	lea	1(%rax), %ecx
+	lea	sym(%rax), %ecx
+	lea	sym(,%riz), %ecx
+
+	lea	(%rax,%rax), %eax
+	lea	(,%rax,2), %eax
+	lea	(%rip), %eax
+	lea	(,%riz), %eax
+
+	lea	(%rax), %rax
+	lea	(%rax), %rcx
+	lea	1-1(%rax), %rcx
+	lea	%gs:(%rax), %rcx
+
+	lea	(%rsi), %eax
+	lea	(%rsi), %esi
+	leal	(%rsi), %eax
+
+	lea	(%rsi), %ax
+	lea	(%rsi), %si
+	leaw	(%rsi), %ax
+
+	lea	(%eax), %rax
+	lea	(%eax), %rcx
+	leaq	(%eax), %rcx
+
+	lea	(%eax), %eax
+	lea	(%eax), %ecx
+
+	lea	(%esi), %ax
+	lea	(%esi), %si
+	leaw	(%esi), %ax
+
+	lea	(,%rcx,1), %rcx
+	lea	(,%rcx,1), %rax
+
+	lea	(,%rcx,1), %ecx
+	lea	(,%rcx,1), %eax
+
+	lea	(,%rcx,1), %cx
+	lea	(,%rcx,1), %ax
+
+	lea	(,%ecx,1), %rcx
+	lea	(,%ecx,1), %rax
+
+	lea	(,%ecx,1), %ecx
+	lea	(,%ecx,1), %eax
+
+	lea	(,%ecx,1), %cx
+	lea	(,%ecx,1), %ax
+
+	lea	1, %rax
+	lea	2, %eax
+	lea	3, %ax
+
+	lea	-1, %rax
+	lea	-2, %eax
+	lea	-3, %ax
+
+	addr32 lea 1, %rax
+	addr32 lea 2, %eax
+	addr32 lea 3, %ax
+
+	addr32 lea -1, %rax
+	addr32 lea -2, %eax
+	addr32 lea -3, %ax
+
+	lea	sym, %rax
+	lea	sym, %eax
+	lea	sym, %ax
+
+	addr32 lea sym, %rax
+	addr32 lea sym, %eax
+	addr32 lea sym, %ax
+
+	lea	(,1), %rax
+	lea	(,1), %eax
+	lea	(,1), %ax
--- a/opcodes/i386-opc.tbl
+++ b/opcodes/i386-opc.tbl
@@ -228,7 +228,7 @@  out, 0xe6, None, 0, W|No_sSuf|No_qSuf|No
 out, 0xee, None, 0, W|No_sSuf|No_qSuf|No_ldSuf, { InOutPortReg }
 
 // Load effective address.
-lea, 0x8d, None, 0, Modrm|Anysize|No_bSuf|No_sSuf|No_ldSuf, { BaseIndex, Reg16|Reg32|Reg64 }
+lea, 0x8d, None, 0, Modrm|Anysize|No_bSuf|No_sSuf|No_ldSuf|Optimize, { BaseIndex, Reg16|Reg32|Reg64 }
 
 // Load segment registers from memory.
 lds, 0xc5, None, CpuNo64, Modrm|No_bSuf|No_sSuf|No_qSuf|No_ldSuf, { DWord|Fword|Unspecified|BaseIndex, Reg16|Reg32 }