[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
Thu Oct 8 23:29:35 PDT 2026
https://github.com/madhur13490 updated https://github.com/llvm/llvm-project/pull/222614
>From 4c198247fdb0c3749f6a1b5dd51a442775c988aa 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 | 35 ++-----------------
.../Vectorize/SLPVectorizer/SLPUtils.cpp | 32 +++++++++++++++++
.../Vectorize/SLPVectorizer/SLPUtils.h | 11 ++++++
3 files changed, 45 insertions(+), 33 deletions(-)
diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
index 0ee63c3e27618..b5ba7cbb0823f 100644
--- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
@@ -9368,20 +9368,6 @@ static bool isPoorThroughputOp(Instruction *I, const TargetTransformInfo &TTI,
[&] { 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");
@@ -16209,24 +16195,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 Loop *L, ScalarEvolution &SE) {
- 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;
-}
-
uint64_t BoUpSLP::getScaleToLoopIterations(const TreeEntry &TE, Value *Scalar,
Instruction *U) {
BasicBlock *Parent = nullptr;
@@ -16328,7 +16296,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(Cur, *SE));
+ uint64_t TC =
+ std::max<uint64_t>(1, getLoopTripCount(Cur, *SE, LoopAwareTripCount));
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 7872d039176c6..e83ec4da9de6b 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"
@@ -27,6 +29,7 @@
#include "llvm/Support/Casting.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/Transforms/Utils/LoopUtils.h"
#include <algorithm>
#include <numeric>
@@ -1594,4 +1597,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 5be848c8fb585..62e8843737377 100644
--- a/llvm/lib/Transforms/Vectorize/SLPVectorizer/SLPUtils.h
+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer/SLPUtils.h
@@ -40,7 +40,9 @@ class DebugLoc;
class Instruction;
class InsertElementInst;
class IRBuilderBase;
+class Loop;
class PHINode;
+class ScalarEvolution;
class TargetLibraryInfo;
class Type;
class Value;
@@ -518,6 +520,15 @@ DebugLoc getDebugLocFromPHI(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