aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Transforms/Scalar/LoopRotation.cpp20
-rw-r--r--test/Transforms/LoopRotate/phi-duplicate.ll22
2 files changed, 37 insertions, 5 deletions
diff --git a/lib/Transforms/Scalar/LoopRotation.cpp b/lib/Transforms/Scalar/LoopRotation.cpp
index 1e4bfa94be..31957ddac1 100644
--- a/lib/Transforms/Scalar/LoopRotation.cpp
+++ b/lib/Transforms/Scalar/LoopRotation.cpp
@@ -261,6 +261,26 @@ bool LoopRotate::rotateLoop(Loop *Lp, LPPassManager &LPM) {
// NewHeader is now the header of the loop.
L->moveToHeader(NewHeader);
+ // Move the original header to the bottom of the loop, where it now more
+ // naturally belongs. This isn't necessary for correctness, and CodeGen can
+ // usually reorder blocks on its own to fix things like this up, but it's
+ // still nice to keep the IR readable.
+ //
+ // The original header should have only one predecessor at this point, since
+ // we checked that the loop had a proper preheader and unique backedge before
+ // we started.
+ assert(OrigHeader->getSinglePredecessor() &&
+ "Original loop header has too many predecessors after loop rotation!");
+ OrigHeader->moveAfter(OrigHeader->getSinglePredecessor());
+
+ // Also, since this original header only has one predecessor, zap its
+ // PHI nodes, which are now trivial.
+ FoldSingleEntryPHINodes(OrigHeader);
+
+ // TODO: We could just go ahead and merge OrigHeader into its predecessor
+ // at this point, if we don't mind updating dominator info.
+
+ // Establish a new preheader, update dominators, etc.
preserveCanonicalLoopForm(LPM);
++NumRotated;
diff --git a/test/Transforms/LoopRotate/phi-duplicate.ll b/test/Transforms/LoopRotate/phi-duplicate.ll
index 9a64e2a9a8..5403e723ee 100644
--- a/test/Transforms/LoopRotate/phi-duplicate.ll
+++ b/test/Transforms/LoopRotate/phi-duplicate.ll
@@ -27,9 +27,21 @@ for.body: ; preds = %for.cond
for.end: ; preds = %for.cond
ret void
}
-; Should only end up with one phi.
-; CHECK: for.body:
-; CHECK-NEXT: %j.02 = phi i64
-; CHECK-NOT: phi
-; CHECK: ret void
+; Should only end up with one phi. Also, the original for.cond block should
+; be moved to the end of the loop so that the new loop header pleasantly
+; ends up at the top.
+
+; CHECK: define void @test
+; CHECK-NEXT: entry:
+; CHECK-NEXT: icmp slt i64
+; CHECK-NEXT: br i1
+; CHECK-NOT: :
+; CHECK: bb.nph:
+; CHECK-NEXT: br label %for.body
+; CHECK-NOT: :
+; CHECK: for.body:
+; CHECK-NEXT: %j.02 = phi i64
+; CHECK-NOT: phi
+; CHECK: ret void
+; CHECK-NEXT: }