[MustExecute] Improve MustExecute to correctly handle loop nest
authorXing Xue <xingxue@outlook.com>
Mon, 27 May 2019 13:57:28 +0000 (13:57 +0000)
committerXing Xue <xingxue@outlook.com>
Mon, 27 May 2019 13:57:28 +0000 (13:57 +0000)
Summary:
for.outer:
  br for.inner
for.inner:
  LI <loop invariant load instruction>
for.inner.latch:
  br for.inner, for.outer.latch
for.outer.latch:
  br for.outer, for.outer.exit

LI is a loop invariant load instruction that post dominate for.outer, so LI should be able to move out of the loop nest. However, there is a bug in allLoopPathsLeadToBlock().

Current algorithm of allLoopPathsLeadToBlock()

  1. get all the transitive predecessors of the basic block LI belongs to (for.inner) ==> for.outer, for.inner.latch
  2. if any successors of any of the predecessors are not for.inner or for.inner's predecessors, then return false
  3. return true

Although for.inner.latch is for.inner's predecessor, but for.inner dominates for.inner.latch, which means if for.inner.latch is ever executed, for.inner should be as well. It should not return false for cases like this.

Author: Whitney (committed by xingxue)

Reviewers: kbarton, jdoerfert, Meinersbur, hfinkel, fhahn

Reviewed By: jdoerfert

Subscribers: hiraditya, jsji, llvm-commits, etiotto, bmahjour

Tags: #LLVM

Differential Revision: https://reviews.llvm.org/D62418

llvm-svn: 361762

llvm/lib/Analysis/MustExecute.cpp
llvm/test/Analysis/MustExecute/loop-header.ll

index e22831c..b616cd6 100644 (file)
@@ -193,7 +193,8 @@ bool LoopSafetyInfo::allLoopPathsLeadToBlock(const Loop *CurLoop,
   SmallPtrSet<const BasicBlock *, 4> Predecessors;
   collectTransitivePredecessors(CurLoop, BB, Predecessors);
 
-  // Make sure that all successors of all predecessors of BB are either:
+  // Make sure that all successors of, all predecessors of BB which are not
+  // dominated by BB, are either:
   // 1) BB,
   // 2) Also predecessors of BB,
   // 3) Exit blocks which are not taken on 1st iteration.
@@ -203,6 +204,12 @@ bool LoopSafetyInfo::allLoopPathsLeadToBlock(const Loop *CurLoop,
     // Predecessor block may throw, so it has a side exit.
     if (blockMayThrow(Pred))
       return false;
+
+    // BB dominates Pred, so if Pred runs, BB must run.
+    // This is true when Pred is a loop latch.
+    if (DT->dominates(BB, Pred))
+      continue;
+
     for (auto *Succ : successors(Pred))
       if (CheckedSuccessors.insert(Succ).second &&
           Succ != BB && !Predecessors.count(Succ))
index d0ec5fa..bc75ed6 100644 (file)
@@ -83,17 +83,15 @@ exit:
   ret i1 false
 }
 
-; FIXME: everything in inner loop header should be must execute
-; for outer as well
 define i1 @nested_no_throw(i32* noalias %p, i32 %high) {
 ; CHECK-LABEL: @nested_no_throw
 ; CHECK-LABEL: loop:                                             ; preds = %next
 ; CHECK:         %iv = phi i32 [ 0, %entry ], [ %iv.next, %next ]      ; (mustexec in: loop)
 ; CHECK:         br label %inner_loop  ; (mustexec in: loop)
 ; CHECK-LABEL: inner_loop:
-; CHECK:         %v = load i32, i32* %p        ; (mustexec in: inner_loop)
-; CHECK:         %inner.test = icmp eq i32 %v, 0       ; (mustexec in: inner_loop)
-; CHECK:         br i1 %inner.test, label %inner_loop, label %next     ; (mustexec in: inner_loop)
+; CHECK:         %v = load i32, i32* %p        ; (mustexec in 2 loops: inner_loop, loop)
+; CHECK:         %inner.test = icmp eq i32 %v, 0       ; (mustexec in 2 loops: inner_loop, loop)
+; CHECK:         br i1 %inner.test, label %inner_loop, label %next     ; (mustexec in 2 loops: inner_loop, loop)
 ; CHECK-LABEL: next:
 ; CHECK:         %iv.next = add nuw nsw i32 %iv, 1 ; (mustexec in: loop)
 ; CHECK:         %exit.test = icmp slt i32 %iv, %high ; (mustexec in: loop)