mirror of
https://github.com/RPCS3/llvm.git
synced 2024-11-25 04:39:51 +00:00
[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<Value>. I had to add the "DerivedUser" Deleter escape hatch for MemorySSA, which derives from User outside of lib/IR. Code in IR cannot include MemorySSA headers or call the MemoryAccess object destructors without introducing a circular dependency, so we need some level of indirection. Unfortunately, no class derived from User may have any virtual methods, because adding a virtual method would break User::getHungOffOperands(), which assumes that it can find the use list immediately prior to the User object. I've added a static_assert to the appropriate OperandTraits templates to help people avoid this trap. Reviewers: chandlerc, mehdi_amini, pete, dberlin, george.burgess.iv Reviewed By: chandlerc Subscribers: krytarowski, eraman, george.burgess.iv, mzolotukhin, Prazek, nlewycky, hans, inglorion, pcc, tejohnson, dberlin, llvm-commits Differential Revision: https://reviews.llvm.org/D31261 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@303362 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
7db2df6d96
commit
816047d44c
@ -84,6 +84,7 @@
|
||||
#include "llvm/Analysis/MemoryLocation.h"
|
||||
#include "llvm/Analysis/PHITransAddr.h"
|
||||
#include "llvm/IR/BasicBlock.h"
|
||||
#include "llvm/IR/DerivedUser.h"
|
||||
#include "llvm/IR/Dominators.h"
|
||||
#include "llvm/IR/Module.h"
|
||||
#include "llvm/IR/OperandTraits.h"
|
||||
@ -127,7 +128,7 @@ using const_memoryaccess_def_iterator =
|
||||
// \brief The base for all memory accesses. All memory accesses in a block are
|
||||
// linked together using an intrusive list.
|
||||
class MemoryAccess
|
||||
: public User,
|
||||
: public DerivedUser,
|
||||
public ilist_node<MemoryAccess, ilist_tag<MSSAHelpers::AllAccessTag>>,
|
||||
public ilist_node<MemoryAccess, ilist_tag<MSSAHelpers::DefsOnlyTag>> {
|
||||
public:
|
||||
@ -145,15 +146,14 @@ public:
|
||||
|
||||
MemoryAccess(const MemoryAccess &) = delete;
|
||||
MemoryAccess &operator=(const MemoryAccess &) = delete;
|
||||
~MemoryAccess() override;
|
||||
|
||||
void *operator new(size_t, unsigned) = delete;
|
||||
void *operator new(size_t) = delete;
|
||||
|
||||
BasicBlock *getBlock() const { return Block; }
|
||||
|
||||
virtual void print(raw_ostream &OS) const = 0;
|
||||
virtual void dump() const;
|
||||
void print(raw_ostream &OS) const;
|
||||
void dump() const;
|
||||
|
||||
/// \brief The user iterators for a memory access
|
||||
typedef user_iterator iterator;
|
||||
@ -207,11 +207,12 @@ protected:
|
||||
|
||||
/// \brief Used for debugging and tracking things about MemoryAccesses.
|
||||
/// Guaranteed unique among MemoryAccesses, no guarantees otherwise.
|
||||
virtual unsigned getID() const = 0;
|
||||
inline unsigned getID() const;
|
||||
|
||||
MemoryAccess(LLVMContext &C, unsigned Vty, BasicBlock *BB,
|
||||
unsigned NumOperands)
|
||||
: User(Type::getVoidTy(C), Vty, nullptr, NumOperands), Block(BB) {}
|
||||
MemoryAccess(LLVMContext &C, unsigned Vty, DeleteValueTy DeleteValue,
|
||||
BasicBlock *BB, unsigned NumOperands)
|
||||
: DerivedUser(Type::getVoidTy(C), Vty, nullptr, NumOperands, DeleteValue),
|
||||
Block(BB) {}
|
||||
|
||||
private:
|
||||
BasicBlock *Block;
|
||||
@ -248,21 +249,21 @@ public:
|
||||
|
||||
// Sadly, these have to be public because they are needed in some of the
|
||||
// iterators.
|
||||
virtual bool isOptimized() const = 0;
|
||||
virtual MemoryAccess *getOptimized() const = 0;
|
||||
virtual void setOptimized(MemoryAccess *) = 0;
|
||||
inline bool isOptimized() const;
|
||||
inline MemoryAccess *getOptimized() const;
|
||||
inline void setOptimized(MemoryAccess *);
|
||||
|
||||
/// \brief Reset the ID of what this MemoryUse was optimized to, causing it to
|
||||
/// be rewalked by the walker if necessary.
|
||||
/// This really should only be called by tests.
|
||||
virtual void resetOptimized() = 0;
|
||||
inline void resetOptimized();
|
||||
|
||||
protected:
|
||||
friend class MemorySSA;
|
||||
friend class MemorySSAUpdater;
|
||||
MemoryUseOrDef(LLVMContext &C, MemoryAccess *DMA, unsigned Vty,
|
||||
Instruction *MI, BasicBlock *BB)
|
||||
: MemoryAccess(C, Vty, BB, 1), MemoryInst(MI) {
|
||||
DeleteValueTy DeleteValue, Instruction *MI, BasicBlock *BB)
|
||||
: MemoryAccess(C, Vty, DeleteValue, BB, 1), MemoryInst(MI) {
|
||||
setDefiningAccess(DMA);
|
||||
}
|
||||
void setDefiningAccess(MemoryAccess *DMA, bool Optimized = false) {
|
||||
@ -292,7 +293,8 @@ public:
|
||||
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(MemoryAccess);
|
||||
|
||||
MemoryUse(LLVMContext &C, MemoryAccess *DMA, Instruction *MI, BasicBlock *BB)
|
||||
: MemoryUseOrDef(C, DMA, MemoryUseVal, MI, BB), OptimizedID(0) {}
|
||||
: MemoryUseOrDef(C, DMA, MemoryUseVal, deleteMe, MI, BB),
|
||||
OptimizedID(0) {}
|
||||
|
||||
// allocate space for exactly one operand
|
||||
void *operator new(size_t s) { return User::operator new(s, 1); }
|
||||
@ -302,32 +304,30 @@ public:
|
||||
return MA->getValueID() == MemoryUseVal;
|
||||
}
|
||||
|
||||
void print(raw_ostream &OS) const override;
|
||||
void print(raw_ostream &OS) const;
|
||||
|
||||
virtual void setOptimized(MemoryAccess *DMA) override {
|
||||
void setOptimized(MemoryAccess *DMA) {
|
||||
OptimizedID = DMA->getID();
|
||||
setOperand(0, DMA);
|
||||
}
|
||||
|
||||
virtual bool isOptimized() const override {
|
||||
bool isOptimized() const {
|
||||
return getDefiningAccess() && OptimizedID == getDefiningAccess()->getID();
|
||||
}
|
||||
|
||||
virtual MemoryAccess *getOptimized() const override {
|
||||
MemoryAccess *getOptimized() const {
|
||||
return getDefiningAccess();
|
||||
}
|
||||
virtual void resetOptimized() override {
|
||||
void resetOptimized() {
|
||||
OptimizedID = INVALID_MEMORYACCESS_ID;
|
||||
}
|
||||
|
||||
protected:
|
||||
friend class MemorySSA;
|
||||
|
||||
unsigned getID() const override {
|
||||
llvm_unreachable("MemoryUses do not have IDs");
|
||||
}
|
||||
|
||||
private:
|
||||
static void deleteMe(DerivedUser *Self);
|
||||
|
||||
unsigned int OptimizedID;
|
||||
};
|
||||
|
||||
@ -350,8 +350,8 @@ public:
|
||||
|
||||
MemoryDef(LLVMContext &C, MemoryAccess *DMA, Instruction *MI, BasicBlock *BB,
|
||||
unsigned Ver)
|
||||
: MemoryUseOrDef(C, DMA, MemoryDefVal, MI, BB), ID(Ver),
|
||||
Optimized(nullptr), OptimizedID(INVALID_MEMORYACCESS_ID) {}
|
||||
: MemoryUseOrDef(C, DMA, MemoryDefVal, deleteMe, MI, BB),
|
||||
ID(Ver), Optimized(nullptr), OptimizedID(INVALID_MEMORYACCESS_ID) {}
|
||||
|
||||
// allocate space for exactly one operand
|
||||
void *operator new(size_t s) { return User::operator new(s, 1); }
|
||||
@ -361,27 +361,28 @@ public:
|
||||
return MA->getValueID() == MemoryDefVal;
|
||||
}
|
||||
|
||||
virtual void setOptimized(MemoryAccess *MA) override {
|
||||
void setOptimized(MemoryAccess *MA) {
|
||||
Optimized = MA;
|
||||
OptimizedID = getDefiningAccess()->getID();
|
||||
}
|
||||
virtual MemoryAccess *getOptimized() const override { return Optimized; }
|
||||
virtual bool isOptimized() const override {
|
||||
MemoryAccess *getOptimized() const { return Optimized; }
|
||||
bool isOptimized() const {
|
||||
return getOptimized() && getDefiningAccess() &&
|
||||
OptimizedID == getDefiningAccess()->getID();
|
||||
}
|
||||
virtual void resetOptimized() override {
|
||||
void resetOptimized() {
|
||||
OptimizedID = INVALID_MEMORYACCESS_ID;
|
||||
}
|
||||
|
||||
void print(raw_ostream &OS) const override;
|
||||
void print(raw_ostream &OS) const;
|
||||
|
||||
protected:
|
||||
friend class MemorySSA;
|
||||
|
||||
unsigned getID() const override { return ID; }
|
||||
unsigned getID() const { return ID; }
|
||||
|
||||
private:
|
||||
static void deleteMe(DerivedUser *Self);
|
||||
|
||||
const unsigned ID;
|
||||
MemoryAccess *Optimized;
|
||||
unsigned int OptimizedID;
|
||||
@ -432,7 +433,8 @@ public:
|
||||
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(MemoryAccess);
|
||||
|
||||
MemoryPhi(LLVMContext &C, BasicBlock *BB, unsigned Ver, unsigned NumPreds = 0)
|
||||
: MemoryAccess(C, MemoryPhiVal, BB, 0), ID(Ver), ReservedSpace(NumPreds) {
|
||||
: MemoryAccess(C, MemoryPhiVal, deleteMe, BB, 0), ID(Ver),
|
||||
ReservedSpace(NumPreds) {
|
||||
allocHungoffUses(ReservedSpace);
|
||||
}
|
||||
|
||||
@ -534,7 +536,9 @@ public:
|
||||
return V->getValueID() == MemoryPhiVal;
|
||||
}
|
||||
|
||||
void print(raw_ostream &OS) const override;
|
||||
void print(raw_ostream &OS) const;
|
||||
|
||||
unsigned getID() const { return ID; }
|
||||
|
||||
protected:
|
||||
friend class MemorySSA;
|
||||
@ -546,8 +550,6 @@ protected:
|
||||
User::allocHungoffUses(N, /* IsPhi */ true);
|
||||
}
|
||||
|
||||
unsigned getID() const final { return ID; }
|
||||
|
||||
private:
|
||||
// For debugging only
|
||||
const unsigned ID;
|
||||
@ -561,8 +563,45 @@ private:
|
||||
ReservedSpace = std::max(E + E / 2, 2u);
|
||||
growHungoffUses(ReservedSpace, /* IsPhi */ true);
|
||||
}
|
||||
|
||||
static void deleteMe(DerivedUser *Self);
|
||||
};
|
||||
|
||||
inline unsigned MemoryAccess::getID() const {
|
||||
assert((isa<MemoryDef>(this) || isa<MemoryPhi>(this)) &&
|
||||
"only memory defs and phis have ids");
|
||||
if (const auto *MD = dyn_cast<MemoryDef>(this))
|
||||
return MD->getID();
|
||||
return cast<MemoryPhi>(this)->getID();
|
||||
}
|
||||
|
||||
inline bool MemoryUseOrDef::isOptimized() const {
|
||||
if (const auto *MD = dyn_cast<MemoryDef>(this))
|
||||
return MD->isOptimized();
|
||||
return cast<MemoryUse>(this)->isOptimized();
|
||||
}
|
||||
|
||||
inline MemoryAccess *MemoryUseOrDef::getOptimized() const {
|
||||
if (const auto *MD = dyn_cast<MemoryDef>(this))
|
||||
return MD->getOptimized();
|
||||
return cast<MemoryUse>(this)->getOptimized();
|
||||
}
|
||||
|
||||
inline void MemoryUseOrDef::setOptimized(MemoryAccess *MA) {
|
||||
if (auto *MD = dyn_cast<MemoryDef>(this))
|
||||
MD->setOptimized(MA);
|
||||
else
|
||||
cast<MemoryUse>(this)->setOptimized(MA);
|
||||
}
|
||||
|
||||
inline void MemoryUseOrDef::resetOptimized() {
|
||||
if (auto *MD = dyn_cast<MemoryDef>(this))
|
||||
MD->resetOptimized();
|
||||
else
|
||||
cast<MemoryUse>(this)->resetOptimized();
|
||||
}
|
||||
|
||||
|
||||
template <> struct OperandTraits<MemoryPhi> : public HungoffOperandTraits<2> {};
|
||||
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(MemoryPhi, MemoryAccess)
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -51,7 +51,7 @@ 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
|
||||
class BasicBlock final : public Value, // Basic blocks are data objects also
|
||||
public ilist_node_with_parent<BasicBlock, Function> {
|
||||
public:
|
||||
using InstListType = SymbolTableList<Instruction>;
|
||||
@ -77,7 +77,7 @@ private:
|
||||
public:
|
||||
BasicBlock(const BasicBlock &) = delete;
|
||||
BasicBlock &operator=(const BasicBlock &) = delete;
|
||||
~BasicBlock() override;
|
||||
~BasicBlock();
|
||||
|
||||
/// \brief Get the context in which this basic block lives.
|
||||
LLVMContext &getContext() const;
|
||||
|
@ -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) {}
|
||||
|
@ -58,8 +58,6 @@ template <class ConstantClass> struct ConstantAggrKeyType;
|
||||
class ConstantData : public Constant {
|
||||
friend class Constant;
|
||||
|
||||
void anchor() override;
|
||||
|
||||
Value *handleOperandChangeImpl(Value *From, Value *To) {
|
||||
llvm_unreachable("Constant data does not have operands!");
|
||||
}
|
||||
@ -93,7 +91,6 @@ class ConstantInt final : public ConstantData {
|
||||
|
||||
ConstantInt(IntegerType *Ty, const APInt& V);
|
||||
|
||||
void anchor() override;
|
||||
void destroyConstantImpl();
|
||||
|
||||
public:
|
||||
@ -274,7 +271,6 @@ class ConstantFP final : public ConstantData {
|
||||
|
||||
ConstantFP(Type *Ty, const APFloat& V);
|
||||
|
||||
void anchor() override;
|
||||
void destroyConstantImpl();
|
||||
|
||||
public:
|
||||
@ -588,7 +584,7 @@ class ConstantDataSequential : public ConstantData {
|
||||
protected:
|
||||
explicit ConstantDataSequential(Type *ty, ValueTy VT, const char *Data)
|
||||
: ConstantData(ty, VT), DataElements(Data), Next(nullptr) {}
|
||||
~ConstantDataSequential() override { delete Next; }
|
||||
~ConstantDataSequential() { delete Next; }
|
||||
|
||||
static Constant *getImpl(StringRef Bytes, Type *Ty);
|
||||
|
||||
@ -692,8 +688,6 @@ class ConstantDataArray final : public ConstantDataSequential {
|
||||
return User::operator new(s, 0);
|
||||
}
|
||||
|
||||
void anchor() override;
|
||||
|
||||
public:
|
||||
ConstantDataArray(const ConstantDataArray &) = delete;
|
||||
|
||||
@ -755,8 +749,6 @@ class ConstantDataVector final : public ConstantDataSequential {
|
||||
return User::operator new(s, 0);
|
||||
}
|
||||
|
||||
void anchor() override;
|
||||
|
||||
public:
|
||||
ConstantDataVector(const ConstantDataVector &) = delete;
|
||||
|
||||
|
41
include/llvm/IR/DerivedUser.h
Normal file
41
include/llvm/IR/DerivedUser.h
Normal file
@ -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
|
@ -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) {
|
||||
|
@ -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 {
|
||||
|
@ -66,7 +66,7 @@ public:
|
||||
GlobalVariable(const GlobalVariable &) = delete;
|
||||
GlobalVariable &operator=(const GlobalVariable &) = delete;
|
||||
|
||||
~GlobalVariable() override {
|
||||
~GlobalVariable() {
|
||||
dropAllReferences();
|
||||
|
||||
// FIXME: needed by operator delete
|
||||
|
@ -28,7 +28,7 @@ class FunctionType;
|
||||
class PointerType;
|
||||
template <class ConstantClass> class ConstantUniqueMap;
|
||||
|
||||
class InlineAsm : public Value {
|
||||
class InlineAsm final : public Value {
|
||||
public:
|
||||
enum AsmDialect {
|
||||
AD_ATT,
|
||||
@ -48,7 +48,6 @@ private:
|
||||
InlineAsm(FunctionType *Ty, const std::string &AsmString,
|
||||
const std::string &Constraints, bool hasSideEffects,
|
||||
bool isAlignStack, AsmDialect asmDialect);
|
||||
~InlineAsm() override;
|
||||
|
||||
/// When the ConstantUniqueMap merges two types and makes two InlineAsms
|
||||
/// identical, it destroys one of them with this method.
|
||||
|
@ -62,9 +62,6 @@ protected:
|
||||
Use *Ops, unsigned NumOps, BasicBlock *InsertAtEnd)
|
||||
: Instruction(Ty, iType, Ops, NumOps, InsertAtEnd) {}
|
||||
|
||||
// Out of line virtual method, so the vtable, etc has a home.
|
||||
~TerminatorInst() override;
|
||||
|
||||
public:
|
||||
/// Return the number of successors that this terminator has.
|
||||
unsigned getNumSuccessors() const;
|
||||
@ -299,9 +296,6 @@ public:
|
||||
|
||||
void *operator new(size_t, unsigned) = delete;
|
||||
|
||||
// Out of line virtual method, so the vtable, etc has a home.
|
||||
~UnaryInstruction() override;
|
||||
|
||||
/// Transparently provide more efficient getOperand methods.
|
||||
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
|
||||
|
||||
@ -568,8 +562,6 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(BinaryOperator, Value)
|
||||
/// if (isa<CastInst>(Instr)) { ... }
|
||||
/// @brief Base class of casting instructions.
|
||||
class CastInst : public UnaryInstruction {
|
||||
void anchor() override;
|
||||
|
||||
protected:
|
||||
/// @brief Constructor with insert-before-instruction semantics for subclasses
|
||||
CastInst(Type *Ty, unsigned iType, Value *S,
|
||||
@ -914,8 +906,6 @@ protected:
|
||||
Value *LHS, Value *RHS, const Twine &Name,
|
||||
BasicBlock *InsertAtEnd);
|
||||
|
||||
void anchor() override; // Out of line virtual method.
|
||||
|
||||
public:
|
||||
CmpInst() = delete;
|
||||
|
||||
|
@ -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
|
||||
|
@ -36,6 +36,10 @@ class FastMathFlags;
|
||||
class MDNode;
|
||||
struct AAMDNodes;
|
||||
|
||||
template <> struct ilist_alloc_traits<Instruction> {
|
||||
static inline void deleteNode(Instruction *V);
|
||||
};
|
||||
|
||||
class Instruction : public User,
|
||||
public ilist_node_with_parent<Instruction, BasicBlock> {
|
||||
BasicBlock *Parent;
|
||||
@ -47,13 +51,13 @@ class Instruction : public User,
|
||||
HasMetadataBit = 1 << 15
|
||||
};
|
||||
|
||||
protected:
|
||||
~Instruction(); // Use deleteValue() to delete a generic Instruction.
|
||||
|
||||
public:
|
||||
Instruction(const Instruction &) = delete;
|
||||
Instruction &operator=(const Instruction &) = delete;
|
||||
|
||||
// Out of line virtual method, so the vtable, etc has a home.
|
||||
~Instruction() override;
|
||||
|
||||
/// Specialize the methods defined in Value, as we know that an instruction
|
||||
/// can only be used by other instructions.
|
||||
Instruction *user_back() { return cast<Instruction>(*user_begin());}
|
||||
@ -640,6 +644,10 @@ private:
|
||||
Instruction *cloneImpl() const;
|
||||
};
|
||||
|
||||
inline void ilist_alloc_traits<Instruction>::deleteNode(Instruction *V) {
|
||||
V->deleteValue();
|
||||
}
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif // LLVM_IR_INSTRUCTION_H
|
||||
|
@ -89,9 +89,6 @@ public:
|
||||
AllocaInst(Type *Ty, unsigned AddrSpace, Value *ArraySize, unsigned Align,
|
||||
const Twine &Name, BasicBlock *InsertAtEnd);
|
||||
|
||||
// Out of line virtual method, so the vtable, etc. has a home.
|
||||
~AllocaInst() override;
|
||||
|
||||
/// Return true if there is an allocation size parameter to the allocation
|
||||
/// instruction that is not 1.
|
||||
bool isArrayAllocation() const;
|
||||
@ -856,7 +853,6 @@ class GetElementPtrInst : public Instruction {
|
||||
ArrayRef<Value *> IdxList, unsigned Values,
|
||||
const Twine &NameStr, BasicBlock *InsertAtEnd);
|
||||
|
||||
void anchor() override;
|
||||
void init(Value *Ptr, ArrayRef<Value *> IdxList, const Twine &NameStr);
|
||||
|
||||
protected:
|
||||
@ -1112,8 +1108,6 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(GetElementPtrInst, Value)
|
||||
/// must be identical types.
|
||||
/// Represent an integer comparison operator.
|
||||
class ICmpInst: public CmpInst {
|
||||
void anchor() override;
|
||||
|
||||
void AssertOK() {
|
||||
assert(getPredicate() >= CmpInst::FIRST_ICMP_PREDICATE &&
|
||||
getPredicate() <= CmpInst::LAST_ICMP_PREDICATE &&
|
||||
@ -1426,8 +1420,6 @@ protected:
|
||||
CallInst *cloneImpl() const;
|
||||
|
||||
public:
|
||||
~CallInst() override;
|
||||
|
||||
static CallInst *Create(Value *Func, ArrayRef<Value *> Args,
|
||||
ArrayRef<OperandBundleDef> Bundles = None,
|
||||
const Twine &NameStr = "",
|
||||
@ -2592,8 +2584,6 @@ class PHINode : public Instruction {
|
||||
return User::operator new(s);
|
||||
}
|
||||
|
||||
void anchor() override;
|
||||
|
||||
protected:
|
||||
// Note: Instruction needs to be a friend here to call cloneImpl.
|
||||
friend class Instruction;
|
||||
@ -2927,8 +2917,6 @@ protected:
|
||||
ReturnInst *cloneImpl() const;
|
||||
|
||||
public:
|
||||
~ReturnInst() override;
|
||||
|
||||
static ReturnInst* Create(LLVMContext &C, Value *retVal = nullptr,
|
||||
Instruction *InsertBefore = nullptr) {
|
||||
return new(!!retVal) ReturnInst(C, retVal, InsertBefore);
|
||||
|
@ -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; }
|
||||
|
@ -30,6 +30,9 @@ namespace llvm {
|
||||
template <typename SubClass, unsigned ARITY>
|
||||
struct FixedNumOperandTraits {
|
||||
static Use *op_begin(SubClass* U) {
|
||||
static_assert(
|
||||
!std::is_polymorphic<SubClass>::value,
|
||||
"adding virtual methods to subclasses of User breaks use lists");
|
||||
return reinterpret_cast<Use*>(U) - ARITY;
|
||||
}
|
||||
static Use *op_end(SubClass* U) {
|
||||
@ -65,6 +68,9 @@ struct OptionalOperandTraits : public FixedNumOperandTraits<SubClass, ARITY> {
|
||||
template <typename SubClass, unsigned MINARITY = 0>
|
||||
struct VariadicOperandTraits {
|
||||
static Use *op_begin(SubClass* U) {
|
||||
static_assert(
|
||||
!std::is_polymorphic<SubClass>::value,
|
||||
"adding virtual methods to subclasses of User breaks use lists");
|
||||
return reinterpret_cast<Use*>(U) - static_cast<User*>(U)->getNumOperands();
|
||||
}
|
||||
static Use *op_end(SubClass* U) {
|
||||
|
@ -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;
|
||||
|
@ -46,8 +46,6 @@ class User : public Value {
|
||||
template <unsigned>
|
||||
friend struct HungoffOperandTraits;
|
||||
|
||||
virtual void anchor();
|
||||
|
||||
LLVM_ATTRIBUTE_ALWAYS_INLINE inline static void *
|
||||
allocateFixedOperandUser(size_t, unsigned, unsigned);
|
||||
|
||||
@ -93,9 +91,11 @@ protected:
|
||||
/// should be called if there are no uses.
|
||||
void growHungoffUses(unsigned N, bool IsPhi = false);
|
||||
|
||||
protected:
|
||||
~User() = default; // Use deleteValue() to delete a generic Instruction.
|
||||
|
||||
public:
|
||||
User(const User &) = delete;
|
||||
~User() override = default;
|
||||
|
||||
/// \brief Free memory allocated for User and Use objects.
|
||||
void operator delete(void *Usr);
|
||||
|
@ -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
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "llvm-c/Types.h"
|
||||
#include <cassert>
|
||||
#include <iterator>
|
||||
#include <memory>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
@ -69,6 +70,8 @@ using ValueName = StringMapEntry<Value*>;
|
||||
/// objects that watch it and listen to RAUW and Destroy events. See
|
||||
/// llvm/IR/ValueHandle.h for details.
|
||||
class Value {
|
||||
// The least-significant bit of the first word of Value *must* be zero:
|
||||
// http://www.llvm.org/docs/ProgrammersManual.html#the-waymarking-algorithm
|
||||
Type *VTy;
|
||||
Use *UseList;
|
||||
|
||||
@ -200,10 +203,19 @@ private:
|
||||
protected:
|
||||
Value(Type *Ty, unsigned scid);
|
||||
|
||||
/// Value's destructor should be virtual by design, but that would require
|
||||
/// that Value and all of its subclasses have a vtable that effectively
|
||||
/// duplicates the information in the value ID. As a size optimization, the
|
||||
/// destructor has been protected, and the caller should manually call
|
||||
/// deleteValue.
|
||||
~Value(); // Use deleteValue() to delete a generic Value.
|
||||
|
||||
public:
|
||||
Value(const Value &) = delete;
|
||||
void operator=(const Value &) = delete;
|
||||
virtual ~Value();
|
||||
|
||||
/// Delete a pointer to a generic Value.
|
||||
void deleteValue();
|
||||
|
||||
/// \brief Support for debugging, callable in GDB: V->dump()
|
||||
void dump() const;
|
||||
@ -643,6 +655,13 @@ protected:
|
||||
void setValueSubclassData(unsigned short D) { SubclassData = D; }
|
||||
};
|
||||
|
||||
struct ValueDeleter { void operator()(Value *V) { V->deleteValue(); } };
|
||||
|
||||
/// Use this instead of std::unique_ptr<Value> or std::unique_ptr<Instruction>.
|
||||
/// Those don't work because Value and Instruction's destructors are protected,
|
||||
/// aren't virtual, and won't destroy the complete object.
|
||||
typedef std::unique_ptr<Value, ValueDeleter> unique_value;
|
||||
|
||||
inline raw_ostream &operator<<(raw_ostream &OS, const Value &V) {
|
||||
V.print(OS);
|
||||
return OS;
|
||||
|
@ -1799,6 +1799,15 @@ bool MemorySSA::dominates(const MemoryAccess *Dominator,
|
||||
|
||||
const static char LiveOnEntryStr[] = "liveOnEntry";
|
||||
|
||||
void MemoryAccess::print(raw_ostream &OS) const {
|
||||
switch (getValueID()) {
|
||||
case MemoryPhiVal: return static_cast<const MemoryPhi *>(this)->print(OS);
|
||||
case MemoryDefVal: return static_cast<const MemoryDef *>(this)->print(OS);
|
||||
case MemoryUseVal: return static_cast<const MemoryUse *>(this)->print(OS);
|
||||
}
|
||||
llvm_unreachable("invalid value id");
|
||||
}
|
||||
|
||||
void MemoryDef::print(raw_ostream &OS) const {
|
||||
MemoryAccess *UO = getDefiningAccess();
|
||||
|
||||
@ -1836,8 +1845,6 @@ void MemoryPhi::print(raw_ostream &OS) const {
|
||||
OS << ')';
|
||||
}
|
||||
|
||||
MemoryAccess::~MemoryAccess() {}
|
||||
|
||||
void MemoryUse::print(raw_ostream &OS) const {
|
||||
MemoryAccess *UO = getDefiningAccess();
|
||||
OS << "MemoryUse(";
|
||||
@ -2054,3 +2061,15 @@ MemoryAccess *DoNothingMemorySSAWalker::getClobberingMemoryAccess(
|
||||
return StartingAccess;
|
||||
}
|
||||
} // namespace llvm
|
||||
|
||||
void MemoryPhi::deleteMe(DerivedUser *Self) {
|
||||
delete static_cast<MemoryPhi *>(Self);
|
||||
}
|
||||
|
||||
void MemoryDef::deleteMe(DerivedUser *Self) {
|
||||
delete static_cast<MemoryDef *>(Self);
|
||||
}
|
||||
|
||||
void MemoryUse::deleteMe(DerivedUser *Self) {
|
||||
delete static_cast<MemoryUse *>(Self);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -37,10 +37,6 @@ using namespace llvm;
|
||||
// Constant Class
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
void Constant::anchor() { }
|
||||
|
||||
void ConstantData::anchor() {}
|
||||
|
||||
bool Constant::isNegativeZeroValue() const {
|
||||
// Floating point values have an explicit -0.0 value.
|
||||
if (const ConstantFP *CFP = dyn_cast<ConstantFP>(this))
|
||||
@ -496,8 +492,6 @@ void Constant::removeDeadConstantUsers() const {
|
||||
// ConstantInt
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
void ConstantInt::anchor() { }
|
||||
|
||||
ConstantInt::ConstantInt(IntegerType *Ty, const APInt &V)
|
||||
: ConstantData(Ty, ConstantIntVal), Val(V) {
|
||||
assert(V.getBitWidth() == Ty->getBitWidth() && "Invalid constant for type");
|
||||
@ -610,8 +604,6 @@ static const fltSemantics *TypeToFloatSemantics(Type *Ty) {
|
||||
return &APFloat::PPCDoubleDouble();
|
||||
}
|
||||
|
||||
void ConstantFP::anchor() { }
|
||||
|
||||
Constant *ConstantFP::get(Type *Ty, double V) {
|
||||
LLVMContext &Context = Ty->getContext();
|
||||
|
||||
@ -2266,9 +2258,6 @@ Type *GetElementPtrConstantExpr::getResultElementType() const {
|
||||
//===----------------------------------------------------------------------===//
|
||||
// ConstantData* implementations
|
||||
|
||||
void ConstantDataArray::anchor() {}
|
||||
void ConstantDataVector::anchor() {}
|
||||
|
||||
Type *ConstantDataSequential::getElementType() const {
|
||||
return getType()->getElementType();
|
||||
}
|
||||
|
@ -44,8 +44,6 @@ namespace llvm {
|
||||
/// UnaryConstantExpr - This class is private to Constants.cpp, and is used
|
||||
/// behind the scenes to implement unary constant exprs.
|
||||
class UnaryConstantExpr : public ConstantExpr {
|
||||
void anchor() override;
|
||||
|
||||
public:
|
||||
UnaryConstantExpr(unsigned Opcode, Constant *C, Type *Ty)
|
||||
: ConstantExpr(Ty, Opcode, &Op<0>(), 1) {
|
||||
@ -65,8 +63,6 @@ public:
|
||||
/// BinaryConstantExpr - This class is private to Constants.cpp, and is used
|
||||
/// behind the scenes to implement binary constant exprs.
|
||||
class BinaryConstantExpr : public ConstantExpr {
|
||||
void anchor() override;
|
||||
|
||||
public:
|
||||
BinaryConstantExpr(unsigned Opcode, Constant *C1, Constant *C2,
|
||||
unsigned Flags)
|
||||
@ -90,8 +86,6 @@ public:
|
||||
/// SelectConstantExpr - This class is private to Constants.cpp, and is used
|
||||
/// behind the scenes to implement select constant exprs.
|
||||
class SelectConstantExpr : public ConstantExpr {
|
||||
void anchor() override;
|
||||
|
||||
public:
|
||||
SelectConstantExpr(Constant *C1, Constant *C2, Constant *C3)
|
||||
: ConstantExpr(C2->getType(), Instruction::Select, &Op<0>(), 3) {
|
||||
@ -115,8 +109,6 @@ public:
|
||||
/// Constants.cpp, and is used behind the scenes to implement
|
||||
/// extractelement constant exprs.
|
||||
class ExtractElementConstantExpr : public ConstantExpr {
|
||||
void anchor() override;
|
||||
|
||||
public:
|
||||
ExtractElementConstantExpr(Constant *C1, Constant *C2)
|
||||
: ConstantExpr(cast<VectorType>(C1->getType())->getElementType(),
|
||||
@ -140,8 +132,6 @@ public:
|
||||
/// Constants.cpp, and is used behind the scenes to implement
|
||||
/// insertelement constant exprs.
|
||||
class InsertElementConstantExpr : public ConstantExpr {
|
||||
void anchor() override;
|
||||
|
||||
public:
|
||||
InsertElementConstantExpr(Constant *C1, Constant *C2, Constant *C3)
|
||||
: ConstantExpr(C1->getType(), Instruction::InsertElement,
|
||||
@ -166,8 +156,6 @@ public:
|
||||
/// Constants.cpp, and is used behind the scenes to implement
|
||||
/// shufflevector constant exprs.
|
||||
class ShuffleVectorConstantExpr : public ConstantExpr {
|
||||
void anchor() override;
|
||||
|
||||
public:
|
||||
ShuffleVectorConstantExpr(Constant *C1, Constant *C2, Constant *C3)
|
||||
: ConstantExpr(VectorType::get(
|
||||
@ -195,8 +183,6 @@ public:
|
||||
/// Constants.cpp, and is used behind the scenes to implement
|
||||
/// extractvalue constant exprs.
|
||||
class ExtractValueConstantExpr : public ConstantExpr {
|
||||
void anchor() override;
|
||||
|
||||
public:
|
||||
ExtractValueConstantExpr(Constant *Agg, ArrayRef<unsigned> IdxList,
|
||||
Type *DestTy)
|
||||
@ -230,8 +216,6 @@ public:
|
||||
/// Constants.cpp, and is used behind the scenes to implement
|
||||
/// insertvalue constant exprs.
|
||||
class InsertValueConstantExpr : public ConstantExpr {
|
||||
void anchor() override;
|
||||
|
||||
public:
|
||||
InsertValueConstantExpr(Constant *Agg, Constant *Val,
|
||||
ArrayRef<unsigned> IdxList, Type *DestTy)
|
||||
@ -271,8 +255,6 @@ class GetElementPtrConstantExpr : public ConstantExpr {
|
||||
GetElementPtrConstantExpr(Type *SrcElementTy, Constant *C,
|
||||
ArrayRef<Constant *> IdxList, Type *DestTy);
|
||||
|
||||
void anchor() override;
|
||||
|
||||
public:
|
||||
static GetElementPtrConstantExpr *Create(Type *SrcElementTy, Constant *C,
|
||||
ArrayRef<Constant *> IdxList,
|
||||
@ -301,8 +283,6 @@ public:
|
||||
// behind the scenes to implement ICmp and FCmp constant expressions. This is
|
||||
// needed in order to store the predicate value for these instructions.
|
||||
class CompareConstantExpr : public ConstantExpr {
|
||||
void anchor() override;
|
||||
|
||||
public:
|
||||
unsigned short predicate;
|
||||
CompareConstantExpr(Type *ty, Instruction::OtherOps opc,
|
||||
|
@ -66,8 +66,6 @@ template class llvm::SymbolTableListTraits<BasicBlock>;
|
||||
// Argument Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
void Argument::anchor() {}
|
||||
|
||||
Argument::Argument(Type *Ty, const Twine &Name, Function *Par, unsigned ArgNo)
|
||||
: Value(Ty, Value::ArgumentVal), Parent(Par), ArgNo(ArgNo) {
|
||||
setName(Name);
|
||||
|
@ -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) {
|
||||
|
@ -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())
|
||||
|
@ -59,9 +59,6 @@ User::op_iterator CallSite::getCallee() const {
|
||||
// TerminatorInst Class
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Out of line virtual method, so the vtable, etc has a home.
|
||||
TerminatorInst::~TerminatorInst() = default;
|
||||
|
||||
unsigned TerminatorInst::getNumSuccessors() const {
|
||||
switch (getOpcode()) {
|
||||
#define HANDLE_TERM_INST(N, OPC, CLASS) \
|
||||
@ -98,13 +95,6 @@ void TerminatorInst::setSuccessor(unsigned idx, BasicBlock *B) {
|
||||
llvm_unreachable("not a terminator");
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// UnaryInstruction Class
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Out of line virtual method, so the vtable, etc has a home.
|
||||
UnaryInstruction::~UnaryInstruction() = default;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// SelectInst Class
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -138,8 +128,6 @@ const char *SelectInst::areInvalidOperands(Value *Op0, Value *Op1, Value *Op2) {
|
||||
// PHINode Class
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
void PHINode::anchor() {}
|
||||
|
||||
PHINode::PHINode(const PHINode &PN)
|
||||
: Instruction(PN.getType(), Instruction::PHI, nullptr, PN.getNumOperands()),
|
||||
ReservedSpace(PN.getNumOperands()) {
|
||||
@ -293,8 +281,6 @@ void LandingPadInst::addClause(Constant *Val) {
|
||||
// CallInst Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
CallInst::~CallInst() = default;
|
||||
|
||||
void CallInst::init(FunctionType *FTy, Value *Func, ArrayRef<Value *> Args,
|
||||
ArrayRef<OperandBundleDef> Bundles, const Twine &NameStr) {
|
||||
this->FTy = FTy;
|
||||
@ -900,8 +886,6 @@ BasicBlock *ReturnInst::getSuccessorV(unsigned idx) const {
|
||||
llvm_unreachable("ReturnInst has no successors!");
|
||||
}
|
||||
|
||||
ReturnInst::~ReturnInst() = default;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// ResumeInst Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -1337,9 +1321,6 @@ AllocaInst::AllocaInst(Type *Ty, unsigned AddrSpace, Value *ArraySize,
|
||||
setName(Name);
|
||||
}
|
||||
|
||||
// Out of line virtual method, so the vtable, etc has a home.
|
||||
AllocaInst::~AllocaInst() = default;
|
||||
|
||||
void AllocaInst::setAlignment(unsigned Align) {
|
||||
assert((Align & (Align-1)) == 0 && "Alignment is not a power of 2!");
|
||||
assert(Align <= MaximumAlignment &&
|
||||
@ -1689,8 +1670,6 @@ FenceInst::FenceInst(LLVMContext &C, AtomicOrdering Ordering,
|
||||
// GetElementPtrInst Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
void GetElementPtrInst::anchor() {}
|
||||
|
||||
void GetElementPtrInst::init(Value *Ptr, ArrayRef<Value *> IdxList,
|
||||
const Twine &Name) {
|
||||
assert(getNumOperands() == 1 + IdxList.size() &&
|
||||
@ -2357,8 +2336,6 @@ float FPMathOperator::getFPAccuracy() const {
|
||||
// CastInst Class
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
void CastInst::anchor() {}
|
||||
|
||||
// Just determine if this cast only deals with integral->integral conversion.
|
||||
bool CastInst::isIntegerCast() const {
|
||||
switch (getOpcode()) {
|
||||
@ -3387,8 +3364,6 @@ AddrSpaceCastInst::AddrSpaceCastInst(
|
||||
// CmpInst Classes
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
void CmpInst::anchor() {}
|
||||
|
||||
CmpInst::CmpInst(Type *ty, OtherOps op, Predicate predicate, Value *LHS,
|
||||
Value *RHS, const Twine &Name, Instruction *InsertBefore)
|
||||
: Instruction(ty, op,
|
||||
@ -3528,8 +3503,6 @@ StringRef CmpInst::getPredicateName(Predicate Pred) {
|
||||
}
|
||||
}
|
||||
|
||||
void ICmpInst::anchor() {}
|
||||
|
||||
ICmpInst::Predicate ICmpInst::getSignedPredicate(Predicate pred) {
|
||||
switch (pred) {
|
||||
default: llvm_unreachable("Unknown icmp predicate!");
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "llvm/IR/Constants.h"
|
||||
#include "llvm/IR/DataLayout.h"
|
||||
#include "llvm/IR/DerivedTypes.h"
|
||||
#include "llvm/IR/DerivedUser.h"
|
||||
#include "llvm/IR/GetElementPtrTypeIterator.h"
|
||||
#include "llvm/IR/InstrTypes.h"
|
||||
#include "llvm/IR/Instructions.h"
|
||||
@ -59,7 +60,7 @@ Value::Value(Type *ty, unsigned scid)
|
||||
(SubclassID < ConstantFirstVal || SubclassID > ConstantLastVal))
|
||||
assert((VTy->isFirstClassType() || VTy->isVoidTy()) &&
|
||||
"Cannot create non-first-class values except for constants!");
|
||||
static_assert(sizeof(Value) == 3 * sizeof(void *) + 2 * sizeof(unsigned),
|
||||
static_assert(sizeof(Value) == 2 * sizeof(void *) + 2 * sizeof(unsigned),
|
||||
"Value too big");
|
||||
}
|
||||
|
||||
@ -89,6 +90,32 @@ Value::~Value() {
|
||||
destroyValueName();
|
||||
}
|
||||
|
||||
void Value::deleteValue() {
|
||||
switch (getValueID()) {
|
||||
#define HANDLE_VALUE(Name) \
|
||||
case Value::Name##Val: \
|
||||
delete static_cast<Name *>(this); \
|
||||
break;
|
||||
#define HANDLE_MEMORY_VALUE(Name) \
|
||||
case Value::Name##Val: \
|
||||
static_cast<DerivedUser *>(this)->DeleteValue( \
|
||||
static_cast<DerivedUser *>(this)); \
|
||||
break;
|
||||
#define HANDLE_INSTRUCTION(Name) /* nothing */
|
||||
#include "llvm/IR/Value.def"
|
||||
|
||||
#define HANDLE_INST(N, OPC, CLASS) \
|
||||
case Value::InstructionVal + Instruction::OPC: \
|
||||
delete static_cast<CLASS *>(this); \
|
||||
break;
|
||||
#define HANDLE_USER_INST(N, OPC, CLASS)
|
||||
#include "llvm/IR/Instruction.def"
|
||||
|
||||
default:
|
||||
llvm_unreachable("attempting to delete unknown value kind");
|
||||
}
|
||||
}
|
||||
|
||||
void Value::destroyValueName() {
|
||||
ValueName *Name = getValueName();
|
||||
if (Name)
|
||||
|
@ -399,7 +399,7 @@ void Simplifier::Context::cleanup() {
|
||||
for (Value *V : Clones) {
|
||||
Instruction *U = cast<Instruction>(V);
|
||||
if (!U->getParent())
|
||||
delete U;
|
||||
U->deleteValue();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
|
@ -2443,7 +2443,7 @@ private:
|
||||
"insert");
|
||||
LI.replaceAllUsesWith(V);
|
||||
Placeholder->replaceAllUsesWith(&LI);
|
||||
delete Placeholder;
|
||||
Placeholder->deleteValue();
|
||||
} else {
|
||||
LI.replaceAllUsesWith(V);
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -317,7 +317,7 @@ void PruningFunctionCloner::CloneBlock(const BasicBlock *BB,
|
||||
|
||||
if (!NewInst->mayHaveSideEffects()) {
|
||||
VMap[&*II] = V;
|
||||
delete NewInst;
|
||||
NewInst->deleteValue();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -578,12 +578,12 @@ private:
|
||||
void eraseInstruction(Instruction *I) {
|
||||
I->removeFromParent();
|
||||
I->dropAllReferences();
|
||||
DeletedInstructions.push_back(std::unique_ptr<Instruction>(I));
|
||||
DeletedInstructions.emplace_back(I);
|
||||
}
|
||||
|
||||
/// Temporary store for deleted instructions. Instructions will be deleted
|
||||
/// eventually when the BoUpSLP is destructed.
|
||||
SmallVector<std::unique_ptr<Instruction>, 8> DeletedInstructions;
|
||||
SmallVector<unique_value, 8> DeletedInstructions;
|
||||
|
||||
/// A list of values that need to extracted out of the tree.
|
||||
/// This list holds pairs of (Internal Scalar : External User). External User
|
||||
|
@ -178,12 +178,13 @@ TEST(ConstantsTest, PointerCast) {
|
||||
ConstantExpr::getAddrSpaceCast(NullInt32Ptr1, Int32PtrTy));
|
||||
}
|
||||
|
||||
#define CHECK(x, y) { \
|
||||
#define CHECK(x, y) \
|
||||
{ \
|
||||
std::string __s; \
|
||||
raw_string_ostream __o(__s); \
|
||||
Instruction *__I = cast<ConstantExpr>(x)->getAsInstruction(); \
|
||||
__I->print(__o); \
|
||||
delete __I; \
|
||||
__I->deleteValue(); \
|
||||
__o.flush(); \
|
||||
EXPECT_EQ(std::string(" <badref> = " y), __s); \
|
||||
}
|
||||
|
@ -406,8 +406,8 @@ TEST(InstructionsTest, FPMathOperator) {
|
||||
EXPECT_TRUE(isa<FPMathOperator>(V1));
|
||||
FPMathOperator *O1 = cast<FPMathOperator>(V1);
|
||||
EXPECT_EQ(O1->getFPAccuracy(), 1.0);
|
||||
delete V1;
|
||||
delete I;
|
||||
V1->deleteValue();
|
||||
I->deleteValue();
|
||||
}
|
||||
|
||||
|
||||
|
@ -218,7 +218,7 @@ TEST_F(MDNodeTest, Delete) {
|
||||
|
||||
EXPECT_EQ(n, wvh);
|
||||
|
||||
delete I;
|
||||
I->deleteValue();
|
||||
}
|
||||
|
||||
TEST_F(MDNodeTest, SelfReference) {
|
||||
|
@ -41,13 +41,18 @@ protected:
|
||||
}
|
||||
|
||||
void eraseClones() {
|
||||
DeleteContainerPointers(Clones);
|
||||
for (Value *V : Clones)
|
||||
V->deleteValue();
|
||||
Clones.clear();
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
eraseClones();
|
||||
DeleteContainerPointers(Orig);
|
||||
delete V;
|
||||
for (Value *V : Orig)
|
||||
V->deleteValue();
|
||||
Orig.clear();
|
||||
if (V)
|
||||
V->deleteValue();
|
||||
}
|
||||
|
||||
SmallPtrSet<Value *, 4> Orig; // Erase on exit
|
||||
|
Loading…
Reference in New Issue
Block a user