summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--polly/lib/Analysis/ScopInfo.cpp52
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;
OpenPOWER on IntegriCloud