summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavide Italiano <davide@freebsd.org>2017-04-24 20:14:11 +0000
committerDavide Italiano <davide@freebsd.org>2017-04-24 20:14:11 +0000
commit0f62eea7ff4a1c5888eecba930d87361430a053b (patch)
tree5a4246c5cadd8424d410d76ff95928ec58183ea8
parent206f65c04964a23a6072b2a6de3bf6496bb1a884 (diff)
downloadbcm5719-llvm-0f62eea7ff4a1c5888eecba930d87361430a053b.tar.gz
bcm5719-llvm-0f62eea7ff4a1c5888eecba930d87361430a053b.zip
[LoopUnroll] Don't try to unroll non canonical loops.
The current Loop Unroll implementation works with loops having a single latch that contains a conditional branch to a block outside the loop (the other successor is, by defition of latch, the header). If this precondition doesn't hold, avoid unrolling the loop as the code is not ready to handle such circumstances. Differential Revision: https://reviews.llvm.org/D32261 llvm-svn: 301239
-rw-r--r--llvm/lib/Transforms/Utils/LoopUnroll.cpp15
-rw-r--r--llvm/test/Transforms/LoopUnroll/not-rotated.ll26
2 files changed, 41 insertions, 0 deletions
diff --git a/llvm/lib/Transforms/Utils/LoopUnroll.cpp b/llvm/lib/Transforms/Utils/LoopUnroll.cpp
index 3c669ce644e..3e3cc5e48a1 100644
--- a/llvm/lib/Transforms/Utils/LoopUnroll.cpp
+++ b/llvm/lib/Transforms/Utils/LoopUnroll.cpp
@@ -318,6 +318,10 @@ bool llvm::UnrollLoop(Loop *L, unsigned Count, unsigned TripCount, bool Force,
return false;
}
+ // The current loop unroll pass can only unroll loops with a single latch
+ // that's a conditional branch exiting the loop.
+ // FIXME: The implementation can be extended to work with more complicated
+ // cases, e.g. loops with multiple latches.
BasicBlock *Header = L->getHeader();
BranchInst *BI = dyn_cast<BranchInst>(LatchBlock->getTerminator());
@@ -328,6 +332,17 @@ bool llvm::UnrollLoop(Loop *L, unsigned Count, unsigned TripCount, bool Force,
return false;
}
+ auto CheckSuccessors = [&](unsigned S1, unsigned S2) {
+ return BI->getSuccessor(S1) == Header && !L->contains(BI->getSuccessor(S2));
+
+ };
+
+ if (!CheckSuccessors(0, 1) && !CheckSuccessors(1, 0)) {
+ DEBUG(dbgs() << "Can't unroll; only loops with one conditional latch"
+ " exiting the loop can be unrolled\n");
+ return false;
+ }
+
if (Header->hasAddressTaken()) {
// The loop-rotate pass can be helpful to avoid this in many cases.
DEBUG(dbgs() <<
diff --git a/llvm/test/Transforms/LoopUnroll/not-rotated.ll b/llvm/test/Transforms/LoopUnroll/not-rotated.ll
new file mode 100644
index 00000000000..ffe80920d94
--- /dev/null
+++ b/llvm/test/Transforms/LoopUnroll/not-rotated.ll
@@ -0,0 +1,26 @@
+; PR28103
+; Bail out if the two successors are not the header
+; and another bb outside of the loop. This case is not
+; properly handled by LoopUnroll, currently.
+
+; RUN: opt -loop-unroll -verify-dom-info %s
+; REQUIRE: asserts
+
+define void @tinkywinky(i1 %patatino) {
+entry:
+ br label %header1
+header1:
+ %indvars.iv = phi i64 [ 1, %body2 ], [ 0, %entry ]
+ %exitcond = icmp ne i64 %indvars.iv, 1
+ br i1 %exitcond, label %body1, label %exit
+body1:
+ br i1 %patatino, label %body2, label %sink
+body2:
+ br i1 %patatino, label %header1, label %body3
+body3:
+ br label %sink
+sink:
+ br label %body2
+exit:
+ ret void
+}
OpenPOWER on IntegriCloud