[llvm] [BOLT][AArch64] Eliminate e843419 veneers (PR #187955)

Elvina Yakubova via llvm-commits llvm-commits at lists.llvm.org
Mon Apr 27 07:43:34 PDT 2026


https://github.com/ElvinaYakubova updated https://github.com/llvm/llvm-project/pull/187955

>From 7cea275a858b87404a2e5daddd81e25f39fc50e2 Mon Sep 17 00:00:00 2001
From: Elvina Yakubova <eyakubova at nvidia.com>
Date: Sun, 8 Mar 2026 17:33:34 -0700
Subject: [PATCH 1/2] [BOLT][AArch64] Eliminate e843419 veneers

Detect and eliminate A53 843419 errata veneers
---
 bolt/include/bolt/Core/MCPlusBuilder.h        |   8 +
 bolt/lib/Core/BinaryFunction.cpp              |   4 +-
 bolt/lib/Passes/VeneerElimination.cpp         |  76 +++++++
 .../Target/AArch64/AArch64MCPlusBuilder.cpp   |  20 ++
 bolt/test/AArch64/veneer-erratum-843419.s     | 198 ++++++++++++++++++
 5 files changed, 305 insertions(+), 1 deletion(-)
 create mode 100644 bolt/test/AArch64/veneer-erratum-843419.s

diff --git a/bolt/include/bolt/Core/MCPlusBuilder.h b/bolt/include/bolt/Core/MCPlusBuilder.h
index f9acaa4ee55a3..d5d66c8bb157b 100644
--- a/bolt/include/bolt/Core/MCPlusBuilder.h
+++ b/bolt/include/bolt/Core/MCPlusBuilder.h
@@ -1890,6 +1890,14 @@ class MCPlusBuilder {
     llvm_unreachable("not implemented");
   }
 
+  /// Match Cortex-A53 erratum 843419 workaround veneer. Such veneers have
+  /// exactly one BB with two instructions: a load/store and an unconditional
+  /// branch back to the call site. Returns true if BF matches this pattern
+  /// (name e843419* or __CortexA53843419_*, 2-instruction body).
+  virtual bool matchE843419Veneer(const BinaryFunction &BF) const {
+    return false;
+  }
+
   virtual bool matchAdrpAddPair(const MCInst &Adrp, const MCInst &Add) const {
     llvm_unreachable("not implemented");
     return false;
diff --git a/bolt/lib/Core/BinaryFunction.cpp b/bolt/lib/Core/BinaryFunction.cpp
index c5aefe685de34..2ebaae1c77a5e 100644
--- a/bolt/lib/Core/BinaryFunction.cpp
+++ b/bolt/lib/Core/BinaryFunction.cpp
@@ -4845,7 +4845,9 @@ bool BinaryFunction::isAArch64Veneer() const {
 
 bool BinaryFunction::isPossibleVeneer() const {
   return BC.isAArch64() &&
-         (isAArch64Veneer() || getOneName().starts_with("__AArch64"));
+         (isAArch64Veneer() || getOneName().starts_with("__AArch64") ||
+          getOneName().starts_with("e843419") ||
+          getOneName().starts_with("__CortexA53843419_"));
 }
 
 void BinaryFunction::addRelocation(uint64_t Address, MCSymbol *Symbol,
diff --git a/bolt/lib/Passes/VeneerElimination.cpp b/bolt/lib/Passes/VeneerElimination.cpp
index c0a6bcfbdd756..e0808738f3eac 100644
--- a/bolt/lib/Passes/VeneerElimination.cpp
+++ b/bolt/lib/Passes/VeneerElimination.cpp
@@ -35,6 +35,8 @@ Error VeneerElimination::runOnFunctions(BinaryContext &BC) {
 
   std::unordered_map<const MCSymbol *, const MCSymbol *> VeneerDestinations;
   uint64_t NumEliminatedVeneers = 0;
+  uint64_t NumE843419Inlined = 0;
+
   for (BinaryFunction &BF : llvm::make_second_range(BC.getBinaryFunctions())) {
     if (!BF.isPossibleVeneer())
       continue;
@@ -42,6 +44,77 @@ Error VeneerElimination::runOnFunctions(BinaryContext &BC) {
     if (BF.isIgnored())
       continue;
 
+    // Cortex-A53 erratum 843419 veneers: inline the veneer body at each
+    // branch site instead of redirecting, so LongJmp do not introduce
+    // code that clobbers registers (e.g. x16) used by the caller.
+    if (BC.MIB->matchE843419Veneer(BF)) {
+      const MCInst &VeneerFirstInstr = BF.front().getInstructionAtIndex(0);
+      const MCSymbol *ReturnTargetSym =
+          BC.MIB->getTargetSymbol(BF.front().getInstructionAtIndex(1));
+
+      // Check if this branch targets our e843419 veneer.
+      auto BranchTargetsVeneer = [&BF, &BC](const MCSymbol *Target) {
+        if (!Target)
+          return false;
+        if (BC.getFunctionForSymbol(Target) == &BF)
+          return true;
+        if (ErrorOr<uint64_t> Addr = BC.getSymbolValue(*Target))
+          return BC.getBinaryFunctionContainingAddress(*Addr) == &BF;
+        return false;
+      };
+
+      uint64_t CallSites = 0;
+
+      // Find caller from veneer's branch-back target so we can limit the scan.
+      BinaryFunction *CallerBF = nullptr;
+      if (ReturnTargetSym) {
+        if (ErrorOr<uint64_t> Addr = BC.getSymbolValue(*ReturnTargetSym))
+          CallerBF = BC.getBinaryFunctionContainingAddress(*Addr);
+      }
+
+      auto ScanForBranchesToVeneer = [&](BinaryFunction &F) {
+        for (BinaryBasicBlock &BB : F) {
+          for (auto II = BB.begin(); II != BB.end();) {
+            MCInst &Instr = *II;
+            if (!BC.MIB->isBranch(Instr)) {
+              ++II;
+              continue;
+            }
+            const MCSymbol *Target = BC.MIB->getTargetSymbol(Instr);
+            if (!BranchTargetsVeneer(Target)) {
+              ++II;
+              continue;
+            }
+            InstructionListType Repl;
+            Repl.emplace_back(VeneerFirstInstr);
+            II = BB.replaceInstruction(II, Repl);
+            ++CallSites;
+            ++NumE843419Inlined;
+          }
+        }
+      };
+
+      if (CallerBF && !CallerBF->isIgnored())
+        ScanForBranchesToVeneer(*CallerBF);
+      else
+        LLVM_DEBUG(dbgs() << "BOLT: skipping e843419 veneer inline for "
+                          << BF.getOneName()
+                          << " (caller not resolved or ignored)\n");
+
+      // Only mark pseudo when we actually inlined at least one branch site.
+      if (CallSites > 0) {
+        ++NumEliminatedVeneers;
+        BF.setPseudo(true);
+        LLVM_DEBUG(dbgs() << "BOLT-INFO: inlined e843419 veneer "
+                          << BF.getOneName() << " at " << CallSites
+                          << " branch sites\n");
+      } else {
+        LLVM_DEBUG(dbgs() << "BOLT: e843419 veneer " << BF.getOneName()
+                          << " left unchanged (no branch sites inlined)\n");
+      }
+      continue;
+    }
+
     MCInst &FirstInstruction = *(BF.begin()->begin());
     const MCSymbol *VeneerTargetSymbol = 0;
     uint64_t TargetAddress;
@@ -67,6 +140,9 @@ Error VeneerElimination::runOnFunctions(BinaryContext &BC) {
 
   BC.outs() << "BOLT-INFO: number of removed linker-inserted veneers: "
             << NumEliminatedVeneers << '\n';
+  if (NumE843419Inlined)
+    BC.outs() << "BOLT-INFO: e843419 veneer call sites inlined: "
+              << NumE843419Inlined << '\n';
 
   // Handle veneers to veneers in case they occur
   for (auto &Entry : VeneerDestinations) {
diff --git a/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp b/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp
index b091378682731..ce359551275ec 100644
--- a/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp
+++ b/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp
@@ -2854,6 +2854,26 @@ class AArch64MCPlusBuilder : public MCPlusBuilder {
     return true;
   }
 
+  /// Match Cortex-A53 erratum 843419 workaround veneer: one BB, two
+  /// instructions (load/store then branch back).
+  bool matchE843419Veneer(const BinaryFunction &BF) const override {
+    StringRef Name = BF.getOneName();
+    if (!Name.starts_with("e843419") && !Name.starts_with("__CortexA53843419_"))
+      return false;
+    if (BF.size() != 1)
+      return false;
+    const BinaryBasicBlock &BB = BF.front();
+    if (BB.size() != 2)
+      return false;
+    const MCInst &First = BB.getInstructionAtIndex(0);
+    const MCInst &Second = BB.getInstructionAtIndex(1);
+    if (!(mayLoad(First) || mayStore(First)))
+      return false;
+    if (!isTailCall(Second))
+      return false;
+    return true;
+  }
+
   bool matchAdrpAddPair(const MCInst &Adrp, const MCInst &Add) const override {
     if (!isADRP(Adrp) || !isAddXri(Add))
       return false;
diff --git a/bolt/test/AArch64/veneer-erratum-843419.s b/bolt/test/AArch64/veneer-erratum-843419.s
new file mode 100644
index 0000000000000..6a9c83268c4fa
--- /dev/null
+++ b/bolt/test/AArch64/veneer-erratum-843419.s
@@ -0,0 +1,198 @@
+## Test case for ARM Cortex-A53 erratum 843419 workaround veneers
+## These veneers have a specific pattern:
+## 1. ADRP instruction to load page address
+## 2. Optional instructions
+## 3. Branch to veneer (e843419 at ...)
+## 4. Veneer contains: LDR/STR using same register, branch back to +1 instruction
+
+# RUN: llvm-mc -filetype=obj -triple aarch64-unknown-unknown %s -o %t.o
+# RUN: %clang %cflags -fPIC -pie %t.o -o %t.exe -nostdlib \
+# RUN:    -fuse-ld=lld -Wl,-q
+# RUN: llvm-bolt %t.exe -o %t.bolt
+# RUN: llvm-objdump -d %t.bolt | FileCheck %s
+
+.text
+.balign 4
+.global target_function
+.type target_function, %function
+target_function:
+  ret
+.size target_function, .-target_function
+
+## Pattern 1: ADRP + multiple instructions + branch to veneer
+.global test_pattern_1
+.type test_pattern_1, %function
+test_pattern_1:
+# CHECK-LABEL: <test_pattern_1>:
+  adrp    x7, target_function
+# CHECK:      adrp
+  stp     w9, w8, [sp, #0xc4]
+  b       e843419_veneer_1
+.Lreturn_1:
+  stur    d0, [sp, #0xbc]
+  blr     x7
+# CHECK-NOT:  b {{.*}} <e843419_veneer_1>
+# CHECK:      blr
+  ret
+.size test_pattern_1, .-test_pattern_1
+
+## Veneer for pattern 1
+.global e843419_veneer_1
+.type e843419_veneer_1, %function
+e843419_veneer_1:
+# CHECK-NOT: <e843419_veneer_1>:
+  ldr     x7, [x7, #0x1a8]
+  b       .Lreturn_1
+.size e843419_veneer_1, .-e843419_veneer_1
+
+## Pattern 2: ADRP + load + mov + branch to veneer
+.global test_pattern_2
+.type test_pattern_2, %function
+test_pattern_2:
+# CHECK-LABEL: <test_pattern_2>:
+  adrp    x13, target_function
+# CHECK:      adrp
+  ldr     w14, [x10]
+  mov     w10, #0x1
+  b       e843419_veneer_2
+.Lreturn_2:
+  mov     x13, #0x220
+# CHECK-NOT:  b {{.*}} <e843419_veneer_2>
+# CHECK:      mov
+  cmp     w14, #0x2ed
+  ret
+.size test_pattern_2, .-test_pattern_2
+
+## Veneer for pattern 2
+.global e843419_veneer_2
+.type e843419_veneer_2, %function
+e843419_veneer_2:
+# CHECK-NOT: <e843419_veneer_2>:
+  ldr     d0, [x13, #0x888]
+  b       .Lreturn_2
+.size e843419_veneer_2, .-e843419_veneer_2
+
+## Pattern 3: Minimal case with just ADRP and branch
+.global test_pattern_3
+.type test_pattern_3, %function
+test_pattern_3:
+# CHECK-LABEL: <test_pattern_3>:
+  adrp    x15, target_function
+# CHECK:      adrp
+  b       e843419_veneer_3
+.Lreturn_3:
+  add     x15, x15, #0x100
+# CHECK-NOT:  b {{.*}} <e843419_veneer_3>
+# CHECK:      add
+  ret
+.size test_pattern_3, .-test_pattern_3
+
+## Veneer for pattern 3
+.global e843419_veneer_3
+.type e843419_veneer_3, %function
+e843419_veneer_3:
+# CHECK-NOT: <e843419_veneer_3>:
+  ldr     x15, [x15, #0x200]
+  b       .Lreturn_3
+.size e843419_veneer_3, .-e843419_veneer_3
+
+## Pattern 4: Using different registers (x8)
+.global test_pattern_4
+.type test_pattern_4, %function
+test_pattern_4:
+# CHECK-LABEL: <test_pattern_4>:
+  adrp    x8, target_function
+# CHECK:      adrp
+  str     x9, [sp, #0x10]
+  b       e843419_veneer_4
+.Lreturn_4:
+  ldr     x9, [x8, #0x50]
+# CHECK-NOT:  b {{.*}} <e843419_veneer_4>
+# CHECK:      ldr
+  ret
+.size test_pattern_4, .-test_pattern_4
+
+## Veneer for pattern 4
+.global e843419_veneer_4
+.type e843419_veneer_4, %function
+e843419_veneer_4:
+# CHECK-NOT: <e843419_veneer_4>:
+  ldr     x8, [x8, #0x400]
+  b       .Lreturn_4
+.size e843419_veneer_4, .-e843419_veneer_4
+
+## Pattern 5: Complex pattern with conditional code
+.global test_pattern_5
+.type test_pattern_5, %function
+test_pattern_5:
+# CHECK-LABEL: <test_pattern_5>:
+  adrp    x20, target_function
+# CHECK:      adrp
+  cbz     x1, .Lskip
+  ldr     x2, [sp, #0x20]
+.Lskip:
+  b       e843419_veneer_5
+.Lreturn_5:
+  ldrb    w3, [x20, #0x10]
+# CHECK-NOT:  b {{.*}} <e843419_veneer_5>
+# CHECK:      ldrb
+  ret
+.size test_pattern_5, .-test_pattern_5
+
+## Veneer for pattern 5
+.global e843419_veneer_5
+.type e843419_veneer_5, %function
+e843419_veneer_5:
+# CHECK-NOT: <e843419_veneer_5>:
+  ldr     x20, [x20, #0x600]
+  b       .Lreturn_5
+.size e843419_veneer_5, .-e843419_veneer_5
+
+## Pattern 6 (x16): mov x16 + branch to veneer; inlining preserves x16 for later use.
+## Without inlining, LongJmp could turn the veneer into adrp/add/br x16 and clobber it.
+.global test_pattern_x16
+.type test_pattern_x16, %function
+test_pattern_x16:
+# CHECK-LABEL: <test_pattern_x16>:
+  adrp    x1, target_function
+  ldr     q2, [x0, #3744]
+  mov     x16, #0x2600
+  b       e843419_x16_veneer
+.Lreturn_x16:
+  adrp    x1, target_function
+  ldr     q3, [x3, #0xee0]
+# CHECK-NOT:  b {{.*}} <e843419_x16_veneer>
+# CHECK:      ldr     q7, [x1, #0xff0]
+# CHECK:      adrp
+  ret
+.size test_pattern_x16, .-test_pattern_x16
+
+.global e843419_x16_veneer
+.type e843419_x16_veneer, %function
+e843419_x16_veneer:
+# CHECK-NOT: <e843419_x16_veneer>:
+  ldr     q7, [x1, #0xff0]
+  b       .Lreturn_x16
+.size e843419_x16_veneer, .-e843419_x16_veneer
+
+## Do NOT inline when target is not the 2-instr e843419 pattern.
+.global test_pattern_anti
+.type test_pattern_anti, %function
+test_pattern_anti:
+# CHECK-LABEL: <test_pattern_anti>:
+  adrp    x8, target_function
+  b       e843419_veneer_anti
+# CHECK:      b {{.*}} <e843419_veneer_anti>
+.Lreturn_anti:
+  blr     x8
+  ret
+.size test_pattern_anti, .-test_pattern_anti
+
+.global e843419_veneer_anti
+.type e843419_veneer_anti, %function
+e843419_veneer_anti:
+# CHECK: <e843419_veneer_anti>:
+  ldr     x8, [x8, #0x100]
+  add     x8, x8, #0
+  b       .Lreturn_anti
+.size e843419_veneer_anti, .-e843419_veneer_anti

>From dacc777d1f2307075fdd869c3f851b63480626af Mon Sep 17 00:00:00 2001
From: Elvina Yakubova <eyakubova at nvidia.com>
Date: Fri, 17 Apr 2026 05:31:28 -0700
Subject: [PATCH 2/2] Updated test to generate veneers with lld

---
 bolt/test/AArch64/veneer-erratum-843419.s | 192 +++++++++-------------
 1 file changed, 80 insertions(+), 112 deletions(-)

diff --git a/bolt/test/AArch64/veneer-erratum-843419.s b/bolt/test/AArch64/veneer-erratum-843419.s
index 6a9c83268c4fa..22fe419bb60ff 100644
--- a/bolt/test/AArch64/veneer-erratum-843419.s
+++ b/bolt/test/AArch64/veneer-erratum-843419.s
@@ -1,17 +1,23 @@
-## Test case for ARM Cortex-A53 erratum 843419 workaround veneers
-## These veneers have a specific pattern:
-## 1. ADRP instruction to load page address
-## 2. Optional instructions
-## 3. Branch to veneer (e843419 at ...)
-## 4. Veneer contains: LDR/STR using same register, branch back to +1 instruction
-
-# RUN: llvm-mc -filetype=obj -triple aarch64-unknown-unknown %s -o %t.o
+## Test case for ARM Cortex-A53 erratum 843419 workaround veneers.
+## LLD emits veneers when linking with --fix-cortex-a53-843419: the erratum
+## sequence is ADRP at 0xff8/0xffc, a qualifying load/store, an optional
+## non-branch, then a load/store (unsigned immediate) using the ADRP register;
+## LLD replaces that final instruction with B to __CortexA53843419_*.
+## BOLT recognizes those veneers (same shape as e843419* stubs) and inlines.
+##
+## Layout follows lld/test/ELF/aarch64-cortex-a53-843419-address.s test cases.
+
+# RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-linux-gnu %s -o %t.o
+# RUN: echo "SECTIONS { \
+# RUN:   . = SIZEOF_HEADERS; \
+# RUN:   .text : { *(.text.main) *(.text.pats) } \
+# RUN:   .data : { *(.data.main) } }" > %t.script
 # RUN: %clang %cflags -fPIC -pie %t.o -o %t.exe -nostdlib \
-# RUN:    -fuse-ld=lld -Wl,-q
+# RUN:   -fuse-ld=lld -Wl,-q -Wl,-T,%t.script -Wl,--fix-cortex-a53-843419
 # RUN: llvm-bolt %t.exe -o %t.bolt
 # RUN: llvm-objdump -d %t.bolt | FileCheck %s
 
-.text
+.section .text.main, "ax", %progbits
 .balign 4
 .global target_function
 .type target_function, %function
@@ -19,180 +25,142 @@ target_function:
   ret
 .size target_function, .-target_function
 
-## Pattern 1: ADRP + multiple instructions + branch to veneer
+## Anti-pattern: manual 3-instruction "veneer" (not LLD's 2-instruction patch).
+## BOLT must not inline this.
+.global test_pattern_anti
+.type test_pattern_anti, %function
+test_pattern_anti:
+# CHECK-LABEL: <test_pattern_anti>:
+  adrp    x8, target_function
+  b       e843419_veneer_anti
+# CHECK:      b {{.*}} <e843419_veneer_anti>
+.Lreturn_anti:
+  blr     x8
+  ret
+.size test_pattern_anti, .-test_pattern_anti
+
+.global e843419_veneer_anti
+.type e843419_veneer_anti, %function
+e843419_veneer_anti:
+# CHECK: <e843419_veneer_anti>:
+  ldr     x8, [x8, #0x100]
+  add     x8, x8, #0
+  b       .Lreturn_anti
+.size e843419_veneer_anti, .-e843419_veneer_anti
+
+.section .text.pats, "ax", %progbits
+
+.balign 4096
+.space 4096 - 8
 .global test_pattern_1
 .type test_pattern_1, %function
 test_pattern_1:
 # CHECK-LABEL: <test_pattern_1>:
-  adrp    x7, target_function
+  adrp    x7, dat
 # CHECK:      adrp
   stp     w9, w8, [sp, #0xc4]
-  b       e843419_veneer_1
+  ldr     x7, [x7, :got_lo12:dat]
+# CHECK-NOT:  b {{.*}} <__CortexA53843419_
 .Lreturn_1:
   stur    d0, [sp, #0xbc]
   blr     x7
-# CHECK-NOT:  b {{.*}} <e843419_veneer_1>
 # CHECK:      blr
   ret
 .size test_pattern_1, .-test_pattern_1
 
-## Veneer for pattern 1
-.global e843419_veneer_1
-.type e843419_veneer_1, %function
-e843419_veneer_1:
-# CHECK-NOT: <e843419_veneer_1>:
-  ldr     x7, [x7, #0x1a8]
-  b       .Lreturn_1
-.size e843419_veneer_1, .-e843419_veneer_1
-
-## Pattern 2: ADRP + load + mov + branch to veneer
+.balign 4096
+.space 4096 - 8
 .global test_pattern_2
 .type test_pattern_2, %function
 test_pattern_2:
 # CHECK-LABEL: <test_pattern_2>:
-  adrp    x13, target_function
+  adrp    x13, dat
 # CHECK:      adrp
   ldr     w14, [x10]
   mov     w10, #0x1
-  b       e843419_veneer_2
+  ldr     d0, [x13, :got_lo12:dat]
+# CHECK-NOT:  b {{.*}} <__CortexA53843419_
 .Lreturn_2:
   mov     x13, #0x220
-# CHECK-NOT:  b {{.*}} <e843419_veneer_2>
 # CHECK:      mov
   cmp     w14, #0x2ed
   ret
 .size test_pattern_2, .-test_pattern_2
 
-## Veneer for pattern 2
-.global e843419_veneer_2
-.type e843419_veneer_2, %function
-e843419_veneer_2:
-# CHECK-NOT: <e843419_veneer_2>:
-  ldr     d0, [x13, #0x888]
-  b       .Lreturn_2
-.size e843419_veneer_2, .-e843419_veneer_2
-
-## Pattern 3: Minimal case with just ADRP and branch
+.balign 4096
+.space 4096 - 8
 .global test_pattern_3
 .type test_pattern_3, %function
 test_pattern_3:
 # CHECK-LABEL: <test_pattern_3>:
-  adrp    x15, target_function
+  adrp    x15, dat
 # CHECK:      adrp
-  b       e843419_veneer_3
+  ldr     w0, [sp, #0x20]
+  ldr     x15, [x15, :got_lo12:dat]
+# CHECK-NOT:  b {{.*}} <__CortexA53843419_
 .Lreturn_3:
   add     x15, x15, #0x100
-# CHECK-NOT:  b {{.*}} <e843419_veneer_3>
 # CHECK:      add
   ret
 .size test_pattern_3, .-test_pattern_3
 
-## Veneer for pattern 3
-.global e843419_veneer_3
-.type e843419_veneer_3, %function
-e843419_veneer_3:
-# CHECK-NOT: <e843419_veneer_3>:
-  ldr     x15, [x15, #0x200]
-  b       .Lreturn_3
-.size e843419_veneer_3, .-e843419_veneer_3
-
-## Pattern 4: Using different registers (x8)
+.balign 4096
+.space 4096 - 8
 .global test_pattern_4
 .type test_pattern_4, %function
 test_pattern_4:
 # CHECK-LABEL: <test_pattern_4>:
-  adrp    x8, target_function
+  adrp    x8, dat
 # CHECK:      adrp
   str     x9, [sp, #0x10]
-  b       e843419_veneer_4
+  ldr     x8, [x8, :got_lo12:dat]
+# CHECK-NOT:  b {{.*}} <__CortexA53843419_
 .Lreturn_4:
   ldr     x9, [x8, #0x50]
-# CHECK-NOT:  b {{.*}} <e843419_veneer_4>
 # CHECK:      ldr
   ret
 .size test_pattern_4, .-test_pattern_4
 
-## Veneer for pattern 4
-.global e843419_veneer_4
-.type e843419_veneer_4, %function
-e843419_veneer_4:
-# CHECK-NOT: <e843419_veneer_4>:
-  ldr     x8, [x8, #0x400]
-  b       .Lreturn_4
-.size e843419_veneer_4, .-e843419_veneer_4
-
-## Pattern 5: Complex pattern with conditional code
+.balign 4096
+.space 4096 - 8
 .global test_pattern_5
 .type test_pattern_5, %function
 test_pattern_5:
 # CHECK-LABEL: <test_pattern_5>:
-  adrp    x20, target_function
+  adrp    x20, dat
 # CHECK:      adrp
-  cbz     x1, .Lskip
   ldr     x2, [sp, #0x20]
-.Lskip:
-  b       e843419_veneer_5
+  orr     x0, x0, x0
+  ldr     x20, [x20, :got_lo12:dat]
+# CHECK-NOT:  b {{.*}} <__CortexA53843419_
 .Lreturn_5:
   ldrb    w3, [x20, #0x10]
-# CHECK-NOT:  b {{.*}} <e843419_veneer_5>
 # CHECK:      ldrb
   ret
 .size test_pattern_5, .-test_pattern_5
 
-## Veneer for pattern 5
-.global e843419_veneer_5
-.type e843419_veneer_5, %function
-e843419_veneer_5:
-# CHECK-NOT: <e843419_veneer_5>:
-  ldr     x20, [x20, #0x600]
-  b       .Lreturn_5
-.size e843419_veneer_5, .-e843419_veneer_5
-
-## Pattern 6 (x16): mov x16 + branch to veneer; inlining preserves x16 for later use.
-## Without inlining, LongJmp could turn the veneer into adrp/add/br x16 and clobber it.
+## Pattern 6 (x16): mov x16 + final load; inlining must preserve x16.
+.balign 4096
+.space 4096 - 8
 .global test_pattern_x16
 .type test_pattern_x16, %function
 test_pattern_x16:
 # CHECK-LABEL: <test_pattern_x16>:
-  adrp    x1, target_function
+  adrp    x1, dat
   ldr     q2, [x0, #3744]
   mov     x16, #0x2600
-  b       e843419_x16_veneer
+  ldr     d7, [x1, :got_lo12:dat]
+# CHECK-NOT:  b {{.*}} <__CortexA53843419_
 .Lreturn_x16:
   adrp    x1, target_function
   ldr     q3, [x3, #0xee0]
-# CHECK-NOT:  b {{.*}} <e843419_x16_veneer>
-# CHECK:      ldr     q7, [x1, #0xff0]
+# CHECK:      ldr{{.*}}d7
 # CHECK:      adrp
   ret
 .size test_pattern_x16, .-test_pattern_x16
 
-.global e843419_x16_veneer
-.type e843419_x16_veneer, %function
-e843419_x16_veneer:
-# CHECK-NOT: <e843419_x16_veneer>:
-  ldr     q7, [x1, #0xff0]
-  b       .Lreturn_x16
-.size e843419_x16_veneer, .-e843419_x16_veneer
-
-## Do NOT inline when target is not the 2-instr e843419 pattern.
-.global test_pattern_anti
-.type test_pattern_anti, %function
-test_pattern_anti:
-# CHECK-LABEL: <test_pattern_anti>:
-  adrp    x8, target_function
-  b       e843419_veneer_anti
-# CHECK:      b {{.*}} <e843419_veneer_anti>
-.Lreturn_anti:
-  blr     x8
-  ret
-.size test_pattern_anti, .-test_pattern_anti
-
-.global e843419_veneer_anti
-.type e843419_veneer_anti, %function
-e843419_veneer_anti:
-# CHECK: <e843419_veneer_anti>:
-  ldr     x8, [x8, #0x100]
-  add     x8, x8, #0
-  b       .Lreturn_anti
-.size e843419_veneer_anti, .-e843419_veneer_anti
+.section .data.main, "aw", %progbits
+.balign 8
+.global dat
+dat:
+  .quad 0



More information about the llvm-commits mailing list