diff --git a/llvm/lib/Analysis/MustExecute.cpp b/llvm/lib/Analysis/MustExecute.cpp index caed62679a683..8e233a5c8d7a5 100644 --- a/llvm/lib/Analysis/MustExecute.cpp +++ b/llvm/lib/Analysis/MustExecute.cpp @@ -162,6 +162,9 @@ static bool CanProveNotTakenFirstIteration(const BasicBlock *ExitBlock, /// Collect all blocks from \p CurLoop which lie on all possible paths from /// the header of \p CurLoop (inclusive) to BB (exclusive) into the set /// \p Predecessors. If \p BB is the header, \p Predecessors will be empty. +/// Note: It's possible that we encounter Irreducible control flow, due to +/// which, we may find that a few predecessors of \p BB are not a part of the +/// \p CurLoop. We only return Predecessors that are a part of \p CurLoop. static void collectTransitivePredecessors( const Loop *CurLoop, const BasicBlock *BB, SmallPtrSetImpl &Predecessors) { @@ -171,6 +174,8 @@ static void collectTransitivePredecessors( return; SmallVector WorkList; for (const auto *Pred : predecessors(BB)) { + if (!CurLoop->contains(Pred)) + continue; Predecessors.insert(Pred); WorkList.push_back(Pred); } @@ -187,7 +192,7 @@ static void collectTransitivePredecessors( // We can ignore backedge of all loops containing BB to get a sligtly more // optimistic result. for (const auto *PredPred : predecessors(Pred)) - if (Predecessors.insert(PredPred).second) + if (CurLoop->contains(PredPred) && Predecessors.insert(PredPred).second) WorkList.push_back(PredPred); } } diff --git a/llvm/test/Analysis/MustExecute/irreducible-cfg.ll b/llvm/test/Analysis/MustExecute/irreducible-cfg.ll new file mode 100644 index 0000000000000..a452761ab3356 --- /dev/null +++ b/llvm/test/Analysis/MustExecute/irreducible-cfg.ll @@ -0,0 +1,29 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 +; RUN: opt -disable-output -passes=print-mustexecute %s 2>&1 | FileCheck %s + +; The loop body has two predecessors, %header and %side-entry. This leads to irreducible-cfg +define i64 @baz() { +; CHECK-LABEL: define i64 @baz() { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: br label %[[HEADER:.*]] +; CHECK: [[HEADER]]: +; CHECK-NEXT: br label %[[BODY:.*]] ; (mustexec in: header) +; CHECK: [[SIDE_ENTRY:.*:]] +; CHECK-NEXT: br label %[[BODY]] +; CHECK: [[BODY]]: +; CHECK-NEXT: [[LOAD:%.*]] = load ptr addrspace(1), ptr addrspace(1) null, align 8 ; (mustexec in: header) +; CHECK-NEXT: br label %[[HEADER]] ; (mustexec in: header) +; +entry: + br label %header + +header: + br label %body + +side-entry: + br label %body + +body: + %load = load ptr addrspace(1), ptr addrspace(1) null, align 8 + br label %header +}