[llvm] [CycleInfo] skip unreachable predecessors (PR #101316)

Sameer Sahasrabuddhe via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 31 03:19:58 PDT 2024


https://github.com/ssahasra created https://github.com/llvm/llvm-project/pull/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.

>From f467bb765e8aacea39d1177f1b6a425d4c5ddf85 Mon Sep 17 00:00:00 2001
From: Sameer Sahasrabuddhe <sameer.sahasrabuddhe at amd.com>
Date: Wed, 31 Jul 2024 15:46:20 +0530
Subject: [PATCH] [CycleInfo] skip unreachable predecessors

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 ab9c421a44693..56d5ba6e06077 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 0000000000000..36a2115bd7a94
--- /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
+}



More information about the llvm-commits mailing list