From d86f2157e57083c57d7c9ee473c758d050bbe1b1 Mon Sep 17 00:00:00 2001 From: Johannes Doerfert Date: Mon, 17 Aug 2015 10:58:17 +0000 Subject: [PATCH] Add a field to the memory access class for a related value. The new field in the MemoryAccess allows us to track a value related to that access: - For real memory accesses the value is the loaded result or the stored value. - For straigt line scalar accesses it is the access instruction itself. - For PHI operand accesses it is the operand value. We use this value to simplify code which deduced information about the value later in the Polly pipeline and was known to be error prone. Reviewers: grosser, Meinsersbur Subscribers: #polly Differential Revision: http://reviews.llvm.org/D12062 llvm-svn: 245213 --- polly/include/polly/ScopInfo.h | 15 +++++++++++++-- polly/include/polly/TempScopInfo.h | 18 +++++++++++------- polly/lib/Analysis/ScopInfo.cpp | 17 +++-------------- polly/lib/Analysis/TempScopInfo.cpp | 23 ++++++++++++++--------- polly/lib/CodeGen/BlockGenerators.cpp | 26 +++++++------------------- 5 files changed, 48 insertions(+), 51 deletions(-) diff --git a/polly/include/polly/ScopInfo.h b/polly/include/polly/ScopInfo.h index 9300150fd459..62e9c6e7a7b8 100644 --- a/polly/include/polly/ScopInfo.h +++ b/polly/include/polly/ScopInfo.h @@ -244,7 +244,15 @@ private: ReductionType RedType = RT_NONE; /// @brief The access instruction of this memory access. - Instruction *Inst; + Instruction *AccessInstruction; + + /// @brief The value associated with this memory access. + /// + /// - For real memory accesses it is the loaded result or the stored value. + /// - For straigt line scalar accesses it is the access instruction itself. + /// - For PHI operand accesses it is the operand value. + /// + Value *AccessValue; /// Updated access relation read from JSCOP file. isl_map *newAccessRelation; @@ -377,8 +385,11 @@ public: const std::string &getBaseName() const { return BaseName; } + /// @brief Return the access value of this memory access. + Value *getAccessValue() const { return AccessValue; } + /// @brief Return the access instruction of this memory access. - Instruction *getAccessInstruction() const { return Inst; } + Instruction *getAccessInstruction() const { return AccessInstruction; } /// Get the stride of this memory access in the specified Schedule. Schedule /// is a map from the statement to a schedule where the innermost dimension is diff --git a/polly/include/polly/TempScopInfo.h b/polly/include/polly/TempScopInfo.h index 26c83155c0c7..d12cc5b5dd56 100644 --- a/polly/include/polly/TempScopInfo.h +++ b/polly/include/polly/TempScopInfo.h @@ -33,6 +33,7 @@ namespace polly { class IRAccess { public: Value *BaseAddress; + Value *AccessValue; const SCEV *Offset; @@ -58,22 +59,25 @@ public: /// /// @param IsPHI Are we modeling special PHI node accesses? explicit IRAccess(TypeKind Type, Value *BaseAddress, const SCEV *Offset, - unsigned elemBytes, bool Affine, bool IsPHI = false) - : BaseAddress(BaseAddress), Offset(Offset), ElemBytes(elemBytes), - Type(Type), IsAffine(Affine), IsPHI(IsPHI) {} + unsigned elemBytes, bool Affine, Value *AccessValue, + bool IsPHI = false) + : BaseAddress(BaseAddress), AccessValue(AccessValue), Offset(Offset), + ElemBytes(elemBytes), Type(Type), IsAffine(Affine), IsPHI(IsPHI) {} explicit IRAccess(TypeKind Type, Value *BaseAddress, const SCEV *Offset, unsigned elemBytes, bool Affine, SmallVector Subscripts, - SmallVector Sizes) - : BaseAddress(BaseAddress), Offset(Offset), ElemBytes(elemBytes), - Type(Type), IsAffine(Affine), IsPHI(false), Subscripts(Subscripts), - Sizes(Sizes) {} + SmallVector Sizes, Value *AccessValue) + : BaseAddress(BaseAddress), AccessValue(AccessValue), Offset(Offset), + ElemBytes(elemBytes), Type(Type), IsAffine(Affine), IsPHI(false), + Subscripts(Subscripts), Sizes(Sizes) {} enum TypeKind getType() const { return Type; } Value *getBase() const { return BaseAddress; } + Value *getAccessValue() const { return AccessValue; } + const SCEV *getOffset() const { return Offset; } unsigned getElemSizeInBytes() const { return ElemBytes; } diff --git a/polly/lib/Analysis/ScopInfo.cpp b/polly/lib/Analysis/ScopInfo.cpp index b6bb23832b4c..3ec2220f169d 100644 --- a/polly/lib/Analysis/ScopInfo.cpp +++ b/polly/lib/Analysis/ScopInfo.cpp @@ -447,7 +447,8 @@ __isl_give isl_map *MemoryAccess::foldAccess(const IRAccess &Access, MemoryAccess::MemoryAccess(const IRAccess &Access, Instruction *AccInst, ScopStmt *Statement, const ScopArrayInfo *SAI, int Identifier) - : AccType(getMemoryAccessType(Access)), Statement(Statement), Inst(AccInst), + : AccType(getMemoryAccessType(Access)), Statement(Statement), + AccessInstruction(AccInst), AccessValue(Access.getAccessValue()), newAccessRelation(nullptr) { isl_ctx *Ctx = Statement->getIslCtx(); @@ -669,18 +670,6 @@ void ScopStmt::restrictDomain(__isl_take isl_set *NewDomain) { Domain = NewDomain; } -// @brief Get the data-type of the elements accessed -static Type *getAccessType(IRAccess &Access, Instruction *AccessInst) { - if (Access.isPHI()) - return Access.getBase()->getType(); - - if (StoreInst *Store = dyn_cast(AccessInst)) - return Store->getValueOperand()->getType(); - if (BranchInst *Branch = dyn_cast(AccessInst)) - return Branch->getCondition()->getType(); - return AccessInst->getType(); -} - void ScopStmt::buildAccesses(TempScop &tempScop, BasicBlock *Block, bool isApproximated) { AccFuncSetType *AFS = tempScop.getAccessFunctions(Block); @@ -690,7 +679,7 @@ void ScopStmt::buildAccesses(TempScop &tempScop, BasicBlock *Block, for (auto &AccessPair : *AFS) { IRAccess &Access = AccessPair.first; Instruction *AccessInst = AccessPair.second; - Type *ElementType = getAccessType(Access, AccessInst); + Type *ElementType = Access.getAccessValue()->getType(); const ScopArrayInfo *SAI = getParent()->getOrCreateScopArrayInfo( Access.getBase(), ElementType, Access.Sizes, Access.isPHI()); diff --git a/polly/lib/Analysis/TempScopInfo.cpp b/polly/lib/Analysis/TempScopInfo.cpp index 56e2fa0a5328..e968545224b8 100644 --- a/polly/lib/Analysis/TempScopInfo.cpp +++ b/polly/lib/Analysis/TempScopInfo.cpp @@ -135,9 +135,10 @@ void TempScopInfo::buildPHIAccesses(PHINode *PHI, Region &R, // we have to insert a scalar dependence from the definition of OpI to // OpBB if the definition is not in OpBB. if (OpIBB != OpBB) { - IRAccess ScalarRead(IRAccess::READ, OpI, ZeroOffset, 1, true); + IRAccess ScalarRead(IRAccess::READ, OpI, ZeroOffset, 1, true, OpI); AccFuncMap[OpBB].push_back(std::make_pair(ScalarRead, PHI)); - IRAccess ScalarWrite(IRAccess::MUST_WRITE, OpI, ZeroOffset, 1, true); + IRAccess ScalarWrite(IRAccess::MUST_WRITE, OpI, ZeroOffset, 1, true, + OpI); AccFuncMap[OpIBB].push_back(std::make_pair(ScalarWrite, OpI)); } } @@ -147,13 +148,13 @@ void TempScopInfo::buildPHIAccesses(PHINode *PHI, Region &R, if (!OpI) OpI = OpBB->getTerminator(); - IRAccess ScalarAccess(IRAccess::MUST_WRITE, PHI, ZeroOffset, 1, true, + IRAccess ScalarAccess(IRAccess::MUST_WRITE, PHI, ZeroOffset, 1, true, Op, /* IsPHI */ true); AccFuncMap[OpBB].push_back(std::make_pair(ScalarAccess, OpI)); } if (!OnlyNonAffineSubRegionOperands) { - IRAccess ScalarAccess(IRAccess::READ, PHI, ZeroOffset, 1, true, + IRAccess ScalarAccess(IRAccess::READ, PHI, ZeroOffset, 1, true, PHI, /* IsPHI */ true); Functions.push_back(std::make_pair(ScalarAccess, PHI)); } @@ -211,7 +212,7 @@ bool TempScopInfo::buildScalarDependences(Instruction *Inst, Region *R, // Do not build a read access that is not in the current SCoP // Use the def instruction as base address of the IRAccess, so that it will // become the name of the scalar access in the polyhedral form. - IRAccess ScalarAccess(IRAccess::READ, Inst, ZeroOffset, 1, true); + IRAccess ScalarAccess(IRAccess::READ, Inst, ZeroOffset, 1, true, Inst); AccFuncMap[UseParent].push_back(std::make_pair(ScalarAccess, UI)); } @@ -224,7 +225,7 @@ bool TempScopInfo::buildScalarDependences(Instruction *Inst, Region *R, if (R->contains(OpInst)) continue; - IRAccess ScalarAccess(IRAccess::READ, Op, ZeroOffset, 1, true); + IRAccess ScalarAccess(IRAccess::READ, Op, ZeroOffset, 1, true, Op); AccFuncMap[Inst->getParent()].push_back( std::make_pair(ScalarAccess, Inst)); } @@ -240,17 +241,20 @@ TempScopInfo::buildIRAccess(Instruction *Inst, Loop *L, Region *R, const ScopDetection::BoxedLoopsSetTy *BoxedLoops) { unsigned Size; Type *SizeType; + Value *Val; enum IRAccess::TypeKind Type; if (LoadInst *Load = dyn_cast(Inst)) { SizeType = Load->getType(); Size = TD->getTypeStoreSize(SizeType); Type = IRAccess::READ; + Val = Load; } else { StoreInst *Store = cast(Inst); SizeType = Store->getValueOperand()->getType(); Size = TD->getTypeStoreSize(SizeType); Type = IRAccess::MUST_WRITE; + Val = Store->getValueOperand(); } const SCEV *AccessFunction = SE->getSCEVAtScope(getPointerOperand(*Inst), L); @@ -264,7 +268,7 @@ TempScopInfo::buildIRAccess(Instruction *Inst, Loop *L, Region *R, if (PollyDelinearize && AccItr != InsnToMemAcc.end()) return IRAccess(Type, BasePointer->getValue(), AccessFunction, Size, true, AccItr->second.DelinearizedSubscripts, - AccItr->second.Shape->DelinearizedSizes); + AccItr->second.Shape->DelinearizedSizes, Val); // Check if the access depends on a loop contained in a non-affine subregion. bool isVariantInNonAffineLoop = false; @@ -287,7 +291,7 @@ TempScopInfo::buildIRAccess(Instruction *Inst, Loop *L, Region *R, Type = IRAccess::MAY_WRITE; return IRAccess(Type, BasePointer->getValue(), AccessFunction, Size, IsAffine, - Subscripts, Sizes); + Subscripts, Sizes, Val); } void TempScopInfo::buildAccessFunctions(Region &R, Region &SR) { @@ -326,7 +330,8 @@ void TempScopInfo::buildAccessFunctions(Region &R, BasicBlock &BB, buildScalarDependences(Inst, &R, NonAffineSubRegion)) { // If the Instruction is used outside the statement, we need to build the // write access. - IRAccess ScalarAccess(IRAccess::MUST_WRITE, Inst, ZeroOffset, 1, true); + IRAccess ScalarAccess(IRAccess::MUST_WRITE, Inst, ZeroOffset, 1, true, + Inst); Functions.push_back(std::make_pair(ScalarAccess, Inst)); } } diff --git a/polly/lib/CodeGen/BlockGenerators.cpp b/polly/lib/CodeGen/BlockGenerators.cpp index 0c9348d2cade..05e04c9aed34 100644 --- a/polly/lib/CodeGen/BlockGenerators.cpp +++ b/polly/lib/CodeGen/BlockGenerators.cpp @@ -495,21 +495,14 @@ void BlockGenerator::generateScalarStores(ScopStmt &Stmt, BasicBlock *BB, continue; Instruction *Base = cast(MA->getBaseAddr()); - Instruction *Inst = MA->getAccessInstruction(); + Value *Val = MA->getAccessValue(); - Value *Val = nullptr; AllocaInst *Address = nullptr; - - if (MA->getScopArrayInfo()->isPHI()) { - PHINode *BasePHI = dyn_cast(Base); - int PHIIdx = BasePHI->getBasicBlockIndex(BB); - assert(PHIIdx >= 0); + if (MA->getScopArrayInfo()->isPHI()) Address = getOrCreateAlloca(Base, PHIOpMap, ".phiops"); - Val = BasePHI->getIncomingValue(PHIIdx); - } else { + else Address = getOrCreateAlloca(Base, ScalarMap, ".s2a"); - Val = Inst; - } + Val = getNewScalarValue(Val, R, ScalarMap, BBMap, GlobalMap); Builder.CreateStore(Val, Address); } @@ -1124,23 +1117,18 @@ void RegionGenerator::generateScalarStores(ScopStmt &Stmt, BasicBlock *BB, Instruction *ScalarBase = cast(MA->getBaseAddr()); Instruction *ScalarInst = MA->getAccessInstruction(); - PHINode *ScalarBasePHI = dyn_cast(ScalarBase); // Only generate accesses that belong to this basic block. if (ScalarInst->getParent() != BB) continue; - Value *Val = nullptr; + Value *Val = MA->getAccessValue(); AllocaInst *ScalarAddr = nullptr; - if (MA->getScopArrayInfo()->isPHI()) { - int PHIIdx = ScalarBasePHI->getBasicBlockIndex(BB); + if (MA->getScopArrayInfo()->isPHI()) ScalarAddr = getOrCreateAlloca(ScalarBase, PHIOpMap, ".phiops"); - Val = ScalarBasePHI->getIncomingValue(PHIIdx); - } else { + else ScalarAddr = getOrCreateAlloca(ScalarBase, ScalarMap, ".s2a"); - Val = ScalarInst; - } Val = getNewScalarValue(Val, R, ScalarMap, BBMap, GlobalMap); Builder.CreateStore(Val, ScalarAddr);