Make User track whether a class has 'hung off uses' and delete them in its destructor.
authorPete Cooper <peter_cooper@apple.com>
Wed, 10 Jun 2015 22:38:34 +0000 (22:38 +0000)
committerPete Cooper <peter_cooper@apple.com>
Wed, 10 Jun 2015 22:38:34 +0000 (22:38 +0000)
Currently all of the logic for deleting hung off uses, which PHI/switch/etc use,
is in their classes.

This adds a bit to Value which tracks whether that user had hung off uses,
then User can be responsible for clearing them instead of the sub classes.

Note, the bit used here was taken from NumOperands which was 30-bits.
Given the reduction to 29 bits, and the average User being just over 100 bytes,
a single User with 29-bits of num operands would need 50GB of RAM for itself
so its reasonable to assume that 29-bits is enough for now.

This is a step towards hiding all the hung off uses logic in the User.

Reviewed by Duncan Exon Smith.

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

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

index 5c6806c1d0d467a510f6fda579c26cd7cb5e4dde..5e216f0c0cf19f109ef64a6dea932515772d16a4 100644 (file)
@@ -2248,7 +2248,7 @@ protected:
   // allocHungoffUses - this is more complicated than the generic
   // User::allocHungoffUses, because we have to allocate Uses for the incoming
   // values and pointers to the incoming blocks, all in one allocation.
-  Use *allocHungoffUses(unsigned N) const {
+  Use *allocHungoffUses(unsigned N) {
     return User::allocHungoffUses(N, /* IsPhi */ true);
   }
 
index 1dacc3f303e7f2f16dbe24dde1834c39ff2953cf..df6034d0b481546023099ecad32e8f1a901733ab 100644 (file)
@@ -57,7 +57,7 @@ protected:
   /// (with bottom bit set) to the User.
   /// \param IsPhi identifies callers which are phi nodes and which need
   /// N BasicBlock* allocated along with N
-  Use *allocHungoffUses(unsigned N, bool IsPhi = false) const;
+  Use *allocHungoffUses(unsigned N, bool IsPhi = false);
   void dropHungoffUses() {
     Use::zap(OperandList, OperandList + NumOperands, true);
     OperandList = nullptr;
index 19a1d6cd91daafb2eb1016c919fb07709f3dde24..83df4cddd7f2e674a823c18ea3c3c6cca6366aa9 100644 (file)
@@ -100,10 +100,11 @@ protected:
   /// 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 : 30;
+  unsigned NumOperands : 29;
 
   bool IsUsedByMD : 1;
   bool HasName : 1;
+  bool HasHungOffUses : 1;
 
 private:
   template <typename UseT> // UseT == 'Use' or 'const Use'
index 4dae071185f6da7f32c7627ec89013467c92d2bc..e54509460063692e5f5a5ca0b234f1b9a03359e6 100644 (file)
@@ -40,7 +40,7 @@ void User::replaceUsesOfWith(Value *From, Value *To) {
 //                         User allocHungoffUses Implementation
 //===----------------------------------------------------------------------===//
 
-Use *User::allocHungoffUses(unsigned N, bool IsPhi) const {
+Use *User::allocHungoffUses(unsigned N, bool IsPhi) {
   // Allocate the array of Uses, followed by a pointer (with bottom bit set) to
   // the User.
   size_t size = N * sizeof(Use) + sizeof(Use::UserRef);
@@ -49,7 +49,11 @@ Use *User::allocHungoffUses(unsigned N, bool IsPhi) const {
   Use *Begin = static_cast<Use*>(::operator new(size));
   Use *End = Begin + N;
   (void) new(End) Use::UserRef(const_cast<User*>(this), 1);
-  return Use::initTags(Begin, End);
+  Use *Uses = Use::initTags(Begin, End);
+  OperandList = Uses;
+  // Tag this operand list as being a hung off.
+  HasHungOffUses = true;
+  return Uses;
 }
 
 //===----------------------------------------------------------------------===//
@@ -62,6 +66,7 @@ void *User::operator new(size_t s, unsigned Us) {
   Use *End = Start + Us;
   User *Obj = reinterpret_cast<User*>(End);
   Obj->OperandList = Start;
+  Obj->HasHungOffUses = false;
   Obj->NumOperands = Us;
   Use::initTags(Start, End);
   return Obj;