Skip to content

Commit 88ed133

Browse files
committed
MC: Store fragment content and fixups out-of-line
Moved `Contents` and `Fixups` SmallVector storage to MCSection, enabling trivial destructors for most fragment subclasses and eliminating the need for MCFragment::destroy in ~MCSection. For appending content to the current section, use getContentsForAppending. During assembler relaxation, prefer setContents/setFixups, which may involve copying and reduce the benefits of https://reviews.llvm.org/D145791. Moving only Contents out-of-line caused a slight performance regression (Alexis Engelke's 2024 prototype). By also moving Fragments out-of-line, fragment destructors become trivial, resulting in minor instructions:u increase and [large max-rss decrease](https://llvm-compile-time-tracker.com/compare.php?from=bb982e733cfcda7e4cfb0583544f68af65211ed1&to=f12d55f97c47717d438951ecddecf8ebd28c296b&stat=max-rss&linkStats=on) for the "stage1-ReleaseLTO-g (link only)" benchmark. Now using plain SmallVector in MCSection for storage, with potential for future allocator optimizations, such as allocating `Contents` as the trailing object of MCDataFragment. (GNU Assembler uses gnulib's obstack for fragment management.) Co-authored-by: Alexis Engelke <engelke@in.tum.de> Pull Request: llvm#146307
1 parent 66cc167 commit 88ed133

File tree

12 files changed

+227
-211
lines changed

12 files changed

+227
-211
lines changed

llvm/include/llvm/MC/MCSection.h

Lines changed: 77 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ class LLVM_ABI MCSection {
132132
public:
133133
friend MCAssembler;
134134
friend MCObjectStreamer;
135+
friend class MCEncodedFragment;
135136
static constexpr unsigned NonUniqueID = ~0U;
136137

137138
enum SectionVariant {
@@ -209,6 +210,10 @@ class LLVM_ABI MCSection {
209210
// subsections.
210211
SmallVector<std::pair<unsigned, FragList>, 1> Subsections;
211212

213+
// Content and fixup storage for fragments
214+
SmallVector<char, 0> ContentStorage;
215+
SmallVector<MCFixup, 0> FixupStorage;
216+
212217
protected:
213218
// TODO Make Name private when possible.
214219
StringRef Name;
@@ -296,10 +301,7 @@ class LLVM_ABI MCSection {
296301

297302
/// Interface implemented by fragments that contain encoded instructions and/or
298303
/// data.
299-
///
300304
class MCEncodedFragment : public MCFragment {
301-
uint8_t BundlePadding = 0;
302-
303305
protected:
304306
MCEncodedFragment(MCFragment::FragmentType FType, bool HasInstructions)
305307
: MCFragment(FType, HasInstructions) {}
@@ -308,6 +310,13 @@ class MCEncodedFragment : public MCFragment {
308310
/// It must be non-null for instructions.
309311
const MCSubtargetInfo *STI = nullptr;
310312

313+
private:
314+
uint32_t ContentStart = 0;
315+
uint32_t ContentEnd = 0;
316+
uint32_t FixupStart = 0;
317+
uint32_t FixupEnd = 0;
318+
uint8_t BundlePadding = 0;
319+
311320
public:
312321
static bool classof(const MCFragment *F) {
313322
MCFragment::FragmentType Kind = F->getKind();
@@ -318,7 +327,10 @@ class MCEncodedFragment : public MCFragment {
318327
case MCFragment::FT_Data:
319328
case MCFragment::FT_Dwarf:
320329
case MCFragment::FT_DwarfFrame:
330+
case MCFragment::FT_LEB:
321331
case MCFragment::FT_PseudoProbe:
332+
case MCFragment::FT_CVInlineLines:
333+
case MCFragment::FT_CVDefRange:
322334
return true;
323335
}
324336
}
@@ -348,48 +360,56 @@ class MCEncodedFragment : public MCFragment {
348360
HasInstructions = true;
349361
this->STI = &STI;
350362
}
351-
};
352-
353-
/// Interface implemented by fragments that contain encoded instructions and/or
354-
/// data and also have fixups registered.
355-
///
356-
template <unsigned ContentsSize, unsigned FixupsSize>
357-
class MCEncodedFragmentWithFixups : public MCEncodedFragment {
358-
SmallVector<char, ContentsSize> Contents;
359-
360-
/// The list of fixups in this fragment.
361-
SmallVector<MCFixup, FixupsSize> Fixups;
362-
363-
protected:
364-
MCEncodedFragmentWithFixups(MCFragment::FragmentType FType,
365-
bool HasInstructions)
366-
: MCEncodedFragment(FType, HasInstructions) {}
367-
368-
public:
369-
SmallVectorImpl<char> &getContents() { return Contents; }
370-
const SmallVectorImpl<char> &getContents() const { return Contents; }
371363

372-
void appendContents(ArrayRef<char> C) { Contents.append(C.begin(), C.end()); }
373-
void appendContents(size_t Num, char Elt) { Contents.append(Num, Elt); }
374-
void setContents(ArrayRef<char> C) { Contents.assign(C.begin(), C.end()); }
375-
376-
void addFixup(MCFixup Fixup) { Fixups.push_back(Fixup); }
377-
SmallVectorImpl<MCFixup> &getFixups() { return Fixups; }
378-
const SmallVectorImpl<MCFixup> &getFixups() const { return Fixups; }
379-
380-
static bool classof(const MCFragment *F) {
381-
MCFragment::FragmentType Kind = F->getKind();
382-
return Kind == MCFragment::FT_Relaxable || Kind == MCFragment::FT_Data ||
383-
Kind == MCFragment::FT_CVDefRange || Kind == MCFragment::FT_Dwarf ||
384-
Kind == MCFragment::FT_DwarfFrame;
364+
// Content-related functions manage parent's storage using ContentStart and
365+
// ContentSize.
366+
void clearContents() { ContentEnd = ContentStart; }
367+
SmallVectorImpl<char> &getContentsForAppending() {
368+
SmallVectorImpl<char> &S = getParent()->ContentStorage;
369+
if (LLVM_UNLIKELY(ContentEnd != S.size())) {
370+
// If not at the storage end, move to the storage end.
371+
auto Size = ContentEnd - ContentStart;
372+
auto I = std::exchange(ContentStart, S.size());
373+
S.reserve(S.size() + Size);
374+
S.append(S.begin() + I, S.begin() + I + Size);
375+
ContentEnd = S.size();
376+
}
377+
return S;
378+
}
379+
void doneAppending() { ContentEnd = getParent()->ContentStorage.size(); }
380+
void appendContents(ArrayRef<char> Contents) {
381+
getContentsForAppending().append(Contents.begin(), Contents.end());
382+
doneAppending();
383+
}
384+
void appendContents(size_t Num, char Elt) {
385+
getContentsForAppending().append(Num, Elt);
386+
doneAppending();
387+
}
388+
void setContents(ArrayRef<char> Contents);
389+
MutableArrayRef<char> getContents() {
390+
return MutableArrayRef(getParent()->ContentStorage)
391+
.slice(ContentStart, ContentEnd - ContentStart);
385392
}
393+
ArrayRef<char> getContents() const {
394+
return ArrayRef(getParent()->ContentStorage)
395+
.slice(ContentStart, ContentEnd - ContentStart);
396+
}
397+
398+
// Fixup-related functions manage parent's storage using FixupStart and
399+
// FixupSize.
400+
void clearFixups() { FixupEnd = FixupStart; }
401+
void addFixup(MCFixup Fixup);
402+
void appendFixups(ArrayRef<MCFixup> Fixups);
403+
void setFixups(ArrayRef<MCFixup> Fixups);
404+
MutableArrayRef<MCFixup> getFixups();
405+
ArrayRef<MCFixup> getFixups() const;
386406
};
387407

388408
/// Fragment for data and encoded instructions.
389409
///
390-
class MCDataFragment : public MCEncodedFragmentWithFixups<32, 4> {
410+
class MCDataFragment : public MCEncodedFragment {
391411
public:
392-
MCDataFragment() : MCEncodedFragmentWithFixups<32, 4>(FT_Data, false) {}
412+
MCDataFragment() : MCEncodedFragment(FT_Data, false) {}
393413

394414
static bool classof(const MCFragment *F) {
395415
return F->getKind() == MCFragment::FT_Data;
@@ -402,13 +422,13 @@ class MCDataFragment : public MCEncodedFragmentWithFixups<32, 4> {
402422
/// A relaxable fragment holds on to its MCInst, since it may need to be
403423
/// relaxed during the assembler layout and relaxation stage.
404424
///
405-
class MCRelaxableFragment : public MCEncodedFragmentWithFixups<8, 1> {
425+
class MCRelaxableFragment : public MCEncodedFragment {
406426
/// The instruction this is a fragment for.
407427
MCInst Inst;
408428

409429
public:
410430
MCRelaxableFragment(const MCInst &Inst, const MCSubtargetInfo &STI)
411-
: MCEncodedFragmentWithFixups(FT_Relaxable, true), Inst(Inst) {
431+
: MCEncodedFragment(FT_Relaxable, true), Inst(Inst) {
412432
this->STI = &STI;
413433
}
414434

@@ -557,7 +577,7 @@ class MCOrgFragment : public MCFragment {
557577
}
558578
};
559579

560-
class MCLEBFragment final : public MCEncodedFragmentWithFixups<8, 0> {
580+
class MCLEBFragment final : public MCEncodedFragment {
561581
/// True if this is a sleb128, false if uleb128.
562582
bool IsSigned;
563583

@@ -566,24 +586,19 @@ class MCLEBFragment final : public MCEncodedFragmentWithFixups<8, 0> {
566586

567587
public:
568588
MCLEBFragment(const MCExpr &Value, bool IsSigned)
569-
: MCEncodedFragmentWithFixups<8, 0>(FT_LEB, false), IsSigned(IsSigned),
570-
Value(&Value) {
571-
getContents().push_back(0);
572-
}
589+
: MCEncodedFragment(FT_LEB, false), IsSigned(IsSigned), Value(&Value) {}
573590

574591
const MCExpr &getValue() const { return *Value; }
575592
void setValue(const MCExpr *Expr) { Value = Expr; }
576593

577594
bool isSigned() const { return IsSigned; }
578595

579-
/// @}
580-
581596
static bool classof(const MCFragment *F) {
582597
return F->getKind() == MCFragment::FT_LEB;
583598
}
584599
};
585600

586-
class MCDwarfLineAddrFragment : public MCEncodedFragmentWithFixups<8, 1> {
601+
class MCDwarfLineAddrFragment : public MCEncodedFragment {
587602
/// The value of the difference between the two line numbers
588603
/// between two .loc dwarf directives.
589604
int64_t LineDelta;
@@ -594,8 +609,8 @@ class MCDwarfLineAddrFragment : public MCEncodedFragmentWithFixups<8, 1> {
594609

595610
public:
596611
MCDwarfLineAddrFragment(int64_t LineDelta, const MCExpr &AddrDelta)
597-
: MCEncodedFragmentWithFixups<8, 1>(FT_Dwarf, false),
598-
LineDelta(LineDelta), AddrDelta(&AddrDelta) {}
612+
: MCEncodedFragment(FT_Dwarf, false), LineDelta(LineDelta),
613+
AddrDelta(&AddrDelta) {}
599614

600615
int64_t getLineDelta() const { return LineDelta; }
601616

@@ -606,15 +621,14 @@ class MCDwarfLineAddrFragment : public MCEncodedFragmentWithFixups<8, 1> {
606621
}
607622
};
608623

609-
class MCDwarfCallFrameFragment : public MCEncodedFragmentWithFixups<8, 1> {
624+
class MCDwarfCallFrameFragment : public MCEncodedFragment {
610625
/// The expression for the difference of the two symbols that
611626
/// make up the address delta between two .cfi_* dwarf directives.
612627
const MCExpr *AddrDelta;
613628

614629
public:
615630
MCDwarfCallFrameFragment(const MCExpr &AddrDelta)
616-
: MCEncodedFragmentWithFixups<8, 1>(FT_DwarfFrame, false),
617-
AddrDelta(&AddrDelta) {}
631+
: MCEncodedFragment(FT_DwarfFrame, false), AddrDelta(&AddrDelta) {}
618632

619633
const MCExpr &getAddrDelta() const { return *AddrDelta; }
620634
void setAddrDelta(const MCExpr *E) { AddrDelta = E; }
@@ -642,13 +656,12 @@ class MCSymbolIdFragment : public MCFragment {
642656

643657
/// Fragment representing the binary annotations produced by the
644658
/// .cv_inline_linetable directive.
645-
class MCCVInlineLineTableFragment : public MCFragment {
659+
class MCCVInlineLineTableFragment : public MCEncodedFragment {
646660
unsigned SiteFuncId;
647661
unsigned StartFileId;
648662
unsigned StartLineNum;
649663
const MCSymbol *FnStartSym;
650664
const MCSymbol *FnEndSym;
651-
SmallString<8> Contents;
652665

653666
/// CodeViewContext has the real knowledge about this format, so let it access
654667
/// our members.
@@ -658,24 +671,21 @@ class MCCVInlineLineTableFragment : public MCFragment {
658671
MCCVInlineLineTableFragment(unsigned SiteFuncId, unsigned StartFileId,
659672
unsigned StartLineNum, const MCSymbol *FnStartSym,
660673
const MCSymbol *FnEndSym)
661-
: MCFragment(FT_CVInlineLines, false), SiteFuncId(SiteFuncId),
674+
: MCEncodedFragment(FT_CVInlineLines, false), SiteFuncId(SiteFuncId),
662675
StartFileId(StartFileId), StartLineNum(StartLineNum),
663676
FnStartSym(FnStartSym), FnEndSym(FnEndSym) {}
664677

665678
const MCSymbol *getFnStartSym() const { return FnStartSym; }
666679
const MCSymbol *getFnEndSym() const { return FnEndSym; }
667680

668-
SmallString<8> &getContents() { return Contents; }
669-
const SmallString<8> &getContents() const { return Contents; }
670-
671681
static bool classof(const MCFragment *F) {
672682
return F->getKind() == MCFragment::FT_CVInlineLines;
673683
}
674684
};
675685

676686
/// Fragment representing the .cv_def_range directive.
677-
class MCCVDefRangeFragment : public MCEncodedFragmentWithFixups<32, 4> {
678-
SmallVector<std::pair<const MCSymbol *, const MCSymbol *>, 2> Ranges;
687+
class MCCVDefRangeFragment : public MCEncodedFragment {
688+
SmallVector<std::pair<const MCSymbol *, const MCSymbol *>, 0> Ranges;
679689
SmallString<32> FixedSizePortion;
680690

681691
/// CodeViewContext has the real knowledge about this format, so let it access
@@ -686,14 +696,15 @@ class MCCVDefRangeFragment : public MCEncodedFragmentWithFixups<32, 4> {
686696
MCCVDefRangeFragment(
687697
ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
688698
StringRef FixedSizePortion)
689-
: MCEncodedFragmentWithFixups<32, 4>(FT_CVDefRange, false),
690-
Ranges(Ranges), FixedSizePortion(FixedSizePortion) {}
699+
: MCEncodedFragment(FT_CVDefRange, false),
700+
Ranges(Ranges.begin(), Ranges.end()),
701+
FixedSizePortion(FixedSizePortion) {}
691702

692703
ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> getRanges() const {
693704
return Ranges;
694705
}
695706

696-
StringRef getFixedSizePortion() const { return FixedSizePortion.str(); }
707+
StringRef getFixedSizePortion() const { return FixedSizePortion; }
697708

698709
static bool classof(const MCFragment *F) {
699710
return F->getKind() == MCFragment::FT_CVDefRange;
@@ -739,23 +750,21 @@ class MCBoundaryAlignFragment : public MCFragment {
739750
}
740751
};
741752

742-
class MCPseudoProbeAddrFragment : public MCEncodedFragmentWithFixups<8, 1> {
753+
class MCPseudoProbeAddrFragment : public MCEncodedFragment {
743754
/// The expression for the difference of the two symbols that
744755
/// make up the address delta between two .pseudoprobe directives.
745756
const MCExpr *AddrDelta;
746757

747758
public:
748759
MCPseudoProbeAddrFragment(const MCExpr *AddrDelta)
749-
: MCEncodedFragmentWithFixups<8, 1>(FT_PseudoProbe, false),
750-
AddrDelta(AddrDelta) {}
760+
: MCEncodedFragment(FT_PseudoProbe, false), AddrDelta(AddrDelta) {}
751761

752762
const MCExpr &getAddrDelta() const { return *AddrDelta; }
753763

754764
static bool classof(const MCFragment *F) {
755765
return F->getKind() == MCFragment::FT_PseudoProbe;
756766
}
757767
};
758-
759768
} // end namespace llvm
760769

761770
#endif // LLVM_MC_MCSECTION_H

0 commit comments

Comments
 (0)