[polly] r297156 - [ScopInfo] Avoid infinite loop during schedule construction
Tobias Grosser via llvm-commits
llvm-commits at lists.llvm.org
Tue Mar 7 08:17:55 PST 2017
Author: grosser
Date: Tue Mar 7 10:17:55 2017
New Revision: 297156
URL: http://llvm.org/viewvc/llvm-project?rev=297156&view=rev
Log:
[ScopInfo] Avoid infinite loop during schedule construction
Our current scop modeling enters an infinite loop when trying to model code
that has unreachable instructions (e.g.,
test/ScopInfo/BoundChecks/single-loop.ll), as the number of basic blocks
returned by the LLVM Loop* does not include unreachable basic blocks that
branch off from the core loop body. This arises for example in the following
piece of code:
for (i = 0; i < N; i++) {
if (i > 1024)
abort(); <- this abort might be translated to an
unreachable
A[i] = ...
}
This patch adds these unreachable basic blocks in our per loop basic block
count to ensure that the schedule construction does not assume a loop has been
processed completely, despite certain unreachable basic blocks still remaining.
The infinite loop is only observable in combination with
https://reviews.llvm.org/D12676 or a similar patch.
Modified:
polly/trunk/lib/Analysis/ScopInfo.cpp
Modified: polly/trunk/lib/Analysis/ScopInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/Analysis/ScopInfo.cpp?rev=297156&r1=297155&r2=297156&view=diff
==============================================================================
--- polly/trunk/lib/Analysis/ScopInfo.cpp (original)
+++ polly/trunk/lib/Analysis/ScopInfo.cpp Tue Mar 7 10:17:55 2017
@@ -2274,8 +2274,32 @@ getRegionNodeSuccessor(RegionNode *RN, T
/// 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(Re
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,
// 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;
More information about the llvm-commits
mailing list