[PATCH] AArch64: Optimize ADD relocations that resolve to zero
Sivan Shani <[email protected]> Fri, 24 Jul 2026 09:58:59 +0000
| Newsgroups | gmane.comp.gnu.binutils |
|---|---|
| Message-ID | <[email protected]> |
The "ELF for the Arm 64-bit Architecture" specification, section 5.7.9,
recommends that linkers optimize ADD instructions whose immediate
becomes zero after relocation. In particular:
ADD x0, x1, 0
ADD x2, x2, 0
may be replaced with:
MOV x0, x1
NOP
Apply this optimization to all supported relocations that set an ADD
immediate field.
Rewrite additions between different registers as MOV. Rewrite 64-bit
additions whose source and destination registers are the same as NOP.
Keep the 32-bit same-register form as MOV because writing to a W
register clears the upper 32 bits. Do not rewrite instructions using
SP, since ADD and the ORR encoding underlying MOV interpret register 31
differently.
Add coverage for every affected relocation and update existing tests.
bfd/
* elfxx-aarch64.c (AARCH64_MOV_REG_OPCODE)
(AARCH64_NOP_OPCODE): Define.
(reencode_add_to_mov): Accept the decoded register fields.
(_bfd_aarch64_elf_put_addend): Optimize ADD relocations whose
encoded immediate is zero.
ld/testsuite/
* ld-aarch64/aarch64-elf.exp: Run the new ADD-immediate
optimization tests.
* ld-aarch64/add-imm-zero-opt.ld: New test linker script.
* ld-aarch64/add-imm-zero-opt.s: New test.
* ld-aarch64/add-imm-zero-opt.d: New expected output.
* ld-aarch64/add-imm-zero-opt-tlsgd.s: New test.
* ld-aarch64/add-imm-zero-opt-tlsgd.d: New expected output.
* ld-aarch64/add-imm-zero-opt-tlsld.s: New test.
* ld-aarch64/add-imm-zero-opt-tlsld.d: New expected output.
* ld-aarch64/add-imm-zero-opt-tlsdesc.s: New test.
* ld-aarch64/add-imm-zero-opt-tlsdesc.d: New expected output.
* ld-aarch64/erratum843419.d: Expect NOP.
* ld-aarch64/erratum843419_tls_ie.d: Likewise.
* ld-aarch64/farcall-b-defsym.d: Likewise.
* ld-aarch64/farcall-b-none-function.d: Likewise.
* ld-aarch64/farcall-b-section.d: Likewise.
* ld-aarch64/farcall-b.d: Likewise.
* ld-aarch64/farcall-back.d: Likewise.
* ld-aarch64/farcall-bl-defsym.d: Likewise.
* ld-aarch64/farcall-bl-none-function.d: Likewise.
* ld-aarch64/farcall-bl-section.d: Likewise.
* ld-aarch64/farcall-bl.d: Likewise.
* ld-aarch64/tls-relax-ld-le-small-ilp32.d: Expect MOV and NOP.
* ld-aarch64/tls-relax-ld-le-small.d: Likewise.
* ld-aarch64/tls-relax-ld-le-tiny-ilp32.d: Likewise.
* ld-aarch64/tls-relax-ld-le-tiny.d: Likewise.
* ld-aarch64/weak-undefined.d: Expect NOP.
---
bfd/elfxx-aarch64.c | 34 ++++++++++++++++---
ld/testsuite/ld-aarch64/aarch64-elf.exp | 5 +++
.../ld-aarch64/add-imm-zero-opt-tlsdesc.d | 16 +++++++++
.../ld-aarch64/add-imm-zero-opt-tlsdesc.s | 16 +++++++++
.../ld-aarch64/add-imm-zero-opt-tlsgd.d | 15 ++++++++
.../ld-aarch64/add-imm-zero-opt-tlsgd.s | 16 +++++++++
.../ld-aarch64/add-imm-zero-opt-tlsld.d | 15 ++++++++
.../ld-aarch64/add-imm-zero-opt-tlsld.s | 15 ++++++++
ld/testsuite/ld-aarch64/add-imm-zero-opt.d | 22 ++++++++++++
ld/testsuite/ld-aarch64/add-imm-zero-opt.ld | 16 +++++++++
ld/testsuite/ld-aarch64/add-imm-zero-opt.s | 34 +++++++++++++++++++
ld/testsuite/ld-aarch64/erratum843419.d | 4 +--
.../ld-aarch64/erratum843419_tls_ie.d | 2 +-
ld/testsuite/ld-aarch64/farcall-b-defsym.d | 2 +-
.../ld-aarch64/farcall-b-none-function.d | 2 +-
ld/testsuite/ld-aarch64/farcall-b-section.d | 2 +-
ld/testsuite/ld-aarch64/farcall-b.d | 2 +-
ld/testsuite/ld-aarch64/farcall-back-be.d | 2 +-
ld/testsuite/ld-aarch64/farcall-back.d | 2 +-
ld/testsuite/ld-aarch64/farcall-bl-defsym.d | 2 +-
.../ld-aarch64/farcall-bl-none-function.d | 2 +-
ld/testsuite/ld-aarch64/farcall-bl-section.d | 2 +-
ld/testsuite/ld-aarch64/farcall-bl.d | 2 +-
.../non-contiguous-mem/non-contiguous-ok-2.d | 2 +-
.../non-contiguous-mem/non-contiguous-ok-4.d | 2 +-
.../non-contiguous-mem/non-contiguous-ok-5.d | 2 +-
.../ld-aarch64/tls-relax-ld-le-small-ilp32.d | 4 +--
.../ld-aarch64/tls-relax-ld-le-small.d | 4 +--
.../ld-aarch64/tls-relax-ld-le-tiny-ilp32.d | 4 +--
.../ld-aarch64/tls-relax-ld-le-tiny.d | 4 +--
.../ld-aarch64/tls-tiny-gd-le-ilp32.d | 2 +-
ld/testsuite/ld-aarch64/tls-tiny-gd-le.d | 2 +-
ld/testsuite/ld-aarch64/tlsle-add-hi12-opt.d | 14 ++++++++
ld/testsuite/ld-aarch64/tlsle-add-hi12-opt.s | 13 +++++++
ld/testsuite/ld-aarch64/weak-undefined.d | 2 +-
35 files changed, 253 insertions(+), 32 deletions(-)
create mode 100644 ld/testsuite/ld-aarch64/add-imm-zero-opt-tlsdesc.d
create mode 100644 ld/testsuite/ld-aarch64/add-imm-zero-opt-tlsdesc.s
create mode 100644 ld/testsuite/ld-aarch64/add-imm-zero-opt-tlsgd.d
create mode 100644 ld/testsuite/ld-aarch64/add-imm-zero-opt-tlsgd.s
create mode 100644 ld/testsuite/ld-aarch64/add-imm-zero-opt-tlsld.d
create mode 100644 ld/testsuite/ld-aarch64/add-imm-zero-opt-tlsld.s
create mode 100644 ld/testsuite/ld-aarch64/add-imm-zero-opt.d
create mode 100644 ld/testsuite/ld-aarch64/add-imm-zero-opt.ld
create mode 100644 ld/testsuite/ld-aarch64/add-imm-zero-opt.s
create mode 100644 ld/testsuite/ld-aarch64/tlsle-add-hi12-opt.d
create mode 100644 ld/testsuite/ld-aarch64/tlsle-add-hi12-opt.s
diff --git a/bfd/elfxx-aarch64.c b/bfd/elfxx-aarch64.c
index 69ef148bf9c..ef25d673798 100644
--- a/bfd/elfxx-aarch64.c
+++ b/bfd/elfxx-aarch64.c
@@ -57,6 +57,18 @@ reencode_add_imm (uint32_t insn, uint32_t imm)
return (insn & ~(MASK (12) << 10)) | ((imm & MASK (12)) << 10);
}
+/* Base encoding for MOV Wd, Wm (ORR Wd, WZR, Wm). */
+#define AARCH64_MOV_REG_OPCODE 0x2a0003e0U
+/* NOP encoding */
+#define AARCH64_NOP_OPCODE 0xd503201fU
+
+/* Reencode ADD immediate as MOV-register (ORR Rd, ZR, Rm). */
+static inline uint32_t
+reencode_add_to_mov (uint32_t insn, unsigned int rd, unsigned int rn)
+{
+ return ((insn & (1U << 31)) | AARCH64_MOV_REG_OPCODE | (rn << 16) | rd);
+}
+
/* Reencode the IMM field of ADR. */
uint32_t
@@ -261,11 +273,23 @@ _bfd_aarch64_elf_put_addend (bfd *abfd,
case BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_HI12:
case BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_LO12:
case BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
- /* Corresponds to: add rd, rn, #uimm12 to provide the low order
- 12 bits of the page offset following
- BFD_RELOC_AARCH64_ADR_HI21_PCREL which computes the
- (pc-relative) page base. */
- contents = reencode_add_imm (contents, addend);
+ /* Optimize an ADD whose relocated 12-bit immediate is zero. */
+ if ((addend & MASK (12)) == 0)
+ {
+ unsigned int rd = contents & MASK (5);
+ unsigned int rn = (contents >> 5) & MASK (5);
+ /* ADD Xd, Xd, #0 --> NOP, check for the 32 bit version
+ since it clear the upper half of the destination register. */
+ if (rd == rn && rd != 31 && (contents & (1U << 31)) != 0)
+ contents = AARCH64_NOP_OPCODE;
+ /* Register 31 denotes SP in ADD but ZR in MOV (ORR). */
+ else if (rd != 31 && rn != 31)
+ contents = reencode_add_to_mov (contents, rd, rn);
+ else
+ contents = reencode_add_imm (contents, addend);
+ }
+ else
+ contents = reencode_add_imm (contents, addend);
break;
case BFD_RELOC_AARCH64_LD32_GOTPAGE_LO14:
diff --git a/ld/testsuite/ld-aarch64/aarch64-elf.exp b/ld/testsuite/ld-aarch64/aarch64-elf.exp
index fa80210500e..5e8f7e0d22f 100644
--- a/ld/testsuite/ld-aarch64/aarch64-elf.exp
+++ b/ld/testsuite/ld-aarch64/aarch64-elf.exp
@@ -284,6 +284,11 @@ run_dump_test_lp64 "tls-large-desc-be"
run_dump_test "tls-tiny-ld"
run_dump_test "tls-small-ld"
run_dump_test_lp64 "tlsle"
+run_dump_test_lp64 "tlsle-add-hi12-opt"
+run_dump_test_lp64 "add-imm-zero-opt"
+run_dump_test_lp64 "add-imm-zero-opt-tlsgd"
+run_dump_test_lp64 "add-imm-zero-opt-tlsld"
+run_dump_test_lp64 "add-imm-zero-opt-tlsdesc"
run_dump_test "tlsle-symbol-offset"
run_dump_test "gc-got-relocs"
run_dump_test "gc-tls-relocs"
diff --git a/ld/testsuite/ld-aarch64/add-imm-zero-opt-tlsdesc.d b/ld/testsuite/ld-aarch64/add-imm-zero-opt-tlsdesc.d
new file mode 100644
index 00000000000..092f891395f
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/add-imm-zero-opt-tlsdesc.d
@@ -0,0 +1,16 @@
+#source: add-imm-zero-opt-tlsdesc.s
+#target: [check_shared_lib_support]
+#ld: -shared -T add-imm-zero-opt.ld --defsym=got_base=0x1ffd8 -e0 --no-warn-rwx-segments
+#objdump: -dr
+
+.*: +file format .*
+
+Disassembly of section .text:
+
+0+10000 <test>:
+ +10000: aa0103e0 mov x0, x1
+ +10004: d503201f nop
+ +10008: 910003e3 mov x3, sp
+ +1000c: 9100009f mov sp, x4
+ +10010: d65f03c0 ret
+#...
diff --git a/ld/testsuite/ld-aarch64/add-imm-zero-opt-tlsdesc.s b/ld/testsuite/ld-aarch64/add-imm-zero-opt-tlsdesc.s
new file mode 100644
index 00000000000..6fa1f19314c
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/add-imm-zero-opt-tlsdesc.s
@@ -0,0 +1,16 @@
+ .section .tbss,"awT",%nobits
+ .global tls_desc
+tls_desc:
+ .zero 8
+
+ .text
+ .global test
+ .type test, %function
+test:
+ add x0, x1, #:tlsdesc_lo12:tls_desc
+ add x2, x2, #:tlsdesc_lo12:tls_desc
+ add x3, sp, #:tlsdesc_lo12:tls_desc
+ add sp, x4, #:tlsdesc_lo12:tls_desc
+ ret
+ .size test, .-test
+
diff --git a/ld/testsuite/ld-aarch64/add-imm-zero-opt-tlsgd.d b/ld/testsuite/ld-aarch64/add-imm-zero-opt-tlsgd.d
new file mode 100644
index 00000000000..cba5d38f3af
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/add-imm-zero-opt-tlsgd.d
@@ -0,0 +1,15 @@
+#source: add-imm-zero-opt-tlsgd.s
+#target: [check_shared_lib_support]
+#ld: -shared -T add-imm-zero-opt.ld --defsym=got_base=0x1fff8 -e0 --no-warn-rwx-segments
+#objdump: -dr
+
+.*: +file format .*
+
+Disassembly of section .text:
+
+0+10000 <test>:
+ +10000: aa0103e0 mov x0, x1
+ +10004: d503201f nop
+ +10008: 910003e3 mov x3, sp
+ +1000c: 9100009f mov sp, x4
+ +10010: d65f03c0 ret
diff --git a/ld/testsuite/ld-aarch64/add-imm-zero-opt-tlsgd.s b/ld/testsuite/ld-aarch64/add-imm-zero-opt-tlsgd.s
new file mode 100644
index 00000000000..349f92cfbd8
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/add-imm-zero-opt-tlsgd.s
@@ -0,0 +1,16 @@
+ .section .tbss,"awT",%nobits
+ .global tls_gd
+tls_gd:
+ .zero 8
+
+ .text
+ .global test
+ .type test, %function
+test:
+ add x0, x1, #:tlsgd_lo12:tls_gd
+ add x2, x2, #:tlsgd_lo12:tls_gd
+ add x3, sp, #:tlsgd_lo12:tls_gd
+ add sp, x4, #:tlsgd_lo12:tls_gd
+ ret
+ .size test, .-test
+
diff --git a/ld/testsuite/ld-aarch64/add-imm-zero-opt-tlsld.d b/ld/testsuite/ld-aarch64/add-imm-zero-opt-tlsld.d
new file mode 100644
index 00000000000..ad08392b798
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/add-imm-zero-opt-tlsld.d
@@ -0,0 +1,15 @@
+#source: add-imm-zero-opt-tlsld.s
+#target: [check_shared_lib_support]
+#ld: -shared -T add-imm-zero-opt.ld --defsym=got_base=0x1fff8 -e0 --no-warn-rwx-segments
+#objdump: -dr
+
+.*: +file format .*
+
+Disassembly of section .text:
+
+0+10000 <test>:
+ +10000: aa0103e0 mov x0, x1
+ +10004: d503201f nop
+ +10008: 910003e3 mov x3, sp
+ +1000c: 9100009f mov sp, x4
+ +10010: d65f03c0 ret
diff --git a/ld/testsuite/ld-aarch64/add-imm-zero-opt-tlsld.s b/ld/testsuite/ld-aarch64/add-imm-zero-opt-tlsld.s
new file mode 100644
index 00000000000..a08675f6ffc
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/add-imm-zero-opt-tlsld.s
@@ -0,0 +1,15 @@
+ .section .tbss,"awT",%nobits
+tls_ld:
+ .zero 8
+
+ .text
+ .global test
+ .type test, %function
+test:
+ add x0, x1, #:tlsldm_lo12_nc:tls_ld
+ add x2, x2, #:tlsldm_lo12_nc:tls_ld
+ add x3, sp, #:tlsldm_lo12_nc:tls_ld
+ add sp, x4, #:tlsldm_lo12_nc:tls_ld
+ ret
+ .size test, .-test
+
diff --git a/ld/testsuite/ld-aarch64/add-imm-zero-opt.d b/ld/testsuite/ld-aarch64/add-imm-zero-opt.d
new file mode 100644
index 00000000000..4395bd01ab2
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/add-imm-zero-opt.d
@@ -0,0 +1,22 @@
+#source: add-imm-zero-opt.s
+#target: [check_shared_lib_support]
+#ld: -shared -T add-imm-zero-opt.ld --defsym=got_base=0x20000 -e0
+#objdump: -dr
+
+.*: +file format .*
+
+Disassembly of section .text:
+
+0+10000 <test>:
+ +10000: d503201f nop
+ +10004: aa0203e1 mov x1, x2
+ +10008: d503201f nop
+ +1000c: aa0503e4 mov x4, x5
+ +10010: aa0703e6 mov x6, x7
+ +10014: d503201f nop
+ +10018: aa0a03e9 mov x9, x10
+ +1001c: 2a0b03eb mov w11, w11
+ +10020: 910003ec mov x12, sp
+ +10024: 910001bf mov sp, x13
+ +10028: 910021ce add x14, x14, #0x8
+ +1002c: d65f03c0 ret
diff --git a/ld/testsuite/ld-aarch64/add-imm-zero-opt.ld b/ld/testsuite/ld-aarch64/add-imm-zero-opt.ld
new file mode 100644
index 00000000000..666ec64e47a
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/add-imm-zero-opt.ld
@@ -0,0 +1,16 @@
+OUTPUT_ARCH(aarch64)
+SECTIONS
+{
+ . = 0x10000;
+ .text : { *(.text) }
+ . = got_base;
+ .got : { *(.got) *(.got.plt) }
+ . = 0x30000;
+ .tdata : { *(.tdata) }
+ .tbss : { *(.tbss) }
+ .data :
+ {
+ *(.data)
+ *(.data.*)
+ }
+}
diff --git a/ld/testsuite/ld-aarch64/add-imm-zero-opt.s b/ld/testsuite/ld-aarch64/add-imm-zero-opt.s
new file mode 100644
index 00000000000..8f71acb3a7d
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/add-imm-zero-opt.s
@@ -0,0 +1,34 @@
+ .section .tbss,"awT",%nobits
+tls0:
+ .zero 4096
+tls_page:
+ .zero 8
+
+ .section .data.page,"aw"
+ .p2align 12
+page_sym:
+ .xword 0
+
+ .text
+ .global test
+ .type test, %function
+test:
+ add x0, x0, #:lo12:page_sym
+ add x1, x2, #:dtprel_hi12:tls0, lsl #12
+ add x3, x3, #:dtprel_lo12:tls0
+ add x4, x5, #:dtprel_lo12_nc:tls_page
+ add x6, x7, #:tprel_hi12:tls0, lsl #12
+ add x8, x8, #:tprel_lo12:tls0-16
+ add x9, x10, #:tprel_lo12_nc:tls_page-16
+
+ /* A 32-bit write must not be replaced with NOP. */
+ add w11, w11, #:lo12:page_sym
+
+ /* Uses of SP must remain ADD instructions. */
+ add x12, sp, #:lo12:page_sym
+ add sp, x13, #:lo12:page_sym
+
+ /* A nonzero immediate must remain an ADD instruction. */
+ add x14, x14, #:lo12:page_sym+8
+ ret
+ .size test, .-test
diff --git a/ld/testsuite/ld-aarch64/erratum843419.d b/ld/testsuite/ld-aarch64/erratum843419.d
index 7adfafde95a..2127194ac39 100644
--- a/ld/testsuite/ld-aarch64/erratum843419.d
+++ b/ld/testsuite/ld-aarch64/erratum843419.d
@@ -33,7 +33,7 @@ Disassembly of section .e843419:
0*20001030 <__e835769_veneer>:
[ ]*20001030: f0f17ff0 adrp x16, 3000000 <e835769>
-[ ]*20001034: 91000210 add x16, x16, #0x0
+[ ]*20001034: d503201f nop
[ ]*20001038: d61f0200 br x16
...
@@ -68,6 +68,6 @@ Disassembly of section .text:
0*400020 <__e843419_veneer>:
[ ]*400020: 900fe010 adrp x16, 20000000 <e843419>
-[ ]*400024: 91000210 add x16, x16, #0x0
+[ ]*400024: d503201f nop
[ ]*400028: d61f0200 br x16
...
diff --git a/ld/testsuite/ld-aarch64/erratum843419_tls_ie.d b/ld/testsuite/ld-aarch64/erratum843419_tls_ie.d
index 4d2b1116442..bd18d629ef6 100644
--- a/ld/testsuite/ld-aarch64/erratum843419_tls_ie.d
+++ b/ld/testsuite/ld-aarch64/erratum843419_tls_ie.d
@@ -44,6 +44,6 @@ Disassembly of section .text:
0*400020 <__farbranch_veneer>:
[ ]*400020: 900fe010 adrp x16, 20000000 <farbranch>
-[ ]*400024: 91000210 add x16, x16, #0x0
+[ ]*400024: d503201f nop
[ ]*400028: d61f0200 br x16
...
diff --git a/ld/testsuite/ld-aarch64/farcall-b-defsym.d b/ld/testsuite/ld-aarch64/farcall-b-defsym.d
index f6b092116cd..da049f9badc 100644
--- a/ld/testsuite/ld-aarch64/farcall-b-defsym.d
+++ b/ld/testsuite/ld-aarch64/farcall-b-defsym.d
@@ -14,6 +14,6 @@ Disassembly of section .text:
[ \t]+100c:[ \t]+d503201f[ \t]+nop
0+1010 <__bar_veneer>:
1010: 90040010 adrp x16, 8001000 <bar>
- 1014: 91000210 add x16, x16, #0x0
+ 1014: d503201f nop
1018: d61f0200 br x16
...
diff --git a/ld/testsuite/ld-aarch64/farcall-b-none-function.d b/ld/testsuite/ld-aarch64/farcall-b-none-function.d
index e06936c347a..54738452e61 100644
--- a/ld/testsuite/ld-aarch64/farcall-b-none-function.d
+++ b/ld/testsuite/ld-aarch64/farcall-b-none-function.d
@@ -15,7 +15,7 @@ Disassembly of section .text:
.* <__bar_veneer>:
1010: 90040010 adrp x16, 8001000 <bar>
- 1014: 91000210 add x16, x16, #0x0
+ 1014: d503201f nop
1018: d61f0200 br x16
...
diff --git a/ld/testsuite/ld-aarch64/farcall-b-section.d b/ld/testsuite/ld-aarch64/farcall-b-section.d
index 3872cd0b7c6..2c9df42d0a7 100644
--- a/ld/testsuite/ld-aarch64/farcall-b-section.d
+++ b/ld/testsuite/ld-aarch64/farcall-b-section.d
@@ -17,7 +17,7 @@ Disassembly of section .text:
.* <__bar_veneer>:
1018: 90040010 adrp x16, 8001000 <bar>
- 101c: 91000210 add x16, x16, #0x0
+ 101c: d503201f nop
1020: d61f0200 br x16
1024: 00000000 udf #0
diff --git a/ld/testsuite/ld-aarch64/farcall-b.d b/ld/testsuite/ld-aarch64/farcall-b.d
index cfa0688646e..05bc7c29ece 100644
--- a/ld/testsuite/ld-aarch64/farcall-b.d
+++ b/ld/testsuite/ld-aarch64/farcall-b.d
@@ -14,7 +14,7 @@ Disassembly of section .text:
[ \t]+100c:[ \t]+d503201f[ \t]+nop
0+1010 <__bar_veneer>:
1010: 90040010 adrp x16, 8001000 <bar>
- 1014: 91000210 add x16, x16, #0x0
+ 1014: d503201f nop
1018: d61f0200 br x16
...
diff --git a/ld/testsuite/ld-aarch64/farcall-back-be.d b/ld/testsuite/ld-aarch64/farcall-back-be.d
index 80992aab67c..42bd5913e09 100644
--- a/ld/testsuite/ld-aarch64/farcall-back-be.d
+++ b/ld/testsuite/ld-aarch64/farcall-back-be.d
@@ -38,7 +38,7 @@ Disassembly of section .text:
000000000000204c <__bar1_veneer>:
204c: d07ffff0 adrp x16, 100000000 <bar1>
- 2050: 91000210 add x16, x16, #0x0
+ 2050: d503201f nop
2054: d61f0200 br x16
...
diff --git a/ld/testsuite/ld-aarch64/farcall-back.d b/ld/testsuite/ld-aarch64/farcall-back.d
index 20204eef5e2..2eea4bb19d1 100644
--- a/ld/testsuite/ld-aarch64/farcall-back.d
+++ b/ld/testsuite/ld-aarch64/farcall-back.d
@@ -39,7 +39,7 @@ Disassembly of section .text:
0000000000002050 <__bar1_veneer>:
2050: d07ffff0 adrp x16, 100000000 <bar1>
- 2054: 91000210 add x16, x16, #0x0
+ 2054: d503201f nop
2058: d61f0200 br x16
...
diff --git a/ld/testsuite/ld-aarch64/farcall-bl-defsym.d b/ld/testsuite/ld-aarch64/farcall-bl-defsym.d
index 4a3ab80d85a..1d682169a45 100644
--- a/ld/testsuite/ld-aarch64/farcall-bl-defsym.d
+++ b/ld/testsuite/ld-aarch64/farcall-bl-defsym.d
@@ -14,6 +14,6 @@ Disassembly of section .text:
[ \t]+100c:[ \t]+d503201f[ \t]+nop
0+1010 <__bar_veneer>:
[ \t]+1010:[ \t]+90040010[ \t]+adrp[ \t]+x16, 8001000 <bar>
-[ \t]+1014:[ \t]+91000210[ \t]+add[ \t]+x16, x16, #0x0
+[ \t]+1014:[ \t]+d503201f[ \t]+nop
[ \t]+1018:[ \t]+d61f0200[ \t]+br[ \t]+x16
...
diff --git a/ld/testsuite/ld-aarch64/farcall-bl-none-function.d b/ld/testsuite/ld-aarch64/farcall-bl-none-function.d
index 4ab9c7eed40..6c9385ea689 100644
--- a/ld/testsuite/ld-aarch64/farcall-bl-none-function.d
+++ b/ld/testsuite/ld-aarch64/farcall-bl-none-function.d
@@ -15,7 +15,7 @@ Disassembly of section .text:
.* <__bar_veneer>:
1010: 90040010 adrp x16, 8001000 <bar>
- 1014: 91000210 add x16, x16, #0x0
+ 1014: d503201f nop
1018: d61f0200 br x16
...
diff --git a/ld/testsuite/ld-aarch64/farcall-bl-section.d b/ld/testsuite/ld-aarch64/farcall-bl-section.d
index 03ebe2991d6..c2cf3da903d 100644
--- a/ld/testsuite/ld-aarch64/farcall-bl-section.d
+++ b/ld/testsuite/ld-aarch64/farcall-bl-section.d
@@ -17,7 +17,7 @@ Disassembly of section .text:
.* <__bar_veneer>:
1018: 90040010 adrp x16, 8001000 <bar>
- 101c: 91000210 add x16, x16, #0x0
+ 101c: d503201f nop
1020: d61f0200 br x16
1024: 00000000 udf #0
diff --git a/ld/testsuite/ld-aarch64/farcall-bl.d b/ld/testsuite/ld-aarch64/farcall-bl.d
index 637225be4dd..971d61dfef1 100644
--- a/ld/testsuite/ld-aarch64/farcall-bl.d
+++ b/ld/testsuite/ld-aarch64/farcall-bl.d
@@ -14,7 +14,7 @@ Disassembly of section .text:
[ \t]+100c:[ \t]+d503201f[ \t]+nop
0+1010 <__bar_veneer>:
[ \t]+1010:[ \t]+90040010[ \t]+adrp[ \t]+x16, 8001000 <bar>
-[ \t]+1014:[ \t]+91000210[ \t]+add[ \t]+x16, x16, #0x0
+[ \t]+1014:[ \t]+d503201f[ \t]+nop
[ \t]+1018:[ \t]+d61f0200[ \t]+br[ \t]+x16
...
diff --git a/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-ok-2.d b/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-ok-2.d
index 74131fb5b58..43fb330c637 100644
--- a/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-ok-2.d
+++ b/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-ok-2.d
@@ -58,7 +58,7 @@ Disassembly of section \.ramu:
0000000020000010 \<__code4_veneer\>:
20000010: 90080210 adrp x16, 30040000 \<code4\>
- 20000014: 91000210 add x16, x16, #0x0
+ 20000014: d503201f nop
20000018: d61f0200 br x16
\.\.\.
diff --git a/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-ok-4.d b/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-ok-4.d
index 18a46b79acc..d6f2dc391d7 100644
--- a/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-ok-4.d
+++ b/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-ok-4.d
@@ -53,7 +53,7 @@ Disassembly of section \.raml:
000000001fff0028 \<__code4_veneer\>:
1fff0028: 90100290 adrp x16, 40040000 \<code4\>
- 1fff002c: 91000210 add x16, x16, #0x0
+ 1fff002c: d503201f nop
1fff0030: d61f0200 br x16
...
diff --git a/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-ok-5.d b/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-ok-5.d
index 5dd222ea342..dea3fad1f17 100644
--- a/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-ok-5.d
+++ b/ld/testsuite/ld-aarch64/non-contiguous-mem/non-contiguous-ok-5.d
@@ -57,7 +57,7 @@ Disassembly of section \.raml:
000000001fff0028 \<__code4_veneer\>:
1fff0028: 90100290 adrp x16, 40040000 \<code4\>
- 1fff002c: 91000210 add x16, x16, #0x0
+ 1fff002c: d503201f nop
1fff0030: d61f0200 br x16
...
diff --git a/ld/testsuite/ld-aarch64/tls-relax-ld-le-small-ilp32.d b/ld/testsuite/ld-aarch64/tls-relax-ld-le-small-ilp32.d
index 2b80db5a542..ac80543d897 100644
--- a/ld/testsuite/ld-aarch64/tls-relax-ld-le-small-ilp32.d
+++ b/ld/testsuite/ld-aarch64/tls-relax-ld-le-small-ilp32.d
@@ -9,7 +9,7 @@
+10008: 11002000 add w0, w0, #0x8
+1000c: d503201f nop
+10010: d503201f nop
- +10014: 91400001 add x1, x0, #0x0, lsl #12
- +10018: 91000021 add x1, x1, #0x0
+ +10014: aa0003e1 mov x1, x0
+ +10018: d503201f nop
+1001c: 90000000 adrp x0, 10000 <.*>
+10020: d65f03c0 ret
diff --git a/ld/testsuite/ld-aarch64/tls-relax-ld-le-small.d b/ld/testsuite/ld-aarch64/tls-relax-ld-le-small.d
index fa648291fdb..b8094889fda 100644
--- a/ld/testsuite/ld-aarch64/tls-relax-ld-le-small.d
+++ b/ld/testsuite/ld-aarch64/tls-relax-ld-le-small.d
@@ -7,7 +7,7 @@
+10008: 91004000 add x0, x0, #0x10
+1000c: d503201f nop
+10010: d503201f nop
- +10014: 91400001 add x1, x0, #0x0, lsl #12
- +10018: 91000021 add x1, x1, #0x0
+ +10014: aa0003e1 mov x1, x0
+ +10018: d503201f nop
+1001c: 90000000 adrp x0, 10000 <.*>
+10020: d65f03c0 ret
diff --git a/ld/testsuite/ld-aarch64/tls-relax-ld-le-tiny-ilp32.d b/ld/testsuite/ld-aarch64/tls-relax-ld-le-tiny-ilp32.d
index 445e79dccf6..7ed81e247f0 100644
--- a/ld/testsuite/ld-aarch64/tls-relax-ld-le-tiny-ilp32.d
+++ b/ld/testsuite/ld-aarch64/tls-relax-ld-le-tiny-ilp32.d
@@ -8,7 +8,7 @@
+10004: d53bd040 mrs x0, tpidr_el0
+10008: 11002000 add w0, w0, #0x8
+1000c: d503201f nop
- +10010: 91400001 add x1, x0, #0x0, lsl #12
- +10014: 91000021 add x1, x1, #0x0
+ +10010: aa0003e1 mov x1, x0
+ +10014: d503201f nop
+10018: 90000000 adrp x0, 10000 <main>
+1001c: d65f03c0 ret
diff --git a/ld/testsuite/ld-aarch64/tls-relax-ld-le-tiny.d b/ld/testsuite/ld-aarch64/tls-relax-ld-le-tiny.d
index db226775346..c6d1a9884a0 100644
--- a/ld/testsuite/ld-aarch64/tls-relax-ld-le-tiny.d
+++ b/ld/testsuite/ld-aarch64/tls-relax-ld-le-tiny.d
@@ -6,7 +6,7 @@
+10004: d53bd040 mrs x0, tpidr_el0
+10008: 91004000 add x0, x0, #0x10
+1000c: d503201f nop
- +10010: 91400001 add x1, x0, #0x0, lsl #12
- +10014: 91000021 add x1, x1, #0x0
+ +10010: aa0003e1 mov x1, x0
+ +10014: d503201f nop
+10018: 90000000 adrp x0, 10000 <main>
+1001c: d65f03c0 ret
diff --git a/ld/testsuite/ld-aarch64/tls-tiny-gd-le-ilp32.d b/ld/testsuite/ld-aarch64/tls-tiny-gd-le-ilp32.d
index cc13bbde21b..8d7cc6866e6 100644
--- a/ld/testsuite/ld-aarch64/tls-tiny-gd-le-ilp32.d
+++ b/ld/testsuite/ld-aarch64/tls-tiny-gd-le-ilp32.d
@@ -9,5 +9,5 @@ Disassembly of section .text:
00010000 \<test\>:
+10000: d53bd041 mrs x1, tpidr_el0
- +10004: 11400020 add w0, w1, #0x0, lsl #12
+ +10004: 2a0103e0 mov w0, w1
+10008: 11002000 add w0, w0, #0x8
diff --git a/ld/testsuite/ld-aarch64/tls-tiny-gd-le.d b/ld/testsuite/ld-aarch64/tls-tiny-gd-le.d
index 016ca70658f..6a1777e5c06 100644
--- a/ld/testsuite/ld-aarch64/tls-tiny-gd-le.d
+++ b/ld/testsuite/ld-aarch64/tls-tiny-gd-le.d
@@ -7,5 +7,5 @@ Disassembly of section .text:
0000000000010000 \<test\>:
+10000: d53bd041 mrs x1, tpidr_el0
- +10004: 91400020 add x0, x1, #0x0, lsl #12
+ +10004: aa0103e0 mov x0, x1
+10008: 91004000 add x0, x0, #0x10
diff --git a/ld/testsuite/ld-aarch64/tlsle-add-hi12-opt.d b/ld/testsuite/ld-aarch64/tlsle-add-hi12-opt.d
new file mode 100644
index 00000000000..0f2c90a4cc4
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tlsle-add-hi12-opt.d
@@ -0,0 +1,14 @@
+#source: tlsle-add-hi12-opt.s
+#target: [check_shared_lib_support]
+#ld: -shared -T relocs.ld -e0
+#objdump: -dr
+
+.*: .*
+
+Disassembly of section .text:
+
+0+10000 <test>:
+ +10000: aa0103e0 mov x0, x1
+ +10004: 914003e2 add x2, sp, #0x0, lsl #12
+ +10008: 9140007f add sp, x3, #0x0, lsl #12
+ +1000c: 914004a4 add x4, x5, #0x1, lsl #12
diff --git a/ld/testsuite/ld-aarch64/tlsle-add-hi12-opt.s b/ld/testsuite/ld-aarch64/tlsle-add-hi12-opt.s
new file mode 100644
index 00000000000..f7a8d876122
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tlsle-add-hi12-opt.s
@@ -0,0 +1,13 @@
+ .global test
+ .section .tbss,"awT",%nobits
+tlsvar:
+ .zero 4080
+tlsvar_hi12:
+ .zero 8
+
+ .text
+test:
+ add x0, x1, #:tprel_hi12:tlsvar
+ add x2, sp, #:tprel_hi12:tlsvar
+ add sp, x3, #:tprel_hi12:tlsvar
+ add x4, x5, #:tprel_hi12:tlsvar_hi12
diff --git a/ld/testsuite/ld-aarch64/weak-undefined.d b/ld/testsuite/ld-aarch64/weak-undefined.d
index 29ba2e5c672..3627d46c82b 100644
--- a/ld/testsuite/ld-aarch64/weak-undefined.d
+++ b/ld/testsuite/ld-aarch64/weak-undefined.d
@@ -15,4 +15,4 @@
+f0000028: 58000000 ldr x0, f0000028 <main\+0x28>
+f000002c: 10000000 adr x0, f000002c <main\+0x2c>
+f0000030: 90000000 adrp x0, f0000000 <main>
- +f0000034: 91000000 add x0, x0, #0x0
+ +f0000034: d503201f nop
--
2.43.0