Skip to content

Commit ca3fef4

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 <[email protected]> Pull Request: llvm#146307
1 parent 7354123 commit ca3fef4

File tree

13 files changed

+239
-204
lines changed

13 files changed

+239
-204
lines changed

llvm/include/llvm/MC/MCFragment.h

Lines changed: 50 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ class MCSection;
3030
class MCSubtargetInfo;
3131
class MCSymbol;
3232

33+
// Represents a contiguous segment of code or data within a section. Its size is
34+
// determined by MCAssembler::layout. All subclasses (except
35+
// MCRelaxableFragment, which stores a MCInst) must have trivial destructors.
3336
class MCFragment {
3437
friend class MCAssembler;
3538
friend class MCObjectStreamer;
@@ -86,12 +89,6 @@ class MCFragment {
8689
MCFragment(const MCFragment &) = delete;
8790
MCFragment &operator=(const MCFragment &) = delete;
8891

89-
/// Destroys the current fragment.
90-
///
91-
/// This must be used instead of delete as MCFragment is non-virtual.
92-
/// This method will dispatch to the appropriate subclass.
93-
LLVM_ABI void destroy();
94-
9592
MCFragment *getNext() const { return Next; }
9693

9794
FragmentType getKind() const { return Kind; }
@@ -113,10 +110,7 @@ class MCFragment {
113110

114111
/// Interface implemented by fragments that contain encoded instructions and/or
115112
/// data.
116-
///
117113
class MCEncodedFragment : public MCFragment {
118-
uint8_t BundlePadding = 0;
119-
120114
protected:
121115
MCEncodedFragment(MCFragment::FragmentType FType, bool HasInstructions)
122116
: MCFragment(FType, HasInstructions) {}
@@ -125,6 +119,13 @@ class MCEncodedFragment : public MCFragment {
125119
/// It must be non-null for instructions.
126120
const MCSubtargetInfo *STI = nullptr;
127121

122+
private:
123+
uint32_t ContentStart = 0;
124+
uint32_t ContentEnd = 0;
125+
uint32_t FixupStart = 0;
126+
uint32_t FixupEnd = 0;
127+
uint8_t BundlePadding = 0;
128+
128129
public:
129130
static bool classof(const MCFragment *F) {
130131
MCFragment::FragmentType Kind = F->getKind();
@@ -135,7 +136,9 @@ class MCEncodedFragment : public MCFragment {
135136
case MCFragment::FT_Data:
136137
case MCFragment::FT_Dwarf:
137138
case MCFragment::FT_DwarfFrame:
139+
case MCFragment::FT_LEB:
138140
case MCFragment::FT_PseudoProbe:
141+
case MCFragment::FT_CVInlineLines:
139142
return true;
140143
}
141144
}
@@ -165,48 +168,33 @@ class MCEncodedFragment : public MCFragment {
165168
HasInstructions = true;
166169
this->STI = &STI;
167170
}
168-
};
169171

170-
/// Interface implemented by fragments that contain encoded instructions and/or
171-
/// data and also have fixups registered.
172-
///
173-
template <unsigned ContentsSize, unsigned FixupsSize>
174-
class MCEncodedFragmentWithFixups : public MCEncodedFragment {
175-
SmallVector<char, ContentsSize> Contents;
176-
177-
/// The list of fixups in this fragment.
178-
SmallVector<MCFixup, FixupsSize> Fixups;
179-
180-
protected:
181-
MCEncodedFragmentWithFixups(MCFragment::FragmentType FType,
182-
bool HasInstructions)
183-
: MCEncodedFragment(FType, HasInstructions) {}
184-
185-
public:
186-
SmallVectorImpl<char> &getContents() { return Contents; }
187-
const SmallVectorImpl<char> &getContents() const { return Contents; }
188-
189-
void appendContents(ArrayRef<char> C) { Contents.append(C.begin(), C.end()); }
190-
void appendContents(size_t Num, char Elt) { Contents.append(Num, Elt); }
191-
void setContents(ArrayRef<char> C) { Contents.assign(C.begin(), C.end()); }
192-
193-
void addFixup(MCFixup Fixup) { Fixups.push_back(Fixup); }
194-
SmallVectorImpl<MCFixup> &getFixups() { return Fixups; }
195-
const SmallVectorImpl<MCFixup> &getFixups() const { return Fixups; }
196-
197-
static bool classof(const MCFragment *F) {
198-
MCFragment::FragmentType Kind = F->getKind();
199-
return Kind == MCFragment::FT_Relaxable || Kind == MCFragment::FT_Data ||
200-
Kind == MCFragment::FT_CVDefRange || Kind == MCFragment::FT_Dwarf ||
201-
Kind == MCFragment::FT_DwarfFrame;
202-
}
172+
// Content-related functions manage parent's storage using ContentStart and
173+
// ContentSize.
174+
void clearContents() { ContentEnd = ContentStart; }
175+
SmallVectorImpl<char> &getContentsForAppending();
176+
void doneAppending();
177+
void appendContents(ArrayRef<char> Contents);
178+
void appendContents(size_t Num, char Elt);
179+
void setContents(ArrayRef<char> Contents);
180+
MutableArrayRef<char> getContents();
181+
ArrayRef<char> getContents() const;
182+
183+
// Fixup-related functions manage parent's storage using FixupStart and
184+
// FixupSize.
185+
void clearFixups() { FixupEnd = FixupStart; }
186+
void addFixup(MCFixup Fixup);
187+
void appendFixups(ArrayRef<MCFixup> Fixups);
188+
void setFixups(ArrayRef<MCFixup> Fixups);
189+
MutableArrayRef<MCFixup> getFixups();
190+
ArrayRef<MCFixup> getFixups() const;
203191
};
204192

205193
/// Fragment for data and encoded instructions.
206194
///
207-
class MCDataFragment : public MCEncodedFragmentWithFixups<32, 4> {
195+
class MCDataFragment : public MCEncodedFragment {
208196
public:
209-
MCDataFragment() : MCEncodedFragmentWithFixups<32, 4>(FT_Data, false) {}
197+
MCDataFragment() : MCEncodedFragment(FT_Data, false) {}
210198

211199
static bool classof(const MCFragment *F) {
212200
return F->getKind() == MCFragment::FT_Data;
@@ -219,13 +207,13 @@ class MCDataFragment : public MCEncodedFragmentWithFixups<32, 4> {
219207
/// A relaxable fragment holds on to its MCInst, since it may need to be
220208
/// relaxed during the assembler layout and relaxation stage.
221209
///
222-
class MCRelaxableFragment : public MCEncodedFragmentWithFixups<8, 1> {
210+
class MCRelaxableFragment : public MCEncodedFragment {
223211
/// The instruction this is a fragment for.
224212
MCInst Inst;
225213

226214
public:
227215
MCRelaxableFragment(const MCInst &Inst, const MCSubtargetInfo &STI)
228-
: MCEncodedFragmentWithFixups(FT_Relaxable, true), Inst(Inst) {
216+
: MCEncodedFragment(FT_Relaxable, true), Inst(Inst) {
229217
this->STI = &STI;
230218
}
231219

@@ -374,7 +362,7 @@ class MCOrgFragment : public MCFragment {
374362
}
375363
};
376364

377-
class MCLEBFragment final : public MCEncodedFragmentWithFixups<8, 0> {
365+
class MCLEBFragment final : public MCEncodedFragment {
378366
/// True if this is a sleb128, false if uleb128.
379367
bool IsSigned;
380368

@@ -383,24 +371,19 @@ class MCLEBFragment final : public MCEncodedFragmentWithFixups<8, 0> {
383371

384372
public:
385373
MCLEBFragment(const MCExpr &Value, bool IsSigned)
386-
: MCEncodedFragmentWithFixups<8, 0>(FT_LEB, false), IsSigned(IsSigned),
387-
Value(&Value) {
388-
getContents().push_back(0);
389-
}
374+
: MCEncodedFragment(FT_LEB, false), IsSigned(IsSigned), Value(&Value) {}
390375

391376
const MCExpr &getValue() const { return *Value; }
392377
void setValue(const MCExpr *Expr) { Value = Expr; }
393378

394379
bool isSigned() const { return IsSigned; }
395380

396-
/// @}
397-
398381
static bool classof(const MCFragment *F) {
399382
return F->getKind() == MCFragment::FT_LEB;
400383
}
401384
};
402385

403-
class MCDwarfLineAddrFragment : public MCEncodedFragmentWithFixups<8, 1> {
386+
class MCDwarfLineAddrFragment : public MCEncodedFragment {
404387
/// The value of the difference between the two line numbers
405388
/// between two .loc dwarf directives.
406389
int64_t LineDelta;
@@ -411,8 +394,8 @@ class MCDwarfLineAddrFragment : public MCEncodedFragmentWithFixups<8, 1> {
411394

412395
public:
413396
MCDwarfLineAddrFragment(int64_t LineDelta, const MCExpr &AddrDelta)
414-
: MCEncodedFragmentWithFixups<8, 1>(FT_Dwarf, false),
415-
LineDelta(LineDelta), AddrDelta(&AddrDelta) {}
397+
: MCEncodedFragment(FT_Dwarf, false), LineDelta(LineDelta),
398+
AddrDelta(&AddrDelta) {}
416399

417400
int64_t getLineDelta() const { return LineDelta; }
418401

@@ -423,15 +406,14 @@ class MCDwarfLineAddrFragment : public MCEncodedFragmentWithFixups<8, 1> {
423406
}
424407
};
425408

426-
class MCDwarfCallFrameFragment : public MCEncodedFragmentWithFixups<8, 1> {
409+
class MCDwarfCallFrameFragment : public MCEncodedFragment {
427410
/// The expression for the difference of the two symbols that
428411
/// make up the address delta between two .cfi_* dwarf directives.
429412
const MCExpr *AddrDelta;
430413

431414
public:
432415
MCDwarfCallFrameFragment(const MCExpr &AddrDelta)
433-
: MCEncodedFragmentWithFixups<8, 1>(FT_DwarfFrame, false),
434-
AddrDelta(&AddrDelta) {}
416+
: MCEncodedFragment(FT_DwarfFrame, false), AddrDelta(&AddrDelta) {}
435417

436418
const MCExpr &getAddrDelta() const { return *AddrDelta; }
437419
void setAddrDelta(const MCExpr *E) { AddrDelta = E; }
@@ -459,13 +441,12 @@ class MCSymbolIdFragment : public MCFragment {
459441

460442
/// Fragment representing the binary annotations produced by the
461443
/// .cv_inline_linetable directive.
462-
class MCCVInlineLineTableFragment : public MCFragment {
444+
class MCCVInlineLineTableFragment : public MCEncodedFragment {
463445
unsigned SiteFuncId;
464446
unsigned StartFileId;
465447
unsigned StartLineNum;
466448
const MCSymbol *FnStartSym;
467449
const MCSymbol *FnEndSym;
468-
SmallString<8> Contents;
469450

470451
/// CodeViewContext has the real knowledge about this format, so let it access
471452
/// our members.
@@ -475,23 +456,20 @@ class MCCVInlineLineTableFragment : public MCFragment {
475456
MCCVInlineLineTableFragment(unsigned SiteFuncId, unsigned StartFileId,
476457
unsigned StartLineNum, const MCSymbol *FnStartSym,
477458
const MCSymbol *FnEndSym)
478-
: MCFragment(FT_CVInlineLines, false), SiteFuncId(SiteFuncId),
459+
: MCEncodedFragment(FT_CVInlineLines, false), SiteFuncId(SiteFuncId),
479460
StartFileId(StartFileId), StartLineNum(StartLineNum),
480461
FnStartSym(FnStartSym), FnEndSym(FnEndSym) {}
481462

482463
const MCSymbol *getFnStartSym() const { return FnStartSym; }
483464
const MCSymbol *getFnEndSym() const { return FnEndSym; }
484465

485-
SmallString<8> &getContents() { return Contents; }
486-
const SmallString<8> &getContents() const { return Contents; }
487-
488466
static bool classof(const MCFragment *F) {
489467
return F->getKind() == MCFragment::FT_CVInlineLines;
490468
}
491469
};
492470

493471
/// Fragment representing the .cv_def_range directive.
494-
class MCCVDefRangeFragment : public MCEncodedFragmentWithFixups<32, 4> {
472+
class MCCVDefRangeFragment : public MCEncodedFragment {
495473
ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges;
496474
StringRef FixedSizePortion;
497475

@@ -503,8 +481,9 @@ class MCCVDefRangeFragment : public MCEncodedFragmentWithFixups<32, 4> {
503481
MCCVDefRangeFragment(
504482
ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
505483
StringRef FixedSizePortion)
506-
: MCEncodedFragmentWithFixups<32, 4>(FT_CVDefRange, false),
507-
Ranges(Ranges), FixedSizePortion(FixedSizePortion) {}
484+
: MCEncodedFragment(FT_CVDefRange, false),
485+
Ranges(Ranges.begin(), Ranges.end()),
486+
FixedSizePortion(FixedSizePortion) {}
508487

509488
ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> getRanges() const {
510489
return Ranges;
@@ -556,15 +535,14 @@ class MCBoundaryAlignFragment : public MCFragment {
556535
}
557536
};
558537

559-
class MCPseudoProbeAddrFragment : public MCEncodedFragmentWithFixups<8, 1> {
538+
class MCPseudoProbeAddrFragment : public MCEncodedFragment {
560539
/// The expression for the difference of the two symbols that
561540
/// make up the address delta between two .pseudoprobe directives.
562541
const MCExpr *AddrDelta;
563542

564543
public:
565544
MCPseudoProbeAddrFragment(const MCExpr *AddrDelta)
566-
: MCEncodedFragmentWithFixups<8, 1>(FT_PseudoProbe, false),
567-
AddrDelta(AddrDelta) {}
545+
: MCEncodedFragment(FT_PseudoProbe, false), AddrDelta(AddrDelta) {}
568546

569547
const MCExpr &getAddrDelta() const { return *AddrDelta; }
570548

llvm/include/llvm/MC/MCSection.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ class LLVM_ABI MCSection {
3939
public:
4040
friend MCAssembler;
4141
friend MCObjectStreamer;
42+
friend class MCEncodedFragment;
4243
static constexpr unsigned NonUniqueID = ~0U;
4344

4445
enum SectionVariant {
@@ -116,6 +117,10 @@ class LLVM_ABI MCSection {
116117
// subsections.
117118
SmallVector<std::pair<unsigned, FragList>, 1> Subsections;
118119

120+
// Content and fixup storage for fragments
121+
SmallVector<char, 0> ContentStorage;
122+
SmallVector<MCFixup, 0> FixupStorage;
123+
119124
protected:
120125
// TODO Make Name private when possible.
121126
StringRef Name;

0 commit comments

Comments
 (0)