Index: lld/ELF/Arch/X86_64.cpp =================================================================== --- lld/ELF/Arch/X86_64.cpp +++ lld/ELF/Arch/X86_64.cpp @@ -500,24 +500,16 @@ uint8_t reg = loc[-1] >> 3; uint8_t *regSlot = loc - 1; - // Note that ADD with RSP or R12 is converted to ADD instead of LEA - // because LEA with these registers needs 4 bytes to encode and thus - // wouldn't fit the space. - - if (memcmp(inst, "\x48\x03\x25", 3) == 0) { - // "addq foo@gottpoff(%rip),%rsp" -> "addq $foo,%rsp" - memcpy(inst, "\x48\x81\xc4", 3); - } else if (memcmp(inst, "\x4c\x03\x25", 3) == 0) { - // "addq foo@gottpoff(%rip),%r12" -> "addq $foo,%r12" - memcpy(inst, "\x49\x81\xc4", 3); - } else if (memcmp(inst, "\x4c\x03", 2) == 0) { - // "addq foo@gottpoff(%rip),%r[8-15]" -> "leaq foo(%r[8-15]),%r[8-15]" - memcpy(inst, "\x4d\x8d", 2); - *regSlot = 0x80 | (reg << 3) | reg; + // Note that ADD cannot be optimized to LEA because it does not set flags + + if (memcmp(inst, "\x4c\x03", 2) == 0) { + // "addq foo@gottpoff(%rip),%r[8-15]" -> "addq $foo,%r[8-15]" + memcpy(inst, "\x49\x81", 2); + *regSlot = 0xc0 | reg; } else if (memcmp(inst, "\x48\x03", 2) == 0) { - // "addq foo@gottpoff(%rip),%reg -> "leaq foo(%reg),%reg" - memcpy(inst, "\x48\x8d", 2); - *regSlot = 0x80 | (reg << 3) | reg; + // "addq foo@gottpoff(%rip),%reg -> "addq $foo,%reg" + memcpy(inst, "\x48\x81", 2); + *regSlot = 0xc0 | reg; } else if (memcmp(inst, "\x4c\x8b", 2) == 0) { // "movq foo@gottpoff(%rip),%r[8-15]" -> "movq $foo,%r[8-15]" memcpy(inst, "\x49\xc7", 2); Index: lld/test/ELF/tls-opt.s =================================================================== --- lld/test/ELF/tls-opt.s +++ lld/test/ELF/tls-opt.s @@ -10,14 +10,14 @@ // DISASM: <_start>: // DISASM-NEXT: movq $-8, %rax // DISASM-NEXT: movq $-8, %r15 -// DISASM-NEXT: leaq -8(%rax), %rax -// DISASM-NEXT: leaq -8(%r15), %r15 +// DISASM-NEXT: addq $-8, %rax +// DISASM-NEXT: addq $-8, %r15 // DISASM-NEXT: addq $-8, %rsp // DISASM-NEXT: addq $-8, %r12 // DISASM-NEXT: movq $-4, %rax // DISASM-NEXT: movq $-4, %r15 -// DISASM-NEXT: leaq -4(%rax), %rax -// DISASM-NEXT: leaq -4(%r15), %r15 +// DISASM-NEXT: addq $-4, %rax +// DISASM-NEXT: addq $-4, %r15 // DISASM-NEXT: addq $-4, %rsp // DISASM-NEXT: addq $-4, %r12 Index: lld/test/ELF/tls-weak-undef.s =================================================================== --- lld/test/ELF/tls-weak-undef.s +++ lld/test/ELF/tls-weak-undef.s @@ -17,7 +17,7 @@ # EXEC: leaq 16(%rax), %rdx ## Initial-exec references to undefined weak symbols can be relaxed to LE ## references. -# EXEC: leaq 32(%rax), %rax +# EXEC: addq $32, %rax # SHARED: leaq 48(%rax), %rcx # RUN: ld.lld -shared %tdef.o -o %tdef.so Index: lld/test/ELF/x86-64-tls-ie-opt-local.s =================================================================== --- lld/test/ELF/x86-64-tls-ie-opt-local.s +++ lld/test/ELF/x86-64-tls-ie-opt-local.s @@ -12,14 +12,14 @@ // DISASM-NEXT: <_start>: // DISASM-NEXT: movq $-8, %rax // DISASM-NEXT: movq $-8, %r15 -// DISASM-NEXT: leaq -8(%rax), %rax -// DISASM-NEXT: leaq -8(%r15), %r15 +// DISASM-NEXT: addq $-8, %rax +// DISASM-NEXT: addq $-8, %r15 // DISASM-NEXT: addq $-8, %rsp // DISASM-NEXT: addq $-8, %r12 // DISASM-NEXT: movq $-4, %rax // DISASM-NEXT: movq $-4, %r15 -// DISASM-NEXT: leaq -4(%rax), %rax -// DISASM-NEXT: leaq -4(%r15), %r15 +// DISASM-NEXT: addq $-4, %rax +// DISASM-NEXT: addq $-4, %r15 // DISASM-NEXT: addq $-4, %rsp // DISASM-NEXT: addq $-4, %r12