summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Trick <atrick@apple.com>2011-11-18 03:42:41 +0000
committerAndrew Trick <atrick@apple.com>2011-11-18 03:42:41 +0000
commit5865a8dfde3be74418b579f1162f111f3e46998d (patch)
tree1a6de422e136fc3276a1e3ec145fc3a8a4b36e60
parentcbbe33fde4f484ffdc9a171b69d6f98eb89dabd9 (diff)
downloadllvm-5865a8dfde3be74418b579f1162f111f3e46998d.tar.gz
llvm-5865a8dfde3be74418b579f1162f111f3e46998d.tar.bz2
llvm-5865a8dfde3be74418b579f1162f111f3e46998d.tar.xz
Fix a corner case in updating LoopInfo after fully unrolling an outer loop.
The loop tree's inclusive block lists are painful and expensive to update. (I have no idea why they're inclusive). The design was supposed to handle this case but the implementation missed it and my unit tests weren't thorough enough. Fixes PR11335: loop unroll update. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@144970 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Analysis/LoopInfo.cpp20
-rw-r--r--test/Transforms/LoopUnroll/unloop.ll41
2 files changed, 50 insertions, 11 deletions
diff --git a/lib/Analysis/LoopInfo.cpp b/lib/Analysis/LoopInfo.cpp
index 85aaccaefc..c7833bf7bb 100644
--- a/lib/Analysis/LoopInfo.cpp
+++ b/lib/Analysis/LoopInfo.cpp
@@ -477,21 +477,19 @@ void UnloopUpdater::updateBlockParents() {
/// removeBlocksFromAncestors - Remove unloop's blocks from all ancestors below
/// their new parents.
void UnloopUpdater::removeBlocksFromAncestors() {
- // Remove unloop's blocks from all ancestors below their new parents.
+ // Remove all unloop's blocks (including those in nested subloops) from
+ // ancestors below the new parent loop.
for (Loop::block_iterator BI = Unloop->block_begin(),
BE = Unloop->block_end(); BI != BE; ++BI) {
- Loop *NewParent = LI->getLoopFor(*BI);
- // If this block is an immediate subloop, remove all blocks (including
- // nested subloops) from ancestors below the new parent loop.
- // Otherwise, if this block is in a nested subloop, skip it.
- if (SubloopParents.count(NewParent))
- NewParent = SubloopParents[NewParent];
- else if (Unloop->contains(NewParent))
- continue;
-
+ Loop *OuterParent = LI->getLoopFor(*BI);
+ if (Unloop->contains(OuterParent)) {
+ while (OuterParent->getParentLoop() != Unloop)
+ OuterParent = OuterParent->getParentLoop();
+ OuterParent = SubloopParents[OuterParent];
+ }
// Remove blocks from former Ancestors except Unloop itself which will be
// deleted.
- for (Loop *OldParent = Unloop->getParentLoop(); OldParent != NewParent;
+ for (Loop *OldParent = Unloop->getParentLoop(); OldParent != OuterParent;
OldParent = OldParent->getParentLoop()) {
assert(OldParent && "new loop is not an ancestor of the original");
OldParent->removeBlockFromLoop(*BI);
diff --git a/test/Transforms/LoopUnroll/unloop.ll b/test/Transforms/LoopUnroll/unloop.ll
index 217c8cea56..5a9cacda44 100644
--- a/test/Transforms/LoopUnroll/unloop.ll
+++ b/test/Transforms/LoopUnroll/unloop.ll
@@ -427,3 +427,44 @@ if.end2413: ; preds = %defchar
return: ; preds = %sw.bb304
ret void
}
+
+; PR11335: the most deeply nested block should be removed from the outer loop.
+; CHECK: @removeSubloopBlocks2
+; CHECK: for.cond3:
+; CHECK-NOT: br
+; CHECK: ret void
+define void @removeSubloopBlocks2() nounwind {
+entry:
+ %tobool.i = icmp ne i32 undef, 0
+ br label %lbl_616
+
+lbl_616.loopexit: ; preds = %for.cond
+ br label %lbl_616
+
+lbl_616: ; preds = %lbl_616.loopexit, %entry
+ br label %for.cond
+
+for.cond: ; preds = %for.cond3, %lbl_616
+ br i1 false, label %for.cond1.preheader, label %lbl_616.loopexit
+
+for.cond1.preheader: ; preds = %for.cond
+ br label %for.cond1
+
+for.cond1.loopexit: ; preds = %for.cond.i
+ br label %for.cond1
+
+for.cond1: ; preds = %for.cond1.loopexit, %for.cond1.preheader
+ br i1 false, label %for.body2, label %for.cond3
+
+for.body2: ; preds = %for.cond1
+ br label %for.cond.i
+
+for.cond.i: ; preds = %for.cond.i, %for.body2
+ br i1 %tobool.i, label %for.cond.i, label %for.cond1.loopexit
+
+for.cond3: ; preds = %for.cond1
+ br i1 false, label %for.cond, label %if.end
+
+if.end: ; preds = %for.cond3
+ ret void
+}