]> granicus.if.org Git - llvm/commitdiff
[LoopUnrollRuntime] Avoid multi-exit nested loop with epilog generation
authorAnna Thomas <anna@azul.com>
Tue, 11 Jul 2017 17:16:33 +0000 (17:16 +0000)
committerAnna Thomas <anna@azul.com>
Tue, 11 Jul 2017 17:16:33 +0000 (17:16 +0000)
The loop structure for the outer loop does not contain the epilog
preheader when we try to unroll inner loop with multiple exits and
epilog code is generated. For now, we just bail out in such cases.
Added a test case that shows the problem. Without this bailout, we would
trip on assert saying LCSSA form is incorrect for outer loop.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@307676 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/Utils/LoopUnrollRuntime.cpp
test/Transforms/LoopUnroll/runtime-loop-multiple-exits.ll

index 59408ffe7a76e2aa852e7c1c4ef6c6b9453a0bee..2b432426b249b31aebd70ad8f5a54a79879d91e1 100644 (file)
@@ -470,8 +470,9 @@ bool llvm::UnrollRuntimeLoopRemainder(Loop *L, unsigned Count,
                                       bool UseEpilogRemainder,
                                       LoopInfo *LI, ScalarEvolution *SE,
                                       DominatorTree *DT, bool PreserveLCSSA) {
-  // for now, only unroll loops that contain a single exit
-  if (!UnrollRuntimeMultiExit && !L->getExitingBlock())
+  bool hasMultipleExitingBlocks = !L->getExitingBlock();
+  // Support only single exiting block unless UnrollRuntimeMultiExit is true.
+  if (!UnrollRuntimeMultiExit && hasMultipleExitingBlocks)
     return false;
 
   // Make sure the loop is in canonical form.
@@ -516,6 +517,13 @@ bool llvm::UnrollRuntimeLoopRemainder(Loop *L, unsigned Count,
   // connectEpilog.
   if (!LatchExit->getSinglePredecessor())
     return false;
+  // FIXME: We bail out of multi-exit unrolling when epilog loop is generated
+  // and L is an inner loop. This is because in presence of multiple exits, the
+  // outer loop is incorrect: we do not add the EpilogPreheader and exit to the
+  // outer loop. This is automatically handled in the prolog case, so we do not
+  // have that bug in prolog generation.
+  if (hasMultipleExitingBlocks && UseEpilogRemainder && L->getParentLoop())
+    return false;
   // Use Scalar Evolution to compute the trip count. This allows more loops to
   // be unrolled than relying on induction var simplification.
   if (!SE)
index 18548c8af73596a38b6d63f51a0f5b2705f1de39..73672e14f78ac16d641527694824ab786690ebe5 100644 (file)
@@ -434,3 +434,47 @@ loopexit1:                                             ; preds = %header
   %sext3 = phi i32 [ %shft, %header ]
   ret i32 %sext3
 }
+
+; Nested loop and inner loop is unrolled
+; FIXME: we cannot unroll with epilog remainder currently, because 
+; the outer loop does not contain the epilog preheader and epilog exit (while
+; infact it should). This causes us to choke up on LCSSA form being incorrect in
+; outer loop. However, the exit block where LCSSA fails, is infact still within
+; the outer loop. For now, we just bail out in presence of outer loop and epilog
+; loop is generated.
+; The outer loop header is the preheader for the inner loop and the inner header
+; branches back to the outer loop.
+define void @test8() {
+; EPILOG: test8(
+; EPILOG-NOT: niter
+
+; PROLOG: test8(
+; PROLOG: outerloop:
+; PROLOG-NEXT: phi i64 [ 3, %bb ], [ 0, %outerloop.loopexit ]
+; PROLOG:      %lcmp.mod = icmp eq i64
+; PROLOG-NEXT: br i1 %lcmp.mod, label %innerH.prol.loopexit, label %innerH.prol.preheader
+; PROLOG: latch.6:
+; PROLOG-NEXT: %tmp4.7 = add nsw i64 %tmp3, 8
+; PROLOG-NEXT: br i1 false, label %outerloop.loopexit.loopexit, label %latch.7
+; PROLOG: latch.7
+; PROLOG-NEXT: %tmp6.7 = icmp ult i64 %tmp4.7, 100
+; PROLOG-NEXT: br i1 %tmp6.7, label %innerH, label %exit.unr-lcssa
+bb:
+  br label %outerloop
+
+outerloop:                                              ; preds = %innerH, %bb
+  %tmp = phi i64 [ 3, %bb ], [ 0, %innerH ]
+  br label %innerH
+
+innerH:                                              ; preds = %latch, %outerloop
+  %tmp3 = phi i64 [ %tmp4, %latch ], [ %tmp, %outerloop ]
+  %tmp4 = add nuw nsw i64 %tmp3, 1
+  br i1 false, label %outerloop, label %latch
+
+latch:                                              ; preds = %innerH
+  %tmp6 = icmp ult i64 %tmp4, 100
+  br i1 %tmp6, label %innerH, label %exit
+
+exit:                                              ; preds = %latch
+  ret void
+}