From: Reid Kleckner Date: Thu, 18 May 2017 17:24:10 +0000 (+0000) Subject: [IR] De-virtualize ~Value to save a vptr X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=816047d44c6cf672981d85e16c22bf610508f09b;p=llvm [IR] De-virtualize ~Value to save a vptr 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. 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 --- diff --git a/include/llvm/Analysis/MemorySSA.h b/include/llvm/Analysis/MemorySSA.h index db31ae9f4f1..f0bba8c4c02 100644 --- a/include/llvm/Analysis/MemorySSA.h +++ b/include/llvm/Analysis/MemorySSA.h @@ -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>, public ilist_node> { 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(this) || isa(this)) && + "only memory defs and phis have ids"); + if (const auto *MD = dyn_cast(this)) + return MD->getID(); + return cast(this)->getID(); +} + +inline bool MemoryUseOrDef::isOptimized() const { + if (const auto *MD = dyn_cast(this)) + return MD->isOptimized(); + return cast(this)->isOptimized(); +} + +inline MemoryAccess *MemoryUseOrDef::getOptimized() const { + if (const auto *MD = dyn_cast(this)) + return MD->getOptimized(); + return cast(this)->getOptimized(); +} + +inline void MemoryUseOrDef::setOptimized(MemoryAccess *MA) { + if (auto *MD = dyn_cast(this)) + MD->setOptimized(MA); + else + cast(this)->setOptimized(MA); +} + +inline void MemoryUseOrDef::resetOptimized() { + if (auto *MD = dyn_cast(this)) + MD->resetOptimized(); + else + cast(this)->resetOptimized(); +} + + template <> struct OperandTraits : public HungoffOperandTraits<2> {}; DEFINE_TRANSPARENT_OPERAND_ACCESSORS(MemoryPhi, MemoryAccess) diff --git a/include/llvm/IR/Argument.h b/include/llvm/IR/Argument.h index 5ed6d030c98..3efcc637b6e 100644 --- a/include/llvm/IR/Argument.h +++ b/include/llvm/IR/Argument.h @@ -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; diff --git a/include/llvm/IR/BasicBlock.h b/include/llvm/IR/BasicBlock.h index 97989cf5c65..c917b1f2cad 100644 --- a/include/llvm/IR/BasicBlock.h +++ b/include/llvm/IR/BasicBlock.h @@ -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 { +class BasicBlock final : public Value, // Basic blocks are data objects also + public ilist_node_with_parent { public: using InstListType = SymbolTableList; @@ -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; diff --git a/include/llvm/IR/Constant.h b/include/llvm/IR/Constant.h index 3b3694e7e60..82afd9a2691 100644 --- a/include/llvm/IR/Constant.h +++ b/include/llvm/IR/Constant.h @@ -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) {} diff --git a/include/llvm/IR/Constants.h b/include/llvm/IR/Constants.h index 5db9b3bb504..fad27cf8892 100644 --- a/include/llvm/IR/Constants.h +++ b/include/llvm/IR/Constants.h @@ -58,8 +58,6 @@ template 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 index 00000000000..4d681e0db61 --- /dev/null +++ b/include/llvm/IR/DerivedUser.h @@ -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 diff --git a/include/llvm/IR/Function.h b/include/llvm/IR/Function.h index 8a2a6ed87eb..f27e5c50a47 100644 --- a/include/llvm/IR/Function.h +++ b/include/llvm/IR/Function.h @@ -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) { diff --git a/include/llvm/IR/GlobalValue.h b/include/llvm/IR/GlobalValue.h index 0793a1c0ee2..20495725f9d 100644 --- a/include/llvm/IR/GlobalValue.h +++ b/include/llvm/IR/GlobalValue.h @@ -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 { diff --git a/include/llvm/IR/GlobalVariable.h b/include/llvm/IR/GlobalVariable.h index 21d334c8f01..3f5d00bd3b3 100644 --- a/include/llvm/IR/GlobalVariable.h +++ b/include/llvm/IR/GlobalVariable.h @@ -66,7 +66,7 @@ public: GlobalVariable(const GlobalVariable &) = delete; GlobalVariable &operator=(const GlobalVariable &) = delete; - ~GlobalVariable() override { + ~GlobalVariable() { dropAllReferences(); // FIXME: needed by operator delete diff --git a/include/llvm/IR/InlineAsm.h b/include/llvm/IR/InlineAsm.h index a57e7d63012..7f03fcd19b6 100644 --- a/include/llvm/IR/InlineAsm.h +++ b/include/llvm/IR/InlineAsm.h @@ -28,7 +28,7 @@ class FunctionType; class PointerType; template 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. diff --git a/include/llvm/IR/InstrTypes.h b/include/llvm/IR/InstrTypes.h index 61ca90de739..e850c015d71 100644 --- a/include/llvm/IR/InstrTypes.h +++ b/include/llvm/IR/InstrTypes.h @@ -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(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; diff --git a/include/llvm/IR/Instruction.def b/include/llvm/IR/Instruction.def index 18711abb806..86617299c44 100644 --- a/include/llvm/IR/Instruction.def +++ b/include/llvm/IR/Instruction.def @@ -102,6 +102,10 @@ #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 diff --git a/include/llvm/IR/Instruction.h b/include/llvm/IR/Instruction.h index fca29900f4c..6e109735ddd 100644 --- a/include/llvm/IR/Instruction.h +++ b/include/llvm/IR/Instruction.h @@ -36,6 +36,10 @@ class FastMathFlags; class MDNode; struct AAMDNodes; +template <> struct ilist_alloc_traits { + static inline void deleteNode(Instruction *V); +}; + class Instruction : public User, public ilist_node_with_parent { 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(*user_begin());} @@ -640,6 +644,10 @@ private: Instruction *cloneImpl() const; }; +inline void ilist_alloc_traits::deleteNode(Instruction *V) { + V->deleteValue(); +} + } // end namespace llvm #endif // LLVM_IR_INSTRUCTION_H diff --git a/include/llvm/IR/Instructions.h b/include/llvm/IR/Instructions.h index c26701af27c..6fab59613dd 100644 --- a/include/llvm/IR/Instructions.h +++ b/include/llvm/IR/Instructions.h @@ -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 IdxList, unsigned Values, const Twine &NameStr, BasicBlock *InsertAtEnd); - void anchor() override; void init(Value *Ptr, ArrayRef 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 Args, ArrayRef 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); diff --git a/include/llvm/IR/Metadata.h b/include/llvm/IR/Metadata.h index 8f24a6a1d69..92f701e01ff 100644 --- a/include/llvm/IR/Metadata.h +++ b/include/llvm/IR/Metadata.h @@ -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; } diff --git a/include/llvm/IR/OperandTraits.h b/include/llvm/IR/OperandTraits.h index e97a8009ccc..7b94283856b 100644 --- a/include/llvm/IR/OperandTraits.h +++ b/include/llvm/IR/OperandTraits.h @@ -30,6 +30,9 @@ namespace llvm { template struct FixedNumOperandTraits { static Use *op_begin(SubClass* U) { + static_assert( + !std::is_polymorphic::value, + "adding virtual methods to subclasses of User breaks use lists"); return reinterpret_cast(U) - ARITY; } static Use *op_end(SubClass* U) { @@ -65,6 +68,9 @@ struct OptionalOperandTraits : public FixedNumOperandTraits { template struct VariadicOperandTraits { static Use *op_begin(SubClass* U) { + static_assert( + !std::is_polymorphic::value, + "adding virtual methods to subclasses of User breaks use lists"); return reinterpret_cast(U) - static_cast(U)->getNumOperands(); } static Use *op_end(SubClass* U) { diff --git a/include/llvm/IR/Operator.h b/include/llvm/IR/Operator.h index 997a85340c2..49fa6a6a877 100644 --- a/include/llvm/IR/Operator.h +++ b/include/llvm/IR/Operator.h @@ -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; diff --git a/include/llvm/IR/User.h b/include/llvm/IR/User.h index 7b9d451aaf5..109a3d5e7be 100644 --- a/include/llvm/IR/User.h +++ b/include/llvm/IR/User.h @@ -46,8 +46,6 @@ class User : public Value { template 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); diff --git a/include/llvm/IR/Value.def b/include/llvm/IR/Value.def index 48842d7f9cd..cebd7f7297e 100644 --- a/include/llvm/IR/Value.def +++ b/include/llvm/IR/Value.def @@ -20,10 +20,14 @@ #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 @@ -54,9 +58,13 @@ 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 diff --git a/include/llvm/IR/Value.h b/include/llvm/IR/Value.h index 96a370dcc35..d669b154407 100644 --- a/include/llvm/IR/Value.h +++ b/include/llvm/IR/Value.h @@ -21,6 +21,7 @@ #include "llvm-c/Types.h" #include #include +#include namespace llvm { @@ -69,6 +70,8 @@ using ValueName = StringMapEntry; /// 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 or std::unique_ptr. +/// 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 unique_value; + inline raw_ostream &operator<<(raw_ostream &OS, const Value &V) { V.print(OS); return OS; diff --git a/lib/Analysis/MemorySSA.cpp b/lib/Analysis/MemorySSA.cpp index 2480fe44d5c..e0e04a91410 100644 --- a/lib/Analysis/MemorySSA.cpp +++ b/lib/Analysis/MemorySSA.cpp @@ -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(this)->print(OS); + case MemoryDefVal: return static_cast(this)->print(OS); + case MemoryUseVal: return static_cast(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(Self); +} + +void MemoryDef::deleteMe(DerivedUser *Self) { + delete static_cast(Self); +} + +void MemoryUse::deleteMe(DerivedUser *Self) { + delete static_cast(Self); +} diff --git a/lib/AsmParser/LLParser.cpp b/lib/AsmParser/LLParser.cpp index d7602c83435..ff1ea44a18a 100644 --- a/lib/AsmParser/LLParser.cpp +++ b/lib/AsmParser/LLParser.cpp @@ -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); } diff --git a/lib/Bitcode/Reader/BitcodeReader.cpp b/lib/Bitcode/Reader/BitcodeReader.cpp index 76298121566..686c9468766 100644 --- a/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/lib/Bitcode/Reader/BitcodeReader.cpp @@ -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); diff --git a/lib/Bitcode/Reader/ValueList.cpp b/lib/Bitcode/Reader/ValueList.cpp index d1a2a11bbfa..f2a3439a87b 100644 --- a/lib/Bitcode/Reader/ValueList.cpp +++ b/lib/Bitcode/Reader/ValueList.cpp @@ -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(); } } diff --git a/lib/CodeGen/CodeGenPrepare.cpp b/lib/CodeGen/CodeGenPrepare.cpp index e2fe87cb3ea..3a1a3020a8d 100644 --- a/lib/CodeGen/CodeGenPrepare.cpp +++ b/lib/CodeGen/CodeGenPrepare.cpp @@ -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; } diff --git a/lib/IR/Constants.cpp b/lib/IR/Constants.cpp index 4b9d89cda53..f0b9dfb2d62 100644 --- a/lib/IR/Constants.cpp +++ b/lib/IR/Constants.cpp @@ -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(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(); } diff --git a/lib/IR/ConstantsContext.h b/lib/IR/ConstantsContext.h index 25eb9452d9d..6c189cf656d 100644 --- a/lib/IR/ConstantsContext.h +++ b/lib/IR/ConstantsContext.h @@ -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(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 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 IdxList, Type *DestTy) @@ -271,8 +255,6 @@ class GetElementPtrConstantExpr : public ConstantExpr { GetElementPtrConstantExpr(Type *SrcElementTy, Constant *C, ArrayRef IdxList, Type *DestTy); - void anchor() override; - public: static GetElementPtrConstantExpr *Create(Type *SrcElementTy, Constant *C, ArrayRef 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, diff --git a/lib/IR/Function.cpp b/lib/IR/Function.cpp index 16a9e51b830..39de4b0a97f 100644 --- a/lib/IR/Function.cpp +++ b/lib/IR/Function.cpp @@ -66,8 +66,6 @@ template class llvm::SymbolTableListTraits; // 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); diff --git a/lib/IR/InlineAsm.cpp b/lib/IR/InlineAsm.cpp index 8feeeb65d44..6c0c5a267f8 100644 --- a/lib/IR/InlineAsm.cpp +++ b/lib/IR/InlineAsm.cpp @@ -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) { diff --git a/lib/IR/Instruction.cpp b/lib/IR/Instruction.cpp index 91b9d9232b5..828e78b1300 100644 --- a/lib/IR/Instruction.cpp +++ b/lib/IR/Instruction.cpp @@ -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()) diff --git a/lib/IR/Instructions.cpp b/lib/IR/Instructions.cpp index 5a5b9c0d06b..01d4ed6c8ee 100644 --- a/lib/IR/Instructions.cpp +++ b/lib/IR/Instructions.cpp @@ -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 Args, ArrayRef 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 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!"); diff --git a/lib/IR/LLVMContextImpl.cpp b/lib/IR/LLVMContextImpl.cpp index 343722463e5..4a30d28c391 100644 --- a/lib/IR/LLVMContextImpl.cpp +++ b/lib/IR/LLVMContextImpl.cpp @@ -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 diff --git a/lib/IR/User.cpp b/lib/IR/User.cpp index 497b4aa1764..d46039107f3 100644 --- a/lib/IR/User.cpp +++ b/lib/IR/User.cpp @@ -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 diff --git a/lib/IR/Value.cpp b/lib/IR/Value.cpp index 02b40c93b5d..51a7d424c1f 100644 --- a/lib/IR/Value.cpp +++ b/lib/IR/Value.cpp @@ -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(this); \ + break; +#define HANDLE_MEMORY_VALUE(Name) \ + case Value::Name##Val: \ + static_cast(this)->DeleteValue( \ + static_cast(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(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) diff --git a/lib/Target/Hexagon/HexagonLoopIdiomRecognition.cpp b/lib/Target/Hexagon/HexagonLoopIdiomRecognition.cpp index e4df7ff5c20..e6ea67d55b4 100644 --- a/lib/Target/Hexagon/HexagonLoopIdiomRecognition.cpp +++ b/lib/Target/Hexagon/HexagonLoopIdiomRecognition.cpp @@ -399,7 +399,7 @@ void Simplifier::Context::cleanup() { for (Value *V : Clones) { Instruction *U = cast(V); if (!U->getParent()) - delete U; + U->deleteValue(); } } diff --git a/lib/Transforms/Scalar/GVN.cpp b/lib/Transforms/Scalar/GVN.cpp index c04646eed49..0490d93f645 100644 --- a/lib/Transforms/Scalar/GVN.cpp +++ b/lib/Transforms/Scalar/GVN.cpp @@ -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; } } diff --git a/lib/Transforms/Scalar/JumpThreading.cpp b/lib/Transforms/Scalar/JumpThreading.cpp index 54ab80e448f..ada22ae38eb 100644 --- a/lib/Transforms/Scalar/JumpThreading.cpp +++ b/lib/Transforms/Scalar/JumpThreading.cpp @@ -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 { diff --git a/lib/Transforms/Scalar/LoopRotation.cpp b/lib/Transforms/Scalar/LoopRotation.cpp index 2ba9265566a..7312d97f8ef 100644 --- a/lib/Transforms/Scalar/LoopRotation.cpp +++ b/lib/Transforms/Scalar/LoopRotation.cpp @@ -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 { diff --git a/lib/Transforms/Scalar/Reassociate.cpp b/lib/Transforms/Scalar/Reassociate.cpp index 53320bff088..a20890b2260 100644 --- a/lib/Transforms/Scalar/Reassociate.cpp +++ b/lib/Transforms/Scalar/Reassociate.cpp @@ -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); diff --git a/lib/Transforms/Scalar/SROA.cpp b/lib/Transforms/Scalar/SROA.cpp index ed7df091b55..24bd0a2b7bd 100644 --- a/lib/Transforms/Scalar/SROA.cpp +++ b/lib/Transforms/Scalar/SROA.cpp @@ -2443,7 +2443,7 @@ private: "insert"); LI.replaceAllUsesWith(V); Placeholder->replaceAllUsesWith(&LI); - delete Placeholder; + Placeholder->deleteValue(); } else { LI.replaceAllUsesWith(V); } diff --git a/lib/Transforms/Scalar/StraightLineStrengthReduce.cpp b/lib/Transforms/Scalar/StraightLineStrengthReduce.cpp index 2be3f5c533b..8b8d6590aa6 100644 --- a/lib/Transforms/Scalar/StraightLineStrengthReduce.cpp +++ b/lib/Transforms/Scalar/StraightLineStrengthReduce.cpp @@ -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(); diff --git a/lib/Transforms/Utils/CloneFunction.cpp b/lib/Transforms/Utils/CloneFunction.cpp index 4aa26fd14fe..bf2ab7c55be 100644 --- a/lib/Transforms/Utils/CloneFunction.cpp +++ b/lib/Transforms/Utils/CloneFunction.cpp @@ -317,7 +317,7 @@ void PruningFunctionCloner::CloneBlock(const BasicBlock *BB, if (!NewInst->mayHaveSideEffects()) { VMap[&*II] = V; - delete NewInst; + NewInst->deleteValue(); continue; } } diff --git a/lib/Transforms/Utils/SimplifyCFG.cpp b/lib/Transforms/Utils/SimplifyCFG.cpp index b44bc74d655..5a04cac0653 100644 --- a/lib/Transforms/Utils/SimplifyCFG.cpp +++ b/lib/Transforms/Utils/SimplifyCFG.cpp @@ -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 { diff --git a/lib/Transforms/Vectorize/SLPVectorizer.cpp b/lib/Transforms/Vectorize/SLPVectorizer.cpp index 64013d6d687..e6f78e6b94a 100644 --- a/lib/Transforms/Vectorize/SLPVectorizer.cpp +++ b/lib/Transforms/Vectorize/SLPVectorizer.cpp @@ -578,12 +578,12 @@ private: void eraseInstruction(Instruction *I) { I->removeFromParent(); I->dropAllReferences(); - DeletedInstructions.push_back(std::unique_ptr(I)); + DeletedInstructions.emplace_back(I); } /// Temporary store for deleted instructions. Instructions will be deleted /// eventually when the BoUpSLP is destructed. - SmallVector, 8> DeletedInstructions; + SmallVector DeletedInstructions; /// A list of values that need to extracted out of the tree. /// This list holds pairs of (Internal Scalar : External User). External User diff --git a/unittests/IR/ConstantsTest.cpp b/unittests/IR/ConstantsTest.cpp index 6959ac85e49..7a8a3045a0d 100644 --- a/unittests/IR/ConstantsTest.cpp +++ b/unittests/IR/ConstantsTest.cpp @@ -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(x)->getAsInstruction(); \ - __I->print(__o); \ - delete __I; \ - __o.flush(); \ - EXPECT_EQ(std::string(" = " y), __s); \ +#define CHECK(x, y) \ + { \ + std::string __s; \ + raw_string_ostream __o(__s); \ + Instruction *__I = cast(x)->getAsInstruction(); \ + __I->print(__o); \ + __I->deleteValue(); \ + __o.flush(); \ + EXPECT_EQ(std::string(" = " y), __s); \ } TEST(ConstantsTest, AsInstructionsTest) { diff --git a/unittests/IR/InstructionsTest.cpp b/unittests/IR/InstructionsTest.cpp index b8d398c5cc3..619ddc5413d 100644 --- a/unittests/IR/InstructionsTest.cpp +++ b/unittests/IR/InstructionsTest.cpp @@ -406,8 +406,8 @@ TEST(InstructionsTest, FPMathOperator) { EXPECT_TRUE(isa(V1)); FPMathOperator *O1 = cast(V1); EXPECT_EQ(O1->getFPAccuracy(), 1.0); - delete V1; - delete I; + V1->deleteValue(); + I->deleteValue(); } diff --git a/unittests/IR/MetadataTest.cpp b/unittests/IR/MetadataTest.cpp index e61e649df19..9f8fc4eaeb6 100644 --- a/unittests/IR/MetadataTest.cpp +++ b/unittests/IR/MetadataTest.cpp @@ -218,7 +218,7 @@ TEST_F(MDNodeTest, Delete) { EXPECT_EQ(n, wvh); - delete I; + I->deleteValue(); } TEST_F(MDNodeTest, SelfReference) { diff --git a/unittests/Transforms/Utils/Cloning.cpp b/unittests/Transforms/Utils/Cloning.cpp index 83f146dca70..d13547a842e 100644 --- a/unittests/Transforms/Utils/Cloning.cpp +++ b/unittests/Transforms/Utils/Cloning.cpp @@ -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 Orig; // Erase on exit