Skip to content

Commit f12d55f

Browse files
committed
MC: Store fragment content and fixups out-of-line
Moved `Contents` and `Fixups` SmallVector storage to MCSection, enabling trivial destructors for all 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 [modest max-rss decrease](https://llvm-compile-time-tracker.com/compare.php?from=e47d4010d34119c2b4a28e7609fde35449a8b437&to=983887637aaf87fc1ca233a8848a5637fac8f524&stat=max-rss&linkStats=on) for the "stage1-ReleaseLTO-g (link only)" benchmark. Now using a plain SmallVector in MCSection for storage, with potential for future allocator optimizations. (GNU Assembler uses gnulib obstack for fragments.) Co-authored-by: Alexis Engelke <engelke@in.tum.de> Pull Request: llvm#146307
1 parent bb982e7 commit f12d55f

File tree

13 files changed

+227
-200
lines changed

13 files changed

+227
-200
lines changed

llvm/include/llvm/MC/MCFragment.h

Lines changed: 49 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 ContentSize = 0;
125+
uint32_t FixupStart = 0;
126+
uint32_t FixupSize = 0;
127+
uint8_t BundlePadding = 0;
128+
128129
public:
129130
static bool classof(const MCFragment *F) {
130131
MCFragment::FragmentType Kind = F->getKind();
@@ -136,6 +137,7 @@ class MCEncodedFragment : public MCFragment {
136137
case MCFragment::FT_Dwarf:
137138
case MCFragment::FT_DwarfFrame:
138139
case MCFragment::FT_PseudoProbe:
140+
case MCFragment::FT_CVInlineLines:
139141
return true;
140142
}
141143
}
@@ -165,48 +167,33 @@ class MCEncodedFragment : public MCFragment {
165167
HasInstructions = true;
166168
this->STI = &STI;
167169
}
168-
};
169170

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-
}
171+
// Content-related functions manage parent's storage using ContentStart and
172+
// ContentSize.
173+
void clearContents() { ContentSize = 0; }
174+
SmallVectorImpl<char> &getContentsForAppending();
175+
void doneAppending();
176+
void appendContents(ArrayRef<char> Contents);
177+
void appendContents(size_t Num, char Elt);
178+
void setContents(ArrayRef<char> Contents);
179+
MutableArrayRef<char> getContents();
180+
ArrayRef<char> getContents() const;
181+
182+
// Fixup-related functions manage parent's storage using FixupStart and
183+
// FixupSize.
184+
void clearFixups() { FixupSize = 0; }
185+
void addFixup(MCFixup Fixup);
186+
void appendFixups(ArrayRef<MCFixup> Fixups);
187+
void setFixups(ArrayRef<MCFixup> Fixups);
188+
MutableArrayRef<MCFixup> getFixups();
189+
ArrayRef<MCFixup> getFixups() const;
203190
};
204191

205192
/// Fragment for data and encoded instructions.
206193
///
207-
class MCDataFragment : public MCEncodedFragmentWithFixups<32, 4> {
194+
class MCDataFragment : public MCEncodedFragment {
208195
public:
209-
MCDataFragment() : MCEncodedFragmentWithFixups<32, 4>(FT_Data, false) {}
196+
MCDataFragment() : MCEncodedFragment(FT_Data, false) {}
210197

211198
static bool classof(const MCFragment *F) {
212199
return F->getKind() == MCFragment::FT_Data;
@@ -219,13 +206,13 @@ class MCDataFragment : public MCEncodedFragmentWithFixups<32, 4> {
219206
/// A relaxable fragment holds on to its MCInst, since it may need to be
220207
/// relaxed during the assembler layout and relaxation stage.
221208
///
222-
class MCRelaxableFragment : public MCEncodedFragmentWithFixups<8, 1> {
209+
class MCRelaxableFragment : public MCEncodedFragment {
223210
/// The instruction this is a fragment for.
224211
MCInst Inst;
225212

226213
public:
227214
MCRelaxableFragment(const MCInst &Inst, const MCSubtargetInfo &STI)
228-
: MCEncodedFragmentWithFixups(FT_Relaxable, true), Inst(Inst) {
215+
: MCEncodedFragment(FT_Relaxable, true), Inst(Inst) {
229216
this->STI = &STI;
230217
}
231218

@@ -374,7 +361,7 @@ class MCOrgFragment : public MCFragment {
374361
}
375362
};
376363

377-
class MCLEBFragment final : public MCEncodedFragmentWithFixups<8, 0> {
364+
class MCLEBFragment final : public MCEncodedFragment {
378365
/// True if this is a sleb128, false if uleb128.
379366
bool IsSigned;
380367

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

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

391375
const MCExpr &getValue() const { return *Value; }
392376
void setValue(const MCExpr *Expr) { Value = Expr; }
393377

394378
bool isSigned() const { return IsSigned; }
395379

396-
/// @}
397-
398380
static bool classof(const MCFragment *F) {
399381
return F->getKind() == MCFragment::FT_LEB;
400382
}
401383
};
402384

403-
class MCDwarfLineAddrFragment : public MCEncodedFragmentWithFixups<8, 1> {
385+
class MCDwarfLineAddrFragment : public MCEncodedFragment {
404386
/// The value of the difference between the two line numbers
405387
/// between two .loc dwarf directives.
406388
int64_t LineDelta;
@@ -411,8 +393,8 @@ class MCDwarfLineAddrFragment : public MCEncodedFragmentWithFixups<8, 1> {
411393

412394
public:
413395
MCDwarfLineAddrFragment(int64_t LineDelta, const MCExpr &AddrDelta)
414-
: MCEncodedFragmentWithFixups<8, 1>(FT_Dwarf, false),
415-
LineDelta(LineDelta), AddrDelta(&AddrDelta) {}
396+
: MCEncodedFragment(FT_Dwarf, false), LineDelta(LineDelta),
397+
AddrDelta(&AddrDelta) {}
416398

417399
int64_t getLineDelta() const { return LineDelta; }
418400

@@ -423,15 +405,14 @@ class MCDwarfLineAddrFragment : public MCEncodedFragmentWithFixups<8, 1> {
423405
}
424406
};
425407

426-
class MCDwarfCallFrameFragment : public MCEncodedFragmentWithFixups<8, 1> {
408+
class MCDwarfCallFrameFragment : public MCEncodedFragment {
427409
/// The expression for the difference of the two symbols that
428410
/// make up the address delta between two .cfi_* dwarf directives.
429411
const MCExpr *AddrDelta;
430412

431413
public:
432414
MCDwarfCallFrameFragment(const MCExpr &AddrDelta)
433-
: MCEncodedFragmentWithFixups<8, 1>(FT_DwarfFrame, false),
434-
AddrDelta(&AddrDelta) {}
415+
: MCEncodedFragment(FT_DwarfFrame, false), AddrDelta(&AddrDelta) {}
435416

436417
const MCExpr &getAddrDelta() const { return *AddrDelta; }
437418
void setAddrDelta(const MCExpr *E) { AddrDelta = E; }
@@ -459,13 +440,12 @@ class MCSymbolIdFragment : public MCFragment {
459440

460441
/// Fragment representing the binary annotations produced by the
461442
/// .cv_inline_linetable directive.
462-
class MCCVInlineLineTableFragment : public MCFragment {
443+
class MCCVInlineLineTableFragment : public MCEncodedFragment {
463444
unsigned SiteFuncId;
464445
unsigned StartFileId;
465446
unsigned StartLineNum;
466447
const MCSymbol *FnStartSym;
467448
const MCSymbol *FnEndSym;
468-
SmallString<8> Contents;
469449

470450
/// CodeViewContext has the real knowledge about this format, so let it access
471451
/// our members.
@@ -475,23 +455,20 @@ class MCCVInlineLineTableFragment : public MCFragment {
475455
MCCVInlineLineTableFragment(unsigned SiteFuncId, unsigned StartFileId,
476456
unsigned StartLineNum, const MCSymbol *FnStartSym,
477457
const MCSymbol *FnEndSym)
478-
: MCFragment(FT_CVInlineLines, false), SiteFuncId(SiteFuncId),
458+
: MCEncodedFragment(FT_CVInlineLines, false), SiteFuncId(SiteFuncId),
479459
StartFileId(StartFileId), StartLineNum(StartLineNum),
480460
FnStartSym(FnStartSym), FnEndSym(FnEndSym) {}
481461

482462
const MCSymbol *getFnStartSym() const { return FnStartSym; }
483463
const MCSymbol *getFnEndSym() const { return FnEndSym; }
484464

485-
SmallString<8> &getContents() { return Contents; }
486-
const SmallString<8> &getContents() const { return Contents; }
487-
488465
static bool classof(const MCFragment *F) {
489466
return F->getKind() == MCFragment::FT_CVInlineLines;
490467
}
491468
};
492469

493470
/// Fragment representing the .cv_def_range directive.
494-
class MCCVDefRangeFragment : public MCEncodedFragmentWithFixups<32, 4> {
471+
class MCCVDefRangeFragment : public MCEncodedFragment {
495472
ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges;
496473
StringRef FixedSizePortion;
497474

@@ -503,8 +480,9 @@ class MCCVDefRangeFragment : public MCEncodedFragmentWithFixups<32, 4> {
503480
MCCVDefRangeFragment(
504481
ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
505482
StringRef FixedSizePortion)
506-
: MCEncodedFragmentWithFixups<32, 4>(FT_CVDefRange, false),
507-
Ranges(Ranges), FixedSizePortion(FixedSizePortion) {}
483+
: MCEncodedFragment(FT_CVDefRange, false),
484+
Ranges(Ranges.begin(), Ranges.end()),
485+
FixedSizePortion(FixedSizePortion) {}
508486

509487
ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> getRanges() const {
510488
return Ranges;
@@ -556,15 +534,14 @@ class MCBoundaryAlignFragment : public MCFragment {
556534
}
557535
};
558536

559-
class MCPseudoProbeAddrFragment : public MCEncodedFragmentWithFixups<8, 1> {
537+
class MCPseudoProbeAddrFragment : public MCEncodedFragment {
560538
/// The expression for the difference of the two symbols that
561539
/// make up the address delta between two .pseudoprobe directives.
562540
const MCExpr *AddrDelta;
563541

564542
public:
565543
MCPseudoProbeAddrFragment(const MCExpr *AddrDelta)
566-
: MCEncodedFragmentWithFixups<8, 1>(FT_PseudoProbe, false),
567-
AddrDelta(AddrDelta) {}
544+
: MCEncodedFragment(FT_PseudoProbe, false), AddrDelta(AddrDelta) {}
568545

569546
const MCExpr &getAddrDelta() const { return *AddrDelta; }
570547

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)