Skip to content

Commit ae46353

Browse files
authored
RISCV,LoongArch: Encode RELAX relocation implicitly
When linker relaxation is enabled, relaxable relocations are followed by a R_RISCV_RELAX/R_LARCH_RELAX relocation. They are encoded as two fixups by CodeEmitter and expected to have the same `IsResolved` value within MCAssembler::evaluateFixup (they must lead to either 0 or 2 relocations). This scheme wasite space and requires RISCVAsmBackend::shouldForceRelocation to be conservative. This patch introduces MCFixup::NeedsRelax to encode the RELAX relocation implicitly. The fixup will lead to either 0 or 2 relocations. Pull Request: #140494
1 parent 07e2ba4 commit ae46353

File tree

8 files changed

+151
-137
lines changed

8 files changed

+151
-137
lines changed

llvm/include/llvm/MC/MCAsmBackend.h

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ class raw_ostream;
4141
/// Generic interface to target specific assembler backends.
4242
class MCAsmBackend {
4343
protected: // Can only create subclasses.
44-
MCAsmBackend(llvm::endianness Endian, unsigned RelaxFixupKind = 0);
44+
MCAsmBackend(llvm::endianness Endian, bool LinkerRelaxation = false);
4545

4646
public:
4747
MCAsmBackend(const MCAsmBackend &) = delete;
@@ -50,10 +50,9 @@ class MCAsmBackend {
5050

5151
const llvm::endianness Endian;
5252

53-
/// Fixup kind used for linker relaxation. Currently only used by RISC-V
54-
/// and LoongArch.
55-
const unsigned RelaxFixupKind;
56-
bool allowLinkerRelaxation() const { return RelaxFixupKind != 0; }
53+
/// True for RISC-V and LoongArch. Relaxable relocations are marked with a
54+
/// RELAX relocation.
55+
bool allowLinkerRelaxation() const { return LinkerRelaxation; }
5756

5857
/// Return true if this target might automatically pad instructions and thus
5958
/// need to emit padding enable/disable directives around sensative code.
@@ -217,6 +216,9 @@ class MCAsmBackend {
217216
}
218217

219218
bool isDarwinCanonicalPersonality(const MCSymbol *Sym) const;
219+
220+
private:
221+
const bool LinkerRelaxation;
220222
};
221223

222224
} // end namespace llvm

llvm/include/llvm/MC/MCFixup.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,12 @@ class MCFixup {
7373
/// determine how the operand value should be encoded into the instruction.
7474
MCFixupKind Kind = FK_NONE;
7575

76+
/// Used by RISC-V style linker relaxation. If the fixup is unresolved,
77+
/// whether a RELAX relocation should follow.
78+
bool NeedsRelax = false;
79+
80+
/// Consider bit fields if we need more flags.
81+
7682
/// The source location which gave rise to the fixup, if any.
7783
SMLoc Loc;
7884
public:
@@ -99,6 +105,9 @@ class MCFixup {
99105

100106
const MCExpr *getValue() const { return Value; }
101107

108+
bool needsRelax() const { return NeedsRelax; }
109+
void setNeedsRelax() { NeedsRelax = true; }
110+
102111
/// Return the generic fixup kind for a value with the given size. It
103112
/// is an error to pass an unsupported size.
104113
static MCFixupKind getKindForSize(unsigned Size, bool IsPCRel) {

llvm/lib/MC/MCAsmBackend.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@
2424

2525
using namespace llvm;
2626

27-
MCAsmBackend::MCAsmBackend(llvm::endianness Endian, unsigned RelaxFixupKind)
28-
: Endian(Endian), RelaxFixupKind(RelaxFixupKind) {}
27+
MCAsmBackend::MCAsmBackend(llvm::endianness Endian, bool LinkerRelaxation)
28+
: Endian(Endian), LinkerRelaxation(LinkerRelaxation) {}
2929

3030
MCAsmBackend::~MCAsmBackend() = default;
3131

llvm/lib/MC/MCELFStreamer.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -448,13 +448,13 @@ void MCELFStreamer::emitInstToData(const MCInst &Inst,
448448
DF->getFixups(), STI);
449449

450450
auto Fixups = MutableArrayRef(DF->getFixups()).slice(FixupStartIndex);
451-
for (auto &Fixup : Fixups)
451+
for (auto &Fixup : Fixups) {
452452
Fixup.setOffset(Fixup.getOffset() + CodeOffset);
453+
if (Fixup.needsRelax())
454+
DF->setLinkerRelaxable();
455+
}
453456

454457
DF->setHasInstructions(STI);
455-
if (!Fixups.empty() && Fixups.back().getTargetKind() ==
456-
getAssembler().getBackend().RelaxFixupKind)
457-
DF->setLinkerRelaxable();
458458
}
459459

460460
void MCELFStreamer::emitBundleAlignMode(Align Alignment) {

llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp

Lines changed: 64 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ using namespace llvm;
3131
LoongArchAsmBackend::LoongArchAsmBackend(const MCSubtargetInfo &STI,
3232
uint8_t OSABI, bool Is64Bit,
3333
const MCTargetOptions &Options)
34-
: MCAsmBackend(llvm::endianness::little, ELF::R_LARCH_RELAX), STI(STI),
35-
OSABI(OSABI), Is64Bit(Is64Bit), TargetOptions(Options) {}
34+
: MCAsmBackend(llvm::endianness::little, /*LinkerRelaxation=*/true),
35+
STI(STI), OSABI(OSABI), Is64Bit(Is64Bit), TargetOptions(Options) {}
3636

3737
std::optional<MCFixupKind>
3838
LoongArchAsmBackend::getFixupKind(StringRef Name) const {
@@ -444,60 +444,72 @@ bool LoongArchAsmBackend::addReloc(MCAssembler &Asm, const MCFragment &F,
444444
return MCAsmBackend::addReloc(Asm, F, Fixup, Target, FixedValue, IsResolved,
445445
CurSTI);
446446
};
447-
if (!Target.getSubSym())
448-
return Fallback();
449-
assert(Target.getSpecifier() == 0 &&
450-
"relocatable SymA-SymB cannot have relocation specifier");
451-
std::pair<MCFixupKind, MCFixupKind> FK;
452447
uint64_t FixedValueA, FixedValueB;
453-
const MCSymbol &SA = *Target.getAddSym();
454-
const MCSymbol &SB = *Target.getSubSym();
455-
456-
bool force = !SA.isInSection() || !SB.isInSection();
457-
if (!force) {
458-
const MCSection &SecA = SA.getSection();
459-
const MCSection &SecB = SB.getSection();
460-
461-
// We need record relocation if SecA != SecB. Usually SecB is same as the
462-
// section of Fixup, which will be record the relocation as PCRel. If SecB
463-
// is not same as the section of Fixup, it will report error. Just return
464-
// false and then this work can be finished by handleFixup.
465-
if (&SecA != &SecB)
466-
return Fallback();
467-
468-
// In SecA == SecB case. If the linker relaxation is enabled, we need record
469-
// the ADD, SUB relocations. Otherwise the FixedValue has already been calc-
470-
// ulated out in evaluateFixup, return true and avoid record relocations.
471-
if (!STI.hasFeature(LoongArch::FeatureRelax))
472-
return true;
448+
if (Target.getSubSym()) {
449+
assert(Target.getSpecifier() == 0 &&
450+
"relocatable SymA-SymB cannot have relocation specifier");
451+
std::pair<MCFixupKind, MCFixupKind> FK;
452+
const MCSymbol &SA = *Target.getAddSym();
453+
const MCSymbol &SB = *Target.getSubSym();
454+
455+
bool force = !SA.isInSection() || !SB.isInSection();
456+
if (!force) {
457+
const MCSection &SecA = SA.getSection();
458+
const MCSection &SecB = SB.getSection();
459+
460+
// We need record relocation if SecA != SecB. Usually SecB is same as the
461+
// section of Fixup, which will be record the relocation as PCRel. If SecB
462+
// is not same as the section of Fixup, it will report error. Just return
463+
// false and then this work can be finished by handleFixup.
464+
if (&SecA != &SecB)
465+
return Fallback();
466+
467+
// In SecA == SecB case. If the linker relaxation is enabled, we need
468+
// record the ADD, SUB relocations. Otherwise the FixedValue has already
469+
// been calc- ulated out in evaluateFixup, return true and avoid record
470+
// relocations.
471+
if (!STI.hasFeature(LoongArch::FeatureRelax))
472+
return true;
473+
}
474+
475+
switch (Fixup.getKind()) {
476+
case llvm::FK_Data_1:
477+
FK = getRelocPairForSize(8);
478+
break;
479+
case llvm::FK_Data_2:
480+
FK = getRelocPairForSize(16);
481+
break;
482+
case llvm::FK_Data_4:
483+
FK = getRelocPairForSize(32);
484+
break;
485+
case llvm::FK_Data_8:
486+
FK = getRelocPairForSize(64);
487+
break;
488+
case llvm::FK_Data_leb128:
489+
FK = getRelocPairForSize(128);
490+
break;
491+
default:
492+
llvm_unreachable("unsupported fixup size");
493+
}
494+
MCValue A = MCValue::get(Target.getAddSym(), nullptr, Target.getConstant());
495+
MCValue B = MCValue::get(Target.getSubSym());
496+
auto FA = MCFixup::create(Fixup.getOffset(), nullptr, std::get<0>(FK));
497+
auto FB = MCFixup::create(Fixup.getOffset(), nullptr, std::get<1>(FK));
498+
Asm.getWriter().recordRelocation(Asm, &F, FA, A, FixedValueA);
499+
Asm.getWriter().recordRelocation(Asm, &F, FB, B, FixedValueB);
500+
FixedValue = FixedValueA - FixedValueB;
501+
return false;
473502
}
474503

475-
switch (Fixup.getKind()) {
476-
case llvm::FK_Data_1:
477-
FK = getRelocPairForSize(8);
478-
break;
479-
case llvm::FK_Data_2:
480-
FK = getRelocPairForSize(16);
481-
break;
482-
case llvm::FK_Data_4:
483-
FK = getRelocPairForSize(32);
484-
break;
485-
case llvm::FK_Data_8:
486-
FK = getRelocPairForSize(64);
487-
break;
488-
case llvm::FK_Data_leb128:
489-
FK = getRelocPairForSize(128);
490-
break;
491-
default:
492-
llvm_unreachable("unsupported fixup size");
504+
IsResolved = Fallback();
505+
// If linker relaxation is enabled and supported by the current relocation,
506+
// append a RELAX relocation.
507+
if (Fixup.needsRelax()) {
508+
auto FA = MCFixup::create(Fixup.getOffset(), nullptr, ELF::R_LARCH_RELAX);
509+
Asm.getWriter().recordRelocation(Asm, &F, FA, MCValue::get(nullptr),
510+
FixedValueA);
493511
}
494-
MCValue A = MCValue::get(Target.getAddSym(), nullptr, Target.getConstant());
495-
MCValue B = MCValue::get(Target.getSubSym());
496-
auto FA = MCFixup::create(Fixup.getOffset(), nullptr, std::get<0>(FK));
497-
auto FB = MCFixup::create(Fixup.getOffset(), nullptr, std::get<1>(FK));
498-
Asm.getWriter().recordRelocation(Asm, &F, FA, A, FixedValueA);
499-
Asm.getWriter().recordRelocation(Asm, &F, FB, B, FixedValueB);
500-
FixedValue = FixedValueA - FixedValueB;
512+
501513
return true;
502514
}
503515

llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.cpp

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -199,14 +199,11 @@ LoongArchMCCodeEmitter::getExprOpValue(const MCInst &MI, const MCOperand &MO,
199199

200200
Fixups.push_back(
201201
MCFixup::create(0, Expr, MCFixupKind(FixupKind), MI.getLoc()));
202-
203-
// Emit an R_LARCH_RELAX if linker relaxation is enabled and LAExpr has relax
204-
// hint.
205-
if (EnableRelax && RelaxCandidate) {
206-
const MCConstantExpr *Dummy = MCConstantExpr::create(0, Ctx);
207-
Fixups.push_back(
208-
MCFixup::create(0, Dummy, ELF::R_LARCH_RELAX, MI.getLoc()));
209-
}
202+
// If linker relaxation is enabled and supported by this relocation, set
203+
// a bit so that if fixup is unresolved, a R_LARCH_RELAX relocation will be
204+
// appended.
205+
if (EnableRelax && RelaxCandidate)
206+
Fixups.back().setNeedsRelax();
210207

211208
return 0;
212209
}
@@ -256,13 +253,8 @@ void LoongArchMCCodeEmitter::expandAddTPRel(const MCInst &MI,
256253
// Emit the correct %le_add_r relocation for the symbol.
257254
Fixups.push_back(
258255
MCFixup::create(0, Expr, ELF::R_LARCH_TLS_LE_ADD_R, MI.getLoc()));
259-
260-
// Emit R_LARCH_RELAX for %le_add_r when the relax feature is enabled.
261-
if (STI.hasFeature(LoongArch::FeatureRelax)) {
262-
const MCConstantExpr *Dummy = MCConstantExpr::create(0, Ctx);
263-
Fixups.push_back(
264-
MCFixup::create(0, Dummy, ELF::R_LARCH_RELAX, MI.getLoc()));
265-
}
256+
if (STI.hasFeature(LoongArch::FeatureRelax))
257+
Fixups.back().setNeedsRelax();
266258

267259
// Emit a normal ADD instruction with the given operands.
268260
unsigned ADD = MI.getOpcode() == LoongArch::PseudoAddTPRel_D

llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp

Lines changed: 50 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ static cl::opt<bool> ULEB128Reloc(
3636

3737
RISCVAsmBackend::RISCVAsmBackend(const MCSubtargetInfo &STI, uint8_t OSABI,
3838
bool Is64Bit, const MCTargetOptions &Options)
39-
: MCAsmBackend(llvm::endianness::little, ELF::R_RISCV_RELAX), STI(STI),
40-
OSABI(OSABI), Is64Bit(Is64Bit), TargetOptions(Options) {
39+
: MCAsmBackend(llvm::endianness::little, /*LinkerRelaxation=*/true),
40+
STI(STI), OSABI(OSABI), Is64Bit(Is64Bit), TargetOptions(Options) {
4141
RISCVFeatures::validate(STI.getTargetTriple(), STI.getFeatureBits());
4242
}
4343

@@ -620,45 +620,56 @@ bool RISCVAsmBackend::addReloc(MCAssembler &Asm, const MCFragment &F,
620620
const MCFixup &Fixup, const MCValue &Target,
621621
uint64_t &FixedValue, bool IsResolved,
622622
const MCSubtargetInfo *STI) {
623-
if (!Target.getSubSym())
624-
return MCAsmBackend::addReloc(Asm, F, Fixup, Target, FixedValue, IsResolved,
625-
STI);
626-
assert(Target.getSpecifier() == 0 &&
627-
"relocatable SymA-SymB cannot have relocation specifier");
628623
uint64_t FixedValueA, FixedValueB;
629-
unsigned TA = 0, TB = 0;
630-
switch (Fixup.getKind()) {
631-
case llvm::FK_Data_1:
632-
TA = ELF::R_RISCV_ADD8;
633-
TB = ELF::R_RISCV_SUB8;
634-
break;
635-
case llvm::FK_Data_2:
636-
TA = ELF::R_RISCV_ADD16;
637-
TB = ELF::R_RISCV_SUB16;
638-
break;
639-
case llvm::FK_Data_4:
640-
TA = ELF::R_RISCV_ADD32;
641-
TB = ELF::R_RISCV_SUB32;
642-
break;
643-
case llvm::FK_Data_8:
644-
TA = ELF::R_RISCV_ADD64;
645-
TB = ELF::R_RISCV_SUB64;
646-
break;
647-
case llvm::FK_Data_leb128:
648-
TA = ELF::R_RISCV_SET_ULEB128;
649-
TB = ELF::R_RISCV_SUB_ULEB128;
650-
break;
651-
default:
652-
llvm_unreachable("unsupported fixup size");
624+
if (Target.getSubSym()) {
625+
assert(Target.getSpecifier() == 0 &&
626+
"relocatable SymA-SymB cannot have relocation specifier");
627+
unsigned TA = 0, TB = 0;
628+
switch (Fixup.getKind()) {
629+
case llvm::FK_Data_1:
630+
TA = ELF::R_RISCV_ADD8;
631+
TB = ELF::R_RISCV_SUB8;
632+
break;
633+
case llvm::FK_Data_2:
634+
TA = ELF::R_RISCV_ADD16;
635+
TB = ELF::R_RISCV_SUB16;
636+
break;
637+
case llvm::FK_Data_4:
638+
TA = ELF::R_RISCV_ADD32;
639+
TB = ELF::R_RISCV_SUB32;
640+
break;
641+
case llvm::FK_Data_8:
642+
TA = ELF::R_RISCV_ADD64;
643+
TB = ELF::R_RISCV_SUB64;
644+
break;
645+
case llvm::FK_Data_leb128:
646+
TA = ELF::R_RISCV_SET_ULEB128;
647+
TB = ELF::R_RISCV_SUB_ULEB128;
648+
break;
649+
default:
650+
llvm_unreachable("unsupported fixup size");
651+
}
652+
MCValue A = MCValue::get(Target.getAddSym(), nullptr, Target.getConstant());
653+
MCValue B = MCValue::get(Target.getSubSym());
654+
auto FA = MCFixup::create(Fixup.getOffset(), nullptr, TA);
655+
auto FB = MCFixup::create(Fixup.getOffset(), nullptr, TB);
656+
Asm.getWriter().recordRelocation(Asm, &F, FA, A, FixedValueA);
657+
Asm.getWriter().recordRelocation(Asm, &F, FB, B, FixedValueB);
658+
FixedValue = FixedValueA - FixedValueB;
659+
return false;
653660
}
654-
MCValue A = MCValue::get(Target.getAddSym(), nullptr, Target.getConstant());
655-
MCValue B = MCValue::get(Target.getSubSym());
656-
auto FA = MCFixup::create(Fixup.getOffset(), nullptr, TA);
657-
auto FB = MCFixup::create(Fixup.getOffset(), nullptr, TB);
658-
Asm.getWriter().recordRelocation(Asm, &F, FA, A, FixedValueA);
659-
Asm.getWriter().recordRelocation(Asm, &F, FB, B, FixedValueB);
660-
FixedValue = FixedValueA - FixedValueB;
661-
return true;
661+
662+
IsResolved = MCAsmBackend::addReloc(Asm, F, Fixup, Target, FixedValue,
663+
IsResolved, STI);
664+
// If linker relaxation is enabled and supported by the current relocation,
665+
// append a RELAX relocation.
666+
if (Fixup.needsRelax()) {
667+
auto FA = MCFixup::create(Fixup.getOffset(), nullptr, ELF::R_RISCV_RELAX);
668+
Asm.getWriter().recordRelocation(Asm, &F, FA, MCValue::get(nullptr),
669+
FixedValueA);
670+
}
671+
672+
return false;
662673
}
663674

664675
void RISCVAsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,

0 commit comments

Comments
 (0)