[llvm] [SimpleLoopUnswitch][NFC] Factor out conditional clone legality check (PR #217884)
Keno Fischer via llvm-commits
llvm-commits at lists.llvm.org
Fri Aug 21 04:29:31 PDT 2026
https://github.com/Keno created https://github.com/llvm/llvm-project/pull/217884
Move the caller-side legality checks of isSafeForNoNTrivialUnswitching (no token values used outside their defining block, no convergent calls, plus the existing Loop::isSafeToClone conditions) into a new Loop::isSafeToCloneConditionally helper, preserving current behavior exactly.
Transformations that may cause cloned loop bodies to execute conditionally need these stricter conditions than plain cloning; a follow-up commit will use the helper from IRCE's LoopConstrainer as well, which is currently missing this check entirely.
Factored out of #151062 by review request.
>From 2cdd7687a0a7d77bf2313f0571388a496e18d35c Mon Sep 17 00:00:00 2001
From: Keno Fischer <keno at juliahub.com>
Date: Fri, 21 Aug 2026 09:37:55 +0000
Subject: [PATCH] [SimpleLoopUnswitch] Factor legality check into
Loop::isSafeToCloneConditionally (NFC)
Move the caller-side legality checks of isSafeForNoNTrivialUnswitching
(no token values used outside their defining block, no convergent
calls, plus the existing Loop::isSafeToClone conditions) into a new
Loop::isSafeToCloneConditionally helper, preserving current behavior
exactly.
Transformations that may cause cloned loop bodies to execute
conditionally need these stricter conditions than plain cloning; a
follow-up commit will use the helper from IRCE's LoopConstrainer as
well, which is currently missing this check entirely.
---
llvm/include/llvm/Analysis/LoopInfo.h | 6 ++++++
llvm/lib/Analysis/LoopInfo.cpp | 18 ++++++++++++++++++
.../Transforms/Scalar/SimpleLoopUnswitch.cpp | 12 +-----------
3 files changed, 25 insertions(+), 11 deletions(-)
diff --git a/llvm/include/llvm/Analysis/LoopInfo.h b/llvm/include/llvm/Analysis/LoopInfo.h
index 15c22e43c44bf..bbac76c85f1ed 100644
--- a/llvm/include/llvm/Analysis/LoopInfo.h
+++ b/llvm/include/llvm/Analysis/LoopInfo.h
@@ -328,6 +328,12 @@ class LLVM_ABI Loop : public LoopBase<BasicBlock, Loop> {
/// Return true if the loop body is safe to clone in practice.
bool isSafeToClone() const;
+ /// Like `isSafeToClone`, but for transformations where the cloned loop
+ /// bodies may run conditionally. This additionally rejects convergent
+ /// calls (which must not gain new control dependencies) and token values
+ /// that are used outside their defining block.
+ bool isSafeToCloneConditionally() const;
+
/// Returns true if the loop is annotated parallel.
///
/// A parallel loop can be assumed to not contain any dependencies between
diff --git a/llvm/lib/Analysis/LoopInfo.cpp b/llvm/lib/Analysis/LoopInfo.cpp
index 16a7690092ff5..ab535e302b305 100644
--- a/llvm/lib/Analysis/LoopInfo.cpp
+++ b/llvm/lib/Analysis/LoopInfo.cpp
@@ -530,6 +530,24 @@ bool Loop::isSafeToClone() const {
return true;
}
+bool Loop::isSafeToCloneConditionally() const {
+ if (!isSafeToClone())
+ return false;
+
+ for (BasicBlock *BB : this->blocks()) {
+ for (Instruction &I : *BB) {
+ if (I.getType()->isTokenTy() && I.isUsedOutsideOfBlock(BB))
+ return false;
+ if (auto *CB = dyn_cast<CallBase>(&I)) {
+ assert(!CB->cannotDuplicate() && "Checked by isSafeToClone().");
+ if (CB->isConvergent())
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
MDNode *Loop::getLoopID() const {
MDNode *LoopID = nullptr;
diff --git a/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp b/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp
index 9425c8a8ac520..619e48f0ce509 100644
--- a/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp
+++ b/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp
@@ -3359,18 +3359,8 @@ static bool collectUnswitchCandidatesWithInjections(
}
static bool isSafeForNoNTrivialUnswitching(Loop &L, LoopInfo &LI) {
- if (!L.isSafeToClone())
+ if (!L.isSafeToCloneConditionally())
return false;
- for (auto *BB : L.blocks())
- for (auto &I : *BB) {
- if (I.getType()->isTokenTy() && I.isUsedOutsideOfBlock(BB))
- return false;
- if (auto *CB = dyn_cast<CallBase>(&I)) {
- assert(!CB->cannotDuplicate() && "Checked by L.isSafeToClone().");
- if (CB->isConvergent())
- return false;
- }
- }
// Check if there are irreducible CFG cycles in this loop. If so, we cannot
// easily unswitch non-trivial edges out of the loop. Doing so might turn the
More information about the llvm-commits
mailing list