Skip to content

Commit 8e7d771

Browse files
committed
[MC] Use subclass data for MCExpr to reduce memory usage
MCExpr has a bunch of free space that is currently going to waste. Repurpose it as 24 bits of subclass data, which is enough to reduce the size of all subclasses by 8 bytes. This gives us some respectable savings for debuginfo builds. Here are the max-rss reductions for the fat LTO link step: kc.link 238MiB 231MiB (-2.82%) sqlite3.link 258MiB 250MiB (-3.27%) consumer-typeset.link 152MiB 148MiB (-2.51%) bullet.link 197MiB 192MiB (-2.30%) tramp3d-v4.link 578MiB 567MiB (-1.92%) pairlocalalign.link 92MiB 90MiB (-1.98%) clamscan.link 230MiB 223MiB (-2.81%) lencod.link 242MiB 235MiB (-2.67%) SPASS.link 235MiB 230MiB (-2.23%) 7zip-benchmark.link 450MiB 435MiB (-3.25%) Differential Revision: https://reviews.llvm.org/D77939
1 parent a916e81 commit 8e7d771

File tree

2 files changed

+64
-31
lines changed

2 files changed

+64
-31
lines changed

llvm/include/llvm/MC/MCExpr.h

Lines changed: 60 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ using SectionAddrMap = DenseMap<const MCSection *, uint64_t>;
3434
/// needed for parsing.
3535
class MCExpr {
3636
public:
37-
enum ExprKind {
37+
enum ExprKind : uint8_t {
3838
Binary, ///< Binary expressions.
3939
Constant, ///< Constant expressions.
4040
SymbolRef, ///< References to labels and assigned expressions.
@@ -43,21 +43,34 @@ class MCExpr {
4343
};
4444

4545
private:
46+
static const unsigned NumSubclassDataBits = 24;
47+
static_assert(
48+
NumSubclassDataBits == CHAR_BIT * (sizeof(unsigned) - sizeof(ExprKind)),
49+
"ExprKind and SubclassData together should take up one word");
50+
4651
ExprKind Kind;
52+
/// Field reserved for use by MCExpr subclasses.
53+
unsigned SubclassData : NumSubclassDataBits;
4754
SMLoc Loc;
4855

4956
bool evaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm,
5057
const MCAsmLayout *Layout,
5158
const SectionAddrMap *Addrs, bool InSet) const;
5259

5360
protected:
54-
explicit MCExpr(ExprKind Kind, SMLoc Loc) : Kind(Kind), Loc(Loc) {}
61+
explicit MCExpr(ExprKind Kind, SMLoc Loc, unsigned SubclassData = 0)
62+
: Kind(Kind), SubclassData(SubclassData), Loc(Loc) {
63+
assert(SubclassData < (1 << NumSubclassDataBits) &&
64+
"Subclass data too large");
65+
}
5566

5667
bool evaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm,
5768
const MCAsmLayout *Layout,
5869
const MCFixup *Fixup,
5970
const SectionAddrMap *Addrs, bool InSet) const;
6071

72+
unsigned getSubclassData() const { return SubclassData; }
73+
6174
public:
6275
MCExpr(const MCExpr &) = delete;
6376
MCExpr &operator=(const MCExpr &) = delete;
@@ -130,19 +143,20 @@ inline raw_ostream &operator<<(raw_ostream &OS, const MCExpr &E) {
130143
//// Represent a constant integer expression.
131144
class MCConstantExpr : public MCExpr {
132145
int64_t Value;
133-
bool PrintInHex = false;
134-
unsigned SizeInBytes = 0;
135146

136-
explicit MCConstantExpr(int64_t Value)
137-
: MCExpr(MCExpr::Constant, SMLoc()), Value(Value) {}
147+
// Subclass data stores SizeInBytes in bits 0..7 and PrintInHex in bit 8.
148+
static const unsigned SizeInBytesBits = 8;
149+
static const unsigned SizeInBytesMask = (1 << SizeInBytesBits) - 1;
150+
static const unsigned PrintInHexBit = 1 << SizeInBytesBits;
138151

139-
MCConstantExpr(int64_t Value, bool PrintInHex)
140-
: MCExpr(MCExpr::Constant, SMLoc()), Value(Value),
141-
PrintInHex(PrintInHex) {}
152+
static unsigned encodeSubclassData(bool PrintInHex, unsigned SizeInBytes) {
153+
assert(SizeInBytes <= sizeof(int64_t) && "Excessive size");
154+
return SizeInBytes | (PrintInHex ? PrintInHexBit : 0);
155+
}
142156

143157
MCConstantExpr(int64_t Value, bool PrintInHex, unsigned SizeInBytes)
144-
: MCExpr(MCExpr::Constant, SMLoc()), Value(Value), PrintInHex(PrintInHex),
145-
SizeInBytes(SizeInBytes) {}
158+
: MCExpr(MCExpr::Constant, SMLoc(),
159+
encodeSubclassData(PrintInHex, SizeInBytes)), Value(Value) {}
146160

147161
public:
148162
/// \name Construction
@@ -157,9 +171,11 @@ class MCConstantExpr : public MCExpr {
157171
/// @{
158172

159173
int64_t getValue() const { return Value; }
160-
unsigned getSizeInBytes() const { return SizeInBytes; }
174+
unsigned getSizeInBytes() const {
175+
return getSubclassData() & SizeInBytesMask;
176+
}
161177

162-
bool useHexFormat() const { return PrintInHex; }
178+
bool useHexFormat() const { return (getSubclassData() & PrintInHexBit) != 0; }
163179

164180
/// @}
165181

@@ -315,17 +331,32 @@ class MCSymbolRefExpr : public MCExpr {
315331
};
316332

317333
private:
318-
/// The symbol reference modifier.
319-
const VariantKind Kind;
334+
/// The symbol being referenced.
335+
const MCSymbol *Symbol;
336+
337+
// Subclass data stores VariantKind in bits 0..15, UseParensForSymbolVariant
338+
// in bit 16 and HasSubsectionsViaSymbols in bit 17.
339+
static const unsigned VariantKindBits = 16;
340+
static const unsigned VariantKindMask = (1 << VariantKindBits) - 1;
320341

321342
/// Specifies how the variant kind should be printed.
322-
const unsigned UseParensForSymbolVariant : 1;
343+
static const unsigned UseParensForSymbolVariantBit = 1 << VariantKindBits;
323344

324345
// FIXME: Remove this bit.
325-
const unsigned HasSubsectionsViaSymbols : 1;
346+
static const unsigned HasSubsectionsViaSymbolsBit =
347+
1 << (VariantKindBits + 1);
348+
349+
static unsigned encodeSubclassData(VariantKind Kind,
350+
bool UseParensForSymbolVariant,
351+
bool HasSubsectionsViaSymbols) {
352+
return (unsigned)Kind |
353+
(UseParensForSymbolVariant ? UseParensForSymbolVariantBit : 0) |
354+
(HasSubsectionsViaSymbols ? HasSubsectionsViaSymbolsBit : 0);
355+
}
326356

327-
/// The symbol being referenced.
328-
const MCSymbol *Symbol;
357+
bool useParensForSymbolVariant() const {
358+
return (getSubclassData() & UseParensForSymbolVariantBit) != 0;
359+
}
329360

330361
explicit MCSymbolRefExpr(const MCSymbol *Symbol, VariantKind Kind,
331362
const MCAsmInfo *MAI, SMLoc Loc = SMLoc());
@@ -349,11 +380,15 @@ class MCSymbolRefExpr : public MCExpr {
349380

350381
const MCSymbol &getSymbol() const { return *Symbol; }
351382

352-
VariantKind getKind() const { return Kind; }
383+
VariantKind getKind() const {
384+
return (VariantKind)(getSubclassData() & VariantKindMask);
385+
}
353386

354387
void printVariantKind(raw_ostream &OS) const;
355388

356-
bool hasSubsectionsViaSymbols() const { return HasSubsectionsViaSymbols; }
389+
bool hasSubsectionsViaSymbols() const {
390+
return (getSubclassData() & HasSubsectionsViaSymbolsBit) != 0;
391+
}
357392

358393
/// @}
359394
/// \name Static Utility Functions
@@ -381,11 +416,10 @@ class MCUnaryExpr : public MCExpr {
381416
};
382417

383418
private:
384-
Opcode Op;
385419
const MCExpr *Expr;
386420

387421
MCUnaryExpr(Opcode Op, const MCExpr *Expr, SMLoc Loc)
388-
: MCExpr(MCExpr::Unary, Loc), Op(Op), Expr(Expr) {}
422+
: MCExpr(MCExpr::Unary, Loc, Op), Expr(Expr) {}
389423

390424
public:
391425
/// \name Construction
@@ -415,7 +449,7 @@ class MCUnaryExpr : public MCExpr {
415449
/// @{
416450

417451
/// Get the kind of this unary expression.
418-
Opcode getOpcode() const { return Op; }
452+
Opcode getOpcode() const { return (Opcode)getSubclassData(); }
419453

420454
/// Get the child of this unary expression.
421455
const MCExpr *getSubExpr() const { return Expr; }
@@ -457,12 +491,11 @@ class MCBinaryExpr : public MCExpr {
457491
};
458492

459493
private:
460-
Opcode Op;
461494
const MCExpr *LHS, *RHS;
462495

463496
MCBinaryExpr(Opcode Op, const MCExpr *LHS, const MCExpr *RHS,
464497
SMLoc Loc = SMLoc())
465-
: MCExpr(MCExpr::Binary, Loc), Op(Op), LHS(LHS), RHS(RHS) {}
498+
: MCExpr(MCExpr::Binary, Loc, Op), LHS(LHS), RHS(RHS) {}
466499

467500
public:
468501
/// \name Construction
@@ -572,7 +605,7 @@ class MCBinaryExpr : public MCExpr {
572605
/// @{
573606

574607
/// Get the kind of this binary expression.
575-
Opcode getOpcode() const { return Op; }
608+
Opcode getOpcode() const { return (Opcode)getSubclassData(); }
576609

577610
/// Get the left-hand side expression of the binary operator.
578611
const MCExpr *getLHS() const { return LHS; }

llvm/lib/MC/MCExpr.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -193,9 +193,9 @@ const MCConstantExpr *MCConstantExpr::create(int64_t Value, MCContext &Ctx,
193193

194194
MCSymbolRefExpr::MCSymbolRefExpr(const MCSymbol *Symbol, VariantKind Kind,
195195
const MCAsmInfo *MAI, SMLoc Loc)
196-
: MCExpr(MCExpr::SymbolRef, Loc), Kind(Kind),
197-
UseParensForSymbolVariant(MAI->useParensForSymbolVariant()),
198-
HasSubsectionsViaSymbols(MAI->hasSubsectionsViaSymbols()),
196+
: MCExpr(MCExpr::SymbolRef, Loc,
197+
encodeSubclassData(Kind, MAI->useParensForSymbolVariant(),
198+
MAI->hasSubsectionsViaSymbols())),
199199
Symbol(Symbol) {
200200
assert(Symbol);
201201
}
@@ -464,7 +464,7 @@ MCSymbolRefExpr::getVariantKindForName(StringRef Name) {
464464
}
465465

466466
void MCSymbolRefExpr::printVariantKind(raw_ostream &OS) const {
467-
if (UseParensForSymbolVariant)
467+
if (useParensForSymbolVariant())
468468
OS << '(' << MCSymbolRefExpr::getVariantKindName(getKind()) << ')';
469469
else
470470
OS << '@' << MCSymbolRefExpr::getVariantKindName(getKind());

0 commit comments

Comments
 (0)