mirror of
https://github.com/intel/llvm.git
synced 2026-01-13 11:02:04 +08:00
MC: Optimize getOrCreateDataFragment
... by eagerly allocating an empty fragment when adding a fragment
with a variable-size tail.
X86AsmBackend, The JCC erratum mitigation and x86-pad-for-align set a
flag for FT_Relaxable, which needs to be moved to emitInstructionBegin.
```
if (CF->getKind() == MCFragment::FT_Relaxable)
CF->setAllowAutoPadding(canPadInst(Inst, OS));
```
Follow-up to #148544
This commit is contained in:
@@ -73,12 +73,14 @@ public:
|
||||
MCSymbol *emitCFILabel() override;
|
||||
void emitCFISections(bool EH, bool Debug) override;
|
||||
|
||||
/// Get a data fragment to write into, creating a new one if the current
|
||||
/// fragment is not FT_Data.
|
||||
MCFragment *getOrCreateDataFragment();
|
||||
// TODO: Change callers to use getCurrentFragment instead.
|
||||
MCFragment *getOrCreateDataFragment() { return getCurrentFragment(); }
|
||||
|
||||
protected:
|
||||
bool changeSectionImpl(MCSection *Section, uint32_t Subsection);
|
||||
MCAlignFragment *createAlignFragment(Align Alignment, int64_t Fill,
|
||||
uint8_t FillLen,
|
||||
unsigned MaxBytesToEmit);
|
||||
|
||||
public:
|
||||
void visitUsedSymbol(const MCSymbol &Sym) override;
|
||||
|
||||
@@ -270,6 +270,8 @@ protected:
|
||||
/// section changes.
|
||||
virtual void changeSection(MCSection *, uint32_t);
|
||||
|
||||
void addFragment(MCFragment *F);
|
||||
|
||||
virtual void emitCFIStartProcImpl(MCDwarfFrameInfo &Frame);
|
||||
virtual void emitCFIEndProcImpl(MCDwarfFrameInfo &CurFrame);
|
||||
|
||||
@@ -456,8 +458,10 @@ public:
|
||||
|
||||
MCSymbol *endSection(MCSection *Section);
|
||||
|
||||
void insert(MCFragment *F);
|
||||
/// Add a new fragment to the current section without a variable-size tail.
|
||||
void newFragment();
|
||||
/// Add a fragment with a variable-size tail and start a new empty fragment.
|
||||
void insert(MCFragment *F);
|
||||
|
||||
/// Returns the mnemonic for \p MI, if the streamer has access to a
|
||||
/// instruction printer and returns an empty string otherwise.
|
||||
|
||||
@@ -166,8 +166,8 @@ void CodeViewContext::emitStringTable(MCObjectStreamer &OS) {
|
||||
// somewhere else. If somebody wants two string tables in their .s file, one
|
||||
// will just be empty.
|
||||
if (!StrTabFragment) {
|
||||
StrTabFragment = Ctx.allocFragment<MCFragment>();
|
||||
OS.insert(StrTabFragment);
|
||||
OS.newFragment();
|
||||
StrTabFragment = OS.getCurrentFragment();
|
||||
}
|
||||
|
||||
OS.emitValueToAlignment(Align(4), 0);
|
||||
|
||||
@@ -106,18 +106,6 @@ void MCObjectStreamer::emitFrames(MCAsmBackend *MAB) {
|
||||
MCDwarfFrameEmitter::Emit(*this, MAB, false);
|
||||
}
|
||||
|
||||
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) {
|
||||
F = getContext().allocFragment<MCFragment>();
|
||||
insert(F);
|
||||
}
|
||||
return F;
|
||||
}
|
||||
|
||||
void MCObjectStreamer::visitUsedSymbol(const MCSymbol &Sym) {
|
||||
Assembler->registerSymbol(Sym);
|
||||
}
|
||||
@@ -379,6 +367,7 @@ void MCObjectStreamer::emitInstToFragment(const MCInst &Inst,
|
||||
F->setVarContents(Data);
|
||||
F->setVarFixups(Fixups);
|
||||
F->setInst(Inst);
|
||||
newFragment();
|
||||
}
|
||||
|
||||
void MCObjectStreamer::emitDwarfLocDirective(unsigned FileNo, unsigned Line,
|
||||
@@ -444,6 +433,7 @@ void MCObjectStreamer::emitDwarfAdvanceLineAddr(int64_t LineDelta,
|
||||
F->Kind = MCFragment::FT_Dwarf;
|
||||
F->setDwarfAddrDelta(buildSymbolDiff(*this, Label, LastLabel, SMLoc()));
|
||||
F->setDwarfLineDelta(LineDelta);
|
||||
newFragment();
|
||||
}
|
||||
|
||||
void MCObjectStreamer::emitDwarfLineEndEntry(MCSection *Section,
|
||||
@@ -474,6 +464,7 @@ void MCObjectStreamer::emitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel,
|
||||
auto *F = getOrCreateDataFragment();
|
||||
F->Kind = MCFragment::FT_DwarfFrame;
|
||||
F->setDwarfAddrDelta(buildSymbolDiff(*this, Label, LastLabel, Loc));
|
||||
newFragment();
|
||||
}
|
||||
|
||||
void MCObjectStreamer::emitCVLocDirective(unsigned FunctionId, unsigned FileNo,
|
||||
@@ -536,32 +527,38 @@ void MCObjectStreamer::emitBytes(StringRef Data) {
|
||||
DF->appendContents(ArrayRef(Data.data(), Data.size()));
|
||||
}
|
||||
|
||||
MCAlignFragment *MCObjectStreamer::createAlignFragment(
|
||||
Align Alignment, int64_t Fill, uint8_t FillLen, unsigned MaxBytesToEmit) {
|
||||
if (MaxBytesToEmit == 0)
|
||||
MaxBytesToEmit = Alignment.value();
|
||||
return getContext().allocFragment<MCAlignFragment>(Alignment, Fill, FillLen,
|
||||
MaxBytesToEmit);
|
||||
}
|
||||
|
||||
void MCObjectStreamer::emitValueToAlignment(Align Alignment, int64_t Fill,
|
||||
uint8_t FillLen,
|
||||
unsigned MaxBytesToEmit) {
|
||||
if (MaxBytesToEmit == 0)
|
||||
MaxBytesToEmit = Alignment.value();
|
||||
insert(getContext().allocFragment<MCAlignFragment>(Alignment, Fill, FillLen,
|
||||
MaxBytesToEmit));
|
||||
|
||||
auto *F = createAlignFragment(Alignment, Fill, FillLen, MaxBytesToEmit);
|
||||
insert(F);
|
||||
// Update the maximum alignment on the current section if necessary.
|
||||
MCSection *CurSec = getCurrentSectionOnly();
|
||||
CurSec->ensureMinAlignment(Alignment);
|
||||
F->getParent()->ensureMinAlignment(Alignment);
|
||||
}
|
||||
|
||||
void MCObjectStreamer::emitCodeAlignment(Align Alignment,
|
||||
const MCSubtargetInfo *STI,
|
||||
unsigned MaxBytesToEmit) {
|
||||
emitValueToAlignment(Alignment, 0, 1, MaxBytesToEmit);
|
||||
auto *F = cast<MCAlignFragment>(getCurrentFragment());
|
||||
auto *F = createAlignFragment(Alignment, 0, 1, MaxBytesToEmit);
|
||||
F->setEmitNops(true, STI);
|
||||
insert(F);
|
||||
// Update the maximum alignment on the current section if necessary.
|
||||
F->getParent()->ensureMinAlignment(Alignment);
|
||||
|
||||
// With RISC-V style linker relaxation, mark the section as linker-relaxable
|
||||
// if the alignment is larger than the minimum NOP size.
|
||||
unsigned Size;
|
||||
if (getAssembler().getBackend().shouldInsertExtraNopBytesForCodeAlign(*F,
|
||||
Size)) {
|
||||
getCurrentSectionOnly()->setLinkerRelaxable();
|
||||
newFragment();
|
||||
F->getParent()->setLinkerRelaxable();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1404,7 +1404,7 @@ MCSymbol *MCStreamer::endSection(MCSection *Section) {
|
||||
return Sym;
|
||||
}
|
||||
|
||||
void MCStreamer::insert(MCFragment *F) {
|
||||
void MCStreamer::addFragment(MCFragment *F) {
|
||||
auto *Sec = CurFrag->getParent();
|
||||
F->setParent(Sec);
|
||||
F->setLayoutOrder(CurFrag->getLayoutOrder() + 1);
|
||||
@@ -1414,7 +1414,14 @@ void MCStreamer::insert(MCFragment *F) {
|
||||
}
|
||||
|
||||
void MCStreamer::newFragment() {
|
||||
insert(getContext().allocFragment<MCFragment>());
|
||||
addFragment(getContext().allocFragment<MCFragment>());
|
||||
}
|
||||
|
||||
void MCStreamer::insert(MCFragment *F) {
|
||||
assert(F->getKind() != MCFragment::FT_Data &&
|
||||
"F should have a variable-size tail");
|
||||
addFragment(F);
|
||||
newFragment();
|
||||
}
|
||||
|
||||
static VersionTuple
|
||||
|
||||
@@ -456,8 +456,6 @@ bool X86AsmBackend::canPadInst(const MCInst &Inst, MCObjectStreamer &OS) const {
|
||||
}
|
||||
|
||||
bool X86AsmBackend::canPadBranches(MCObjectStreamer &OS) const {
|
||||
if (!OS.getAllowAutoPadding())
|
||||
return false;
|
||||
assert(allowAutoPadding() && "incorrect initialization!");
|
||||
|
||||
// We only pad in text section.
|
||||
@@ -491,8 +489,15 @@ void X86AsmBackend::emitInstructionBegin(MCObjectStreamer &OS,
|
||||
// fragment will have changed.
|
||||
IsRightAfterData =
|
||||
isRightAfterData(OS.getCurrentFragment(), PrevInstPosition);
|
||||
bool CanPadInst = false;
|
||||
bool AutoPadding = OS.getAllowAutoPadding();
|
||||
if (LLVM_UNLIKELY(AutoPadding || X86PadForAlign)) {
|
||||
CanPadInst = canPadInst(Inst, OS);
|
||||
if (CanPadInst)
|
||||
OS.getCurrentFragment()->setAllowAutoPadding(true);
|
||||
}
|
||||
|
||||
if (!canPadBranches(OS))
|
||||
if (!AutoPadding || !canPadBranches(OS))
|
||||
return;
|
||||
|
||||
// NB: PrevInst only valid if canPadBranches is true.
|
||||
@@ -504,7 +509,7 @@ void X86AsmBackend::emitInstructionBegin(MCObjectStreamer &OS,
|
||||
// we call canPadInst (not cheap) twice. However, in the common case, we can
|
||||
// avoid unnecessary calls to that, as this is otherwise only used for
|
||||
// relaxable fragments.
|
||||
if (!canPadInst(Inst, OS))
|
||||
if (!CanPadInst)
|
||||
return;
|
||||
|
||||
if (PendingBA && PendingBA->getNext() == OS.getCurrentFragment()) {
|
||||
@@ -542,15 +547,12 @@ void X86AsmBackend::emitInstructionBegin(MCObjectStreamer &OS,
|
||||
/// Set the last fragment to be aligned for the BoundaryAlignFragment.
|
||||
void X86AsmBackend::emitInstructionEnd(MCObjectStreamer &OS,
|
||||
const MCInst &Inst) {
|
||||
MCFragment *CF = OS.getCurrentFragment();
|
||||
if (CF->getKind() == MCFragment::FT_Relaxable)
|
||||
CF->setAllowAutoPadding(canPadInst(Inst, OS));
|
||||
|
||||
// Update PrevInstOpcode here, canPadInst() reads that.
|
||||
MCFragment *CF = OS.getCurrentFragment();
|
||||
PrevInstOpcode = Inst.getOpcode();
|
||||
PrevInstPosition = std::make_pair(CF, getSizeForInstFragment(CF));
|
||||
|
||||
if (!canPadBranches(OS))
|
||||
if (!OS.getAllowAutoPadding() || !canPadBranches(OS))
|
||||
return;
|
||||
|
||||
// PrevInst is only needed if canPadBranches. Copying an MCInst isn't cheap.
|
||||
|
||||
Reference in New Issue
Block a user