diff options
-rw-r--r-- | polly/lib/Analysis/ScopInfo.cpp | 52 |
1 files changed, 49 insertions, 3 deletions
diff --git a/polly/lib/Analysis/ScopInfo.cpp b/polly/lib/Analysis/ScopInfo.cpp index 5930380cc0b..0a8b4bb4f99 100644 --- a/polly/lib/Analysis/ScopInfo.cpp +++ b/polly/lib/Analysis/ScopInfo.cpp @@ -2274,8 +2274,32 @@ getRegionNodeSuccessor(RegionNode *RN, TerminatorInst *TI, unsigned idx) { /// Return the smallest loop surrounding @p RN. static inline Loop *getRegionNodeLoop(RegionNode *RN, LoopInfo &LI) { - if (!RN->isSubRegion()) - return LI.getLoopFor(RN->getNodeAs<BasicBlock>()); + if (!RN->isSubRegion()) { + BasicBlock *BB = RN->getNodeAs<BasicBlock>(); + Loop *L = LI.getLoopFor(BB); + + // Unreachable statements are not considered to belong to a LLVM loop, as + // they are not part of an actual loop in the control flow graph. + // Nevertheless, we handle certain unreachable statements that are common + // when modeling run-time bounds checks as being part of the loop to be + // able to model them and to later eliminate the run-time bounds checks. + // + // Specifically, for basic blocks that terminate in an unreachable and + // where the immeditate predecessor is part of a loop, we assume these + // basic blocks belong to the loop the predecessor belongs to. This + // allows us to model the following code. + // + // for (i = 0; i < N; i++) { + // if (i > 1024) + // abort(); <- this abort might be translated to an + // unreachable + // + // A[i] = ... + // } + if (!L && isa<UnreachableInst>(BB->getTerminator()) && BB->getPrevNode()) + L = LI.getLoopFor(BB->getPrevNode()); + return L; + } Region *NonAffineSubRegion = RN->getNodeAs<Region>(); Loop *L = LI.getLoopFor(NonAffineSubRegion->getEntry()); @@ -2284,6 +2308,28 @@ static inline Loop *getRegionNodeLoop(RegionNode *RN, LoopInfo &LI) { return L; } +/// Get the number of blocks in @p L. +/// +/// The number of blocks in a loop are the number of basic blocks actually +/// belonging to the loop, as well as all single basic blocks that the loop +/// exits to and which terminate in an unreachable instruction. We do not +/// allow such basic blocks in the exit of a scop, hence they belong to the +/// scop and represent run-time conditions which we want to model and +/// subsequently speculate away. +/// +/// @see getRegionNodeLoop for additional details. +long getNumBlocksInLoop(Loop *L) { + long NumBlocks = L->getNumBlocks(); + SmallVector<llvm::BasicBlock *, 4> ExitBlocks; + L->getExitBlocks(ExitBlocks); + + for (auto ExitBlock : ExitBlocks) { + if (isa<UnreachableInst>(ExitBlock->getTerminator())) + NumBlocks++; + } + return NumBlocks; +} + static inline unsigned getNumBlocksInRegionNode(RegionNode *RN) { if (!RN->isSubRegion()) return 1; @@ -4511,7 +4557,7 @@ void Scop::buildSchedule(RegionNode *RN, LoopStackTy &LoopStack, LoopInfo &LI) { // Then continue to check surrounding loops, which might also have been // completed by this node. while (LoopData.L && - LoopData.NumBlocksProcessed == LoopData.L->getNumBlocks()) { + LoopData.NumBlocksProcessed == getNumBlocksInLoop(LoopData.L)) { auto *Schedule = LoopData.Schedule; auto NumBlocksProcessed = LoopData.NumBlocksProcessed; |