aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSameer Sahasrabuddhe <sameer.sahasrabuddhe@amd.com>2024-07-31 19:44:14 +0530
committerGitHub <noreply@github.com>2024-07-31 19:44:14 +0530
commit05c3a4b8f99d13df4249e9486d8aa42a37957685 (patch)
tree267d21a0e0770f4e35f45bbcfa0da79294b8b894
parent93fecc2577ece0329f3bbe2719bbc5b4b9b30010 (diff)
downloadllvm-05c3a4b8f99d13df4249e9486d8aa42a37957685.zip
llvm-05c3a4b8f99d13df4249e9486d8aa42a37957685.tar.gz
llvm-05c3a4b8f99d13df4249e9486d8aa42a37957685.tar.bz2
[CycleInfo] skip unreachable predecessors (#101316)
If an unreachable block B branches to a block S inside a cycle, it may cause S to be incorrectly treated as an entry to the cycle. We avoid that by skipping unreachable predecessors when locating entries.
-rw-r--r--llvm/include/llvm/ADT/GenericCycleImpl.h8
-rw-r--r--llvm/test/Analysis/CycleInfo/unreachable-predecessor.ll23
2 files changed, 31 insertions, 0 deletions
diff --git a/llvm/include/llvm/ADT/GenericCycleImpl.h b/llvm/include/llvm/ADT/GenericCycleImpl.h
index ab9c421..56d5ba6 100644
--- a/llvm/include/llvm/ADT/GenericCycleImpl.h
+++ b/llvm/include/llvm/ADT/GenericCycleImpl.h
@@ -134,6 +134,8 @@ template <typename ContextT> class GenericCycleInfoCompute {
DFSInfo() = default;
explicit DFSInfo(unsigned Start) : Start(Start) {}
+ explicit operator bool() const { return Start; }
+
/// Whether this node is an ancestor (or equal to) the node \p Other
/// in the DFS tree.
bool isAncestorOf(const DFSInfo &Other) const {
@@ -231,6 +233,8 @@ void GenericCycleInfoCompute<ContextT>::run(BlockT *EntryBlock) {
for (BlockT *Pred : predecessors(HeaderCandidate)) {
const DFSInfo PredDFSInfo = BlockDFSInfo.lookup(Pred);
+ // This automatically ignores unreachable predecessors since they have
+ // zeros in their DFSInfo.
if (CandidateInfo.isAncestorOf(PredDFSInfo))
Worklist.push_back(Pred);
}
@@ -257,6 +261,10 @@ void GenericCycleInfoCompute<ContextT>::run(BlockT *EntryBlock) {
const DFSInfo PredDFSInfo = BlockDFSInfo.lookup(Pred);
if (CandidateInfo.isAncestorOf(PredDFSInfo)) {
Worklist.push_back(Pred);
+ } else if (!PredDFSInfo) {
+ // Ignore an unreachable predecessor. It will will incorrectly cause
+ // Block to be treated as a cycle entry.
+ LLVM_DEBUG(errs() << " skipped unreachable predecessor.\n");
} else {
IsEntry = true;
}
diff --git a/llvm/test/Analysis/CycleInfo/unreachable-predecessor.ll b/llvm/test/Analysis/CycleInfo/unreachable-predecessor.ll
new file mode 100644
index 0000000..36a2115
--- /dev/null
+++ b/llvm/test/Analysis/CycleInfo/unreachable-predecessor.ll
@@ -0,0 +1,23 @@
+; RUN: opt < %s -disable-output -passes='print<cycles>' 2>&1 | FileCheck %s
+; CHECK-LABEL: CycleInfo for function: unreachable
+; CHECK: depth=1: entries(loop.body) loop.latch inner.block
+define void @unreachable(i32 %n) {
+entry:
+ br label %loop.body
+
+loop.body:
+ br label %inner.block
+
+; This branch should not cause %inner.block to appear as an entry.
+unreachable.block:
+ br label %inner.block
+
+inner.block:
+ br i1 undef, label %loop.exit, label %loop.latch
+
+loop.latch:
+ br label %loop.body
+
+loop.exit:
+ ret void
+}