[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