From b584ca4bdfaa7dc184dfe3f671418fa247bb8880 Mon Sep 17 00:00:00 2001 From: Sameer Sahasrabuddhe Date: Wed, 31 Jul 2024 19:44:14 +0530 Subject: [PATCH] [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. --- llvm/include/llvm/ADT/GenericCycleImpl.h | 8 +++++++ .../CycleInfo/unreachable-predecessor.ll | 23 +++++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 llvm/test/Analysis/CycleInfo/unreachable-predecessor.ll diff --git a/llvm/include/llvm/ADT/GenericCycleImpl.h b/llvm/include/llvm/ADT/GenericCycleImpl.h index ab9c421a4469360..56d5ba6e0607722 100644 --- a/llvm/include/llvm/ADT/GenericCycleImpl.h +++ b/llvm/include/llvm/ADT/GenericCycleImpl.h @@ -134,6 +134,8 @@ template 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::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::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 000000000000000..36a2115bd7a9433 --- /dev/null +++ b/llvm/test/Analysis/CycleInfo/unreachable-predecessor.ll @@ -0,0 +1,23 @@ +; RUN: opt < %s -disable-output -passes='print' 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 +}