[llvm] [LoongArch][MC] Pre-mark align fragments as linker-relaxable (PR #213582)

via llvm-commits llvm-commits at lists.llvm.org
Sun Aug 2 20:13:33 PDT 2026


https://github.com/wangleiat created https://github.com/llvm/llvm-project/pull/213582

Extract `shouldRelaxAlign` from `relaxAlign` and call it during
`emitCodeAlignment` to eagerly set the linker-relaxable flag on align
fragments. This ensures `isRangeRelaxable` returns correct results
before the layout phase.


>From adb5a33bdc27d052dc2ca051cbd25b9f4e77ce4c Mon Sep 17 00:00:00 2001
From: Ray Wang <wangray1021 at gmail.com>
Date: Mon, 3 Aug 2026 11:09:32 +0800
Subject: [PATCH] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20initia?=
 =?UTF-8?q?l=20version?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Created using spr 1.3.7
---
 .../MCTargetDesc/LoongArchAsmBackend.cpp      | 43 ++++++++++---------
 .../MCTargetDesc/LoongArchAsmBackend.h        |  3 ++
 .../MCTargetDesc/LoongArchELFStreamer.cpp     | 21 +++++----
 .../MCTargetDesc/LoongArchELFStreamer.h       | 11 +++++
 4 files changed, 49 insertions(+), 29 deletions(-)

diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp
index 0b988a5257253..3e0ad792d6fab 100644
--- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp
+++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp
@@ -196,12 +196,8 @@ getRelocPairForSize(unsigned Size) {
   }
 }
 
-// Check if an R_LARCH_ALIGN relocation is needed for an alignment directive.
-// If conditions are met, compute the padding size and create a fixup encoding
-// the padding size in the addend. If MaxBytesToEmit is smaller than the padding
-// size, the fixup encodes MaxBytesToEmit in the higher bits and references a
-// per-section marker symbol.
-bool LoongArchAsmBackend::relaxAlign(MCFragment &F, unsigned &Size) {
+// Check whether an alignment fragment needs linker relaxation.
+bool LoongArchAsmBackend::shouldRelaxAlign(const MCFragment &F) {
   // Alignments before the first linker-relaxable instruction have fixed sizes
   // and do not require relocations. Alignments after a linker-relaxable
   // instruction require a relocation, even if the STI specifies norelax.
@@ -213,17 +209,27 @@ bool LoongArchAsmBackend::relaxAlign(MCFragment &F, unsigned &Size) {
   if (F.getLayoutOrder() <= Sec->firstLinkerRelaxable())
     return false;
 
-  // Use default handling unless linker relaxation is enabled and the
-  // MaxBytesToEmit >= the nop size.
   const unsigned MinNopLen = 4;
-  unsigned MaxBytesToEmit = F.getAlignMaxBytesToEmit();
-  if (MaxBytesToEmit < MinNopLen)
+  if (F.getAlignMaxBytesToEmit() < MinNopLen)
     return false;
-
-  Size = F.getAlignment().value() - MinNopLen;
   if (F.getAlignment() <= MinNopLen)
     return false;
 
+  return true;
+}
+
+// Check if an R_LARCH_ALIGN relocation is needed for an alignment directive.
+// If conditions are met, compute the padding size and create a fixup encoding
+// the padding size in the addend. If MaxBytesToEmit is smaller than the padding
+// size, the fixup encodes MaxBytesToEmit in the higher bits and references a
+// per-section marker symbol.
+bool LoongArchAsmBackend::relaxAlign(MCFragment &F, unsigned &Size) {
+  if (!shouldRelaxAlign(F))
+    return false;
+
+  Size = F.getAlignment().value() - 4;
+  unsigned MaxBytesToEmit = F.getAlignMaxBytesToEmit();
+
   MCContext &Ctx = getContext();
   const MCExpr *Expr = nullptr;
   if (MaxBytesToEmit >= Size) {
@@ -436,14 +442,11 @@ void LoongArchAsmBackend::addReloc(const MCFragment &F, const MCFixup &Fixup,
           isPCRelFixupResolved(Target.getSubSym(), F))
         return Fallback();
 
-      if (&SecA == &SecB) {
-        // If the section is not linker-relaxable, or if the fixup is in a .dwo
-        // section (where relocations are forbidden), we must resolve the
-        // difference directly. The computed Value in evaluateFixup is correct
-        // based on the current layout.
-        if (!SecA.isLinkerRelaxable() || SecCur.getName().ends_with(".dwo"))
-          return;
-      }
+      // In SecA == SecB case. If the section is not linker-relaxable, the
+      // FixedValue has already been calculated out in evaluateFixup,
+      // return true and avoid record relocations.
+      if (&SecA == &SecB && !SecA.isLinkerRelaxable())
+        return;
     }
 
     switch (Fixup.getKind()) {
diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.h b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.h
index 637a6b2478f14..297bac0841326 100644
--- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.h
+++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.h
@@ -48,6 +48,9 @@ class LoongArchAsmBackend : public MCAsmBackend {
 
   MCFixupKindInfo getFixupKindInfo(MCFixupKind Kind) const override;
 
+  /// Check whether an alignment fragment needs linker relaxation.
+  static bool shouldRelaxAlign(const MCFragment &F);
+
   bool relaxAlign(MCFragment &F, unsigned &Size) override;
   bool relaxDwarfLineAddr(MCFragment &) const override;
   bool relaxDwarfCFA(MCFragment &) const override;
diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchELFStreamer.cpp b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchELFStreamer.cpp
index be62601080b79..91433d8eaddc5 100644
--- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchELFStreamer.cpp
+++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchELFStreamer.cpp
@@ -17,6 +17,7 @@
 #include "llvm/MC/MCAssembler.h"
 #include "llvm/MC/MCCodeEmitter.h"
 #include "llvm/MC/MCELFObjectWriter.h"
+#include "llvm/MC/MCSection.h"
 
 using namespace llvm;
 
@@ -88,15 +89,17 @@ void LoongArchTargetELFStreamer::finish() {
   W.setELFHeaderEFlags(EFlags);
 }
 
-namespace {
-class LoongArchELFStreamer : public MCELFStreamer {
-public:
-  LoongArchELFStreamer(MCContext &C, std::unique_ptr<MCAsmBackend> MAB,
-                       std::unique_ptr<MCObjectWriter> MOW,
-                       std::unique_ptr<MCCodeEmitter> MCE)
-      : MCELFStreamer(C, std::move(MAB), std::move(MOW), std::move(MCE)) {}
-};
-} // end namespace
+void LoongArchELFStreamer::emitCodeAlignment(Align Alignment,
+                                             const MCSubtargetInfo &STI,
+                                             unsigned MaxBytesToEmit) {
+  // Save the Align fragment.
+  auto *AlignFrag = getCurrentFragment();
+  MCELFStreamer::emitCodeAlignment(Alignment, STI, MaxBytesToEmit);
+
+  // Pre-mark the Align fragment as linker-relaxable.
+  if (LoongArchAsmBackend::shouldRelaxAlign(*AlignFrag))
+    AlignFrag->setLinkerRelaxable();
+}
 
 namespace llvm {
 MCELFStreamer *createLoongArchELFStreamer(MCContext &C,
diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchELFStreamer.h b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchELFStreamer.h
index 5c27f3629e81d..a9e5ec2bb527c 100644
--- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchELFStreamer.h
+++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchELFStreamer.h
@@ -29,6 +29,17 @@ class LoongArchTargetELFStreamer : public LoongArchTargetStreamer {
   void finish() override;
 };
 
+class LoongArchELFStreamer : public MCELFStreamer {
+public:
+  LoongArchELFStreamer(MCContext &C, std::unique_ptr<MCAsmBackend> MAB,
+                       std::unique_ptr<MCObjectWriter> MOW,
+                       std::unique_ptr<MCCodeEmitter> MCE)
+      : MCELFStreamer(C, std::move(MAB), std::move(MOW), std::move(MCE)) {}
+
+  void emitCodeAlignment(Align Alignment, const MCSubtargetInfo &STI,
+                         unsigned MaxBytesToEmit) override;
+};
+
 MCELFStreamer *createLoongArchELFStreamer(MCContext &C,
                                           std::unique_ptr<MCAsmBackend> MAB,
                                           std::unique_ptr<MCObjectWriter> MOW,



More information about the llvm-commits mailing list