https://github.com/madhur13490 updated https://github.com/llvm/llvm-project/pull/222614
>From d893a2af8192f5a8561693bba6898c56998e2000 Mon Sep 17 00:00:00 2001 From: Madhur Amilkanthwar <[email protected]> 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 d532b15fc29425..a15a6c5be977ec 100644 --- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp +++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp @@ -9211,20 +9211,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"); @@ -16159,25 +16145,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; @@ -16279,7 +16246,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 6024b071338652..be0bd091c6b38f 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> @@ -1627,4 +1630,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 bd1d830c80ffcf..b870c8b0451a6f 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 _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
