IR: Move NumOperands from User to Value, NFC
authorDuncan P. N. Exon Smith <dexonsmith@apple.com>
Wed, 15 Oct 2014 20:39:05 +0000 (20:39 +0000)
committerDuncan P. N. Exon Smith <dexonsmith@apple.com>
Wed, 15 Oct 2014 20:39:05 +0000 (20:39 +0000)
Store `User::NumOperands` (and `MDNode::NumOperands`) in `Value`.

On 64-bit host architectures, this reduces `sizeof(User)` and all
subclasses by 8, and has no effect on `sizeof(Value)` (or, incidentally,
on `sizeof(MDNode)`).

On 32-bit host architectures, this increases `sizeof(Value)` by 4.
However, it has no effect on `sizeof(User)` and `sizeof(MDNode)`, so the
only concrete subclasses of `Value` that actually see the increase are
`BasicBlock`, `Argument`, `InlineAsm`, and `MDString`.  Moreover, I'll
be shocked and confused if this causes a tangible memory regression.

This has no functionality change (other than memory footprint).

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@219845 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/IR/Metadata.h
include/llvm/IR/User.h
include/llvm/IR/Value.h
lib/IR/Value.cpp

index 8b33d7022c7f2d88f6292f49979494613e4668b4..be0f54974fdee3c31bc9cd3234af15709e92bbc0 100644 (file)
@@ -126,9 +126,6 @@ class MDNode : public Value, public FoldingSetNode {
   /// \brief If the MDNode is uniqued cache the hash to speed up lookup.
   unsigned Hash;
 
-  /// \brief Number of co-allocated 'MDNodeOperand' items.
-  unsigned NumOperands;
-
   /// \brief Subclass data enums.
   enum {
     /// FunctionLocalBit - This bit is set if this MDNode is function local.
index fb5abe0c0e4d2f8c5992ede1d4e81509ca913869..f578227d6cae9b56c8285efff2413e89e3657113 100644 (file)
@@ -39,9 +39,6 @@ class User : public Value {
   friend struct HungoffOperandTraits;
   virtual void anchor();
 protected:
-  /// \brief The number of values used by this User.
-  unsigned NumOperands;
-
   /// \brief This is a pointer to the array of Uses for this User.
   ///
   /// For nodes of fixed arity (e.g. a binary operator) this array will live
@@ -52,7 +49,9 @@ protected:
 
   void *operator new(size_t s, unsigned Us);
   User(Type *ty, unsigned vty, Use *OpList, unsigned NumOps)
-    : Value(ty, vty), NumOperands(NumOps), OperandList(OpList) {}
+      : Value(ty, vty), OperandList(OpList) {
+    NumOperands = NumOps;
+  }
   Use *allocHungoffUses(unsigned) const;
   void dropHungoffUses() {
     Use::zap(OperandList, OperandList + NumOperands, true);
index 02630d8c6664ae405511e8ef85328a6658815e6c..efe0cca7bb45fa237ccaf66fb1190194a417e570 100644 (file)
@@ -92,6 +92,19 @@ private:
   /// field is initialized to zero by the ctor.
   unsigned short SubclassData;
 
+protected:
+  /// \brief The number of operands in the subclass.
+  ///
+  /// This member is defined by this class, but not used for anything.
+  /// Subclasses can use it to store their number of operands, if they have
+  /// any.
+  ///
+  /// This is stored here to save space in User on 64-bit hosts.  Since most
+  /// instances of Value have operands, 32-bit hosts aren't significantly
+  /// affected.
+  unsigned NumOperands;
+
+private:
   template <typename UseT> // UseT == 'Use' or 'const Use'
   class use_iterator_impl
       : public std::iterator<std::forward_iterator_tag, UseT *, ptrdiff_t> {
index b5af72b858ea9df48bed461d3890ae2b26723c28..862f08c896627c8c61f6c05b352ecfd25976e4b8 100644 (file)
@@ -45,7 +45,8 @@ static inline Type *checkType(Type *Ty) {
 
 Value::Value(Type *ty, unsigned scid)
     : VTy(checkType(ty)), UseList(nullptr), Name(nullptr), SubclassID(scid),
-      HasValueHandle(0), SubclassOptionalData(0), SubclassData(0) {
+      HasValueHandle(0), SubclassOptionalData(0), SubclassData(0),
+      NumOperands(0) {
   // FIXME: Why isn't this in the subclass gunk??
   // Note, we cannot call isa<CallInst> before the CallInst has been
   // constructed.