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

via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 5 17:48:44 PDT 2026


Author: wanglei
Date: 2026-08-06T08:48:40+08:00
New Revision: c9655589fe0be65f81f9b43ae3e7e59aff9d90e9

URL: https://github.com/llvm/llvm-project/commit/c9655589fe0be65f81f9b43ae3e7e59aff9d90e9
DIFF: https://github.com/llvm/llvm-project/commit/c9655589fe0be65f81f9b43ae3e7e59aff9d90e9.diff

LOG: [LoongArch][MC] Pre-mark align fragments as linker-relaxable (#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.

Added: 
    

Modified: 
    llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp
    llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.h
    llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchELFStreamer.cpp
    llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchELFStreamer.h

Removed: 
    


################################################################################
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
-        // 
diff erence 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