[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
This commit is contained in:
Nikita Popov 2020-04-10 22:06:12 +02:00
parent a916e81927
commit 8e7d771cf9
2 changed files with 67 additions and 34 deletions

View File

@ -34,7 +34,7 @@ using SectionAddrMap = DenseMap<const MCSection *, uint64_t>;
/// needed for parsing. /// needed for parsing.
class MCExpr { class MCExpr {
public: public:
enum ExprKind { enum ExprKind : uint8_t {
Binary, ///< Binary expressions. Binary, ///< Binary expressions.
Constant, ///< Constant expressions. Constant, ///< Constant expressions.
SymbolRef, ///< References to labels and assigned expressions. SymbolRef, ///< References to labels and assigned expressions.
@ -43,7 +43,14 @@ public:
}; };
private: private:
static const unsigned NumSubclassDataBits = 24;
static_assert(
NumSubclassDataBits == CHAR_BIT * (sizeof(unsigned) - sizeof(ExprKind)),
"ExprKind and SubclassData together should take up one word");
ExprKind Kind; ExprKind Kind;
/// Field reserved for use by MCExpr subclasses.
unsigned SubclassData : NumSubclassDataBits;
SMLoc Loc; SMLoc Loc;
bool evaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm, bool evaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm,
@ -51,13 +58,19 @@ private:
const SectionAddrMap *Addrs, bool InSet) const; const SectionAddrMap *Addrs, bool InSet) const;
protected: protected:
explicit MCExpr(ExprKind Kind, SMLoc Loc) : Kind(Kind), Loc(Loc) {} explicit MCExpr(ExprKind Kind, SMLoc Loc, unsigned SubclassData = 0)
: Kind(Kind), SubclassData(SubclassData), Loc(Loc) {
assert(SubclassData < (1 << NumSubclassDataBits) &&
"Subclass data too large");
}
bool evaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm, bool evaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm,
const MCAsmLayout *Layout, const MCAsmLayout *Layout,
const MCFixup *Fixup, const MCFixup *Fixup,
const SectionAddrMap *Addrs, bool InSet) const; const SectionAddrMap *Addrs, bool InSet) const;
unsigned getSubclassData() const { return SubclassData; }
public: public:
MCExpr(const MCExpr &) = delete; MCExpr(const MCExpr &) = delete;
MCExpr &operator=(const MCExpr &) = delete; MCExpr &operator=(const MCExpr &) = delete;
@ -130,19 +143,20 @@ inline raw_ostream &operator<<(raw_ostream &OS, const MCExpr &E) {
//// Represent a constant integer expression. //// Represent a constant integer expression.
class MCConstantExpr : public MCExpr { class MCConstantExpr : public MCExpr {
int64_t Value; int64_t Value;
bool PrintInHex = false;
unsigned SizeInBytes = 0;
explicit MCConstantExpr(int64_t Value) // Subclass data stores SizeInBytes in bits 0..7 and PrintInHex in bit 8.
: MCExpr(MCExpr::Constant, SMLoc()), Value(Value) {} static const unsigned SizeInBytesBits = 8;
static const unsigned SizeInBytesMask = (1 << SizeInBytesBits) - 1;
static const unsigned PrintInHexBit = 1 << SizeInBytesBits;
MCConstantExpr(int64_t Value, bool PrintInHex) static unsigned encodeSubclassData(bool PrintInHex, unsigned SizeInBytes) {
: MCExpr(MCExpr::Constant, SMLoc()), Value(Value), assert(SizeInBytes <= sizeof(int64_t) && "Excessive size");
PrintInHex(PrintInHex) {} return SizeInBytes | (PrintInHex ? PrintInHexBit : 0);
}
MCConstantExpr(int64_t Value, bool PrintInHex, unsigned SizeInBytes) MCConstantExpr(int64_t Value, bool PrintInHex, unsigned SizeInBytes)
: MCExpr(MCExpr::Constant, SMLoc()), Value(Value), PrintInHex(PrintInHex), : MCExpr(MCExpr::Constant, SMLoc(),
SizeInBytes(SizeInBytes) {} encodeSubclassData(PrintInHex, SizeInBytes)), Value(Value) {}
public: public:
/// \name Construction /// \name Construction
@ -157,9 +171,11 @@ public:
/// @{ /// @{
int64_t getValue() const { return Value; } int64_t getValue() const { return Value; }
unsigned getSizeInBytes() const { return SizeInBytes; } unsigned getSizeInBytes() const {
return getSubclassData() & SizeInBytesMask;
}
bool useHexFormat() const { return PrintInHex; } bool useHexFormat() const { return (getSubclassData() & PrintInHexBit) != 0; }
/// @} /// @}
@ -315,18 +331,33 @@ public:
}; };
private: private:
/// The symbol reference modifier.
const VariantKind Kind;
/// Specifies how the variant kind should be printed.
const unsigned UseParensForSymbolVariant : 1;
// FIXME: Remove this bit.
const unsigned HasSubsectionsViaSymbols : 1;
/// The symbol being referenced. /// The symbol being referenced.
const MCSymbol *Symbol; const MCSymbol *Symbol;
// Subclass data stores VariantKind in bits 0..15, UseParensForSymbolVariant
// in bit 16 and HasSubsectionsViaSymbols in bit 17.
static const unsigned VariantKindBits = 16;
static const unsigned VariantKindMask = (1 << VariantKindBits) - 1;
/// Specifies how the variant kind should be printed.
static const unsigned UseParensForSymbolVariantBit = 1 << VariantKindBits;
// FIXME: Remove this bit.
static const unsigned HasSubsectionsViaSymbolsBit =
1 << (VariantKindBits + 1);
static unsigned encodeSubclassData(VariantKind Kind,
bool UseParensForSymbolVariant,
bool HasSubsectionsViaSymbols) {
return (unsigned)Kind |
(UseParensForSymbolVariant ? UseParensForSymbolVariantBit : 0) |
(HasSubsectionsViaSymbols ? HasSubsectionsViaSymbolsBit : 0);
}
bool useParensForSymbolVariant() const {
return (getSubclassData() & UseParensForSymbolVariantBit) != 0;
}
explicit MCSymbolRefExpr(const MCSymbol *Symbol, VariantKind Kind, explicit MCSymbolRefExpr(const MCSymbol *Symbol, VariantKind Kind,
const MCAsmInfo *MAI, SMLoc Loc = SMLoc()); const MCAsmInfo *MAI, SMLoc Loc = SMLoc());
@ -349,11 +380,15 @@ public:
const MCSymbol &getSymbol() const { return *Symbol; } const MCSymbol &getSymbol() const { return *Symbol; }
VariantKind getKind() const { return Kind; } VariantKind getKind() const {
return (VariantKind)(getSubclassData() & VariantKindMask);
}
void printVariantKind(raw_ostream &OS) const; void printVariantKind(raw_ostream &OS) const;
bool hasSubsectionsViaSymbols() const { return HasSubsectionsViaSymbols; } bool hasSubsectionsViaSymbols() const {
return (getSubclassData() & HasSubsectionsViaSymbolsBit) != 0;
}
/// @} /// @}
/// \name Static Utility Functions /// \name Static Utility Functions
@ -381,11 +416,10 @@ public:
}; };
private: private:
Opcode Op;
const MCExpr *Expr; const MCExpr *Expr;
MCUnaryExpr(Opcode Op, const MCExpr *Expr, SMLoc Loc) MCUnaryExpr(Opcode Op, const MCExpr *Expr, SMLoc Loc)
: MCExpr(MCExpr::Unary, Loc), Op(Op), Expr(Expr) {} : MCExpr(MCExpr::Unary, Loc, Op), Expr(Expr) {}
public: public:
/// \name Construction /// \name Construction
@ -415,7 +449,7 @@ public:
/// @{ /// @{
/// Get the kind of this unary expression. /// Get the kind of this unary expression.
Opcode getOpcode() const { return Op; } Opcode getOpcode() const { return (Opcode)getSubclassData(); }
/// Get the child of this unary expression. /// Get the child of this unary expression.
const MCExpr *getSubExpr() const { return Expr; } const MCExpr *getSubExpr() const { return Expr; }
@ -457,12 +491,11 @@ public:
}; };
private: private:
Opcode Op;
const MCExpr *LHS, *RHS; const MCExpr *LHS, *RHS;
MCBinaryExpr(Opcode Op, const MCExpr *LHS, const MCExpr *RHS, MCBinaryExpr(Opcode Op, const MCExpr *LHS, const MCExpr *RHS,
SMLoc Loc = SMLoc()) SMLoc Loc = SMLoc())
: MCExpr(MCExpr::Binary, Loc), Op(Op), LHS(LHS), RHS(RHS) {} : MCExpr(MCExpr::Binary, Loc, Op), LHS(LHS), RHS(RHS) {}
public: public:
/// \name Construction /// \name Construction
@ -572,7 +605,7 @@ public:
/// @{ /// @{
/// Get the kind of this binary expression. /// Get the kind of this binary expression.
Opcode getOpcode() const { return Op; } Opcode getOpcode() const { return (Opcode)getSubclassData(); }
/// Get the left-hand side expression of the binary operator. /// Get the left-hand side expression of the binary operator.
const MCExpr *getLHS() const { return LHS; } const MCExpr *getLHS() const { return LHS; }

View File

@ -193,9 +193,9 @@ const MCConstantExpr *MCConstantExpr::create(int64_t Value, MCContext &Ctx,
MCSymbolRefExpr::MCSymbolRefExpr(const MCSymbol *Symbol, VariantKind Kind, MCSymbolRefExpr::MCSymbolRefExpr(const MCSymbol *Symbol, VariantKind Kind,
const MCAsmInfo *MAI, SMLoc Loc) const MCAsmInfo *MAI, SMLoc Loc)
: MCExpr(MCExpr::SymbolRef, Loc), Kind(Kind), : MCExpr(MCExpr::SymbolRef, Loc,
UseParensForSymbolVariant(MAI->useParensForSymbolVariant()), encodeSubclassData(Kind, MAI->useParensForSymbolVariant(),
HasSubsectionsViaSymbols(MAI->hasSubsectionsViaSymbols()), MAI->hasSubsectionsViaSymbols())),
Symbol(Symbol) { Symbol(Symbol) {
assert(Symbol); assert(Symbol);
} }
@ -464,7 +464,7 @@ MCSymbolRefExpr::getVariantKindForName(StringRef Name) {
} }
void MCSymbolRefExpr::printVariantKind(raw_ostream &OS) const { void MCSymbolRefExpr::printVariantKind(raw_ostream &OS) const {
if (UseParensForSymbolVariant) if (useParensForSymbolVariant())
OS << '(' << MCSymbolRefExpr::getVariantKindName(getKind()) << ')'; OS << '(' << MCSymbolRefExpr::getVariantKindName(getKind()) << ')';
else else
OS << '@' << MCSymbolRefExpr::getVariantKindName(getKind()); OS << '@' << MCSymbolRefExpr::getVariantKindName(getKind());