diff options
author | Sameer Sahasrabuddhe <sameer.sahasrabuddhe@amd.com> | 2024-07-31 19:44:14 +0530 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-07-31 19:44:14 +0530 |
commit | 05c3a4b8f99d13df4249e9486d8aa42a37957685 (patch) | |
tree | 267d21a0e0770f4e35f45bbcfa0da79294b8b894 | |
parent | 93fecc2577ece0329f3bbe2719bbc5b4b9b30010 (diff) | |
download | llvm-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.h | 8 | ||||
-rw-r--r-- | llvm/test/Analysis/CycleInfo/unreachable-predecessor.ll | 23 |
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 +} |