]> granicus.if.org Git - llvm/commitdiff
[IR] De-virtualize ~Value to save a vptr
authorReid Kleckner <rnk@google.com>
Thu, 18 May 2017 17:24:10 +0000 (17:24 +0000)
committerReid Kleckner <rnk@google.com>
Thu, 18 May 2017 17:24:10 +0000 (17:24 +0000)
Summary:
Implements PR889

Removing the virtual table pointer from Value saves 1% of RSS when doing
LTO of llc on Linux. The impact on time was positive, but too noisy to
conclusively say that performance improved. Here is a link to the
spreadsheet with the original data:

https://docs.google.com/spreadsheets/d/1F4FHir0qYnV0MEp2sYYp_BuvnJgWlWPhWOwZ6LbW7W4/edit?usp=sharing

This change makes it invalid to directly delete a Value, User, or
Instruction pointer. Instead, such code can be rewritten to a null check
and a call Value::deleteValue(). Value objects tend to have their
lifetimes managed through iplist, so for the most part, this isn't a big
deal.  However, there are some places where LLVM deletes values, and
those places had to be migrated to deleteValue.  I have also created
llvm::unique_value, which has a custom deleter, so it can be used in
place of std::unique_ptr<Value>.

I had to add the "DerivedUser" Deleter escape hatch for MemorySSA, which
derives from User outside of lib/IR. Code in IR cannot include MemorySSA
headers or call the MemoryAccess object destructors without introducing
a circular dependency, so we need some level of indirection.
Unfortunately, no class derived from User may have any virtual methods,
because adding a virtual method would break User::getHungOffOperands(),
which assumes that it can find the use list immediately prior to the
User object. I've added a static_assert to the appropriate OperandTraits
templates to help people avoid this trap.

Reviewers: chandlerc, mehdi_amini, pete, dberlin, george.burgess.iv

Reviewed By: chandlerc

Subscribers: krytarowski, eraman, george.burgess.iv, mzolotukhin, Prazek, nlewycky, hans, inglorion, pcc, tejohnson, dberlin, llvm-commits

Differential Revision: https://reviews.llvm.org/D31261

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

48 files changed:
include/llvm/Analysis/MemorySSA.h
include/llvm/IR/Argument.h
include/llvm/IR/BasicBlock.h
include/llvm/IR/Constant.h
include/llvm/IR/Constants.h
include/llvm/IR/DerivedUser.h [new file with mode: 0644]
include/llvm/IR/Function.h
include/llvm/IR/GlobalValue.h
include/llvm/IR/GlobalVariable.h
include/llvm/IR/InlineAsm.h
include/llvm/IR/InstrTypes.h
include/llvm/IR/Instruction.def
include/llvm/IR/Instruction.h
include/llvm/IR/Instructions.h
include/llvm/IR/Metadata.h
include/llvm/IR/OperandTraits.h
include/llvm/IR/Operator.h
include/llvm/IR/User.h
include/llvm/IR/Value.def
include/llvm/IR/Value.h
lib/Analysis/MemorySSA.cpp
lib/AsmParser/LLParser.cpp
lib/Bitcode/Reader/BitcodeReader.cpp
lib/Bitcode/Reader/ValueList.cpp
lib/CodeGen/CodeGenPrepare.cpp
lib/IR/Constants.cpp
lib/IR/ConstantsContext.h
lib/IR/Function.cpp
lib/IR/InlineAsm.cpp
lib/IR/Instruction.cpp
lib/IR/Instructions.cpp
lib/IR/LLVMContextImpl.cpp
lib/IR/User.cpp
lib/IR/Value.cpp
lib/Target/Hexagon/HexagonLoopIdiomRecognition.cpp
lib/Transforms/Scalar/GVN.cpp
lib/Transforms/Scalar/JumpThreading.cpp
lib/Transforms/Scalar/LoopRotation.cpp
lib/Transforms/Scalar/Reassociate.cpp
lib/Transforms/Scalar/SROA.cpp
lib/Transforms/Scalar/StraightLineStrengthReduce.cpp
lib/Transforms/Utils/CloneFunction.cpp
lib/Transforms/Utils/SimplifyCFG.cpp
lib/Transforms/Vectorize/SLPVectorizer.cpp
unittests/IR/ConstantsTest.cpp
unittests/IR/InstructionsTest.cpp
unittests/IR/MetadataTest.cpp
unittests/Transforms/Utils/Cloning.cpp

index db31ae9f4f109196e70da6cf6556c0aa1bb8ac96..f0bba8c4c0209d39e5e2bf3e3c21946767c286a4 100644 (file)
@@ -84,6 +84,7 @@
 #include "llvm/Analysis/MemoryLocation.h"
 #include "llvm/Analysis/PHITransAddr.h"
 #include "llvm/IR/BasicBlock.h"
+#include "llvm/IR/DerivedUser.h"
 #include "llvm/IR/Dominators.h"
 #include "llvm/IR/Module.h"
 #include "llvm/IR/OperandTraits.h"
@@ -127,7 +128,7 @@ using const_memoryaccess_def_iterator =
 // \brief The base for all memory accesses. All memory accesses in a block are
 // linked together using an intrusive list.
 class MemoryAccess
-    : public User,
+    : public DerivedUser,
       public ilist_node<MemoryAccess, ilist_tag<MSSAHelpers::AllAccessTag>>,
       public ilist_node<MemoryAccess, ilist_tag<MSSAHelpers::DefsOnlyTag>> {
 public:
@@ -145,15 +146,14 @@ public:
 
   MemoryAccess(const MemoryAccess &) = delete;
   MemoryAccess &operator=(const MemoryAccess &) = delete;
-  ~MemoryAccess() override;
 
   void *operator new(size_t, unsigned) = delete;
   void *operator new(size_t) = delete;
 
   BasicBlock *getBlock() const { return Block; }
 
-  virtual void print(raw_ostream &OS) const = 0;
-  virtual void dump() const;
+  void print(raw_ostream &OS) const;
+  void dump() const;
 
   /// \brief The user iterators for a memory access
   typedef user_iterator iterator;
@@ -207,11 +207,12 @@ protected:
 
   /// \brief Used for debugging and tracking things about MemoryAccesses.
   /// Guaranteed unique among MemoryAccesses, no guarantees otherwise.
-  virtual unsigned getID() const = 0;
+  inline unsigned getID() const;
 
-  MemoryAccess(LLVMContext &C, unsigned Vty, BasicBlock *BB,
-               unsigned NumOperands)
-      : User(Type::getVoidTy(C), Vty, nullptr, NumOperands), Block(BB) {}
+  MemoryAccess(LLVMContext &C, unsigned Vty, DeleteValueTy DeleteValue,
+               BasicBlock *BB, unsigned NumOperands)
+      : DerivedUser(Type::getVoidTy(C), Vty, nullptr, NumOperands, DeleteValue),
+        Block(BB) {}
 
 private:
   BasicBlock *Block;
@@ -248,21 +249,21 @@ public:
 
   // Sadly, these have to be public because they are needed in some of the
   // iterators.
-  virtual bool isOptimized() const = 0;
-  virtual MemoryAccess *getOptimized() const = 0;
-  virtual void setOptimized(MemoryAccess *) = 0;
+  inline bool isOptimized() const;
+  inline MemoryAccess *getOptimized() const;
+  inline void setOptimized(MemoryAccess *);
 
   /// \brief Reset the ID of what this MemoryUse was optimized to, causing it to
   /// be rewalked by the walker if necessary.
   /// This really should only be called by tests.
-  virtual void resetOptimized() = 0;
+  inline void resetOptimized();
 
 protected:
   friend class MemorySSA;
   friend class MemorySSAUpdater;
   MemoryUseOrDef(LLVMContext &C, MemoryAccess *DMA, unsigned Vty,
-                 Instruction *MI, BasicBlock *BB)
-      : MemoryAccess(C, Vty, BB, 1), MemoryInst(MI) {
+                 DeleteValueTy DeleteValue, Instruction *MI, BasicBlock *BB)
+      : MemoryAccess(C, Vty, DeleteValue, BB, 1), MemoryInst(MI) {
     setDefiningAccess(DMA);
   }
   void setDefiningAccess(MemoryAccess *DMA, bool Optimized = false) {
@@ -292,7 +293,8 @@ public:
   DECLARE_TRANSPARENT_OPERAND_ACCESSORS(MemoryAccess);
 
   MemoryUse(LLVMContext &C, MemoryAccess *DMA, Instruction *MI, BasicBlock *BB)
-      : MemoryUseOrDef(C, DMA, MemoryUseVal, MI, BB), OptimizedID(0) {}
+      : MemoryUseOrDef(C, DMA, MemoryUseVal, deleteMe, MI, BB),
+        OptimizedID(0) {}
 
   // allocate space for exactly one operand
   void *operator new(size_t s) { return User::operator new(s, 1); }
@@ -302,32 +304,30 @@ public:
     return MA->getValueID() == MemoryUseVal;
   }
 
-  void print(raw_ostream &OS) const override;
+  void print(raw_ostream &OS) const;
 
-  virtual void setOptimized(MemoryAccess *DMA) override {
+  void setOptimized(MemoryAccess *DMA) {
     OptimizedID = DMA->getID();
     setOperand(0, DMA);
   }
 
-  virtual bool isOptimized() const override {
+  bool isOptimized() const {
     return getDefiningAccess() && OptimizedID == getDefiningAccess()->getID();
   }
 
-  virtual MemoryAccess *getOptimized() const override {
+  MemoryAccess *getOptimized() const {
     return getDefiningAccess();
   }
-  virtual void resetOptimized() override {
+  void resetOptimized() {
     OptimizedID = INVALID_MEMORYACCESS_ID;
   }
 
 protected:
   friend class MemorySSA;
 
-  unsigned getID() const override {
-    llvm_unreachable("MemoryUses do not have IDs");
-  }
-
 private:
+  static void deleteMe(DerivedUser *Self);
+
   unsigned int OptimizedID;
 };
 
@@ -350,8 +350,8 @@ public:
 
   MemoryDef(LLVMContext &C, MemoryAccess *DMA, Instruction *MI, BasicBlock *BB,
             unsigned Ver)
-      : MemoryUseOrDef(C, DMA, MemoryDefVal, MI, BB), ID(Ver),
-        Optimized(nullptr), OptimizedID(INVALID_MEMORYACCESS_ID) {}
+      : MemoryUseOrDef(C, DMA, MemoryDefVal, deleteMe, MI, BB),
+        ID(Ver), Optimized(nullptr), OptimizedID(INVALID_MEMORYACCESS_ID) {}
 
   // allocate space for exactly one operand
   void *operator new(size_t s) { return User::operator new(s, 1); }
@@ -361,27 +361,28 @@ public:
     return MA->getValueID() == MemoryDefVal;
   }
 
-  virtual void setOptimized(MemoryAccess *MA) override {
+  void setOptimized(MemoryAccess *MA) {
     Optimized = MA;
     OptimizedID = getDefiningAccess()->getID();
   }
-  virtual MemoryAccess *getOptimized() const override { return Optimized; }
-  virtual bool isOptimized() const override {
+  MemoryAccess *getOptimized() const { return Optimized; }
+  bool isOptimized() const {
     return getOptimized() && getDefiningAccess() &&
            OptimizedID == getDefiningAccess()->getID();
   }
-  virtual void resetOptimized() override {
+  void resetOptimized() {
     OptimizedID = INVALID_MEMORYACCESS_ID;
   }
 
-  void print(raw_ostream &OS) const override;
+  void print(raw_ostream &OS) const;
 
-protected:
   friend class MemorySSA;
 
-  unsigned getID() const override { return ID; }
+  unsigned getID() const { return ID; }
 
 private:
+  static void deleteMe(DerivedUser *Self);
+
   const unsigned ID;
   MemoryAccess *Optimized;
   unsigned int OptimizedID;
@@ -432,7 +433,8 @@ public:
   DECLARE_TRANSPARENT_OPERAND_ACCESSORS(MemoryAccess);
 
   MemoryPhi(LLVMContext &C, BasicBlock *BB, unsigned Ver, unsigned NumPreds = 0)
-      : MemoryAccess(C, MemoryPhiVal, BB, 0), ID(Ver), ReservedSpace(NumPreds) {
+      : MemoryAccess(C, MemoryPhiVal, deleteMe, BB, 0), ID(Ver),
+        ReservedSpace(NumPreds) {
     allocHungoffUses(ReservedSpace);
   }
 
@@ -534,7 +536,9 @@ public:
     return V->getValueID() == MemoryPhiVal;
   }
 
-  void print(raw_ostream &OS) const override;
+  void print(raw_ostream &OS) const;
+
+  unsigned getID() const { return ID; }
 
 protected:
   friend class MemorySSA;
@@ -546,8 +550,6 @@ protected:
     User::allocHungoffUses(N, /* IsPhi */ true);
   }
 
-  unsigned getID() const final { return ID; }
-
 private:
   // For debugging only
   const unsigned ID;
@@ -561,8 +563,45 @@ private:
     ReservedSpace = std::max(E + E / 2, 2u);
     growHungoffUses(ReservedSpace, /* IsPhi */ true);
   }
+
+  static void deleteMe(DerivedUser *Self);
 };
 
+inline unsigned MemoryAccess::getID() const {
+  assert((isa<MemoryDef>(this) || isa<MemoryPhi>(this)) &&
+         "only memory defs and phis have ids");
+  if (const auto *MD = dyn_cast<MemoryDef>(this))
+    return MD->getID();
+  return cast<MemoryPhi>(this)->getID();
+}
+
+inline bool MemoryUseOrDef::isOptimized() const {
+  if (const auto *MD = dyn_cast<MemoryDef>(this))
+    return MD->isOptimized();
+  return cast<MemoryUse>(this)->isOptimized();
+}
+
+inline MemoryAccess *MemoryUseOrDef::getOptimized() const {
+  if (const auto *MD = dyn_cast<MemoryDef>(this))
+    return MD->getOptimized();
+  return cast<MemoryUse>(this)->getOptimized();
+}
+
+inline void MemoryUseOrDef::setOptimized(MemoryAccess *MA) {
+  if (auto *MD = dyn_cast<MemoryDef>(this))
+    MD->setOptimized(MA);
+  else
+    cast<MemoryUse>(this)->setOptimized(MA);
+}
+
+inline void MemoryUseOrDef::resetOptimized() {
+  if (auto *MD = dyn_cast<MemoryDef>(this))
+    MD->resetOptimized();
+  else
+    cast<MemoryUse>(this)->resetOptimized();
+}
+
+
 template <> struct OperandTraits<MemoryPhi> : public HungoffOperandTraits<2> {};
 DEFINE_TRANSPARENT_OPERAND_ACCESSORS(MemoryPhi, MemoryAccess)
 
index 5ed6d030c98438bc6c71ce0e334dd4a7074bc0e6..3efcc637b6edab75536409f2a55524606993c4a8 100644 (file)
@@ -27,8 +27,7 @@ namespace llvm {
 /// for a specific function. When used in the body of said function, the
 /// argument of course represents the value of the actual argument that the
 /// function was called with.
-class Argument : public Value {
-  virtual void anchor();
+class Argument final : public Value {
   Function *Parent;
   unsigned ArgNo;
 
index 97989cf5c65259dd4c028f9094b1c9bf061194a8..c917b1f2cada1616ee0ca93eaa9bdb49634b1dc8 100644 (file)
@@ -51,8 +51,8 @@ class ValueSymbolTable;
 /// occur because it may be useful in the intermediate stage of constructing or
 /// modifying a program. However, the verifier will ensure that basic blocks
 /// are "well formed".
-class BasicBlock : public Value, // Basic blocks are data objects also
-                   public ilist_node_with_parent<BasicBlock, Function> {
+class BasicBlock final : public Value, // Basic blocks are data objects also
+                         public ilist_node_with_parent<BasicBlock, Function> {
 public:
   using InstListType = SymbolTableList<Instruction>;
 
@@ -77,7 +77,7 @@ private:
 public:
   BasicBlock(const BasicBlock &) = delete;
   BasicBlock &operator=(const BasicBlock &) = delete;
-  ~BasicBlock() override;
+  ~BasicBlock();
 
   /// \brief Get the context in which this basic block lives.
   LLVMContext &getContext() const;
index 3b3694e7e60d0c2ba96f5b203c77abf5de1d88a7..82afd9a2691f5a0a197c7ecb174a70dd70d48d02 100644 (file)
@@ -40,8 +40,6 @@ class APInt;
 /// don't have to worry about the lifetime of the objects.
 /// @brief LLVM Constant Representation
 class Constant : public User {
-  void anchor() override;
-
 protected:
   Constant(Type *ty, ValueTy vty, Use *Ops, unsigned NumOps)
     : User(ty, vty, Ops, NumOps) {}
index 5db9b3bb50483bfc80f1ada44f94adbe7ae2d3fc..fad27cf8892362c9cb7e85fc1ee5f8f0534c8315 100644 (file)
@@ -58,8 +58,6 @@ template <class ConstantClass> struct ConstantAggrKeyType;
 class ConstantData : public Constant {
   friend class Constant;
 
-  void anchor() override;
-
   Value *handleOperandChangeImpl(Value *From, Value *To) {
     llvm_unreachable("Constant data does not have operands!");
   }
@@ -93,7 +91,6 @@ class ConstantInt final : public ConstantData {
 
   ConstantInt(IntegerType *Ty, const APInt& V);
 
-  void anchor() override;
   void destroyConstantImpl();
 
 public:
@@ -274,7 +271,6 @@ class ConstantFP final : public ConstantData {
 
   ConstantFP(Type *Ty, const APFloat& V);
 
-  void anchor() override;
   void destroyConstantImpl();
 
 public:
@@ -588,7 +584,7 @@ class ConstantDataSequential : public ConstantData {
 protected:
   explicit ConstantDataSequential(Type *ty, ValueTy VT, const char *Data)
       : ConstantData(ty, VT), DataElements(Data), Next(nullptr) {}
-  ~ConstantDataSequential() override { delete Next; }
+  ~ConstantDataSequential() { delete Next; }
 
   static Constant *getImpl(StringRef Bytes, Type *Ty);
 
@@ -692,8 +688,6 @@ class ConstantDataArray final : public ConstantDataSequential {
     return User::operator new(s, 0);
   }
 
-  void anchor() override;
-
 public:
   ConstantDataArray(const ConstantDataArray &) = delete;
 
@@ -755,8 +749,6 @@ class ConstantDataVector final : public ConstantDataSequential {
     return User::operator new(s, 0);
   }
 
-  void anchor() override;
-
 public:
   ConstantDataVector(const ConstantDataVector &) = delete;
 
diff --git a/include/llvm/IR/DerivedUser.h b/include/llvm/IR/DerivedUser.h
new file mode 100644 (file)
index 0000000..4d681e0
--- /dev/null
@@ -0,0 +1,41 @@
+//===-- DerivedUser.h - Base for non-IR Users -------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_IR_DERIVEDUSER_H
+#define LLVM_IR_DERIVEDUSER_H
+
+#include "llvm/IR/User.h"
+
+namespace llvm {
+
+/// Extension point for the Value hierarchy. All classes outside of lib/IR
+/// that wish to inherit from User should instead inherit from DerivedUser
+/// instead. Inheriting from this class is discouraged.
+///
+/// Generally speaking, Value is the base of a closed class hierarchy
+/// that can't be extended by code outside of lib/IR. This class creates a
+/// loophole that allows classes outside of lib/IR to extend User to leverage
+/// its use/def list machinery.
+class DerivedUser : public User {
+protected:
+  typedef void (*DeleteValueTy)(DerivedUser *);
+
+private:
+  friend Value;
+  DeleteValueTy DeleteValue;
+
+public:
+  DerivedUser(Type *Ty, unsigned VK, Use *U, unsigned NumOps,
+              DeleteValueTy DeleteValue)
+      : User(Ty, VK, U, NumOps), DeleteValue(DeleteValue) {}
+};
+
+} // namespace llvm
+
+#endif // LLVM_IR_DERIVEDUSER_H
index 8a2a6ed87eb287e1fabde7dd89d8407d1ce231e2..f27e5c50a47f239e34a9bbfbbf181fb813d69edd 100644 (file)
@@ -123,7 +123,7 @@ private:
 public:
   Function(const Function&) = delete;
   void operator=(const Function&) = delete;
-  ~Function() override;
+  ~Function();
 
   static Function *Create(FunctionType *Ty, LinkageTypes Linkage,
                           const Twine &N = "", Module *M = nullptr) {
index 0793a1c0ee2edb0be9b9e4396e890b4199bd4948..20495725f9d0fbef1ac32c9d81647b5a769171cc 100644 (file)
@@ -161,6 +161,10 @@ protected:
     Parent = parent;
   }
 
+  ~GlobalValue() {
+    removeDeadConstantUsers();   // remove any dead constants using this.
+  }
+
 public:
   enum ThreadLocalMode {
     NotThreadLocal = 0,
@@ -172,10 +176,6 @@ public:
 
   GlobalValue(const GlobalValue &) = delete;
 
-  ~GlobalValue() override {
-    removeDeadConstantUsers();   // remove any dead constants using this.
-  }
-
   unsigned getAlignment() const;
 
   enum class UnnamedAddr {
index 21d334c8f01db2eb98cf40d7a02731e447505964..3f5d00bd3b3aca33111afbc726c4ff0bf455c34a 100644 (file)
@@ -66,7 +66,7 @@ public:
   GlobalVariable(const GlobalVariable &) = delete;
   GlobalVariable &operator=(const GlobalVariable &) = delete;
 
-  ~GlobalVariable() override {
+  ~GlobalVariable() {
     dropAllReferences();
 
     // FIXME: needed by operator delete
index a57e7d63012b35b5bce0e433b812caccb1e03a45..7f03fcd19b650df29611f86850812c17b8b442f3 100644 (file)
@@ -28,7 +28,7 @@ class FunctionType;
 class PointerType;
 template <class ConstantClass> class ConstantUniqueMap;
 
-class InlineAsm : public Value {
+class InlineAsm final : public Value {
 public:
   enum AsmDialect {
     AD_ATT,
@@ -48,7 +48,6 @@ private:
   InlineAsm(FunctionType *Ty, const std::string &AsmString,
             const std::string &Constraints, bool hasSideEffects,
             bool isAlignStack, AsmDialect asmDialect);
-  ~InlineAsm() override;
 
   /// When the ConstantUniqueMap merges two types and makes two InlineAsms
   /// identical, it destroys one of them with this method.
index 61ca90de7393cea68de3a745f65399040284beb1..e850c015d7118555c3faaf6f6b0152c4b6e323d5 100644 (file)
@@ -62,9 +62,6 @@ protected:
                  Use *Ops, unsigned NumOps, BasicBlock *InsertAtEnd)
     : Instruction(Ty, iType, Ops, NumOps, InsertAtEnd) {}
 
-  // Out of line virtual method, so the vtable, etc has a home.
-  ~TerminatorInst() override;
-
 public:
   /// Return the number of successors that this terminator has.
   unsigned getNumSuccessors() const;
@@ -299,9 +296,6 @@ public:
 
   void *operator new(size_t, unsigned) = delete;
 
-  // Out of line virtual method, so the vtable, etc has a home.
-  ~UnaryInstruction() override;
-
   /// Transparently provide more efficient getOperand methods.
   DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
 
@@ -568,8 +562,6 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(BinaryOperator, Value)
 /// if (isa<CastInst>(Instr)) { ... }
 /// @brief Base class of casting instructions.
 class CastInst : public UnaryInstruction {
-  void anchor() override;
-
 protected:
   /// @brief Constructor with insert-before-instruction semantics for subclasses
   CastInst(Type *Ty, unsigned iType, Value *S,
@@ -914,8 +906,6 @@ protected:
           Value *LHS, Value *RHS, const Twine &Name,
           BasicBlock *InsertAtEnd);
 
-  void anchor() override; // Out of line virtual method.
-
 public:
   CmpInst() = delete;
 
index 18711abb8060d6f2a90486dd35d46fc826883f83..86617299c44ac6a2713a4fc8a4be7e325eace047 100644 (file)
 #define LAST_OTHER_INST(num)
 #endif
 
+#ifndef HANDLE_USER_INST
+#define HANDLE_USER_INST(num, opc, Class) HANDLE_OTHER_INST(num, opc, Class)
+#endif
+
 // Terminator Instructions - These instructions are used to terminate a basic
 // block of the program.   Every basic block must end with one of these
 // instructions for it to be a well formed basic block.
@@ -185,8 +189,8 @@ HANDLE_OTHER_INST(52, FCmp   , FCmpInst   )  // Floating point comparison instr.
 HANDLE_OTHER_INST(53, PHI    , PHINode    )  // PHI node instruction
 HANDLE_OTHER_INST(54, Call   , CallInst   )  // Call a function
 HANDLE_OTHER_INST(55, Select , SelectInst )  // select instruction
-HANDLE_OTHER_INST(56, UserOp1, Instruction)  // May be used internally in a pass
-HANDLE_OTHER_INST(57, UserOp2, Instruction)  // Internal to passes only
+HANDLE_USER_INST (56, UserOp1, Instruction)  // May be used internally in a pass
+HANDLE_USER_INST (57, UserOp2, Instruction)  // Internal to passes only
 HANDLE_OTHER_INST(58, VAArg  , VAArgInst  )  // vaarg instruction
 HANDLE_OTHER_INST(59, ExtractElement, ExtractElementInst)// extract from vector
 HANDLE_OTHER_INST(60, InsertElement, InsertElementInst)  // insert into vector
@@ -220,6 +224,8 @@ HANDLE_OTHER_INST(64, LandingPad, LandingPadInst)  // Landing pad instruction.
 #undef HANDLE_OTHER_INST
 #undef   LAST_OTHER_INST
 
+#undef HANDLE_USER_INST
+
 #ifdef HANDLE_INST
 #undef HANDLE_INST
 #endif
index fca29900f4c298cfeb93c7d22301a55627c6a25f..6e109735ddd3678cf19e449082598b86aa58e215 100644 (file)
@@ -36,6 +36,10 @@ class FastMathFlags;
 class MDNode;
 struct AAMDNodes;
 
+template <> struct ilist_alloc_traits<Instruction> {
+  static inline void deleteNode(Instruction *V);
+};
+
 class Instruction : public User,
                     public ilist_node_with_parent<Instruction, BasicBlock> {
   BasicBlock *Parent;
@@ -47,13 +51,13 @@ class Instruction : public User,
     HasMetadataBit = 1 << 15
   };
 
+protected:
+  ~Instruction(); // Use deleteValue() to delete a generic Instruction.
+
 public:
   Instruction(const Instruction &) = delete;
   Instruction &operator=(const Instruction &) = delete;
 
-  // Out of line virtual method, so the vtable, etc has a home.
-  ~Instruction() override;
-
   /// Specialize the methods defined in Value, as we know that an instruction
   /// can only be used by other instructions.
   Instruction       *user_back()       { return cast<Instruction>(*user_begin());}
@@ -640,6 +644,10 @@ private:
   Instruction *cloneImpl() const;
 };
 
+inline void ilist_alloc_traits<Instruction>::deleteNode(Instruction *V) {
+  V->deleteValue();
+}
+
 } // end namespace llvm
 
 #endif // LLVM_IR_INSTRUCTION_H
index c26701af27ce423f1f5a610bed122d7f9432c4c9..6fab59613dd6d170778fa23686a0b82a52848e0f 100644 (file)
@@ -89,9 +89,6 @@ public:
   AllocaInst(Type *Ty, unsigned AddrSpace, Value *ArraySize, unsigned Align,
              const Twine &Name, BasicBlock *InsertAtEnd);
 
-  // Out of line virtual method, so the vtable, etc. has a home.
-  ~AllocaInst() override;
-
   /// Return true if there is an allocation size parameter to the allocation
   /// instruction that is not 1.
   bool isArrayAllocation() const;
@@ -856,7 +853,6 @@ class GetElementPtrInst : public Instruction {
                            ArrayRef<Value *> IdxList, unsigned Values,
                            const Twine &NameStr, BasicBlock *InsertAtEnd);
 
-  void anchor() override;
   void init(Value *Ptr, ArrayRef<Value *> IdxList, const Twine &NameStr);
 
 protected:
@@ -1112,8 +1108,6 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(GetElementPtrInst, Value)
 /// must be identical types.
 /// Represent an integer comparison operator.
 class ICmpInst: public CmpInst {
-  void anchor() override;
-
   void AssertOK() {
     assert(getPredicate() >= CmpInst::FIRST_ICMP_PREDICATE &&
            getPredicate() <= CmpInst::LAST_ICMP_PREDICATE &&
@@ -1426,8 +1420,6 @@ protected:
   CallInst *cloneImpl() const;
 
 public:
-  ~CallInst() override;
-
   static CallInst *Create(Value *Func, ArrayRef<Value *> Args,
                           ArrayRef<OperandBundleDef> Bundles = None,
                           const Twine &NameStr = "",
@@ -2592,8 +2584,6 @@ class PHINode : public Instruction {
     return User::operator new(s);
   }
 
-  void anchor() override;
-
 protected:
   // Note: Instruction needs to be a friend here to call cloneImpl.
   friend class Instruction;
@@ -2927,8 +2917,6 @@ protected:
   ReturnInst *cloneImpl() const;
 
 public:
-  ~ReturnInst() override;
-
   static ReturnInst* Create(LLVMContext &C, Value *retVal = nullptr,
                             Instruction *InsertBefore = nullptr) {
     return new(!!retVal) ReturnInst(C, retVal, InsertBefore);
index 8f24a6a1d69d842699a238269c0c345938666152..92f701e01ff3844029352d4a7cb9738f3f857e5a 100644 (file)
@@ -174,12 +174,13 @@ class MetadataAsValue : public Value {
   Metadata *MD;
 
   MetadataAsValue(Type *Ty, Metadata *MD);
-  ~MetadataAsValue() override;
 
   /// \brief Drop use of metadata (during teardown).
   void dropUse() { MD = nullptr; }
 
 public:
+  ~MetadataAsValue();
+
   static MetadataAsValue *get(LLVMContext &Context, Metadata *MD);
   static MetadataAsValue *getIfExists(LLVMContext &Context, Metadata *MD);
   Metadata *getMetadata() const { return MD; }
index e97a8009ccc03cb406298c79c98927b49484f0bd..7b94283856b6d6bc3937a6bcb53a7333cc2b3e35 100644 (file)
@@ -30,6 +30,9 @@ namespace llvm {
 template <typename SubClass, unsigned ARITY>
 struct FixedNumOperandTraits {
   static Use *op_begin(SubClass* U) {
+    static_assert(
+        !std::is_polymorphic<SubClass>::value,
+        "adding virtual methods to subclasses of User breaks use lists");
     return reinterpret_cast<Use*>(U) - ARITY;
   }
   static Use *op_end(SubClass* U) {
@@ -65,6 +68,9 @@ struct OptionalOperandTraits : public FixedNumOperandTraits<SubClass, ARITY> {
 template <typename SubClass, unsigned MINARITY = 0>
 struct VariadicOperandTraits {
   static Use *op_begin(SubClass* U) {
+    static_assert(
+        !std::is_polymorphic<SubClass>::value,
+        "adding virtual methods to subclasses of User breaks use lists");
     return reinterpret_cast<Use*>(U) - static_cast<User*>(U)->getNumOperands();
   }
   static Use *op_end(SubClass* U) {
index 997a85340c2591e43df0dfe58f0a947c809bb77b..49fa6a6a877aa42537223c20cf369d78853d726c 100644 (file)
@@ -29,16 +29,11 @@ namespace llvm {
 /// This is a utility class that provides an abstraction for the common
 /// functionality between Instructions and ConstantExprs.
 class Operator : public User {
-protected:
-  // NOTE: Cannot use = delete because it's not legal to delete
-  // an overridden method that's not deleted in the base class. Cannot leave
-  // this unimplemented because that leads to an ODR-violation.
-  ~Operator() override;
-
 public:
   // The Operator class is intended to be used as a utility, and is never itself
   // instantiated.
   Operator() = delete;
+  ~Operator() = delete;
 
   void *operator new(size_t, unsigned) = delete;
   void *operator new(size_t s) = delete;
index 7b9d451aaf5374f7507ae049fd8bc06dc89f9430..109a3d5e7be8d02d31dd38f14cbefb0f721b49fd 100644 (file)
@@ -46,8 +46,6 @@ class User : public Value {
   template <unsigned>
   friend struct HungoffOperandTraits;
 
-  virtual void anchor();
-
   LLVM_ATTRIBUTE_ALWAYS_INLINE inline static void *
   allocateFixedOperandUser(size_t, unsigned, unsigned);
 
@@ -93,9 +91,11 @@ protected:
   /// should be called if there are no uses.
   void growHungoffUses(unsigned N, bool IsPhi = false);
 
+protected:
+  ~User() = default; // Use deleteValue() to delete a generic Instruction.
+
 public:
   User(const User &) = delete;
-  ~User() override = default;
 
   /// \brief Free memory allocated for User and Use objects.
   void operator delete(void *Usr);
index 48842d7f9cd56421c31f6685e2f95003ecce4436..cebd7f7297ef3b9b40080d17eb117c31c47c4754 100644 (file)
 #if !(defined HANDLE_GLOBAL_VALUE || defined HANDLE_CONSTANT ||                \
       defined HANDLE_INSTRUCTION || defined HANDLE_INLINE_ASM_VALUE ||         \
       defined HANDLE_METADATA_VALUE || defined HANDLE_VALUE ||                 \
-      defined HANDLE_CONSTANT_MARKER)
+      defined HANDLE_CONSTANT_MARKER || defined HANDLE_MEMORY_VALUE)
 #error "Missing macro definition of HANDLE_VALUE*"
 #endif
 
+#ifndef HANDLE_MEMORY_VALUE
+#define HANDLE_MEMORY_VALUE(ValueName) HANDLE_VALUE(ValueName)
+#endif
+
 #ifndef HANDLE_GLOBAL_VALUE
 #define HANDLE_GLOBAL_VALUE(ValueName) HANDLE_CONSTANT(ValueName)
 #endif
 
 HANDLE_VALUE(Argument)
 HANDLE_VALUE(BasicBlock)
-HANDLE_VALUE(MemoryUse)
-HANDLE_VALUE(MemoryDef)
-HANDLE_VALUE(MemoryPhi)
+
+// FIXME: It's awkward that Value.def knows about classes in Analysis. While
+// this doesn't introduce a strict link or include dependency, we should remove
+// the circular dependency eventually.
+HANDLE_MEMORY_VALUE(MemoryUse)
+HANDLE_MEMORY_VALUE(MemoryDef)
+HANDLE_MEMORY_VALUE(MemoryPhi)
 
 HANDLE_GLOBAL_VALUE(Function)
 HANDLE_GLOBAL_VALUE(GlobalAlias)
@@ -94,6 +102,7 @@ HANDLE_CONSTANT_MARKER(ConstantDataLastVal, ConstantTokenNone)
 HANDLE_CONSTANT_MARKER(ConstantAggregateFirstVal, ConstantArray)
 HANDLE_CONSTANT_MARKER(ConstantAggregateLastVal, ConstantVector)
 
+#undef HANDLE_MEMORY_VALUE
 #undef HANDLE_GLOBAL_VALUE
 #undef HANDLE_CONSTANT
 #undef HANDLE_INSTRUCTION
index 96a370dcc35f06c2364fbff552c2027538b24060..d669b1544070f0fd105200fd9662635a504db192 100644 (file)
@@ -21,6 +21,7 @@
 #include "llvm-c/Types.h"
 #include <cassert>
 #include <iterator>
+#include <memory>
 
 namespace llvm {
 
@@ -69,6 +70,8 @@ using ValueName = StringMapEntry<Value*>;
 /// objects that watch it and listen to RAUW and Destroy events.  See
 /// llvm/IR/ValueHandle.h for details.
 class Value {
+  // The least-significant bit of the first word of Value *must* be zero:
+  //   http://www.llvm.org/docs/ProgrammersManual.html#the-waymarking-algorithm
   Type *VTy;
   Use *UseList;
 
@@ -200,10 +203,19 @@ private:
 protected:
   Value(Type *Ty, unsigned scid);
 
+  /// Value's destructor should be virtual by design, but that would require
+  /// that Value and all of its subclasses have a vtable that effectively
+  /// duplicates the information in the value ID. As a size optimization, the
+  /// destructor has been protected, and the caller should manually call
+  /// deleteValue.
+  ~Value(); // Use deleteValue() to delete a generic Value.
+
 public:
   Value(const Value &) = delete;
   void operator=(const Value &) = delete;
-  virtual ~Value();
+
+  /// Delete a pointer to a generic Value.
+  void deleteValue();
 
   /// \brief Support for debugging, callable in GDB: V->dump()
   void dump() const;
@@ -643,6 +655,13 @@ protected:
   void setValueSubclassData(unsigned short D) { SubclassData = D; }
 };
 
+struct ValueDeleter { void operator()(Value *V) { V->deleteValue(); } };
+
+/// Use this instead of std::unique_ptr<Value> or std::unique_ptr<Instruction>.
+/// Those don't work because Value and Instruction's destructors are protected,
+/// aren't virtual, and won't destroy the complete object.
+typedef std::unique_ptr<Value, ValueDeleter> unique_value;
+
 inline raw_ostream &operator<<(raw_ostream &OS, const Value &V) {
   V.print(OS);
   return OS;
index 2480fe44d5c0e737515569197b36c0af36a83b2a..e0e04a91410ff3ee2d40d5c68fc58c810c14110d 100644 (file)
@@ -1799,6 +1799,15 @@ bool MemorySSA::dominates(const MemoryAccess *Dominator,
 
 const static char LiveOnEntryStr[] = "liveOnEntry";
 
+void MemoryAccess::print(raw_ostream &OS) const {
+  switch (getValueID()) {
+  case MemoryPhiVal: return static_cast<const MemoryPhi *>(this)->print(OS);
+  case MemoryDefVal: return static_cast<const MemoryDef *>(this)->print(OS);
+  case MemoryUseVal: return static_cast<const MemoryUse *>(this)->print(OS);
+  }
+  llvm_unreachable("invalid value id");
+}
+
 void MemoryDef::print(raw_ostream &OS) const {
   MemoryAccess *UO = getDefiningAccess();
 
@@ -1836,8 +1845,6 @@ void MemoryPhi::print(raw_ostream &OS) const {
   OS << ')';
 }
 
-MemoryAccess::~MemoryAccess() {}
-
 void MemoryUse::print(raw_ostream &OS) const {
   MemoryAccess *UO = getDefiningAccess();
   OS << "MemoryUse(";
@@ -2054,3 +2061,15 @@ MemoryAccess *DoNothingMemorySSAWalker::getClobberingMemoryAccess(
   return StartingAccess;
 }
 } // namespace llvm
+
+void MemoryPhi::deleteMe(DerivedUser *Self) {
+  delete static_cast<MemoryPhi *>(Self);
+}
+
+void MemoryDef::deleteMe(DerivedUser *Self) {
+  delete static_cast<MemoryDef *>(Self);
+}
+
+void MemoryUse::deleteMe(DerivedUser *Self) {
+  delete static_cast<MemoryUse *>(Self);
+}
index d7602c83435cddcc3de9674e127066df1d414084..ff1ea44a18a705072363ab6287874ce736453d83 100644 (file)
@@ -2502,7 +2502,7 @@ LLParser::PerFunctionState::~PerFunctionState() {
       continue;
     P.second.first->replaceAllUsesWith(
         UndefValue::get(P.second.first->getType()));
-    delete P.second.first;
+    P.second.first->deleteValue();
   }
 
   for (const auto &P : ForwardRefValIDs) {
@@ -2510,7 +2510,7 @@ LLParser::PerFunctionState::~PerFunctionState() {
       continue;
     P.second.first->replaceAllUsesWith(
         UndefValue::get(P.second.first->getType()));
-    delete P.second.first;
+    P.second.first->deleteValue();
   }
 }
 
@@ -2642,7 +2642,7 @@ bool LLParser::PerFunctionState::SetInstName(int NameID,
                        getTypeString(FI->second.first->getType()) + "'");
 
       Sentinel->replaceAllUsesWith(Inst);
-      delete Sentinel;
+      Sentinel->deleteValue();
       ForwardRefValIDs.erase(FI);
     }
 
@@ -2659,7 +2659,7 @@ bool LLParser::PerFunctionState::SetInstName(int NameID,
                      getTypeString(FI->second.first->getType()) + "'");
 
     Sentinel->replaceAllUsesWith(Inst);
-    delete Sentinel;
+    Sentinel->deleteValue();
     ForwardRefVals.erase(FI);
   }
 
index 76298121566aa789c3ec99798ba6b57f66979b53..686c946876696b81eae629d568ac5921a0b18f4f 100644 (file)
@@ -4489,11 +4489,11 @@ Error BitcodeReader::parseFunctionBody(Function *F) {
     // Add instruction to end of current BB.  If there is no current BB, reject
     // this file.
     if (!CurBB) {
-      delete I;
+      I->deleteValue();
       return error("Invalid instruction with no BB");
     }
     if (!OperandBundles.empty()) {
-      delete I;
+      I->deleteValue();
       return error("Operand bundles found with no consumer");
     }
     CurBB->getInstList().push_back(I);
index d1a2a11bbfadb5cdc8c00c90603988128cc98972..f2a3439a87be6ea5a99b909370cfa7b8e56e624d 100644 (file)
@@ -73,7 +73,7 @@ void BitcodeReaderValueList::assignValue(Value *V, unsigned Idx) {
     // If there was a forward reference to this value, replace it.
     Value *PrevVal = OldV;
     OldV->replaceAllUsesWith(V);
-    delete PrevVal;
+    PrevVal->deleteValue();
   }
 }
 
@@ -194,6 +194,6 @@ void BitcodeReaderValueList::resolveConstantForwardRefs() {
 
     // Update all ValueHandles, they should be the only users at this point.
     Placeholder->replaceAllUsesWith(RealVal);
-    delete Placeholder;
+    Placeholder->deleteValue();
   }
 }
index e2fe87cb3ea1bb4cfce317107c198df992f1c557..3a1a3020a8d4d05d1670ee3bf4693e8faaa362ba 100644 (file)
@@ -350,7 +350,7 @@ bool CodeGenPrepare::runOnFunction(Function &F) {
 
     // Really free removed instructions during promotion.
     for (Instruction *I : RemovedInsts)
-      delete I;
+      I->deleteValue();
 
     EverMadeChange |= MadeChange;
   }
index 4b9d89cda539d99d61d388e91962f1d2723d5e4e..f0b9dfb2d6201fd960f1c51c1f04e94de9a0b6ef 100644 (file)
@@ -37,10 +37,6 @@ using namespace llvm;
 //                              Constant Class
 //===----------------------------------------------------------------------===//
 
-void Constant::anchor() { }
-
-void ConstantData::anchor() {}
-
 bool Constant::isNegativeZeroValue() const {
   // Floating point values have an explicit -0.0 value.
   if (const ConstantFP *CFP = dyn_cast<ConstantFP>(this))
@@ -496,8 +492,6 @@ void Constant::removeDeadConstantUsers() const {
 //                                ConstantInt
 //===----------------------------------------------------------------------===//
 
-void ConstantInt::anchor() { }
-
 ConstantInt::ConstantInt(IntegerType *Ty, const APInt &V)
     : ConstantData(Ty, ConstantIntVal), Val(V) {
   assert(V.getBitWidth() == Ty->getBitWidth() && "Invalid constant for type");
@@ -610,8 +604,6 @@ static const fltSemantics *TypeToFloatSemantics(Type *Ty) {
   return &APFloat::PPCDoubleDouble();
 }
 
-void ConstantFP::anchor() { }
-
 Constant *ConstantFP::get(Type *Ty, double V) {
   LLVMContext &Context = Ty->getContext();
 
@@ -2266,9 +2258,6 @@ Type *GetElementPtrConstantExpr::getResultElementType() const {
 //===----------------------------------------------------------------------===//
 //                       ConstantData* implementations
 
-void ConstantDataArray::anchor() {}
-void ConstantDataVector::anchor() {}
-
 Type *ConstantDataSequential::getElementType() const {
   return getType()->getElementType();
 }
index 25eb9452d9d008c4bc1eca4200c4c533de02bdfd..6c189cf656debf73dc026457c879583a9d00c42b 100644 (file)
@@ -44,8 +44,6 @@ namespace llvm {
 /// UnaryConstantExpr - This class is private to Constants.cpp, and is used
 /// behind the scenes to implement unary constant exprs.
 class UnaryConstantExpr : public ConstantExpr {
-  void anchor() override;
-
 public:
   UnaryConstantExpr(unsigned Opcode, Constant *C, Type *Ty)
     : ConstantExpr(Ty, Opcode, &Op<0>(), 1) {
@@ -65,8 +63,6 @@ public:
 /// BinaryConstantExpr - This class is private to Constants.cpp, and is used
 /// behind the scenes to implement binary constant exprs.
 class BinaryConstantExpr : public ConstantExpr {
-  void anchor() override;
-
 public:
   BinaryConstantExpr(unsigned Opcode, Constant *C1, Constant *C2,
                      unsigned Flags)
@@ -90,8 +86,6 @@ public:
 /// SelectConstantExpr - This class is private to Constants.cpp, and is used
 /// behind the scenes to implement select constant exprs.
 class SelectConstantExpr : public ConstantExpr {
-  void anchor() override;
-
 public:
   SelectConstantExpr(Constant *C1, Constant *C2, Constant *C3)
     : ConstantExpr(C2->getType(), Instruction::Select, &Op<0>(), 3) {
@@ -115,8 +109,6 @@ public:
 /// Constants.cpp, and is used behind the scenes to implement
 /// extractelement constant exprs.
 class ExtractElementConstantExpr : public ConstantExpr {
-  void anchor() override;
-
 public:
   ExtractElementConstantExpr(Constant *C1, Constant *C2)
     : ConstantExpr(cast<VectorType>(C1->getType())->getElementType(),
@@ -140,8 +132,6 @@ public:
 /// Constants.cpp, and is used behind the scenes to implement
 /// insertelement constant exprs.
 class InsertElementConstantExpr : public ConstantExpr {
-  void anchor() override;
-
 public:
   InsertElementConstantExpr(Constant *C1, Constant *C2, Constant *C3)
     : ConstantExpr(C1->getType(), Instruction::InsertElement,
@@ -166,8 +156,6 @@ public:
 /// Constants.cpp, and is used behind the scenes to implement
 /// shufflevector constant exprs.
 class ShuffleVectorConstantExpr : public ConstantExpr {
-  void anchor() override;
-
 public:
   ShuffleVectorConstantExpr(Constant *C1, Constant *C2, Constant *C3)
   : ConstantExpr(VectorType::get(
@@ -195,8 +183,6 @@ public:
 /// Constants.cpp, and is used behind the scenes to implement
 /// extractvalue constant exprs.
 class ExtractValueConstantExpr : public ConstantExpr {
-  void anchor() override;
-
 public:
   ExtractValueConstantExpr(Constant *Agg, ArrayRef<unsigned> IdxList,
                            Type *DestTy)
@@ -230,8 +216,6 @@ public:
 /// Constants.cpp, and is used behind the scenes to implement
 /// insertvalue constant exprs.
 class InsertValueConstantExpr : public ConstantExpr {
-  void anchor() override;
-
 public:
   InsertValueConstantExpr(Constant *Agg, Constant *Val,
                           ArrayRef<unsigned> IdxList, Type *DestTy)
@@ -271,8 +255,6 @@ class GetElementPtrConstantExpr : public ConstantExpr {
   GetElementPtrConstantExpr(Type *SrcElementTy, Constant *C,
                             ArrayRef<Constant *> IdxList, Type *DestTy);
 
-  void anchor() override;
-
 public:
   static GetElementPtrConstantExpr *Create(Type *SrcElementTy, Constant *C,
                                            ArrayRef<Constant *> IdxList,
@@ -301,8 +283,6 @@ public:
 // behind the scenes to implement ICmp and FCmp constant expressions. This is
 // needed in order to store the predicate value for these instructions.
 class CompareConstantExpr : public ConstantExpr {
-  void anchor() override;
-
 public:
   unsigned short predicate;
   CompareConstantExpr(Type *ty, Instruction::OtherOps opc,
index 16a9e51b830695b86fc30757d0fee51f77b69d74..39de4b0a97fad1ca3d92f65e545dc148827dcc82 100644 (file)
@@ -66,8 +66,6 @@ template class llvm::SymbolTableListTraits<BasicBlock>;
 // Argument Implementation
 //===----------------------------------------------------------------------===//
 
-void Argument::anchor() {}
-
 Argument::Argument(Type *Ty, const Twine &Name, Function *Par, unsigned ArgNo)
     : Value(Ty, Value::ArgumentVal), Parent(Par), ArgNo(ArgNo) {
   setName(Name);
index 8feeeb65d445ef4f664140ffa7fcc94876f483b4..6c0c5a267f81518d9d8c5c1f878268680fb30449 100644 (file)
@@ -40,10 +40,6 @@ InlineAsm::InlineAsm(FunctionType *FTy, const std::string &asmString,
          "Function type not legal for constraints!");
 }
 
-// Implement the first virtual method in this class in this file so the
-// InlineAsm vtable is emitted here.
-InlineAsm::~InlineAsm() = default;
-
 InlineAsm *InlineAsm::get(FunctionType *FTy, StringRef AsmString,
                           StringRef Constraints, bool hasSideEffects,
                           bool isAlignStack, AsmDialect asmDialect) {
index 91b9d9232b5470a814b331bd30019be4d1d61520..828e78b1300520bca1a51b6ded7ba1fe6e72a2f6 100644 (file)
@@ -43,8 +43,6 @@ Instruction::Instruction(Type *ty, unsigned it, Use *Ops, unsigned NumOps,
   InsertAtEnd->getInstList().push_back(this);
 }
 
-
-// Out of line virtual method, so the vtable, etc has a home.
 Instruction::~Instruction() {
   assert(!Parent && "Instruction still linked in the program!");
   if (hasMetadataHashEntry())
index 5a5b9c0d06bbde2ba7232e773e7d3603469bd59f..01d4ed6c8eefaf89c238145f46bf4674ffa05c08 100644 (file)
@@ -59,9 +59,6 @@ User::op_iterator CallSite::getCallee() const {
 //                            TerminatorInst Class
 //===----------------------------------------------------------------------===//
 
-// Out of line virtual method, so the vtable, etc has a home.
-TerminatorInst::~TerminatorInst() = default;
-
 unsigned TerminatorInst::getNumSuccessors() const {
   switch (getOpcode()) {
 #define HANDLE_TERM_INST(N, OPC, CLASS)                                        \
@@ -98,13 +95,6 @@ void TerminatorInst::setSuccessor(unsigned idx, BasicBlock *B) {
   llvm_unreachable("not a terminator");
 }
 
-//===----------------------------------------------------------------------===//
-//                           UnaryInstruction Class
-//===----------------------------------------------------------------------===//
-
-// Out of line virtual method, so the vtable, etc has a home.
-UnaryInstruction::~UnaryInstruction() = default;
-
 //===----------------------------------------------------------------------===//
 //                              SelectInst Class
 //===----------------------------------------------------------------------===//
@@ -138,8 +128,6 @@ const char *SelectInst::areInvalidOperands(Value *Op0, Value *Op1, Value *Op2) {
 //                               PHINode Class
 //===----------------------------------------------------------------------===//
 
-void PHINode::anchor() {}
-
 PHINode::PHINode(const PHINode &PN)
     : Instruction(PN.getType(), Instruction::PHI, nullptr, PN.getNumOperands()),
       ReservedSpace(PN.getNumOperands()) {
@@ -293,8 +281,6 @@ void LandingPadInst::addClause(Constant *Val) {
 //                        CallInst Implementation
 //===----------------------------------------------------------------------===//
 
-CallInst::~CallInst() = default;
-
 void CallInst::init(FunctionType *FTy, Value *Func, ArrayRef<Value *> Args,
                     ArrayRef<OperandBundleDef> Bundles, const Twine &NameStr) {
   this->FTy = FTy;
@@ -900,8 +886,6 @@ BasicBlock *ReturnInst::getSuccessorV(unsigned idx) const {
   llvm_unreachable("ReturnInst has no successors!");
 }
 
-ReturnInst::~ReturnInst() = default;
-
 //===----------------------------------------------------------------------===//
 //                        ResumeInst Implementation
 //===----------------------------------------------------------------------===//
@@ -1337,9 +1321,6 @@ AllocaInst::AllocaInst(Type *Ty, unsigned AddrSpace, Value *ArraySize,
   setName(Name);
 }
 
-// Out of line virtual method, so the vtable, etc has a home.
-AllocaInst::~AllocaInst() = default;
-
 void AllocaInst::setAlignment(unsigned Align) {
   assert((Align & (Align-1)) == 0 && "Alignment is not a power of 2!");
   assert(Align <= MaximumAlignment &&
@@ -1689,8 +1670,6 @@ FenceInst::FenceInst(LLVMContext &C, AtomicOrdering Ordering,
 //                       GetElementPtrInst Implementation
 //===----------------------------------------------------------------------===//
 
-void GetElementPtrInst::anchor() {}
-
 void GetElementPtrInst::init(Value *Ptr, ArrayRef<Value *> IdxList,
                              const Twine &Name) {
   assert(getNumOperands() == 1 + IdxList.size() &&
@@ -2357,8 +2336,6 @@ float FPMathOperator::getFPAccuracy() const {
 //                                CastInst Class
 //===----------------------------------------------------------------------===//
 
-void CastInst::anchor() {}
-
 // Just determine if this cast only deals with integral->integral conversion.
 bool CastInst::isIntegerCast() const {
   switch (getOpcode()) {
@@ -3387,8 +3364,6 @@ AddrSpaceCastInst::AddrSpaceCastInst(
 //                               CmpInst Classes
 //===----------------------------------------------------------------------===//
 
-void CmpInst::anchor() {}
-
 CmpInst::CmpInst(Type *ty, OtherOps op, Predicate predicate, Value *LHS,
                  Value *RHS, const Twine &Name, Instruction *InsertBefore)
   : Instruction(ty, op,
@@ -3528,8 +3503,6 @@ StringRef CmpInst::getPredicateName(Predicate Pred) {
   }
 }
 
-void ICmpInst::anchor() {}
-
 ICmpInst::Predicate ICmpInst::getSignedPredicate(Predicate pred) {
   switch (pred) {
     default: llvm_unreachable("Unknown icmp predicate!");
index 343722463e5faed2bda618bb584b156a5f88c495..4a30d28c39138485c502b0888b810d49660ed001 100644 (file)
@@ -215,27 +215,6 @@ uint32_t LLVMContextImpl::getOperandBundleTagID(StringRef Tag) const {
   return I->second;
 }
 
-// ConstantsContext anchors
-void UnaryConstantExpr::anchor() { }
-
-void BinaryConstantExpr::anchor() { }
-
-void SelectConstantExpr::anchor() { }
-
-void ExtractElementConstantExpr::anchor() { }
-
-void InsertElementConstantExpr::anchor() { }
-
-void ShuffleVectorConstantExpr::anchor() { }
-
-void ExtractValueConstantExpr::anchor() { }
-
-void InsertValueConstantExpr::anchor() { }
-
-void GetElementPtrConstantExpr::anchor() { }
-
-void CompareConstantExpr::anchor() { }
-
 /// Singleton instance of the OptBisect class.
 ///
 /// This singleton is accessed via the LLVMContext::getOptBisect() function.  It
index 497b4aa176434a7447bd87e14fef2a50ae5eaa94..d46039107f33176dde94da3e748f4d9acd94a6da 100644 (file)
@@ -19,8 +19,6 @@ class BasicBlock;
 //                                 User Class
 //===----------------------------------------------------------------------===//
 
-void User::anchor() {}
-
 void User::replaceUsesOfWith(Value *From, Value *To) {
   if (From == To) return;   // Duh what?
 
@@ -193,12 +191,4 @@ void User::operator delete(void *Usr) {
   }
 }
 
-//===----------------------------------------------------------------------===//
-//                             Operator Class
-//===----------------------------------------------------------------------===//
-
-Operator::~Operator() {
-  llvm_unreachable("should never destroy an Operator");
-}
-
 } // End llvm namespace
index 02b40c93b5d8b9cf5f94f8520fe49ed6bb2907db..51a7d424c1f331821b43c798e815142e08d7b274 100644 (file)
@@ -20,6 +20,7 @@
 #include "llvm/IR/Constants.h"
 #include "llvm/IR/DataLayout.h"
 #include "llvm/IR/DerivedTypes.h"
+#include "llvm/IR/DerivedUser.h"
 #include "llvm/IR/GetElementPtrTypeIterator.h"
 #include "llvm/IR/InstrTypes.h"
 #include "llvm/IR/Instructions.h"
@@ -59,7 +60,7 @@ Value::Value(Type *ty, unsigned scid)
            (SubclassID < ConstantFirstVal || SubclassID > ConstantLastVal))
     assert((VTy->isFirstClassType() || VTy->isVoidTy()) &&
            "Cannot create non-first-class values except for constants!");
-  static_assert(sizeof(Value) == 3 * sizeof(void *) + 2 * sizeof(unsigned),
+  static_assert(sizeof(Value) == 2 * sizeof(void *) + 2 * sizeof(unsigned),
                 "Value too big");
 }
 
@@ -89,6 +90,32 @@ Value::~Value() {
   destroyValueName();
 }
 
+void Value::deleteValue() {
+  switch (getValueID()) {
+#define HANDLE_VALUE(Name)                                                     \
+  case Value::Name##Val:                                                       \
+    delete static_cast<Name *>(this);                                          \
+    break;
+#define HANDLE_MEMORY_VALUE(Name)                                              \
+  case Value::Name##Val:                                                       \
+    static_cast<DerivedUser *>(this)->DeleteValue(                             \
+        static_cast<DerivedUser *>(this));                                     \
+    break;
+#define HANDLE_INSTRUCTION(Name)  /* nothing */
+#include "llvm/IR/Value.def"
+
+#define HANDLE_INST(N, OPC, CLASS)                                             \
+  case Value::InstructionVal + Instruction::OPC:                               \
+    delete static_cast<CLASS *>(this);                                         \
+    break;
+#define HANDLE_USER_INST(N, OPC, CLASS)
+#include "llvm/IR/Instruction.def"
+
+  default:
+    llvm_unreachable("attempting to delete unknown value kind");
+  }
+}
+
 void Value::destroyValueName() {
   ValueName *Name = getValueName();
   if (Name)
index e4df7ff5c2008f3118f72feec209e1892b171182..e6ea67d55b43ca3400d79f94c5b35ebcc83cf80c 100644 (file)
@@ -399,7 +399,7 @@ void Simplifier::Context::cleanup() {
   for (Value *V : Clones) {
     Instruction *U = cast<Instruction>(V);
     if (!U->getParent())
-      delete U;
+      U->deleteValue();
   }
 }
 
index c04646eed49a88f9c22316dbdbf3e56b3a638b8c..0490d93f64553808f7ac922d1be42c5941739c8a 100644 (file)
@@ -2057,7 +2057,7 @@ bool GVN::performScalarPRE(Instruction *CurInst) {
     if (!performScalarPREInsertion(PREInstr, PREPred, ValNo)) {
       // If we failed insertion, make sure we remove the instruction.
       DEBUG(verifyRemoved(PREInstr));
-      delete PREInstr;
+      PREInstr->deleteValue();
       return false;
     }
   }
index 54ab80e448fde0663840527383cd8831e47a4a7a..ada22ae38eb8d1fd8e76ac2402b7f626a1d95023 100644 (file)
@@ -1906,7 +1906,7 @@ bool JumpThreadingPass::DuplicateCondBranchOnPHIIntoPred(
             {BB->getModule()->getDataLayout(), TLI, nullptr, nullptr, New})) {
       ValueMapping[&*BI] = IV;
       if (!New->mayHaveSideEffects()) {
-        delete New;
+        New->deleteValue();
         New = nullptr;
       }
     } else {
index 2ba9265566a8caf30292cf5dc468b3e8ce8b8da6..7312d97f8efe126d580eb1d5c18b6583d373c318 100644 (file)
@@ -347,7 +347,7 @@ bool LoopRotate::rotateLoop(Loop *L, bool SimplifiedLatch) {
       // in the map.
       ValueMap[Inst] = V;
       if (!C->mayHaveSideEffects()) {
-        delete C;
+        C->deleteValue();
         C = nullptr;
       }
     } else {
index 53320bff08833c092f90013e259731674103c8c7..a20890b22603ea5e812f54c66a36dec188232a1e 100644 (file)
@@ -1582,7 +1582,7 @@ Value *ReassociatePass::OptimizeAdd(Instruction *I,
     }
 
     // No need for extra uses anymore.
-    delete DummyInst;
+    DummyInst->deleteValue();
 
     unsigned NumAddedValues = NewMulOps.size();
     Value *V = EmitAddTreeOfValues(I, NewMulOps);
index ed7df091b55411d8b0915fb03634d115308c2a6d..24bd0a2b7bdf273d3159ffffd44d02e1cc42c44a 100644 (file)
@@ -2443,7 +2443,7 @@ private:
                         "insert");
       LI.replaceAllUsesWith(V);
       Placeholder->replaceAllUsesWith(&LI);
-      delete Placeholder;
+      Placeholder->deleteValue();
     } else {
       LI.replaceAllUsesWith(V);
     }
index 2be3f5c533b9a607ec2d56c64849bb7ba46590ad..8b8d6590aa6a08dcd9d6ca671aa5f606c39e277d 100644 (file)
@@ -693,7 +693,7 @@ bool StraightLineStrengthReduce::runOnFunction(Function &F) {
       UnlinkedInst->setOperand(I, nullptr);
       RecursivelyDeleteTriviallyDeadInstructions(Op);
     }
-    delete UnlinkedInst;
+    UnlinkedInst->deleteValue();
   }
   bool Ret = !UnlinkedInstructions.empty();
   UnlinkedInstructions.clear();
index 4aa26fd14fee3dada6307f4afc8379c38b3ed994..bf2ab7c55be22a5e3482d235c01f1d706965f36a 100644 (file)
@@ -317,7 +317,7 @@ void PruningFunctionCloner::CloneBlock(const BasicBlock *BB,
 
         if (!NewInst->mayHaveSideEffects()) {
           VMap[&*II] = V;
-          delete NewInst;
+          NewInst->deleteValue();
           continue;
         }
       }
index b44bc74d6551ee6ad5b91cbf4351a5ffcc140476..5a04cac065349689e17a67d629c19ad08e327eec 100644 (file)
@@ -2235,7 +2235,7 @@ static bool FoldCondBranchOnPHI(BranchInst *BI, const DataLayout &DL,
         if (!BBI->use_empty())
           TranslateMap[&*BBI] = V;
         if (!N->mayHaveSideEffects()) {
-          delete N; // Instruction folded away, don't need actual inst
+          N->deleteValue(); // Instruction folded away, don't need actual inst
           N = nullptr;
         }
       } else {
index 64013d6d687dfc63c4e55aed0bfe11a9c9f9ccad..e6f78e6b94a3431941fd1b4e2e43160ac3bd604f 100644 (file)
@@ -578,12 +578,12 @@ private:
   void eraseInstruction(Instruction *I) {
     I->removeFromParent();
     I->dropAllReferences();
-    DeletedInstructions.push_back(std::unique_ptr<Instruction>(I));
+    DeletedInstructions.emplace_back(I);
   }
 
   /// Temporary store for deleted instructions. Instructions will be deleted
   /// eventually when the BoUpSLP is destructed.
-  SmallVector<std::unique_ptr<Instruction>, 8> DeletedInstructions;
+  SmallVector<unique_value, 8> DeletedInstructions;
 
   /// A list of values that need to extracted out of the tree.
   /// This list holds pairs of (Internal Scalar : External User). External User
index 6959ac85e49d0bf0ae302e32dfef8afcf49c59e3..7a8a3045a0d4909fc87e3eac699c2f6aaf74607b 100644 (file)
@@ -178,14 +178,15 @@ TEST(ConstantsTest, PointerCast) {
             ConstantExpr::getAddrSpaceCast(NullInt32Ptr1, Int32PtrTy));
 }
 
-#define CHECK(x, y) {                                                  \
-    std::string __s;                                                   \
-    raw_string_ostream __o(__s);                                       \
-    Instruction *__I = cast<ConstantExpr>(x)->getAsInstruction();      \
-    __I->print(__o);                                                   \
-    delete __I;                                                        \
-    __o.flush();                                                       \
-    EXPECT_EQ(std::string("  <badref> = " y), __s);                    \
+#define CHECK(x, y)                                                            \
+  {                                                                            \
+    std::string __s;                                                           \
+    raw_string_ostream __o(__s);                                               \
+    Instruction *__I = cast<ConstantExpr>(x)->getAsInstruction();              \
+    __I->print(__o);                                                           \
+    __I->deleteValue();                                                        \
+    __o.flush();                                                               \
+    EXPECT_EQ(std::string("  <badref> = " y), __s);                            \
   }
 
 TEST(ConstantsTest, AsInstructionsTest) {
index b8d398c5cc388554bd4ecd61425c60f51e9d7149..619ddc5413df04cb9593ab2dcbee496664b31016 100644 (file)
@@ -406,8 +406,8 @@ TEST(InstructionsTest, FPMathOperator) {
   EXPECT_TRUE(isa<FPMathOperator>(V1));
   FPMathOperator *O1 = cast<FPMathOperator>(V1);
   EXPECT_EQ(O1->getFPAccuracy(), 1.0);
-  delete V1;
-  delete I;
+  V1->deleteValue();
+  I->deleteValue();
 }
 
 
index e61e649df191dc0878d004aeacfa075c0aeef832..9f8fc4eaeb6f9f02a4a718a4acc8d7dd10ecf4e3 100644 (file)
@@ -218,7 +218,7 @@ TEST_F(MDNodeTest, Delete) {
 
   EXPECT_EQ(n, wvh);
 
-  delete I;
+  I->deleteValue();
 }
 
 TEST_F(MDNodeTest, SelfReference) {
index 83f146dca704a4cfea477dcc5b229de5ee500055..d13547a842e4d5d8ef86df81fed11302784aad76 100644 (file)
@@ -41,13 +41,18 @@ protected:
   }
 
   void eraseClones() {
-    DeleteContainerPointers(Clones);
+    for (Value *V : Clones)
+      V->deleteValue();
+    Clones.clear();
   }
 
   void TearDown() override {
     eraseClones();
-    DeleteContainerPointers(Orig);
-    delete V;
+    for (Value *V : Orig)
+      V->deleteValue();
+    Orig.clear();
+    if (V)
+      V->deleteValue();
   }
 
   SmallPtrSet<Value *, 4> Orig;   // Erase on exit