[llvm-branch-commits] [llvm] [SLP][modularisation][NFC] Move loop trip-count helpers to SLPUtils (PR #222614)
Madhur Amilkanthwar via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Sun Oct 18 00:08:29 PDT 2026
https://github.com/madhur13490 updated https://github.com/llvm/llvm-project/pull/222614
>From 226c19ae7c563f20d753f2d5fbd03df5902e51d8 Mon Sep 17 00:00:00 2001
From: Madhur Amilkanthwar <madhura at nvidia.com>
Date: Thu, 10 Sep 2026 04:21:05 -0700
Subject: [PATCH] [SLP][modularisation][NFC] Move loop trip-count helpers to
SLPUtils
Move the BoUpSLP-independent helpers findInnermostNonInvariantLoop and
getLoopTripCount out of SLPVectorizer.cpp into the self-contained
SLPVectorizer/SLPUtils.{h,cpp} module. getLoopTripCount reads the file-local
LoopAwareTripCount cl::opt, which stays static in SLPVectorizer.cpp and is
passed to the moved helper as an explicit parameter. NFC.
Part of the SLPVectorizer.cpp modularization effort:
https://discourse.llvm.org/t/modularizing-slpvectorizer-cpp/90922
---
.../Transforms/Vectorize/SLPVectorizer.cpp | 36 ++-----------------
.../Vectorize/SLPVectorizer/SLPUtils.cpp | 32 +++++++++++++++++
.../Vectorize/SLPVectorizer/SLPUtils.h | 11 ++++++
3 files changed, 45 insertions(+), 34 deletions(-)
diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
index 4da01f369b90c..fdd65d2795e1c 100644
--- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
@@ -9229,20 +9229,6 @@ static bool isPoorThroughputOp(const VectorizeOptions &Opts, Instruction *I,
[&] { Cache.CheapOpcodes.insert(Key); });
}
-/// Find the innermost loop starting from \p L, for which at least a single
-/// value in \p VL is not invariant.
-static const Loop *findInnermostNonInvariantLoop(const Loop *L,
- ArrayRef<Value *> VL) {
- assert(L && "Expected valid loop");
- auto IsLoopInvariant = [&](const Loop *L, ArrayRef<Value *> VL) {
- return all_of(make_isa_range<Instruction>(VL),
- [L](Instruction *I) { return L->isLoopInvariant(I); });
- };
- while (L && IsLoopInvariant(L, VL))
- L = L->getParentLoop();
- return L;
-}
-
/// Get the loop nest for the given loop.
ArrayRef<const Loop *> BoUpSLP::getLoopNest(const Loop *L) {
assert(L && "Expected valid loop");
@@ -16260,25 +16246,6 @@ TTI::CastContextHint BoUpSLP::getCastContextHint(const TreeEntry &TE) const {
return TTI::CastContextHint::None;
}
-/// Get the assumed loop trip count for the loop \p L.
-static unsigned getLoopTripCount(const VectorizeOptions &Opts, const Loop *L,
- ScalarEvolution &SE) {
- if (Opts.slp_cost_loop_trip_count == 0)
- return 1;
- unsigned Scale = SE.getSmallConstantTripCount(L);
- if (Scale == 0)
- Scale = getLoopEstimatedTripCount(const_cast<Loop *>(L)).value_or(0);
- if (Scale != 0) {
- // Multiple exiting blocks - choose the minimum between trip count (scale)
- // and LoopAwareTripCount, since the multiple exit loops can be terminated
- // early.
- if (!L->getExitingBlock())
- return std::min(Opts.slp_cost_loop_trip_count, Scale);
- return Scale;
- }
- return Opts.slp_cost_loop_trip_count;
-}
-
uint64_t BoUpSLP::getScaleToLoopIterations(const TreeEntry &TE, Value *Scalar,
Instruction *U) {
BasicBlock *Parent = nullptr;
@@ -16380,7 +16347,8 @@ uint64_t BoUpSLP::getLoopNestScale(const Loop *L) {
// Use SaturatingMultiply to clamp at uint64_t max on deep/large nests
// rather than wrapping around.
for (const Loop *Cur : reverse(Chain)) {
- uint64_t TC = std::max<uint64_t>(1, getLoopTripCount(Opts, Cur, *SE));
+ uint64_t TC = std::max<uint64_t>(
+ 1, getLoopTripCount(Cur, *SE, Opts.slp_cost_loop_trip_count));
Scale = SaturatingMultiply(Scale, TC);
LoopNestScaleCache.try_emplace(Cur, std::max<uint64_t>(1, Scale));
}
diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer/SLPUtils.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer/SLPUtils.cpp
index 514c87e89cad9..d57b0cacb094e 100644
--- a/llvm/lib/Transforms/Vectorize/SLPVectorizer/SLPUtils.cpp
+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer/SLPUtils.cpp
@@ -13,6 +13,8 @@
#include "llvm/ADT/Sequence.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Analysis/AssumptionCache.h"
+#include "llvm/Analysis/LoopInfo.h"
+#include "llvm/Analysis/ScalarEvolution.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/Analysis/VectorUtils.h"
#include "llvm/IR/Constants.h"
@@ -28,6 +30,7 @@
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/Transforms/Utils/LoopUtils.h"
#include <algorithm>
#include <numeric>
@@ -1636,4 +1639,33 @@ std::optional<unsigned> getAggregateSize(Instruction *InsertInst) {
} while (true);
}
+const Loop *findInnermostNonInvariantLoop(const Loop *L, ArrayRef<Value *> VL) {
+ assert(L && "Expected valid loop");
+ auto IsLoopInvariant = [&](const Loop *L, ArrayRef<Value *> VL) {
+ return all_of(make_isa_range<Instruction>(VL),
+ [L](Instruction *I) { return L->isLoopInvariant(I); });
+ };
+ while (L && IsLoopInvariant(L, VL))
+ L = L->getParentLoop();
+ return L;
+}
+
+unsigned getLoopTripCount(const Loop *L, ScalarEvolution &SE,
+ unsigned LoopAwareTripCount) {
+ if (LoopAwareTripCount == 0)
+ return 1;
+ unsigned Scale = SE.getSmallConstantTripCount(L);
+ if (Scale == 0)
+ Scale = getLoopEstimatedTripCount(const_cast<Loop *>(L)).value_or(0);
+ if (Scale != 0) {
+ // Multiple exiting blocks - choose the minimum between trip count (scale)
+ // and LoopAwareTripCount, since the multiple exit loops can be terminated
+ // early.
+ if (!L->getExitingBlock())
+ return std::min<unsigned>(LoopAwareTripCount, Scale);
+ return Scale;
+ }
+ return LoopAwareTripCount;
+}
+
} // namespace llvm::slpvectorizer
diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer/SLPUtils.h b/llvm/lib/Transforms/Vectorize/SLPVectorizer/SLPUtils.h
index 895d9561f1a91..e4f6941495f05 100644
--- a/llvm/lib/Transforms/Vectorize/SLPVectorizer/SLPUtils.h
+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer/SLPUtils.h
@@ -41,7 +41,9 @@ class InsertElementInst;
class Instruction;
class IRBuilderBase;
class LoadInst;
+class Loop;
class PHINode;
+class ScalarEvolution;
class TargetLibraryInfo;
class Type;
class Value;
@@ -534,6 +536,15 @@ DebugLoc getDebugLocFromPHI(const PHINode &PN);
/// a homogeneous aggregate.
std::optional<unsigned> getAggregateSize(Instruction *InsertInst);
+/// \returns the innermost loop starting from \p L for which at least one value
+/// in \p VL is not loop-invariant.
+const Loop *findInnermostNonInvariantLoop(const Loop *L, ArrayRef<Value *> VL);
+
+/// \returns an estimated trip count for \p L, bounded by the loop-aware budget
+/// \p LoopAwareTripCount. Returns 1 when the budget is 0.
+unsigned getLoopTripCount(const Loop *L, ScalarEvolution &SE,
+ unsigned LoopAwareTripCount);
+
} // namespace llvm::slpvectorizer
#endif // LLVM_LIB_TRANSFORMS_VECTORIZE_SLPVECTORIZER_SLPUTILS_H
More information about the llvm-branch-commits
mailing list