[llvm] [ADT] Align `GenericCycle::getExitBlocks`/`getExitingBlocks` methods with LoopBase (PR #189916)
Antonio Frighetto via llvm-commits
llvm-commits at lists.llvm.org
Wed Apr 1 05:45:06 PDT 2026
https://github.com/antoniofrighetto updated https://github.com/llvm/llvm-project/pull/189916
>From 03b5539dd58584e6821e11123d5c8546147a6f41 Mon Sep 17 00:00:00 2001
From: Antonio Frighetto <me at antoniofrighetto.com>
Date: Wed, 1 Apr 2026 10:21:52 +0200
Subject: [PATCH] [ADT] Align `GenericCycle::getExitBlocks`/`getExitingBlocks`
methods with LoopBase
Ensure `GenericCycle::getExitBlocks` does not replace the content
of the output vector and behaves as `LoopBase::getExitBlocks`,
previously exposing an issue within `isPotentiallyReachable`.
Fixes: https://github.com/llvm/llvm-project/issues/189800.
Fixes: https://github.com/llvm/llvm-project/issues/189289.
Fixes: https://github.com/llvm/llvm-project/issues/189234.
Fixes: https://github.com/llvm/llvm-project/issues/189180.
---
llvm/include/llvm/ADT/GenericCycleImpl.h | 23 ++++++++++-------------
llvm/unittests/Analysis/CFGTest.cpp | 20 ++++++++++++++++++++
2 files changed, 30 insertions(+), 13 deletions(-)
diff --git a/llvm/include/llvm/ADT/GenericCycleImpl.h b/llvm/include/llvm/ADT/GenericCycleImpl.h
index 1a28fb1cef921..0d868857b14d9 100644
--- a/llvm/include/llvm/ADT/GenericCycleImpl.h
+++ b/llvm/include/llvm/ADT/GenericCycleImpl.h
@@ -48,36 +48,33 @@ template <typename ContextT>
void GenericCycle<ContextT>::getExitBlocks(
SmallVectorImpl<BlockT *> &TmpStorage) const {
if (!ExitBlocksCache.empty()) {
- TmpStorage = ExitBlocksCache;
+ TmpStorage.append(ExitBlocksCache.begin(), ExitBlocksCache.end());
return;
}
- TmpStorage.clear();
-
size_t NumExitBlocks = 0;
for (BlockT *Block : blocks()) {
- llvm::append_range(TmpStorage, successors(Block));
+ llvm::append_range(ExitBlocksCache, successors(Block));
- for (size_t Idx = NumExitBlocks, End = TmpStorage.size(); Idx < End;
+ for (size_t Idx = NumExitBlocks, End = ExitBlocksCache.size(); Idx < End;
++Idx) {
- BlockT *Succ = TmpStorage[Idx];
+ BlockT *Succ = ExitBlocksCache[Idx];
if (!contains(Succ)) {
- auto ExitEndIt = TmpStorage.begin() + NumExitBlocks;
- if (std::find(TmpStorage.begin(), ExitEndIt, Succ) == ExitEndIt)
- TmpStorage[NumExitBlocks++] = Succ;
+ auto ExitEndIt = ExitBlocksCache.begin() + NumExitBlocks;
+ if (std::find(ExitBlocksCache.begin(), ExitEndIt, Succ) == ExitEndIt)
+ ExitBlocksCache[NumExitBlocks++] = Succ;
}
}
- TmpStorage.resize(NumExitBlocks);
+ ExitBlocksCache.resize(NumExitBlocks);
}
- ExitBlocksCache.append(TmpStorage.begin(), TmpStorage.end());
+
+ TmpStorage.append(ExitBlocksCache.begin(), ExitBlocksCache.end());
}
template <typename ContextT>
void GenericCycle<ContextT>::getExitingBlocks(
SmallVectorImpl<BlockT *> &TmpStorage) const {
- TmpStorage.clear();
-
for (BlockT *Block : blocks()) {
for (BlockT *Succ : successors(Block)) {
if (!contains(Succ)) {
diff --git a/llvm/unittests/Analysis/CFGTest.cpp b/llvm/unittests/Analysis/CFGTest.cpp
index a9938b381f9db..d4ac8ecfdd3c8 100644
--- a/llvm/unittests/Analysis/CFGTest.cpp
+++ b/llvm/unittests/Analysis/CFGTest.cpp
@@ -517,3 +517,23 @@ TEST_F(IsPotentiallyReachableTest, UnreachableToReachable) {
"}");
ExpectPath(true);
}
+
+TEST_F(IsPotentiallyReachableTest, CycleExitBlocksSelfLoop) {
+ ParseAssembly("define void @test() {\n"
+ "entry:\n"
+ " br label %loop.header\n"
+ "loop.header:\n"
+ " %A = bitcast i32 0 to i32\n"
+ " br i1 undef, label %loop.latch, label %loop.exit\n"
+ "loop.latch:\n"
+ " br label %loop.header\n"
+ "loop.exit:\n"
+ " br i1 undef, label %exit, label %loop.body\n"
+ "loop.body:\n"
+ " br label %loop.body\n"
+ "exit:\n"
+ " %B = bitcast i32 0 to i32\n"
+ " ret void\n"
+ "}");
+ ExpectPath(true);
+}
More information about the llvm-commits
mailing list