diff options
author | Fangrui Song <i@maskray.me> | 2025-07-18 09:51:21 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-07-18 09:51:21 -0700 |
commit | 73e4b589ba9526c72f495ca6898ed18d730d2db4 (patch) | |
tree | cb47ed45a62ea47be7eb0aef515d044f9b7b9a0a /llvm/lib/MC/MCObjectStreamer.cpp | |
parent | 01213141357e4a79d2d97187ff0cb89d8d173634 (diff) | |
download | llvm-73e4b589ba9526c72f495ca6898ed18d730d2db4.zip llvm-73e4b589ba9526c72f495ca6898ed18d730d2db4.tar.gz llvm-73e4b589ba9526c72f495ca6898ed18d730d2db4.tar.bz2 |
MC: Simplify fragment reuse determination
First, avoid checking MCSubtargetInfo by reducing unnecessary overhead
introduced in https://reviews.llvm.org/D44928 . That change passed STI
to both FT_Data and FT_Relaxable fragments, but STI is only necessary
for FT_Relaxable.
The use of STI in FT_Data was added for:
* Bundle alignment mode, which has been removed (#148781).
* ARM, which inappropriately uses STI in `ARMAsmBackend::applyFixup` due
to tech debt, unlike other targets. All tests passed even without the
`copySTI` change.
To ensure safety, `copySTI` now starts a new fragment to prevent mixed
STI values.
Second, avoid checking LinkerRelaxable by eagerly starting a new
fragment when a FT_Data/FT_Align fragment is marked linker-relaxable.
There is currently an extra empty FT_Data if an alignment immediately
follows a linker-relaxable fragment, which will be improved in the
future when FT_Align information is moved to the variable-tail.
Pull Request: https://github.com/llvm/llvm-project/pull/149471
Diffstat (limited to 'llvm/lib/MC/MCObjectStreamer.cpp')
-rw-r--r-- | llvm/lib/MC/MCObjectStreamer.cpp | 43 |
1 files changed, 19 insertions, 24 deletions
diff --git a/llvm/lib/MC/MCObjectStreamer.cpp b/llvm/lib/MC/MCObjectStreamer.cpp index 67433f2..d5b8f22 100644 --- a/llvm/lib/MC/MCObjectStreamer.cpp +++ b/llvm/lib/MC/MCObjectStreamer.cpp @@ -106,26 +106,12 @@ void MCObjectStreamer::emitFrames(MCAsmBackend *MAB) { MCDwarfFrameEmitter::Emit(*this, MAB, false); } -static bool canReuseDataFragment(const MCFragment &F, - const MCAssembler &Assembler, - const MCSubtargetInfo *STI) { - if (!F.hasInstructions()) - return true; - // Do not add data after a linker-relaxable instruction. The difference - // between a new label and a label at or before the linker-relaxable - // instruction cannot be resolved at assemble-time. - if (F.isLinkerRelaxable()) - return false; - // If the subtarget is changed mid fragment we start a new fragment to record - // the new STI. - return !STI || F.getSubtargetInfo() == STI; -} - -MCFragment * -MCObjectStreamer::getOrCreateDataFragment(const MCSubtargetInfo *STI) { +MCFragment *MCObjectStreamer::getOrCreateDataFragment() { + // TODO: Start a new fragment whenever finalizing the variable-size tail of a + // previous one, so that all getOrCreateDataFragment calls can be replaced + // with getCurrentFragment auto *F = getCurrentFragment(); - if (F->getKind() != MCFragment::FT_Data || - !canReuseDataFragment(*F, *Assembler, STI)) { + if (F->getKind() != MCFragment::FT_Data) { F = getContext().allocFragment<MCFragment>(); insert(F); } @@ -363,16 +349,23 @@ void MCObjectStreamer::emitInstToData(const MCInst &Inst, F->doneAppending(); if (!Fixups.empty()) F->appendFixups(Fixups); + F->setHasInstructions(STI); + bool MarkedLinkerRelaxable = false; for (auto &Fixup : MutableArrayRef(F->getFixups()).slice(FixupStartIndex)) { Fixup.setOffset(Fixup.getOffset() + CodeOffset); - if (Fixup.isLinkerRelaxable()) { - F->setLinkerRelaxable(); + if (!Fixup.isLinkerRelaxable()) + continue; + F->setLinkerRelaxable(); + // Do not add data after a linker-relaxable instruction. The difference + // between a new label and a label at or before the linker-relaxable + // instruction cannot be resolved at assemble-time. + if (!MarkedLinkerRelaxable) { + MarkedLinkerRelaxable = true; getCurrentSectionOnly()->setLinkerRelaxable(); + newFragment(); } } - - F->setHasInstructions(STI); } void MCObjectStreamer::emitInstToFragment(const MCInst &Inst, @@ -568,8 +561,10 @@ void MCObjectStreamer::emitCodeAlignment(Align Alignment, // if the alignment is larger than the minimum NOP size. unsigned Size; if (getAssembler().getBackend().shouldInsertExtraNopBytesForCodeAlign(*F, - Size)) + Size)) { getCurrentSectionOnly()->setLinkerRelaxable(); + newFragment(); + } } void MCObjectStreamer::emitValueToOffset(const MCExpr *Offset, |