diff options
Diffstat (limited to 'polly/lib')
| -rw-r--r-- | polly/lib/Analysis/ScopInfo.cpp | 208 | ||||
| -rw-r--r-- | polly/lib/Support/ScopHelper.cpp | 11 |
2 files changed, 84 insertions, 135 deletions
diff --git a/polly/lib/Analysis/ScopInfo.cpp b/polly/lib/Analysis/ScopInfo.cpp index eca8837e42b..bbb60758473 100644 --- a/polly/lib/Analysis/ScopInfo.cpp +++ b/polly/lib/Analysis/ScopInfo.cpp @@ -3677,25 +3677,6 @@ void ScopInfo::buildPHIAccesses(PHINode *PHI, Region &R, continue; OnlyNonAffineSubRegionOperands = false; - - if (!R.contains(OpBB)) - continue; - - Instruction *OpI = dyn_cast<Instruction>(Op); - if (OpI) { - BasicBlock *OpIBB = OpI->getParent(); - // As we pretend there is a use (or more precise a write) of OpI in OpBB - // we have to insert a scalar dependence from the definition of OpI to - // OpBB if the definition is not in OpBB. - if (scop->getStmtForBasicBlock(OpIBB) != - scop->getStmtForBasicBlock(OpBB)) { - ensureValueRead(OpI, OpBB); - ensureValueWrite(OpI); - } - } else if (ModelReadOnlyScalars && !isa<Constant>(Op)) { - ensureValueRead(Op, OpBB); - } - ensurePHIWrite(PHI, OpBB, Op, IsExitBlock); } @@ -3704,115 +3685,41 @@ void ScopInfo::buildPHIAccesses(PHINode *PHI, Region &R, } } -bool ScopInfo::buildScalarDependences(Instruction *Inst, Region *R, - Region *NonAffineSubRegion) { - bool canSynthesizeInst = canSynthesize(Inst, LI, SE, R); - if (isIgnoredIntrinsic(Inst)) - return false; - - bool AnyCrossStmtUse = false; - BasicBlock *ParentBB = Inst->getParent(); - - for (User *U : Inst->users()) { - Instruction *UI = dyn_cast<Instruction>(U); - - // Ignore the strange user - if (UI == 0) - continue; - - BasicBlock *UseParent = UI->getParent(); - - // Ignore basic block local uses. A value that is defined in a scop, but - // used in a PHI node in the same basic block does not count as basic block - // local, as for such cases a control flow edge is passed between definition - // and use. - if (UseParent == ParentBB && !isa<PHINode>(UI)) - continue; - - // Uses by PHI nodes in the entry node count as external uses in case the - // use is through an incoming block that is itself not contained in the - // region. - if (R->getEntry() == UseParent) { - if (auto *PHI = dyn_cast<PHINode>(UI)) { - bool ExternalUse = false; - for (unsigned i = 0; i < PHI->getNumIncomingValues(); i++) { - if (PHI->getIncomingValue(i) == Inst && - !R->contains(PHI->getIncomingBlock(i))) { - ExternalUse = true; - break; - } - } - - if (ExternalUse) { - AnyCrossStmtUse = true; - continue; - } - } - } - - // Do not build scalar dependences inside a non-affine subregion. - if (NonAffineSubRegion && NonAffineSubRegion->contains(UseParent)) - continue; - - // Check for PHI nodes in the region exit and skip them, if they will be - // modeled as PHI nodes. - // - // PHI nodes in the region exit that have more than two incoming edges need - // to be modeled as PHI-Nodes to correctly model the fact that depending on - // the control flow a different value will be assigned to the PHI node. In - // case this is the case, there is no need to create an additional normal - // scalar dependence. Hence, bail out before we register an "out-of-region" - // use for this definition. - if (isa<PHINode>(UI) && UI->getParent() == R->getExit() && - !R->getExitingBlock()) - continue; - - // Check whether or not the use is in the SCoP. - if (!R->contains(UseParent)) { - AnyCrossStmtUse = true; - continue; - } +void ScopInfo::buildScalarDependences(Instruction *Inst) { + assert(!isa<PHINode>(Inst)); - // If the instruction can be synthesized and the user is in the region - // we do not need to add scalar dependences. - if (canSynthesizeInst) - continue; + // Pull-in required operands. + for (Use &Op : Inst->operands()) + ensureValueRead(Op.get(), Inst->getParent()); +} - // No need to translate these scalar dependences into polyhedral form, - // because synthesizable scalars can be generated by the code generator. - if (canSynthesize(UI, LI, SE, R)) - continue; +void ScopInfo::buildEscapingDependences(Instruction *Inst) { + Region *R = &scop->getRegion(); - // Skip PHI nodes in the region as they handle their operands on their own. - if (isa<PHINode>(UI)) + // Check for uses of this instruction outside the scop. Because we do not + // iterate over such instructions and therefore did not "ensure" the existence + // of a write, we must determine such use here. + for (Use &U : Inst->uses()) { + Instruction *UI = dyn_cast<Instruction>(U.getUser()); + if (!UI) continue; - // Now U is used in another statement. - AnyCrossStmtUse = true; - - // Do not build a read access that is not in the current SCoP - // Use the def instruction as base address of the MemoryAccess, so that it - // will become the name of the scalar access in the polyhedral form. - ensureValueRead(Inst, UI->getParent()); - } - - if (ModelReadOnlyScalars && !isa<PHINode>(Inst)) { - for (Value *Op : Inst->operands()) { - if (canSynthesize(Op, LI, SE, R)) - continue; - - if (Instruction *OpInst = dyn_cast<Instruction>(Op)) - if (R->contains(OpInst)) - continue; - - if (isa<Constant>(Op)) - continue; - - ensureValueRead(Op, Inst->getParent()); + BasicBlock *UseParent = getUseBlock(U); + BasicBlock *UserParent = UI->getParent(); + + // An escaping value is either used by an instruction not within the scop, + // or (when the scop region's exit needs to be simplified) by a PHI in the + // scop's exit block. This is because region simplification before code + // generation inserts new basic blocks before the PHI such that its incoming + // blocks are not in the scop anymore. + if (!R->contains(UseParent) || + (isa<PHINode>(UI) && UserParent == R->getExit() && + R->getExitingBlock())) { + // At least one escaping use found. + ensureValueWrite(Inst); + break; } } - - return AnyCrossStmtUse; } extern MapInsnToMemAcc InsnToMemAcc; @@ -4018,10 +3925,8 @@ void ScopInfo::buildAccessFunctions(Region &R, BasicBlock &BB, // The set of loads that are required to be invariant. auto &ScopRIL = *SD->getRequiredInvariantLoads(&R); - for (BasicBlock::iterator I = BB.begin(), E = --BB.end(); I != E; ++I) { - Instruction *Inst = &*I; - - PHINode *PHI = dyn_cast<PHINode>(Inst); + for (Instruction &Inst : BB) { + PHINode *PHI = dyn_cast<PHINode>(&Inst); if (PHI) buildPHIAccesses(PHI, R, NonAffineSubRegion, IsExitBlock); @@ -4036,18 +3941,13 @@ void ScopInfo::buildAccessFunctions(Region &R, BasicBlock &BB, if (auto MemInst = MemAccInst::dyn_cast(Inst)) buildMemoryAccess(MemInst, L, &R, BoxedLoops, ScopRIL); - if (isIgnoredIntrinsic(Inst)) + if (isIgnoredIntrinsic(&Inst)) continue; - // Do not build scalar dependences for required invariant loads as we will - // hoist them later on anyway or drop the SCoP if we cannot. - if (ScopRIL.count(dyn_cast<LoadInst>(Inst))) - continue; - - if (buildScalarDependences(Inst, &R, NonAffineSubRegion)) { - if (!isa<StoreInst>(Inst)) - ensureValueWrite(Inst); - } + if (!PHI) + buildScalarDependences(&Inst); + if (!IsExitBlock) + buildEscapingDependences(&Inst); } } @@ -4127,18 +4027,45 @@ void ScopInfo::ensureValueWrite(Instruction *Value) { } void ScopInfo::ensureValueRead(Value *Value, BasicBlock *UserBB) { + // There cannot be an "access" for literal constants. BasicBlock references + // (jump destinations) also never change. + if ((isa<Constant>(Value) && !isa<GlobalVariable>(Value)) || + isa<BasicBlock>(Value)) + return; + // If the instruction can be synthesized and the user is in the region we do // not need to add a value dependences. Region &ScopRegion = scop->getRegion(); if (canSynthesize(Value, LI, SE, &ScopRegion)) return; + // Do not build scalar dependences for required invariant loads as we will + // hoist them later on anyway or drop the SCoP if we cannot. + auto ScopRIL = SD->getRequiredInvariantLoads(&ScopRegion); + if (ScopRIL->count(dyn_cast<LoadInst>(Value))) + return; + + // Determine the ScopStmt containing the value's definition and use. There is + // no defining ScopStmt if the value is a function argument, a global value, + // or defined outside the SCoP. + Instruction *ValueInst = dyn_cast<Instruction>(Value); + ScopStmt *ValueStmt = + ValueInst ? scop->getStmtForBasicBlock(ValueInst->getParent()) : nullptr; + ScopStmt *UserStmt = scop->getStmtForBasicBlock(UserBB); // We do not model uses outside the scop. if (!UserStmt) return; + // Add MemoryAccess for invariant values only if requested. + if (!ModelReadOnlyScalars && !ValueStmt) + return; + + // Ignore use-def chains within the same ScopStmt. + if (ValueStmt == UserStmt) + return; + // Do not create another MemoryAccess for reloading the value if one already // exists. if (UserStmt->lookupValueReadOf(Value)) @@ -4147,10 +4074,21 @@ void ScopInfo::ensureValueRead(Value *Value, BasicBlock *UserBB) { addMemoryAccess(UserBB, nullptr, MemoryAccess::READ, Value, 1, true, Value, ArrayRef<const SCEV *>(), ArrayRef<const SCEV *>(), ScopArrayInfo::MK_Value); + if (ValueInst) + ensureValueWrite(ValueInst); } void ScopInfo::ensurePHIWrite(PHINode *PHI, BasicBlock *IncomingBlock, Value *IncomingValue, bool IsExitBlock) { ScopStmt *IncomingStmt = scop->getStmtForBasicBlock(IncomingBlock); + if (!IncomingStmt) + return; + + // Take care for the incoming value being available in the incoming block. + // This must be done before the check for multiple PHI writes because multiple + // exiting edges from subregion each can be the effective written value of the + // subregion. As such, all of them must be made available in the subregion + // statement. + ensureValueRead(IncomingValue, IncomingBlock); // Do not add more than one MemoryAccess per PHINode and ScopStmt. if (MemoryAccess *Acc = IncomingStmt->lookupPHIWriteOf(PHI)) { diff --git a/polly/lib/Support/ScopHelper.cpp b/polly/lib/Support/ScopHelper.cpp index 9bdfbc3e530..63f91b81e13 100644 --- a/polly/lib/Support/ScopHelper.cpp +++ b/polly/lib/Support/ScopHelper.cpp @@ -442,3 +442,14 @@ bool polly::canSynthesize(const Value *V, const llvm::LoopInfo *LI, return false; } + +llvm::BasicBlock *polly::getUseBlock(llvm::Use &U) { + Instruction *UI = dyn_cast<Instruction>(U.getUser()); + if (!UI) + return nullptr; + + if (PHINode *PHI = dyn_cast<PHINode>(UI)) + return PHI->getIncomingBlock(U); + + return UI->getParent(); +} |

