Index: llvm/include/llvm/IR/Argument.h =================================================================== --- llvm/include/llvm/IR/Argument.h +++ llvm/include/llvm/IR/Argument.h @@ -27,8 +27,7 @@ /// 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: llvm/include/llvm/IR/BasicBlock.h =================================================================== --- llvm/include/llvm/IR/BasicBlock.h +++ llvm/include/llvm/IR/BasicBlock.h @@ -48,8 +48,8 @@ /// 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: typedef SymbolTableList InstListType; @@ -74,7 +74,7 @@ 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: llvm/include/llvm/IR/Constant.h =================================================================== --- llvm/include/llvm/IR/Constant.h +++ llvm/include/llvm/IR/Constant.h @@ -40,8 +40,6 @@ /// 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: llvm/include/llvm/IR/Constants.h =================================================================== --- llvm/include/llvm/IR/Constants.h +++ llvm/include/llvm/IR/Constants.h @@ -57,8 +57,6 @@ class ConstantData : public Constant { friend class Constant; - void anchor() override; - Value *handleOperandChangeImpl(Value *From, Value *To) { llvm_unreachable("Constant data does not have operands!"); } @@ -92,7 +90,6 @@ ConstantInt(IntegerType *Ty, const APInt& V); - void anchor() override; void destroyConstantImpl(); public: @@ -273,7 +270,6 @@ ConstantFP(Type *Ty, const APFloat& V); - void anchor() override; void destroyConstantImpl(); public: @@ -580,7 +576,7 @@ 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); @@ -684,8 +680,6 @@ return User::operator new(s, 0); } - void anchor() override; - public: ConstantDataArray(const ConstantDataArray &) = delete; @@ -747,8 +741,6 @@ return User::operator new(s, 0); } - void anchor() override; - public: ConstantDataVector(const ConstantDataVector &) = delete; Index: llvm/include/llvm/IR/DerivedUser.h =================================================================== --- /dev/null +++ llvm/include/llvm/IR/DerivedUser.h @@ -0,0 +1,50 @@ +//===-- 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. +// +//===----------------------------------------------------------------------===// +// +// This file declares the DerivedUser class, which is an extension point for the +// Value class hierarchy. 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. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_DERIVEDUSER_H +#define LLVM_IR_DERIVEDUSER_H + +#include "llvm/IR/User.h" + +namespace llvm { + +class ValueCallbacks; + +/// Extension point for the Value hierarchy. All classes outside of lib/IR +/// that wish to inherit from User should instead inherit from DerivedUser +/// instead. +class DerivedUser : public User { + friend Value; + ValueCallbacks *VCallbacks; + +public: + DerivedUser(Type *Ty, unsigned VK, Use *U, unsigned NumOps, + ValueCallbacks *VC) + : User(Ty, VK, U, NumOps), VCallbacks(VC) {} +}; + +/// Interface implemented for DerivedUser subclasses implemented outside of +/// lib/IR. +class ValueCallbacks { +public: + virtual ~ValueCallbacks(); // Satisfy -Wweak-vtables and -Wnon-virtual-dtor. + virtual void deleteValue(Value *DV) = 0; +}; + +} // namespace llvm + +#endif // LLVM_IR_DERIVEDUSER_H Index: llvm/include/llvm/IR/Function.h =================================================================== --- llvm/include/llvm/IR/Function.h +++ llvm/include/llvm/IR/Function.h @@ -115,7 +115,7 @@ 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) { @@ -485,7 +485,7 @@ /// copyAttributesFrom - copy all additional attributes (those not needed to /// create a Function) from the Function Src to this one. - void copyAttributesFrom(const GlobalValue *Src) override; + void copyAttributesFrom(const Function *Src); /// deleteBody - This method deletes the body of the function, and converts /// the linkage to external. @@ -498,12 +498,12 @@ /// removeFromParent - This method unlinks 'this' from the containing module, /// but does not delete it. /// - void removeFromParent() override; + void removeFromParent(); /// eraseFromParent - This method unlinks 'this' from the containing module /// and deletes it. /// - void eraseFromParent() override; + void eraseFromParent(); /// Steal arguments from another function. /// Index: llvm/include/llvm/IR/GlobalAlias.h =================================================================== --- llvm/include/llvm/IR/GlobalAlias.h +++ llvm/include/llvm/IR/GlobalAlias.h @@ -59,15 +59,19 @@ // Linkage, Type, Parent and AddressSpace taken from the Aliasee. static GlobalAlias *create(const Twine &Name, GlobalValue *Aliasee); + void copyAttributesFrom(const GlobalValue *Src) { + GlobalValue::copyAttributesFrom(Src); + } + /// removeFromParent - This method unlinks 'this' from the containing module, /// but does not delete it. /// - void removeFromParent() override; + void removeFromParent(); /// eraseFromParent - This method unlinks 'this' from the containing module /// and deletes it. /// - void eraseFromParent() override; + void eraseFromParent(); /// These methods retrieve and set alias target. void setAliasee(Constant *Aliasee); Index: llvm/include/llvm/IR/GlobalIFunc.h =================================================================== --- llvm/include/llvm/IR/GlobalIFunc.h +++ llvm/include/llvm/IR/GlobalIFunc.h @@ -47,12 +47,16 @@ LinkageTypes Linkage, const Twine &Name, Constant *Resolver, Module *Parent); + void copyAttributesFrom(const GlobalIFunc *Src) { + GlobalValue::copyAttributesFrom(Src); + } + /// This method unlinks 'this' from the containing module, but does not /// delete it. - void removeFromParent() final; + void removeFromParent(); /// This method unlinks 'this' from the containing module and deletes it. - void eraseFromParent() final; + void eraseFromParent(); /// These methods retrieve and set ifunc resolver function. void setResolver(Constant *Resolver) { Index: llvm/include/llvm/IR/GlobalObject.h =================================================================== --- llvm/include/llvm/IR/GlobalObject.h +++ llvm/include/llvm/IR/GlobalObject.h @@ -150,8 +150,10 @@ void addTypeMetadata(unsigned Offset, Metadata *TypeID); - void copyAttributesFrom(const GlobalValue *Src) override; +protected: + void copyAttributesFrom(const GlobalObject *Src); +public: // Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const Value *V) { return V->getValueID() == Value::FunctionVal || Index: llvm/include/llvm/IR/GlobalValue.h =================================================================== --- llvm/include/llvm/IR/GlobalValue.h +++ llvm/include/llvm/IR/GlobalValue.h @@ -161,6 +161,10 @@ Parent = parent; } + ~GlobalValue() { + removeDeadConstantUsers(); // remove any dead constants using this. + } + public: enum ThreadLocalMode { NotThreadLocal = 0, @@ -172,10 +176,7 @@ GlobalValue(const GlobalValue &) = delete; - ~GlobalValue() override { - removeDeadConstantUsers(); // remove any dead constants using this. - } - +public: unsigned getAlignment() const; enum class UnnamedAddr { @@ -435,10 +436,12 @@ bool isWeakForLinker() const { return isWeakForLinker(getLinkage()); } +protected: /// Copy all additional attributes (those not needed to create a GlobalValue) /// from the GlobalValue Src to this one. - virtual void copyAttributesFrom(const GlobalValue *Src); + void copyAttributesFrom(const GlobalValue *Src); +public: /// If special LLVM prefix that is used to inform the asm printer to not emit /// usual symbol prefix before the symbol name is used then return linkage /// name after skipping this special LLVM prefix. @@ -530,10 +533,10 @@ /// This method unlinks 'this' from the containing module, but does not delete /// it. - virtual void removeFromParent() = 0; + void removeFromParent(); /// This method unlinks 'this' from the containing module and deletes it. - virtual void eraseFromParent() = 0; + void eraseFromParent(); /// Get the module that this global value is contained inside of... Module *getParent() { return Parent; } Index: llvm/include/llvm/IR/GlobalVariable.h =================================================================== --- llvm/include/llvm/IR/GlobalVariable.h +++ llvm/include/llvm/IR/GlobalVariable.h @@ -64,7 +64,7 @@ GlobalVariable(const GlobalVariable &) = delete; GlobalVariable &operator=(const GlobalVariable &) = delete; - ~GlobalVariable() override { + ~GlobalVariable() { dropAllReferences(); // FIXME: needed by operator delete @@ -156,17 +156,17 @@ /// copyAttributesFrom - copy all additional attributes (those not needed to /// create a GlobalVariable) from the GlobalVariable Src to this one. - void copyAttributesFrom(const GlobalValue *Src) override; + void copyAttributesFrom(const GlobalVariable *Src); /// removeFromParent - This method unlinks 'this' from the containing module, /// but does not delete it. /// - void removeFromParent() override; + void removeFromParent(); /// eraseFromParent - This method unlinks 'this' from the containing module /// and deletes it. /// - void eraseFromParent() override; + void eraseFromParent(); /// Drop all references in preparation to destroy the GlobalVariable. This /// drops not only the reference to the initializer but also to any metadata. Index: llvm/include/llvm/IR/InlineAsm.h =================================================================== --- llvm/include/llvm/IR/InlineAsm.h +++ llvm/include/llvm/IR/InlineAsm.h @@ -28,7 +28,7 @@ class PointerType; template class ConstantUniqueMap; -class InlineAsm : public Value { +class InlineAsm final : public Value { public: enum AsmDialect { AD_ATT, @@ -48,7 +48,6 @@ 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: llvm/include/llvm/IR/InstrTypes.h =================================================================== --- llvm/include/llvm/IR/InstrTypes.h +++ llvm/include/llvm/IR/InstrTypes.h @@ -60,30 +60,15 @@ 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; - - /// Virtual methods - Terminators should overload these and provide inline - /// overrides of non-V methods. - virtual BasicBlock *getSuccessorV(unsigned idx) const = 0; - virtual unsigned getNumSuccessorsV() const = 0; - virtual void setSuccessorV(unsigned idx, BasicBlock *B) = 0; - public: /// Return the number of successors that this terminator has. - unsigned getNumSuccessors() const { - return getNumSuccessorsV(); - } + unsigned getNumSuccessors() const; /// Return the specified successor. - BasicBlock *getSuccessor(unsigned idx) const { - return getSuccessorV(idx); - } + BasicBlock *getSuccessor(unsigned idx) const; /// Update the specified successor to point at the provided block. - void setSuccessor(unsigned idx, BasicBlock *B) { - setSuccessorV(idx, B); - } + void setSuccessor(unsigned idx, BasicBlock *B); // Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const Instruction *I) { @@ -309,9 +294,6 @@ 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); @@ -576,8 +558,6 @@ /// 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, @@ -922,8 +902,6 @@ Value *LHS, Value *RHS, const Twine &Name, BasicBlock *InsertAtEnd); - void anchor() override; // Out of line virtual method. - public: CmpInst() = delete; Index: llvm/include/llvm/IR/Instruction.h =================================================================== --- llvm/include/llvm/IR/Instruction.h +++ llvm/include/llvm/IR/Instruction.h @@ -36,6 +36,10 @@ 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; @@ -51,9 +55,10 @@ Instruction(const Instruction &) = delete; Instruction &operator=(const Instruction &) = delete; - // Out of line virtual method, so the vtable, etc has a home. - ~Instruction() override; +protected: + ~Instruction(); // Use deleteValue() to delete a generic Instruction. +public: /// 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());} @@ -634,6 +639,10 @@ Instruction *cloneImpl() const; }; +inline void ilist_alloc_traits::deleteNode(Instruction *V) { + V->deleteValue(); +} + } // end namespace llvm #endif // LLVM_IR_INSTRUCTION_H Index: llvm/include/llvm/IR/Instruction.def =================================================================== --- llvm/include/llvm/IR/Instruction.def +++ llvm/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(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 @@ #undef HANDLE_OTHER_INST #undef LAST_OTHER_INST +#undef HANDLE_USER_INST + #ifdef HANDLE_INST #undef HANDLE_INST #endif Index: llvm/include/llvm/IR/Instructions.h =================================================================== --- llvm/include/llvm/IR/Instructions.h +++ llvm/include/llvm/IR/Instructions.h @@ -81,9 +81,6 @@ AllocaInst(Type *Ty, 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; @@ -831,8 +828,6 @@ Type *SourceElementType; Type *ResultElementType; - void anchor() override; - GetElementPtrInst(const GetElementPtrInst &GEPI); void init(Value *Ptr, ArrayRef IdxList, const Twine &NameStr); @@ -1100,8 +1095,6 @@ /// 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 && @@ -1414,8 +1407,6 @@ CallInst *cloneImpl() const; public: - ~CallInst() override; - static CallInst *Create(Value *Func, ArrayRef Args, ArrayRef Bundles = None, const Twine &NameStr = "", @@ -2554,8 +2545,6 @@ return User::operator new(s); } - void anchor() override; - protected: // Note: Instruction needs to be a friend here to call cloneImpl. friend class Instruction; @@ -2887,8 +2876,6 @@ ReturnInst *cloneImpl() const; public: - ~ReturnInst() override; - static ReturnInst* Create(LLVMContext &C, Value *retVal = nullptr, Instruction *InsertBefore = nullptr) { return new(!!retVal) ReturnInst(C, retVal, InsertBefore); @@ -2922,9 +2909,10 @@ } private: - BasicBlock *getSuccessorV(unsigned idx) const override; - unsigned getNumSuccessorsV() const override; - void setSuccessorV(unsigned idx, BasicBlock *B) override; + friend TerminatorInst; + BasicBlock *getSuccessorV(unsigned idx) const; + unsigned getNumSuccessorsV() const; + void setSuccessorV(unsigned idx, BasicBlock *B); }; template <> @@ -3032,9 +3020,10 @@ } private: - BasicBlock *getSuccessorV(unsigned idx) const override; - unsigned getNumSuccessorsV() const override; - void setSuccessorV(unsigned idx, BasicBlock *B) override; + friend TerminatorInst; + BasicBlock *getSuccessorV(unsigned idx) const; + unsigned getNumSuccessorsV() const; + void setSuccessorV(unsigned idx, BasicBlock *B); }; template <> @@ -3348,9 +3337,10 @@ } private: - BasicBlock *getSuccessorV(unsigned idx) const override; - unsigned getNumSuccessorsV() const override; - void setSuccessorV(unsigned idx, BasicBlock *B) override; + friend TerminatorInst; + BasicBlock *getSuccessorV(unsigned idx) const; + unsigned getNumSuccessorsV() const; + void setSuccessorV(unsigned idx, BasicBlock *B); }; template <> @@ -3453,9 +3443,10 @@ } private: - BasicBlock *getSuccessorV(unsigned idx) const override; - unsigned getNumSuccessorsV() const override; - void setSuccessorV(unsigned idx, BasicBlock *B) override; + friend TerminatorInst; + BasicBlock *getSuccessorV(unsigned idx) const; + unsigned getNumSuccessorsV() const; + void setSuccessorV(unsigned idx, BasicBlock *B); }; template <> @@ -3923,9 +3914,10 @@ } private: - BasicBlock *getSuccessorV(unsigned idx) const override; - unsigned getNumSuccessorsV() const override; - void setSuccessorV(unsigned idx, BasicBlock *B) override; + friend TerminatorInst; + BasicBlock *getSuccessorV(unsigned idx) const; + unsigned getNumSuccessorsV() const; + void setSuccessorV(unsigned idx, BasicBlock *B); template bool hasFnAttrImpl(AttrKind Kind) const { if (Attrs.hasAttribute(AttributeList::FunctionIndex, Kind)) @@ -4022,9 +4014,10 @@ } private: - BasicBlock *getSuccessorV(unsigned idx) const override; - unsigned getNumSuccessorsV() const override; - void setSuccessorV(unsigned idx, BasicBlock *B) override; + friend TerminatorInst; + BasicBlock *getSuccessorV(unsigned idx) const; + unsigned getNumSuccessorsV() const; + void setSuccessorV(unsigned idx, BasicBlock *B); }; template <> @@ -4205,9 +4198,10 @@ } private: - BasicBlock *getSuccessorV(unsigned Idx) const override; - unsigned getNumSuccessorsV() const override; - void setSuccessorV(unsigned Idx, BasicBlock *B) override; + friend TerminatorInst; + BasicBlock *getSuccessorV(unsigned Idx) const; + unsigned getNumSuccessorsV() const; + void setSuccessorV(unsigned Idx, BasicBlock *B); }; template <> @@ -4370,9 +4364,10 @@ } private: - BasicBlock *getSuccessorV(unsigned Idx) const override; - unsigned getNumSuccessorsV() const override; - void setSuccessorV(unsigned Idx, BasicBlock *B) override; + friend TerminatorInst; + BasicBlock *getSuccessorV(unsigned Idx) const; + unsigned getNumSuccessorsV() const; + void setSuccessorV(unsigned Idx, BasicBlock *B); }; template <> @@ -4458,9 +4453,10 @@ } private: - BasicBlock *getSuccessorV(unsigned Idx) const override; - unsigned getNumSuccessorsV() const override; - void setSuccessorV(unsigned Idx, BasicBlock *B) override; + friend TerminatorInst; + BasicBlock *getSuccessorV(unsigned Idx) const; + unsigned getNumSuccessorsV() const; + void setSuccessorV(unsigned Idx, BasicBlock *B); // Shadow Instruction::setInstructionSubclassData with a private forwarding // method so that subclasses cannot accidentally use it. @@ -4513,9 +4509,10 @@ } private: - BasicBlock *getSuccessorV(unsigned idx) const override; - unsigned getNumSuccessorsV() const override; - void setSuccessorV(unsigned idx, BasicBlock *B) override; + friend TerminatorInst; + BasicBlock *getSuccessorV(unsigned idx) const; + unsigned getNumSuccessorsV() const; + void setSuccessorV(unsigned idx, BasicBlock *B); }; //===----------------------------------------------------------------------===// Index: llvm/include/llvm/IR/Metadata.h =================================================================== --- llvm/include/llvm/IR/Metadata.h +++ llvm/include/llvm/IR/Metadata.h @@ -165,12 +165,13 @@ 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: llvm/include/llvm/IR/Operator.h =================================================================== --- llvm/include/llvm/IR/Operator.h +++ llvm/include/llvm/IR/Operator.h @@ -29,16 +29,11 @@ /// 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: llvm/include/llvm/IR/User.h =================================================================== --- llvm/include/llvm/IR/User.h +++ llvm/include/llvm/IR/User.h @@ -46,8 +46,6 @@ template friend struct HungoffOperandTraits; - virtual void anchor(); - LLVM_ATTRIBUTE_ALWAYS_INLINE inline static void * allocateFixedOperandUser(size_t, unsigned, unsigned); @@ -95,8 +93,10 @@ public: User(const User &) = delete; - ~User() override = default; +protected: + ~User() = default; +public: /// \brief Free memory allocated for User and Use objects. void operator delete(void *Usr); /// \brief Placement delete - required by std, but never called. Index: llvm/include/llvm/IR/Value.h =================================================================== --- llvm/include/llvm/IR/Value.h +++ llvm/include/llvm/IR/Value.h @@ -21,6 +21,7 @@ #include "llvm-c/Types.h" #include #include +#include namespace llvm { @@ -201,7 +202,18 @@ public: Value(const Value &) = delete; void operator=(const Value &) = delete; - virtual ~Value(); + +protected: + /// 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: + + /// Delete a pointer to a generic Value. + void deleteValue(); /// \brief Support for debugging, callable in GDB: V->dump() void dump() const; @@ -629,6 +641,13 @@ 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; Index: llvm/include/llvm/IR/Value.def =================================================================== --- llvm/include/llvm/IR/Value.def +++ llvm/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,10 @@ HANDLE_VALUE(Argument) HANDLE_VALUE(BasicBlock) -HANDLE_VALUE(MemoryUse) -HANDLE_VALUE(MemoryDef) -HANDLE_VALUE(MemoryPhi) + +HANDLE_MEMORY_VALUE(MemoryUse) +HANDLE_MEMORY_VALUE(MemoryDef) +HANDLE_MEMORY_VALUE(MemoryPhi) HANDLE_GLOBAL_VALUE(Function) HANDLE_GLOBAL_VALUE(GlobalAlias) @@ -94,6 +99,7 @@ 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: llvm/include/llvm/Transforms/Utils/MemorySSA.h =================================================================== --- llvm/include/llvm/Transforms/Utils/MemorySSA.h +++ llvm/include/llvm/Transforms/Utils/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 @@ // \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 @@ 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 @@ /// \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, + MemoryAccess(LLVMContext &C, unsigned Vty, ValueCallbacks *VC, BasicBlock *BB, unsigned NumOperands) - : User(Type::getVoidTy(C), Vty, nullptr, NumOperands), Block(BB) {} + : DerivedUser(Type::getVoidTy(C), Vty, nullptr, NumOperands, VC), + Block(BB) {} private: BasicBlock *Block; @@ -248,21 +249,21 @@ // 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) { + ValueCallbacks *VC, Instruction *MI, BasicBlock *BB) + : MemoryAccess(C, Vty, VC, BB, 1), MemoryInst(MI) { setDefiningAccess(DMA); } void setDefiningAccess(MemoryAccess *DMA, bool Optimized = false) { @@ -292,7 +293,8 @@ 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, getValueCallbacks(), 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 @@ 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: + ValueCallbacks *getValueCallbacks(); + unsigned int OptimizedID; }; @@ -350,8 +350,8 @@ 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, getValueCallbacks(), 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 @@ 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: + ValueCallbacks *getValueCallbacks(); + const unsigned ID; MemoryAccess *Optimized; unsigned int OptimizedID; @@ -432,7 +433,8 @@ 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, getValueCallbacks(), BB, 0), ID(Ver), + ReservedSpace(NumPreds) { allocHungoffUses(ReservedSpace); } @@ -534,7 +536,9 @@ 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 @@ User::allocHungoffUses(N, /* IsPhi */ true); } - unsigned getID() const final { return ID; } - private: // For debugging only const unsigned ID; @@ -561,8 +563,45 @@ ReservedSpace = std::max(E + E / 2, 2u); growHungoffUses(ReservedSpace, /* IsPhi */ true); } + + ValueCallbacks *getValueCallbacks(); }; +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) Index: llvm/lib/AsmParser/LLParser.cpp =================================================================== --- llvm/lib/AsmParser/LLParser.cpp +++ llvm/lib/AsmParser/LLParser.cpp @@ -2468,7 +2468,7 @@ continue; P.second.first->replaceAllUsesWith( UndefValue::get(P.second.first->getType())); - delete P.second.first; + P.second.first->deleteValue(); } for (const auto &P : ForwardRefValIDs) { @@ -2476,7 +2476,7 @@ continue; P.second.first->replaceAllUsesWith( UndefValue::get(P.second.first->getType())); - delete P.second.first; + P.second.first->deleteValue(); } } @@ -2608,7 +2608,7 @@ getTypeString(FI->second.first->getType()) + "'"); Sentinel->replaceAllUsesWith(Inst); - delete Sentinel; + Sentinel->deleteValue(); ForwardRefValIDs.erase(FI); } @@ -2625,7 +2625,7 @@ getTypeString(FI->second.first->getType()) + "'"); Sentinel->replaceAllUsesWith(Inst); - delete Sentinel; + Sentinel->deleteValue(); ForwardRefVals.erase(FI); } Index: llvm/lib/Bitcode/Reader/BitcodeReader.cpp =================================================================== --- llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -4332,11 +4332,11 @@ // 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: llvm/lib/Bitcode/Reader/ValueList.cpp =================================================================== --- llvm/lib/Bitcode/Reader/ValueList.cpp +++ llvm/lib/Bitcode/Reader/ValueList.cpp @@ -73,7 +73,7 @@ // 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 @@ // Update all ValueHandles, they should be the only users at this point. Placeholder->replaceAllUsesWith(RealVal); - delete Placeholder; + Placeholder->deleteValue(); } } Index: llvm/lib/CodeGen/CodeGenPrepare.cpp =================================================================== --- llvm/lib/CodeGen/CodeGenPrepare.cpp +++ llvm/lib/CodeGen/CodeGenPrepare.cpp @@ -349,7 +349,7 @@ // Really free removed instructions during promotion. for (Instruction *I : RemovedInsts) - delete I; + I->deleteValue(); EverMadeChange |= MadeChange; } Index: llvm/lib/IR/Constants.cpp =================================================================== --- llvm/lib/IR/Constants.cpp +++ llvm/lib/IR/Constants.cpp @@ -37,10 +37,6 @@ // 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 @@ // 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"); @@ -618,8 +612,6 @@ return &APFloat::PPCDoubleDouble(); } -void ConstantFP::anchor() { } - Constant *ConstantFP::get(Type *Ty, double V) { LLVMContext &Context = Ty->getContext(); @@ -2285,9 +2277,6 @@ //===----------------------------------------------------------------------===// // ConstantData* implementations -void ConstantDataArray::anchor() {} -void ConstantDataVector::anchor() {} - Type *ConstantDataSequential::getElementType() const { return getType()->getElementType(); } Index: llvm/lib/IR/ConstantsContext.h =================================================================== --- llvm/lib/IR/ConstantsContext.h +++ llvm/lib/IR/ConstantsContext.h @@ -43,8 +43,6 @@ /// 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) { @@ -64,8 +62,6 @@ /// 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) @@ -89,8 +85,6 @@ /// 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) { @@ -114,8 +108,6 @@ /// 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(), @@ -139,8 +131,6 @@ /// 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, @@ -165,8 +155,6 @@ /// 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( @@ -194,8 +182,6 @@ /// 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) @@ -229,8 +215,6 @@ /// 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) @@ -270,8 +254,6 @@ GetElementPtrConstantExpr(Type *SrcElementTy, Constant *C, ArrayRef IdxList, Type *DestTy); - void anchor() override; - public: static GetElementPtrConstantExpr *Create(Type *SrcElementTy, Constant *C, ArrayRef IdxList, @@ -300,8 +282,6 @@ // 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: llvm/lib/IR/Function.cpp =================================================================== --- llvm/lib/IR/Function.cpp +++ llvm/lib/IR/Function.cpp @@ -36,8 +36,6 @@ // 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); @@ -388,24 +386,20 @@ /// Copy all additional attributes (those not needed to create a Function) from /// the Function Src to this one. -void Function::copyAttributesFrom(const GlobalValue *Src) { +void Function::copyAttributesFrom(const Function *Src) { GlobalObject::copyAttributesFrom(Src); - const Function *SrcF = dyn_cast(Src); - if (!SrcF) - return; - - setCallingConv(SrcF->getCallingConv()); - setAttributes(SrcF->getAttributes()); - if (SrcF->hasGC()) - setGC(SrcF->getGC()); + setCallingConv(Src->getCallingConv()); + setAttributes(Src->getAttributes()); + if (Src->hasGC()) + setGC(Src->getGC()); else clearGC(); - if (SrcF->hasPersonalityFn()) - setPersonalityFn(SrcF->getPersonalityFn()); - if (SrcF->hasPrefixData()) - setPrefixData(SrcF->getPrefixData()); - if (SrcF->hasPrologueData()) - setPrologueData(SrcF->getPrologueData()); + if (Src->hasPersonalityFn()) + setPersonalityFn(Src->getPersonalityFn()); + if (Src->hasPrefixData()) + setPrefixData(Src->getPrefixData()); + if (Src->hasPrologueData()) + setPrologueData(Src->getPrologueData()); } /// Table of string intrinsic names indexed by enum value. Index: llvm/lib/IR/Globals.cpp =================================================================== --- llvm/lib/IR/Globals.cpp +++ llvm/lib/IR/Globals.cpp @@ -69,6 +69,30 @@ setDLLStorageClass(Src->getDLLStorageClass()); } +void GlobalValue::removeFromParent() { + switch (getValueID()) { +#define HANDLE_GLOBAL_VALUE(NAME) \ + case Value::NAME##Val: \ + return static_cast(this)->removeFromParent(); +#include "llvm/IR/Value.def" + default: + break; + } + llvm_unreachable("not a global"); +} + +void GlobalValue::eraseFromParent() { + switch (getValueID()) { +#define HANDLE_GLOBAL_VALUE(NAME) \ + case Value::NAME##Val: \ + return static_cast(this)->eraseFromParent(); +#include "llvm/IR/Value.def" + default: + break; + } + llvm_unreachable("not a global"); +} + unsigned GlobalValue::getAlignment() const { if (auto *GA = dyn_cast(this)) { // In general we cannot compute this at the IR level, but we try. @@ -93,12 +117,10 @@ assert(getAlignment() == Align && "Alignment representation error!"); } -void GlobalObject::copyAttributesFrom(const GlobalValue *Src) { +void GlobalObject::copyAttributesFrom(const GlobalObject *Src) { GlobalValue::copyAttributesFrom(Src); - if (const auto *GV = dyn_cast(Src)) { - setAlignment(GV->getAlignment()); - setSection(GV->getSection()); - } + setAlignment(Src->getAlignment()); + setSection(Src->getSection()); } std::string GlobalValue::getGlobalIdentifier(StringRef Name, @@ -333,12 +355,10 @@ /// Copy all additional attributes (those not needed to create a GlobalVariable) /// from the GlobalVariable Src to this one. -void GlobalVariable::copyAttributesFrom(const GlobalValue *Src) { +void GlobalVariable::copyAttributesFrom(const GlobalVariable *Src) { GlobalObject::copyAttributesFrom(Src); - if (const GlobalVariable *SrcVar = dyn_cast(Src)) { - setThreadLocalMode(SrcVar->getThreadLocalMode()); - setExternallyInitialized(SrcVar->isExternallyInitialized()); - } + setThreadLocalMode(Src->getThreadLocalMode()); + setExternallyInitialized(Src->isExternallyInitialized()); } void GlobalVariable::dropAllReferences() { Index: llvm/lib/IR/InlineAsm.cpp =================================================================== --- llvm/lib/IR/InlineAsm.cpp +++ llvm/lib/IR/InlineAsm.cpp @@ -40,10 +40,6 @@ "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: llvm/lib/IR/Instruction.cpp =================================================================== --- llvm/lib/IR/Instruction.cpp +++ llvm/lib/IR/Instruction.cpp @@ -43,8 +43,6 @@ 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: llvm/lib/IR/Instructions.cpp =================================================================== --- llvm/lib/IR/Instructions.cpp +++ llvm/lib/IR/Instructions.cpp @@ -41,16 +41,40 @@ // TerminatorInst Class //===----------------------------------------------------------------------===// -// Out of line virtual method, so the vtable, etc has a home. -TerminatorInst::~TerminatorInst() { +unsigned TerminatorInst::getNumSuccessors() const { + switch (getOpcode()) { +#define HANDLE_TERM_INST(N, OPC, CLASS) \ + case Instruction::OPC: \ + return static_cast(this)->getNumSuccessorsV(); +#include "llvm/IR/Instruction.def" + default: + break; + } + llvm_unreachable("not a terminator"); } -//===----------------------------------------------------------------------===// -// UnaryInstruction Class -//===----------------------------------------------------------------------===// +BasicBlock *TerminatorInst::getSuccessor(unsigned idx) const { + switch (getOpcode()) { +#define HANDLE_TERM_INST(N, OPC, CLASS) \ + case Instruction::OPC: \ + return static_cast(this)->getSuccessorV(idx); +#include "llvm/IR/Instruction.def" + default: + break; + } + llvm_unreachable("not a terminator"); +} -// Out of line virtual method, so the vtable, etc has a home. -UnaryInstruction::~UnaryInstruction() { +void TerminatorInst::setSuccessor(unsigned idx, BasicBlock *B) { + switch (getOpcode()) { +#define HANDLE_TERM_INST(N, OPC, CLASS) \ + case Instruction::OPC: \ + return static_cast(this)->setSuccessorV(idx, B); +#include "llvm/IR/Instruction.def" + default: + break; + } + llvm_unreachable("not a terminator"); } //===----------------------------------------------------------------------===// @@ -87,8 +111,6 @@ // PHINode Class //===----------------------------------------------------------------------===// -void PHINode::anchor() {} - PHINode::PHINode(const PHINode &PN) : Instruction(PN.getType(), Instruction::PHI, nullptr, PN.getNumOperands()), ReservedSpace(PN.getNumOperands()) { @@ -242,9 +264,6 @@ // CallInst Implementation //===----------------------------------------------------------------------===// -CallInst::~CallInst() { -} - void CallInst::init(FunctionType *FTy, Value *Func, ArrayRef Args, ArrayRef Bundles, const Twine &NameStr) { this->FTy = FTy; @@ -806,9 +825,6 @@ llvm_unreachable("ReturnInst has no successors!"); } -ReturnInst::~ReturnInst() { -} - //===----------------------------------------------------------------------===// // ResumeInst Implementation //===----------------------------------------------------------------------===// @@ -1233,10 +1249,6 @@ setName(Name); } -// Out of line virtual method, so the vtable, etc has a home. -AllocaInst::~AllocaInst() { -} - void AllocaInst::setAlignment(unsigned Align) { assert((Align & (Align-1)) == 0 && "Alignment is not a power of 2!"); assert(Align <= MaximumAlignment && @@ -1588,8 +1600,6 @@ // GetElementPtrInst Implementation //===----------------------------------------------------------------------===// -void GetElementPtrInst::anchor() {} - void GetElementPtrInst::init(Value *Ptr, ArrayRef IdxList, const Twine &Name) { assert(getNumOperands() == 1 + IdxList.size() && @@ -2266,8 +2276,6 @@ // CastInst Class //===----------------------------------------------------------------------===// -void CastInst::anchor() {} - // Just determine if this cast only deals with integral->integral conversion. bool CastInst::isIntegerCast() const { switch (getOpcode()) { @@ -3299,8 +3307,6 @@ // 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, @@ -3441,8 +3447,6 @@ } } -void ICmpInst::anchor() {} - ICmpInst::Predicate ICmpInst::getSignedPredicate(Predicate pred) { switch (pred) { default: llvm_unreachable("Unknown icmp predicate!"); Index: llvm/lib/IR/LLVMContextImpl.cpp =================================================================== --- llvm/lib/IR/LLVMContextImpl.cpp +++ llvm/lib/IR/LLVMContextImpl.cpp @@ -215,27 +215,6 @@ 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: llvm/lib/IR/User.cpp =================================================================== --- llvm/lib/IR/User.cpp +++ llvm/lib/IR/User.cpp @@ -19,8 +19,6 @@ // User Class //===----------------------------------------------------------------------===// -void User::anchor() {} - void User::replaceUsesOfWith(Value *From, Value *To) { if (From == To) return; // Duh what? @@ -193,12 +191,4 @@ } } -//===----------------------------------------------------------------------===// -// Operator Class -//===----------------------------------------------------------------------===// - -Operator::~Operator() { - llvm_unreachable("should never destroy an Operator"); -} - } // End llvm namespace Index: llvm/lib/IR/Value.cpp =================================================================== --- llvm/lib/IR/Value.cpp +++ llvm/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 @@ (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,31 @@ 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)->VCallbacks->deleteValue(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) @@ -900,3 +926,6 @@ // Pin the vtable to this file. void CallbackVH::anchor() {} + +// Pin the vtable to this file. +ValueCallbacks::~ValueCallbacks() {} Index: llvm/lib/Linker/IRMover.cpp =================================================================== --- llvm/lib/Linker/IRMover.cpp +++ llvm/lib/Linker/IRMover.cpp @@ -602,6 +602,7 @@ /*insertbefore*/ nullptr, SGVar->getThreadLocalMode(), SGVar->getType()->getAddressSpace()); NewDGV->setAlignment(SGVar->getAlignment()); + NewDGV->copyAttributesFrom(SGVar); return NewDGV; } @@ -610,8 +611,11 @@ Function *IRLinker::copyFunctionProto(const Function *SF) { // If there is no linkage to be performed or we are linking from the source, // bring SF over. - return Function::Create(TypeMap.get(SF->getFunctionType()), - GlobalValue::ExternalLinkage, SF->getName(), &DstM); + auto *F = + Function::Create(TypeMap.get(SF->getFunctionType()), + GlobalValue::ExternalLinkage, SF->getName(), &DstM); + F->copyAttributesFrom(SF); + return F; } /// Set up prototypes for any aliases that come over from the source module. @@ -619,9 +623,11 @@ // If there is no linkage to be performed or we're linking from the source, // bring over SGA. auto *Ty = TypeMap.get(SGA->getValueType()); - return GlobalAlias::create(Ty, SGA->getType()->getPointerAddressSpace(), - GlobalValue::ExternalLinkage, SGA->getName(), - &DstM); + auto *GA = + GlobalAlias::create(Ty, SGA->getType()->getPointerAddressSpace(), + GlobalValue::ExternalLinkage, SGA->getName(), &DstM); + GA->copyAttributesFrom(SGA); + return GA; } GlobalValue *IRLinker::copyGlobalValueProto(const GlobalValue *SGV, @@ -648,8 +654,6 @@ else if (SGV->hasExternalWeakLinkage()) NewGV->setLinkage(GlobalValue::ExternalWeakLinkage); - NewGV->copyAttributesFrom(SGV); - if (auto *NewGO = dyn_cast(NewGV)) { // Metadata for global variables and function declarations is copied eagerly. if (isa(SGV) || SGV->isDeclaration()) Index: llvm/lib/Target/Hexagon/HexagonLoopIdiomRecognition.cpp =================================================================== --- llvm/lib/Target/Hexagon/HexagonLoopIdiomRecognition.cpp +++ llvm/lib/Target/Hexagon/HexagonLoopIdiomRecognition.cpp @@ -398,7 +398,7 @@ for (Value *V : Clones) { Instruction *U = cast(V); if (!U->getParent()) - delete U; + U->deleteValue(); } } Index: llvm/lib/Transforms/Scalar/GVN.cpp =================================================================== --- llvm/lib/Transforms/Scalar/GVN.cpp +++ llvm/lib/Transforms/Scalar/GVN.cpp @@ -2057,7 +2057,7 @@ 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: llvm/lib/Transforms/Scalar/JumpThreading.cpp =================================================================== --- llvm/lib/Transforms/Scalar/JumpThreading.cpp +++ llvm/lib/Transforms/Scalar/JumpThreading.cpp @@ -1857,7 +1857,7 @@ SimplifyInstruction(New, BB->getModule()->getDataLayout())) { ValueMapping[&*BI] = IV; if (!New->mayHaveSideEffects()) { - delete New; + New->deleteValue(); New = nullptr; } } else { Index: llvm/lib/Transforms/Scalar/LoopRotation.cpp =================================================================== --- llvm/lib/Transforms/Scalar/LoopRotation.cpp +++ llvm/lib/Transforms/Scalar/LoopRotation.cpp @@ -349,7 +349,7 @@ // in the map. ValueMap[Inst] = V; if (!C->mayHaveSideEffects()) { - delete C; + C->deleteValue(); C = nullptr; } } else { Index: llvm/lib/Transforms/Scalar/Reassociate.cpp =================================================================== --- llvm/lib/Transforms/Scalar/Reassociate.cpp +++ llvm/lib/Transforms/Scalar/Reassociate.cpp @@ -1582,7 +1582,7 @@ } // No need for extra uses anymore. - delete DummyInst; + DummyInst->deleteValue(); unsigned NumAddedValues = NewMulOps.size(); Value *V = EmitAddTreeOfValues(I, NewMulOps); Index: llvm/lib/Transforms/Scalar/SROA.cpp =================================================================== --- llvm/lib/Transforms/Scalar/SROA.cpp +++ llvm/lib/Transforms/Scalar/SROA.cpp @@ -2439,7 +2439,7 @@ "insert"); LI.replaceAllUsesWith(V); Placeholder->replaceAllUsesWith(&LI); - delete Placeholder; + Placeholder->deleteValue(); } else { LI.replaceAllUsesWith(V); } Index: llvm/lib/Transforms/Scalar/StraightLineStrengthReduce.cpp =================================================================== --- llvm/lib/Transforms/Scalar/StraightLineStrengthReduce.cpp +++ llvm/lib/Transforms/Scalar/StraightLineStrengthReduce.cpp @@ -693,7 +693,7 @@ UnlinkedInst->setOperand(I, nullptr); RecursivelyDeleteTriviallyDeadInstructions(Op); } - delete UnlinkedInst; + UnlinkedInst->deleteValue(); } bool Ret = !UnlinkedInstructions.empty(); UnlinkedInstructions.clear(); Index: llvm/lib/Transforms/Utils/CloneFunction.cpp =================================================================== --- llvm/lib/Transforms/Utils/CloneFunction.cpp +++ llvm/lib/Transforms/Utils/CloneFunction.cpp @@ -298,7 +298,7 @@ if (!NewInst->mayHaveSideEffects()) { VMap[&*II] = V; - delete NewInst; + NewInst->deleteValue(); continue; } } Index: llvm/lib/Transforms/Utils/MemorySSA.cpp =================================================================== --- llvm/lib/Transforms/Utils/MemorySSA.cpp +++ llvm/lib/Transforms/Utils/MemorySSA.cpp @@ -1806,6 +1806,15 @@ 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(); @@ -1843,8 +1852,6 @@ OS << ')'; } -MemoryAccess::~MemoryAccess() {} - void MemoryUse::print(raw_ostream &OS) const { MemoryAccess *UO = getDefiningAccess(); OS << "MemoryUse("; @@ -2061,3 +2068,20 @@ return StartingAccess; } } // namespace llvm + +// Stamp out value callbacks to delete Memory SSA Value objects. +#define DEFINE_MEMORY_VALUE_CALLBACKS(Class) \ + namespace { \ + class Class##Callbacks : public ValueCallbacks { \ + public: \ + void deleteValue(Value *V) override { delete static_cast(V); } \ + }; \ + } /* end namespace */ \ + ValueCallbacks *llvm::Class::getValueCallbacks() { \ + static Class##Callbacks CB; \ + return &CB; \ + } +DEFINE_MEMORY_VALUE_CALLBACKS(MemoryPhi) +DEFINE_MEMORY_VALUE_CALLBACKS(MemoryDef) +DEFINE_MEMORY_VALUE_CALLBACKS(MemoryUse) +#undef DEFINE_MEMORY_VALUE_CALLBACKS Index: llvm/lib/Transforms/Utils/SimplifyCFG.cpp =================================================================== --- llvm/lib/Transforms/Utils/SimplifyCFG.cpp +++ llvm/lib/Transforms/Utils/SimplifyCFG.cpp @@ -2235,7 +2235,7 @@ 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: llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp =================================================================== --- llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp +++ llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp @@ -586,12 +586,12 @@ 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 Index: llvm/unittests/IR/ConstantsTest.cpp =================================================================== --- llvm/unittests/IR/ConstantsTest.cpp +++ llvm/unittests/IR/ConstantsTest.cpp @@ -178,14 +178,15 @@ 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) { Index: llvm/unittests/IR/InstructionsTest.cpp =================================================================== --- llvm/unittests/IR/InstructionsTest.cpp +++ llvm/unittests/IR/InstructionsTest.cpp @@ -405,8 +405,8 @@ EXPECT_TRUE(isa(V1)); FPMathOperator *O1 = cast(V1); EXPECT_EQ(O1->getFPAccuracy(), 1.0); - delete V1; - delete I; + V1->deleteValue(); + I->deleteValue(); } Index: llvm/unittests/IR/MetadataTest.cpp =================================================================== --- llvm/unittests/IR/MetadataTest.cpp +++ llvm/unittests/IR/MetadataTest.cpp @@ -218,7 +218,7 @@ EXPECT_EQ(n, wvh); - delete I; + I->deleteValue(); } TEST_F(MDNodeTest, SelfReference) { Index: llvm/unittests/Transforms/Utils/Cloning.cpp =================================================================== --- llvm/unittests/Transforms/Utils/Cloning.cpp +++ llvm/unittests/Transforms/Utils/Cloning.cpp @@ -41,13 +41,18 @@ } 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