Index: include/polly/Support/ScopHelper.h =================================================================== --- include/polly/Support/ScopHelper.h +++ include/polly/Support/ScopHelper.h @@ -64,150 +64,95 @@ private: llvm::Instruction *I; + template inline static T *StaticAssertLegalT(T *V) { + static_assert(std::is_same::value && + std::is_same::value, + "Only LoadInst and StoreInst are supported!"); + return V; + } + public: MemAccInst() : I(nullptr) {} MemAccInst(const MemAccInst &Inst) : I(Inst.I) {} - /* implicit */ MemAccInst(llvm::LoadInst &LI) : I(&LI) {} - /* implicit */ MemAccInst(llvm::LoadInst *LI) : I(LI) {} - /* implicit */ MemAccInst(llvm::StoreInst &SI) : I(&SI) {} - /* implicit */ MemAccInst(llvm::StoreInst *SI) : I(SI) {} - explicit MemAccInst(llvm::Instruction &I) : I(&I) { assert(isa(I)); } - explicit MemAccInst(llvm::Instruction *I) : I(I) { assert(isa(I)); } - - static bool isa(const llvm::Value &V) { - return llvm::isa(V) || llvm::isa(V); - } - static bool isa(const llvm::Value *V) { - return llvm::isa(V) || llvm::isa(V); - } - static MemAccInst cast(llvm::Value &V) { - return MemAccInst(llvm::cast(V)); - } - static MemAccInst cast(llvm::Value *V) { - return MemAccInst(llvm::cast(V)); - } - static MemAccInst cast_or_null(llvm::Value &V) { - return MemAccInst(llvm::cast(V)); - } - static MemAccInst cast_or_null(llvm::Value *V) { - if (!V) - return MemAccInst(); - return MemAccInst(llvm::cast(V)); - } - static MemAccInst dyn_cast(llvm::Value &V) { - if (isa(V)) - return MemAccInst(llvm::cast(V)); - return MemAccInst(); - } - static MemAccInst dyn_cast(llvm::Value *V) { - assert(V); - if (isa(V)) - return MemAccInst(llvm::cast(V)); - return MemAccInst(); + MemAccInst(MemAccInst &Inst) : I(Inst.I) {} + + template + /* implicit */ MemAccInst(T *I) + : I((I && llvm::isa(I)) ? I : nullptr) {} + template + /* implicit */ MemAccInst(T &I) : MemAccInst(&I) {} + + static bool classof(const llvm::Value *I) { + return llvm::isa(I) || llvm::isa(I); } + static bool classof(const llvm::LoadInst *) { return true; } + static bool classof(const llvm::StoreInst *) { return true; } MemAccInst &operator=(const MemAccInst &Inst) { I = Inst.I; return *this; } - MemAccInst &operator=(llvm::LoadInst &LI) { - I = &LI; - return *this; - } - MemAccInst &operator=(llvm::LoadInst *LI) { - I = LI; - return *this; - } - MemAccInst &operator=(llvm::StoreInst &SI) { - I = &SI; + + template MemAccInst &operator=(T *RHS) { + I = StaticAssertLegalT(RHS); return *this; } - MemAccInst &operator=(llvm::StoreInst *SI) { - I = SI; - return *this; + + template MemAccInst &operator=(T &RHS) { + return operator=(&RHS); } operator llvm::Instruction *() const { return asInstruction(); } + llvm::Instruction *operator->() const { return asInstruction(); } explicit operator bool() const { return isInstruction(); } bool operator!() const { return isNull(); } - llvm::Value *getOperand(unsigned i) const { return I->getOperand(i); } - llvm::BasicBlock *getParent() const { return I->getParent(); } - llvm::LLVMContext &getContext() const { return I->getContext(); } - void getAAMetadata(llvm::AAMDNodes &N, bool Merge = false) const { - I->getAAMetadata(N, Merge); - } + llvm::Value *getValueOperand() const { + assert(!isNull() && "Operation not supported on nullptr"); + if (auto LI = llvm::dyn_cast_or_null(asInstruction())) + return LI; - /// @brief Get the debug location of this instruction. - /// - /// @returns The debug location of this instruction. - const llvm::DebugLoc &getDebugLoc() const { - if (I) - return I->getDebugLoc(); - llvm_unreachable("Operation not supported on nullptr"); + return llvm::cast(asInstruction())->getValueOperand(); } - llvm::Value *getValueOperand() const { - if (isLoad()) - return asLoad(); - if (isStore()) - return asStore()->getValueOperand(); - llvm_unreachable("Operation not supported on nullptr"); - } +#define MEMACCINST_DELEGATE_GETTER(METHOD) \ + assert(!isNull() && "Operation not supported on nullptr"); \ + if (auto LI = llvm::dyn_cast_or_null(asInstruction())) \ + return LI->METHOD; \ + \ + return llvm::cast(asInstruction())->METHOD; + llvm::Value *getPointerOperand() const { - if (isLoad()) - return asLoad()->getPointerOperand(); - if (isStore()) - return asStore()->getPointerOperand(); - llvm_unreachable("Operation not supported on nullptr"); + MEMACCINST_DELEGATE_GETTER(getPointerOperand()); } - unsigned getAlignment() const { - if (isLoad()) - return asLoad()->getAlignment(); - if (isStore()) - return asStore()->getAlignment(); - llvm_unreachable("Operation not supported on nullptr"); - } - bool isVolatile() const { - if (isLoad()) - return asLoad()->isVolatile(); - if (isStore()) - return asStore()->isVolatile(); - llvm_unreachable("Operation not supported on nullptr"); - } - bool isSimple() const { - if (isLoad()) - return asLoad()->isSimple(); - if (isStore()) - return asStore()->isSimple(); - llvm_unreachable("Operation not supported on nullptr"); - } + unsigned getAlignment() const { MEMACCINST_DELEGATE_GETTER(getAlignment()); } + bool isVolatile() const { MEMACCINST_DELEGATE_GETTER(isVolatile()); } + bool isSimple() const { MEMACCINST_DELEGATE_GETTER(isSimple()); } llvm::AtomicOrdering getOrdering() const { - if (isLoad()) - return asLoad()->getOrdering(); - if (isStore()) - return asStore()->getOrdering(); - llvm_unreachable("Operation not supported on nullptr"); - } - bool isUnordered() const { - if (isLoad()) - return asLoad()->isUnordered(); - if (isStore()) - return asStore()->isUnordered(); - llvm_unreachable("Operation not supported on nullptr"); + MEMACCINST_DELEGATE_GETTER(getOrdering()); } + bool isUnordered() const { MEMACCINST_DELEGATE_GETTER(isUnordered()); } bool isNull() const { return !I; } bool isInstruction() const { return I; } - bool isLoad() const { return I && llvm::isa(I); } - bool isStore() const { return I && llvm::isa(I); } llvm::Instruction *asInstruction() const { return I; } - llvm::LoadInst *asLoad() const { return llvm::cast(I); } - llvm::StoreInst *asStore() const { return llvm::cast(I); } }; +} + +namespace llvm { +/// @brief Specialize simplify_type for MemAccInst to enable dyn_cast and cast +/// from a MemAccInst object. +template <> struct simplify_type { + typedef Instruction *SimpleType; + static SimpleType getSimplifiedValue(polly::MemAccInst &I) { + return I.asInstruction(); + } +}; +} +namespace polly { /// @brief Check if the PHINode has any incoming Invoke edge. /// /// @param PN The PHINode to check. Index: lib/Analysis/ScopDetection.cpp =================================================================== --- lib/Analysis/ScopDetection.cpp +++ lib/Analysis/ScopDetection.cpp @@ -767,7 +767,7 @@ Region &CurRegion = Context.CurRegion; Value *Ptr = Inst.getPointerOperand(); - Loop *L = LI->getLoopFor(Inst.getParent()); + Loop *L = LI->getLoopFor(Inst->getParent()); const SCEV *AccessFunction = SE->getSCEVAtScope(Ptr, L); const SCEVUnknown *BasePointer; Value *BaseValue; @@ -831,7 +831,7 @@ // Check if the base pointer of the memory access does alias with // any other pointer. This cannot be handled at the moment. AAMDNodes AATags; - Inst.getAAMetadata(AATags); + Inst->getAAMetadata(AATags); AliasSet &AS = Context.AST.getAliasSetForPointer( BaseValue, MemoryLocation::UnknownSize, AATags); @@ -894,9 +894,9 @@ } // Check the access function. - if (auto MemInst = MemAccInst::dyn_cast(Inst)) { - Context.hasStores |= MemInst.isLoad(); - Context.hasLoads |= MemInst.isStore(); + if (MemAccInst MemInst = Inst) { + Context.hasStores |= isa(MemInst); + Context.hasLoads |= isa(MemInst); if (!MemInst.isSimple()) return invalid(Context, /*Assert=*/true, &Inst); Index: lib/Analysis/ScopInfo.cpp =================================================================== --- lib/Analysis/ScopInfo.cpp +++ lib/Analysis/ScopInfo.cpp @@ -3752,7 +3752,7 @@ const SCEVUnknown *BasePointer = dyn_cast(SE->getPointerBase(AccessFunction)); enum MemoryAccess::AccessType Type = - Inst.isLoad() ? MemoryAccess::READ : MemoryAccess::MUST_WRITE; + isa(Inst) ? MemoryAccess::READ : MemoryAccess::MUST_WRITE; if (isa(Address) || isa(Address)) { auto NewAddress = Address; @@ -3805,7 +3805,7 @@ Type *SizeType = Val->getType(); unsigned ElementSize = DL->getTypeAllocSize(SizeType); enum MemoryAccess::AccessType Type = - Inst.isLoad() ? MemoryAccess::READ : MemoryAccess::MUST_WRITE; + isa(Inst) ? MemoryAccess::READ : MemoryAccess::MUST_WRITE; const SCEV *AccessFunction = SE->getSCEVAtScope(Address, L); const SCEVUnknown *BasePointer = @@ -3829,7 +3829,7 @@ cast(Sizes.back())->getAPInt().getSExtValue(); Sizes.pop_back(); if (ElementSize != DelinearizedSize) - scop->invalidate(DELINEARIZATION, Inst.getDebugLoc()); + scop->invalidate(DELINEARIZATION, Inst->getDebugLoc()); addArrayAccess(Inst, Type, BasePointer->getValue(), ElementSize, true, AccItr->second.DelinearizedSubscripts, Sizes, Val); @@ -3847,7 +3847,7 @@ Type *SizeType = Val->getType(); unsigned ElementSize = DL->getTypeAllocSize(SizeType); enum MemoryAccess::AccessType Type = - Inst.isLoad() ? MemoryAccess::READ : MemoryAccess::MUST_WRITE; + isa(Inst) ? MemoryAccess::READ : MemoryAccess::MUST_WRITE; const SCEV *AccessFunction = SE->getSCEVAtScope(Address, L); const SCEVUnknown *BasePointer = @@ -3956,7 +3956,7 @@ // invariant and will be hoisted for the SCoP to be processed. Though, // there might be other invariant accesses that will be hoisted and // that would allow to make a non-affine access affine. - if (auto MemInst = MemAccInst::dyn_cast(Inst)) + if (MemAccInst MemInst = Inst) buildMemoryAccess(MemInst, L, &R, BoxedLoops, ScopRIL, InsnToMemAcc); if (isIgnoredIntrinsic(&Inst)) @@ -4023,8 +4023,8 @@ ArrayRef Subscripts, ArrayRef Sizes, Value *AccessValue) { - assert(MemAccInst.isLoad() == (Type == MemoryAccess::READ)); - addMemoryAccess(MemAccInst.getParent(), MemAccInst, Type, BaseAddress, + assert(isa(MemAccInst) == (Type == MemoryAccess::READ)); + addMemoryAccess(MemAccInst->getParent(), MemAccInst, Type, BaseAddress, ElemBytes, IsAffine, AccessValue, Subscripts, Sizes, ScopArrayInfo::MK_Array); } Index: lib/CodeGen/IRBuilder.cpp =================================================================== --- lib/CodeGen/IRBuilder.cpp +++ lib/CodeGen/IRBuilder.cpp @@ -131,7 +131,7 @@ if (!AliasScopeDomain) return; - auto MemInst = MemAccInst::dyn_cast(Inst); + MemAccInst MemInst(Inst); if (!MemInst) return; Index: lib/CodeGen/IslNodeBuilder.cpp =================================================================== --- lib/CodeGen/IslNodeBuilder.cpp +++ lib/CodeGen/IslNodeBuilder.cpp @@ -839,7 +839,7 @@ // the parent of Inst and lastly if the parent of Inst has an empty // domain. In the first and last case the instruction is dead but if // there is a statement or the domain is not empty Inst is not dead. - auto MemInst = MemAccInst::dyn_cast(Inst); + MemAccInst MemInst(Inst); auto Address = MemInst ? MemInst.getPointerOperand() : nullptr; if (Address && SE.getUnknown(UndefValue::get(Address->getType())) ==