[llvm] [BOLT][AArch64] Add support for LDR relaxtion on LDRSl/LDRDl/LDRQl (PR #196983)

Shanzhi Chen via llvm-commits llvm-commits at lists.llvm.org
Sat Jun 13 03:18:44 PDT 2026


https://github.com/chenshanzhi updated https://github.com/llvm/llvm-project/pull/196983

>From c889d5ff1da0d50f7b5784b0e4dc220237786e76 Mon Sep 17 00:00:00 2001
From: Shanzhi Chen <chenshanzhi at huawei.com>
Date: Mon, 11 May 2026 23:17:06 +0800
Subject: [PATCH 1/3] [BOLT][AArch64] Add support for LDR relaxtion on
 LDRSl/LDRDl/LDRQl

AArch64 currently has 6 `LoadLiteral` instructions:
- 3 with a GPR as the destination register (LDRWl, LDRXl, LDRSWl)
- 3 with an FPR as the destination register (LDRSl, LDRDl, LDRQl)

BOLT already supports LDR relaxation for the first three instructions.
For the latter three, the destination register cannot be used to hold the base
address directly. Therefore LivenessAnalysis can be used to obtain usable
registers for LDR relaxation, allowing BOLT to support LDR relaxation for
these instructions as well.

In addition, a hidden option is added to control the LDR relaxation for
LDRSl/LDRDl/LDRQl because LivenessAnalysis may be expensive and may not
always find usable registers for a specific ProgramPoint.
---
 bolt/include/bolt/Core/MCPlusBuilder.h        |  8 +-
 .../bolt/Passes/AArch64RelaxationPass.h       |  7 ++
 bolt/lib/Passes/AArch64RelaxationPass.cpp     | 40 ++++++--
 .../Target/AArch64/AArch64MCPlusBuilder.cpp   | 30 +++++-
 bolt/test/AArch64/ldr-relaxation.s            | 98 +++++++++++++++++++
 5 files changed, 171 insertions(+), 12 deletions(-)

diff --git a/bolt/include/bolt/Core/MCPlusBuilder.h b/bolt/include/bolt/Core/MCPlusBuilder.h
index 3a840615bec8f..8d7c39d05bb02 100644
--- a/bolt/include/bolt/Core/MCPlusBuilder.h
+++ b/bolt/include/bolt/Core/MCPlusBuilder.h
@@ -866,6 +866,11 @@ class MCPlusBuilder {
     return false;
   }
 
+  virtual bool isLoadLiteralFPR(const MCInst &Inst) const {
+    llvm_unreachable("not implemented");
+    return false;
+  }
+
   virtual bool isMOVW(const MCInst &Inst) const {
     llvm_unreachable("not implemented");
     return false;
@@ -1852,7 +1857,8 @@ class MCPlusBuilder {
   ///     adrp x0, PageBase(label)
   ///     ldr  x0, [x0, PageOffset(label)]
   virtual InstructionListType createAdrpLdr(const MCInst &LDRInst,
-                                            MCContext *Ctx) const {
+                                            MCContext *Ctx,
+                                            MCPhysReg Reg = 0) const {
     llvm_unreachable("not implemented");
   }
 
diff --git a/bolt/include/bolt/Passes/AArch64RelaxationPass.h b/bolt/include/bolt/Passes/AArch64RelaxationPass.h
index b9185a1e34388..36126c5436709 100644
--- a/bolt/include/bolt/Passes/AArch64RelaxationPass.h
+++ b/bolt/include/bolt/Passes/AArch64RelaxationPass.h
@@ -19,11 +19,18 @@
 #define BOLT_PASSES_AARCH64RELAXATIONPASS_H
 
 #include "bolt/Passes/BinaryPasses.h"
+#include <memory>
 
 namespace llvm {
 namespace bolt {
 
+class RegAnalysis;
+class BinaryFunctionCallGraph;
+
 class AArch64RelaxationPass : public BinaryFunctionPass {
+  std::unique_ptr<RegAnalysis> RA;
+  std::unique_ptr<BinaryFunctionCallGraph> CG;
+
 public:
   explicit AArch64RelaxationPass(const cl::opt<bool> &PrintPass)
       : BinaryFunctionPass(PrintPass) {}
diff --git a/bolt/lib/Passes/AArch64RelaxationPass.cpp b/bolt/lib/Passes/AArch64RelaxationPass.cpp
index 2b7384dc848dd..89cc030c4abc4 100644
--- a/bolt/lib/Passes/AArch64RelaxationPass.cpp
+++ b/bolt/lib/Passes/AArch64RelaxationPass.cpp
@@ -11,9 +11,12 @@
 //===----------------------------------------------------------------------===//
 
 #include "bolt/Passes/AArch64RelaxationPass.h"
+#include "bolt/Core/BinaryFunctionCallGraph.h"
 #include "bolt/Core/ParallelUtilities.h"
+#include "bolt/Passes/DataflowInfoManager.h"
 #include "bolt/Utils/CommandLineOpts.h"
 #include <iterator>
+#include <memory>
 
 using namespace llvm;
 
@@ -24,6 +27,12 @@ static cl::opt<bool> AArch64PassOpt(
     "aarch64-relaxation",
     cl::desc("Replace ARM non-local ADR/LDR instructions with ADRP"),
     cl::init(true), cl::cat(BoltCategory), cl::ReallyHidden);
+
+static cl::opt<bool> AArch64RelaxLoadLiteralFPR(
+    "aarch64-relax-ldr-fp-using-la",
+    cl::desc("Replace AArch64 LDR (literal, SIMD&FP) with ADRP, "
+             "using LivenessAnalysis to find available regsiters"),
+    cl::init(true), cl::cat(BoltCategory), cl::Hidden);
 } // namespace opts
 
 namespace llvm {
@@ -44,9 +53,10 @@ void AArch64RelaxationPass::runOnFunction(BinaryFunction &BF) {
     for (auto It = BB.begin(); It != BB.end(); ++It) {
       MCInst &Inst = *It;
       bool IsADR = BC.MIB->isADR(Inst);
-
-      // TODO: Handle other types of LDR (literal, PC-relative) instructions.
-      if (!IsADR && !BC.MIB->isLoadLiteralGPR(Inst))
+      bool IsLoadLiteralGPR = BC.MIB->isLoadLiteralGPR(Inst);
+      bool IsLoadLiteralFPR =
+          (opts::AArch64RelaxLoadLiteralFPR && BC.MIB->isLoadLiteralFPR(Inst));
+      if (!IsADR && !IsLoadLiteralGPR && !IsLoadLiteralFPR)
         continue;
 
       const MCSymbol *Symbol = BC.MIB->getTargetSymbol(Inst, IsADR ? 0 : 1);
@@ -77,9 +87,27 @@ void AArch64RelaxationPass::runOnFunction(BinaryFunction &BF) {
       InstructionListType AdrpMaterialization;
       {
         auto L = BC.scopeLock();
-        AdrpMaterialization =
-            IsADR ? BC.MIB->undoAdrpAddRelaxation(Inst, BC.Ctx.get())
-                  : BC.MIB->createAdrpLdr(Inst, BC.Ctx.get());
+        if (IsADR) {
+          AdrpMaterialization =
+              BC.MIB->undoAdrpAddRelaxation(Inst, BC.Ctx.get());
+        } else if (IsLoadLiteralGPR) {
+          AdrpMaterialization = BC.MIB->createAdrpLdr(Inst, BC.Ctx.get());
+        } else if (IsLoadLiteralFPR) {
+          if (!RA) {
+            CG.reset(new BinaryFunctionCallGraph(buildCallGraph(BC)));
+            RA.reset(new RegAnalysis(BC, &BC.getBinaryFunctions(), &*CG));
+          }
+          DataflowInfoManager Info(BF, RA.get(), nullptr);
+          auto Reg = Info.getLivenessAnalysis().scavengeRegAfter(&Inst);
+          if (Reg == 0) {
+            BC.outs()
+                << "BOLT-INFO: For lack of a register to hold the address, "
+                << "this LDR (literal, SIMD&FP) cannot be relaxed:\n";
+            BC.printInstruction(BC.outs(), Inst);
+            continue;
+          }
+          AdrpMaterialization = BC.MIB->createAdrpLdr(Inst, BC.Ctx.get(), Reg);
+        }
       }
 
       if (It != BB.begin() && BC.MIB->isNoop(*std::prev(It))) {
diff --git a/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp b/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp
index 6695198802006..03eb70a0fd7c4 100644
--- a/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp
+++ b/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp
@@ -721,6 +721,12 @@ class AArch64MCPlusBuilder : public MCPlusBuilder {
            OpCode == AArch64::LDRSWl;
   }
 
+  bool isLoadLiteralFPR(const MCInst &Inst) const override {
+    unsigned OpCode = Inst.getOpcode();
+    return OpCode == AArch64::LDRSl || OpCode == AArch64::LDRDl ||
+           OpCode == AArch64::LDRQl;
+  }
+
   MCPhysReg getADRReg(const MCInst &Inst) const {
     assert((isADR(Inst) || isADRP(Inst)) && "Not an ADR instruction");
     assert(MCPlus::getNumPrimeOperands(Inst) != 0 &&
@@ -740,10 +746,8 @@ class AArch64MCPlusBuilder : public MCPlusBuilder {
     return materializeAddress(Target, Ctx, Reg, Addend);
   }
 
-  InstructionListType createAdrpLdr(const MCInst &LDRInst,
-                                    MCContext *Ctx) const override {
-    assert(isLoadLiteralGPR(LDRInst) &&
-           "LDR (literal) or LDRSW (literal) expected");
+  InstructionListType createAdrpLdr(const MCInst &LDRInst, MCContext *Ctx,
+                                    MCPhysReg Reg) const override {
     assert(LDRInst.getOperand(0).isReg() &&
            "unexpected operand in LDR instruction");
     const MCPhysReg DataReg = LDRInst.getOperand(0).getReg();
@@ -768,8 +772,24 @@ class AArch64MCPlusBuilder : public MCPlusBuilder {
       OpCode = AArch64::LDRSWui;
       RelType = ELF::R_AARCH64_LDST64_ABS_LO12_NC;
       break;
+    case AArch64::LDRSl:
+      AddrReg = Reg;
+      OpCode = AArch64::LDRSui;
+      RelType = ELF::R_AARCH64_LDST32_ABS_LO12_NC;
+      break;
+    case AArch64::LDRDl:
+      AddrReg = Reg;
+      OpCode = AArch64::LDRDui;
+      RelType = ELF::R_AARCH64_LDST64_ABS_LO12_NC;
+      break;
+    case AArch64::LDRQl:
+      AddrReg = Reg;
+      OpCode = AArch64::LDRQui;
+      RelType = ELF::R_AARCH64_LDST128_ABS_LO12_NC;
+      break;
     default:
-      llvm_unreachable("LDR (literal) or LDRSW (literal) expected");
+      llvm_unreachable("LDR (literal), LDRSW (literal), LDR (literal, SIMD&FP) "
+                       "expected");
     }
 
     const MCSymbol *Target = getTargetSymbol(LDRInst, 1);
diff --git a/bolt/test/AArch64/ldr-relaxation.s b/bolt/test/AArch64/ldr-relaxation.s
index 58ffeb034c253..2c4f3e64e3c21 100644
--- a/bolt/test/AArch64/ldr-relaxation.s
+++ b/bolt/test/AArch64/ldr-relaxation.s
@@ -135,6 +135,98 @@ _start:
   ret
   .cfi_endproc
 .size _start, .-_start
+.endif
+
+## Check LDR relaxation works on loading S registers.
+
+# RUN: llvm-mc -filetype=obj -triple aarch64-unknown-unknown \
+# RUN:    --defsym RELAX_SIMPLE_LDR_FP32=1 %s -o %t.o
+# RUN: %clang %cflags %t.o -o %t.so -Wl,-q
+# RUN: llvm-bolt %t.so -o %t.bolt
+# RUN: llvm-objdump -d %t.bolt | FileCheck %s --check-prefix=RELAX_LDR_FP32
+
+# RELAX_LDR_FP32: adrp
+# RELAX_LDR_FP32-NEXT: ldr s0
+.ifdef RELAX_SIMPLE_LDR_FP32
+  .text
+  .global _start
+  .type _start, %function
+_start:
+  .cfi_startproc
+  ldr s0, _bar
+  mov x0, xzr
+  ret
+  .cfi_endproc
+.size _start, .-_start
+.endif
+
+## Check LDR relaxation works on loading D registers.
+
+# RUN: llvm-mc -filetype=obj -triple aarch64-unknown-unknown \
+# RUN:    --defsym RELAX_SIMPLE_LDR_FP64=1 %s -o %t.o
+# RUN: %clang %cflags %t.o -o %t.so -Wl,-q
+# RUN: llvm-bolt %t.so -o %t.bolt
+# RUN: llvm-objdump -d %t.bolt | FileCheck %s --check-prefix=RELAX_LDR_FP64
+
+# RELAX_LDR_FP64: adrp
+# RELAX_LDR_FP64-NEXT: ldr d0
+.ifdef RELAX_SIMPLE_LDR_FP64
+  .text
+  .global _start
+  .type _start, %function
+_start:
+  .cfi_startproc
+  ldr d0, _bar
+  mov x0, xzr
+  ret
+  .cfi_endproc
+.size _start, .-_start
+.endif
+
+## Check LDR relaxation works on loading Q registers.
+
+# RUN: llvm-mc -filetype=obj -triple aarch64-unknown-unknown \
+# RUN:    --defsym RELAX_SIMPLE_LDR_FP128=1 %s -o %t.o
+# RUN: %clang %cflags %t.o -o %t.so -Wl,-q
+# RUN: llvm-bolt %t.so -o %t.bolt
+# RUN: llvm-objdump -d %t.bolt | FileCheck %s --check-prefix=RELAX_LDR_FP128
+
+# RELAX_LDR_FP128: adrp
+# RELAX_LDR_FP128-NEXT: ldr q0
+.ifdef RELAX_SIMPLE_LDR_FP128
+  .text
+  .global _start
+  .type _start, %function
+_start:
+  .cfi_startproc
+  ldr q0, _bar
+  mov x0, xzr
+  ret
+  .cfi_endproc
+.size _start, .-_start
+.endif
+
+## Check that disabling LDR relaxation for LDR (literal, SIMD&FP)
+## triggers a link error when such an instruction needs relaxation.
+
+# RUN: llvm-mc -filetype=obj -triple aarch64-unknown-unknown \
+# RUN:    --defsym NO_RELAX_SIMPLE_LDR_FP=1 %s -o %t.o
+# RUN: %clang %cflags %t.o -o %t.so -Wl,-q
+# RUN: not llvm-bolt %t.so -o %t.bolt -aarch64-relax-ldr-fp-using-la=false \
+# RUN:    2>&1 | FileCheck %s --check-prefix=NO_RELAX_LDR_FP
+
+# NO_RELAX_LDR_FP: BOLT-ERROR: JITLink failed: In graph in-memory object file, section .text: relocation target {{0x[0-9a-f]+}} {{.*}} is out of range of LDRLiteral19 fixup at address {{0x[0-9a-f]+}} {{.*}}
+.ifdef NO_RELAX_SIMPLE_LDR_FP
+  .text
+  .global _start
+  .type _start, %function
+_start:
+  .cfi_startproc
+  ldr q0, _bar
+  mov x0, xzr
+  ret
+  .cfi_endproc
+.size _start, .-_start
 .endif
 
   .section .text_cold
@@ -143,3 +235,9 @@ _start:
 _foo:
   .long 0x12345678
 .size _foo, .-_foo
+  .global _bar
+  .align 4
+_bar:
+  .xword  0x0000000000000000
+  .xword  0x0000000000000000
+.size _bar, .-_bar

>From 380e9baa343568ed82470553f81308840bb0552b Mon Sep 17 00:00:00 2001
From: Shanzhi Chen <chenshanzhi at huawei.com>
Date: Thu, 11 Jun 2026 20:49:27 +0800
Subject: [PATCH 2/3] [BOLT][AArch64] Add initial support for LDR relaxtion on
 LDRSl/LDRDl/LDRQl

AArch64 currently has 6 `LoadLiteral` instructions:
- 3 with a GPR as the destination register (LDRWl, LDRXl, LDRSWl)
- 3 with an FPR as the destination register (LDRSl, LDRDl, LDRQl)

BOLT already supports LDR relaxation for the first three instructions.
For the latter three, the destination register cannot be used to hold the base
address directly. Therefore one general-purpose register firstly is saved to
the stack, then is used to hold the base address, and finally is restored from
the stack.
---
 bolt/include/bolt/Core/MCPlusBuilder.h        | 15 ++++++--
 .../bolt/Passes/AArch64RelaxationPass.h       |  7 ----
 bolt/lib/Passes/AArch64RelaxationPass.cpp     | 37 +++++++------------
 .../Target/AArch64/AArch64MCPlusBuilder.cpp   | 20 ++++++++++
 bolt/test/AArch64/ldr-relaxation.s            | 26 -------------
 5 files changed, 45 insertions(+), 60 deletions(-)

diff --git a/bolt/include/bolt/Core/MCPlusBuilder.h b/bolt/include/bolt/Core/MCPlusBuilder.h
index 8d7c39d05bb02..0b1736564cbdc 100644
--- a/bolt/include/bolt/Core/MCPlusBuilder.h
+++ b/bolt/include/bolt/Core/MCPlusBuilder.h
@@ -1856,9 +1856,18 @@ class MCPlusBuilder {
   ///
   ///     adrp x0, PageBase(label)
   ///     ldr  x0, [x0, PageOffset(label)]
-  virtual InstructionListType createAdrpLdr(const MCInst &LDRInst,
-                                            MCContext *Ctx,
-                                            MCPhysReg Reg = 0) const {
+  ///
+  /// For
+  ///
+  ///     ldr  q0, [label]
+  ///
+  /// the following sequence will be generated:
+  ///
+  ///     adrp Reg, PageBase(label)
+  ///     ldr  x0, [Reg, PageOffset(label)]
+  virtual InstructionListType
+  createAdrpLdr(const MCInst &LDRInst, MCContext *Ctx,
+                MCPhysReg Reg = MCRegister::NoRegister) const {
     llvm_unreachable("not implemented");
   }
 
diff --git a/bolt/include/bolt/Passes/AArch64RelaxationPass.h b/bolt/include/bolt/Passes/AArch64RelaxationPass.h
index 36126c5436709..b9185a1e34388 100644
--- a/bolt/include/bolt/Passes/AArch64RelaxationPass.h
+++ b/bolt/include/bolt/Passes/AArch64RelaxationPass.h
@@ -19,18 +19,11 @@
 #define BOLT_PASSES_AARCH64RELAXATIONPASS_H
 
 #include "bolt/Passes/BinaryPasses.h"
-#include <memory>
 
 namespace llvm {
 namespace bolt {
 
-class RegAnalysis;
-class BinaryFunctionCallGraph;
-
 class AArch64RelaxationPass : public BinaryFunctionPass {
-  std::unique_ptr<RegAnalysis> RA;
-  std::unique_ptr<BinaryFunctionCallGraph> CG;
-
 public:
   explicit AArch64RelaxationPass(const cl::opt<bool> &PrintPass)
       : BinaryFunctionPass(PrintPass) {}
diff --git a/bolt/lib/Passes/AArch64RelaxationPass.cpp b/bolt/lib/Passes/AArch64RelaxationPass.cpp
index 89cc030c4abc4..2d402c64810bf 100644
--- a/bolt/lib/Passes/AArch64RelaxationPass.cpp
+++ b/bolt/lib/Passes/AArch64RelaxationPass.cpp
@@ -11,12 +11,9 @@
 //===----------------------------------------------------------------------===//
 
 #include "bolt/Passes/AArch64RelaxationPass.h"
-#include "bolt/Core/BinaryFunctionCallGraph.h"
 #include "bolt/Core/ParallelUtilities.h"
-#include "bolt/Passes/DataflowInfoManager.h"
 #include "bolt/Utils/CommandLineOpts.h"
 #include <iterator>
-#include <memory>
 
 using namespace llvm;
 
@@ -28,11 +25,6 @@ static cl::opt<bool> AArch64PassOpt(
     cl::desc("Replace ARM non-local ADR/LDR instructions with ADRP"),
     cl::init(true), cl::cat(BoltCategory), cl::ReallyHidden);
 
-static cl::opt<bool> AArch64RelaxLoadLiteralFPR(
-    "aarch64-relax-ldr-fp-using-la",
-    cl::desc("Replace AArch64 LDR (literal, SIMD&FP) with ADRP, "
-             "using LivenessAnalysis to find available regsiters"),
-    cl::init(true), cl::cat(BoltCategory), cl::Hidden);
 } // namespace opts
 
 namespace llvm {
@@ -54,8 +46,7 @@ void AArch64RelaxationPass::runOnFunction(BinaryFunction &BF) {
       MCInst &Inst = *It;
       bool IsADR = BC.MIB->isADR(Inst);
       bool IsLoadLiteralGPR = BC.MIB->isLoadLiteralGPR(Inst);
-      bool IsLoadLiteralFPR =
-          (opts::AArch64RelaxLoadLiteralFPR && BC.MIB->isLoadLiteralFPR(Inst));
+      bool IsLoadLiteralFPR = BC.MIB->isLoadLiteralFPR(Inst);
       if (!IsADR && !IsLoadLiteralGPR && !IsLoadLiteralFPR)
         continue;
 
@@ -93,20 +84,18 @@ void AArch64RelaxationPass::runOnFunction(BinaryFunction &BF) {
         } else if (IsLoadLiteralGPR) {
           AdrpMaterialization = BC.MIB->createAdrpLdr(Inst, BC.Ctx.get());
         } else if (IsLoadLiteralFPR) {
-          if (!RA) {
-            CG.reset(new BinaryFunctionCallGraph(buildCallGraph(BC)));
-            RA.reset(new RegAnalysis(BC, &BC.getBinaryFunctions(), &*CG));
-          }
-          DataflowInfoManager Info(BF, RA.get(), nullptr);
-          auto Reg = Info.getLivenessAnalysis().scavengeRegAfter(&Inst);
-          if (Reg == 0) {
-            BC.outs()
-                << "BOLT-INFO: For lack of a register to hold the address, "
-                << "this LDR (literal, SIMD&FP) cannot be relaxed:\n";
-            BC.printInstruction(BC.outs(), Inst);
-            continue;
-          }
-          AdrpMaterialization = BC.MIB->createAdrpLdr(Inst, BC.Ctx.get(), Reg);
+          MCInst PushReg, PopReg;
+          InstructionListType Insts;
+
+          MCPhysReg X0 = BC.MIB->getIntArgRegister(0);
+          BC.MIB->createPushRegister(PushReg, X0, 8);
+          Insts = BC.MIB->createAdrpLdr(Inst, BC.Ctx.get(), X0);
+          BC.MIB->createPopRegister(PopReg, X0, 8);
+
+          AdrpMaterialization.emplace_back(PushReg);
+          AdrpMaterialization.insert(AdrpMaterialization.end(), Insts.begin(),
+                                     Insts.end());
+          AdrpMaterialization.emplace_back(PopReg);
         }
       }
 
diff --git a/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp b/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp
index 03eb70a0fd7c4..5f290be5d1553 100644
--- a/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp
+++ b/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp
@@ -2641,6 +2641,26 @@ class AArch64MCPlusBuilder : public MCPlusBuilder {
     return false;
   }
 
+  void createPushRegister(MCInst &Inst, MCPhysReg Reg,
+                          unsigned Size) const override {
+    assert(Size == 8 && "Unexpected Size");
+    Inst = MCInstBuilder(AArch64::STRXpre)
+               .addReg(AArch64::SP)
+               .addReg(Reg)
+               .addReg(AArch64::SP)
+               .addImm(-8);
+  }
+
+  void createPopRegister(MCInst &Inst, MCPhysReg Reg,
+                         unsigned Size) const override {
+    assert(Size == 8 && "Unexpected Size");
+    Inst = MCInstBuilder(AArch64::LDRXpost)
+               .addReg(AArch64::SP)
+               .addReg(Reg)
+               .addReg(AArch64::SP)
+               .addImm(8);
+  }
+
   void createDirectCall(MCInst &Inst, const MCSymbol *Target, MCContext *Ctx,
                         bool IsTailCall) override {
     Inst.setOpcode(IsTailCall ? AArch64::B : AArch64::BL);
diff --git a/bolt/test/AArch64/ldr-relaxation.s b/bolt/test/AArch64/ldr-relaxation.s
index 2c4f3e64e3c21..b9cbc82cc10ea 100644
--- a/bolt/test/AArch64/ldr-relaxation.s
+++ b/bolt/test/AArch64/ldr-relaxation.s
@@ -154,7 +154,6 @@ _start:
 _start:
   .cfi_startproc
   ldr s0, _bar
-  mov x0, xzr
   ret
   .cfi_endproc
 .size _start, .-_start
@@ -177,7 +176,6 @@ _start:
 _start:
   .cfi_startproc
   ldr d0, _bar
-  mov x0, xzr
   ret
   .cfi_endproc
 .size _start, .-_start
@@ -200,30 +198,6 @@ _start:
 _start:
   .cfi_startproc
   ldr q0, _bar
-  mov x0, xzr
-  ret
-  .cfi_endproc
-.size _start, .-_start
-.endif
-
-## Check that disabling LDR relaxation for LDR (literal, SIMD&FP)
-## triggers a link error when such an instruction needs relaxation.
-
-# RUN: llvm-mc -filetype=obj -triple aarch64-unknown-unknown \
-# RUN:    --defsym NO_RELAX_SIMPLE_LDR_FP=1 %s -o %t.o
-# RUN: %clang %cflags %t.o -o %t.so -Wl,-q
-# RUN: not llvm-bolt %t.so -o %t.bolt -aarch64-relax-ldr-fp-using-la=false \
-# RUN:    2>&1 | FileCheck %s --check-prefix=NO_RELAX_LDR_FP
-
-# NO_RELAX_LDR_FP: BOLT-ERROR: JITLink failed: In graph in-memory object file, section .text: relocation target {{0x[0-9a-f]+}} {{.*}} is out of range of LDRLiteral19 fixup at address {{0x[0-9a-f]+}} {{.*}}
-.ifdef NO_RELAX_SIMPLE_LDR_FP
-  .text
-  .global _start
-  .type _start, %function
-_start:
-  .cfi_startproc
-  ldr q0, _bar
-  mov x0, xzr
   ret
   .cfi_endproc
 .size _start, .-_start

>From 09134775324beff3db4dc0dc16eae39fda3a7ee0 Mon Sep 17 00:00:00 2001
From: Shanzhi Chen <chenshanzhi at huawei.com>
Date: Sat, 13 Jun 2026 18:07:16 +0800
Subject: [PATCH 3/3] fixup! [BOLT][AArch64] Add initial support for LDR
 relaxtion on LDRSl/LDRDl/LDRQl

---
 bolt/lib/Passes/AArch64RelaxationPass.cpp | 1 -
 1 file changed, 1 deletion(-)

diff --git a/bolt/lib/Passes/AArch64RelaxationPass.cpp b/bolt/lib/Passes/AArch64RelaxationPass.cpp
index 2d402c64810bf..68be00fa103c0 100644
--- a/bolt/lib/Passes/AArch64RelaxationPass.cpp
+++ b/bolt/lib/Passes/AArch64RelaxationPass.cpp
@@ -24,7 +24,6 @@ static cl::opt<bool> AArch64PassOpt(
     "aarch64-relaxation",
     cl::desc("Replace ARM non-local ADR/LDR instructions with ADRP"),
     cl::init(true), cl::cat(BoltCategory), cl::ReallyHidden);
-
 } // namespace opts
 
 namespace llvm {



More information about the llvm-commits mailing list