[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