[llvm] 8e7d771 - [MC] Use subclass data for MCExpr to reduce memory usage

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Wed Apr 15 11:02:37 PDT 2020


Author: Nikita Popov
Date: 2020-04-15T20:02:11+02:00
New Revision: 8e7d771cf9b6197c723e1ea8739563d24aca2e3c

URL: https://github.com/llvm/llvm-project/commit/8e7d771cf9b6197c723e1ea8739563d24aca2e3c
DIFF: https://github.com/llvm/llvm-project/commit/8e7d771cf9b6197c723e1ea8739563d24aca2e3c.diff

LOG: [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

Added: 
    

Modified: 
    llvm/include/llvm/MC/MCExpr.h
    llvm/lib/MC/MCExpr.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/MC/MCExpr.h b/llvm/include/llvm/MC/MCExpr.h
index 386fa9c533c1..d1ffef779a52 100644
--- a/llvm/include/llvm/MC/MCExpr.h
+++ b/llvm/include/llvm/MC/MCExpr.h
@@ -34,7 +34,7 @@ using SectionAddrMap = DenseMap<const MCSection *, uint64_t>;
 /// 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 @@ class MCExpr {
   };
 
 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 @@ class MCExpr {
                           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 @@ class MCConstantExpr : public MCExpr {
   /// @{
 
   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 @@ class MCSymbolRefExpr : public MCExpr {
   };
 
 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 @@ class MCSymbolRefExpr : public MCExpr {
 
   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 @@ class MCUnaryExpr : public MCExpr {
   };
 
 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 @@ class MCUnaryExpr : public MCExpr {
   /// @{
 
   /// 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 @@ class MCBinaryExpr : public MCExpr {
   };
 
 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 @@ class MCBinaryExpr : public MCExpr {
   /// @{
 
   /// 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 091880250ec5..1448a54a04e3 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());


        


More information about the llvm-commits mailing list