From 8e7d771cf9b6197c723e1ea8739563d24aca2e3c Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Fri, 10 Apr 2020 22:06:12 +0200 Subject: [PATCH] [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 --- llvm/include/llvm/MC/MCExpr.h | 87 +++++++++++++++++++++++++++++-------------- llvm/lib/MC/MCExpr.cpp | 8 ++-- 2 files changed, 64 insertions(+), 31 deletions(-) diff --git a/llvm/include/llvm/MC/MCExpr.h b/llvm/include/llvm/MC/MCExpr.h index 386fa9c..d1ffef7 100644 --- a/llvm/include/llvm/MC/MCExpr.h +++ b/llvm/include/llvm/MC/MCExpr.h @@ -34,7 +34,7 @@ using SectionAddrMap = DenseMap; /// needed for parsing. class MCExpr { public: - enum ExprKind { + enum ExprKind : uint8_t { Binary, ///< Binary expressions. Constant, ///< Constant expressions. SymbolRef, ///< References to labels and assigned expressions. @@ -43,7 +43,14 @@ public: }; 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; + /// Field reserved for use by MCExpr subclasses. + unsigned SubclassData : NumSubclassDataBits; SMLoc Loc; bool evaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm, @@ -51,13 +58,19 @@ private: const SectionAddrMap *Addrs, bool InSet) const; 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, const MCAsmLayout *Layout, const MCFixup *Fixup, const SectionAddrMap *Addrs, bool InSet) const; + unsigned getSubclassData() const { return SubclassData; } + public: MCExpr(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. class MCConstantExpr : public MCExpr { int64_t Value; - bool PrintInHex = false; - unsigned SizeInBytes = 0; - explicit MCConstantExpr(int64_t Value) - : MCExpr(MCExpr::Constant, SMLoc()), Value(Value) {} + // Subclass data stores SizeInBytes in bits 0..7 and PrintInHex in bit 8. + static const unsigned SizeInBytesBits = 8; + static const unsigned SizeInBytesMask = (1 << SizeInBytesBits) - 1; + static const unsigned PrintInHexBit = 1 << SizeInBytesBits; - MCConstantExpr(int64_t Value, bool PrintInHex) - : MCExpr(MCExpr::Constant, SMLoc()), Value(Value), - PrintInHex(PrintInHex) {} + static unsigned encodeSubclassData(bool PrintInHex, unsigned SizeInBytes) { + assert(SizeInBytes <= sizeof(int64_t) && "Excessive size"); + return SizeInBytes | (PrintInHex ? PrintInHexBit : 0); + } MCConstantExpr(int64_t Value, bool PrintInHex, unsigned SizeInBytes) - : MCExpr(MCExpr::Constant, SMLoc()), Value(Value), PrintInHex(PrintInHex), - SizeInBytes(SizeInBytes) {} + : MCExpr(MCExpr::Constant, SMLoc(), + encodeSubclassData(PrintInHex, SizeInBytes)), Value(Value) {} public: /// \name Construction @@ -157,9 +171,11 @@ public: /// @{ 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,17 +331,32 @@ public: }; private: - /// The symbol reference modifier. - const VariantKind Kind; + /// The symbol being referenced. + 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. - const unsigned UseParensForSymbolVariant : 1; + static const unsigned UseParensForSymbolVariantBit = 1 << VariantKindBits; // FIXME: Remove this bit. - const unsigned HasSubsectionsViaSymbols : 1; + 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); + } - /// The symbol being referenced. - const MCSymbol *Symbol; + bool useParensForSymbolVariant() const { + return (getSubclassData() & UseParensForSymbolVariantBit) != 0; + } explicit MCSymbolRefExpr(const MCSymbol *Symbol, VariantKind Kind, const MCAsmInfo *MAI, SMLoc Loc = SMLoc()); @@ -349,11 +380,15 @@ public: const MCSymbol &getSymbol() const { return *Symbol; } - VariantKind getKind() const { return Kind; } + VariantKind getKind() const { + return (VariantKind)(getSubclassData() & VariantKindMask); + } void printVariantKind(raw_ostream &OS) const; - bool hasSubsectionsViaSymbols() const { return HasSubsectionsViaSymbols; } + bool hasSubsectionsViaSymbols() const { + return (getSubclassData() & HasSubsectionsViaSymbolsBit) != 0; + } /// @} /// \name Static Utility Functions @@ -381,11 +416,10 @@ public: }; private: - Opcode Op; const MCExpr *Expr; MCUnaryExpr(Opcode Op, const MCExpr *Expr, SMLoc Loc) - : MCExpr(MCExpr::Unary, Loc), Op(Op), Expr(Expr) {} + : MCExpr(MCExpr::Unary, Loc, Op), Expr(Expr) {} public: /// \name Construction @@ -415,7 +449,7 @@ public: /// @{ /// 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. const MCExpr *getSubExpr() const { return Expr; } @@ -457,12 +491,11 @@ public: }; private: - Opcode Op; const MCExpr *LHS, *RHS; MCBinaryExpr(Opcode Op, const MCExpr *LHS, const MCExpr *RHS, SMLoc Loc = SMLoc()) - : MCExpr(MCExpr::Binary, Loc), Op(Op), LHS(LHS), RHS(RHS) {} + : MCExpr(MCExpr::Binary, Loc, Op), LHS(LHS), RHS(RHS) {} public: /// \name Construction @@ -572,7 +605,7 @@ public: /// @{ /// 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. const MCExpr *getLHS() const { return LHS; } diff --git a/llvm/lib/MC/MCExpr.cpp b/llvm/lib/MC/MCExpr.cpp index 0918802..1448a54 100644 --- a/llvm/lib/MC/MCExpr.cpp +++ b/llvm/lib/MC/MCExpr.cpp @@ -193,9 +193,9 @@ const MCConstantExpr *MCConstantExpr::create(int64_t Value, MCContext &Ctx, MCSymbolRefExpr::MCSymbolRefExpr(const MCSymbol *Symbol, VariantKind Kind, const MCAsmInfo *MAI, SMLoc Loc) - : MCExpr(MCExpr::SymbolRef, Loc), Kind(Kind), - UseParensForSymbolVariant(MAI->useParensForSymbolVariant()), - HasSubsectionsViaSymbols(MAI->hasSubsectionsViaSymbols()), + : MCExpr(MCExpr::SymbolRef, Loc, + encodeSubclassData(Kind, MAI->useParensForSymbolVariant(), + MAI->hasSubsectionsViaSymbols())), Symbol(Symbol) { assert(Symbol); } @@ -464,7 +464,7 @@ MCSymbolRefExpr::getVariantKindForName(StringRef Name) { } void MCSymbolRefExpr::printVariantKind(raw_ostream &OS) const { - if (UseParensForSymbolVariant) + if (useParensForSymbolVariant()) OS << '(' << MCSymbolRefExpr::getVariantKindName(getKind()) << ')'; else OS << '@' << MCSymbolRefExpr::getVariantKindName(getKind()); -- 2.7.4