[llvm] [SLP] Loop aware cost model/tree building (PR #150450)
Alexey Bataev via llvm-commits
llvm-commits at lists.llvm.org
Mon Mar 2 11:47:06 PST 2026
================
@@ -10418,13 +10437,77 @@ getVectorCallCosts(CallInst *CI, FixedVectorType *VecTy,
return {IntrinsicCost, LibCost};
}
+/// Find the innermost loop starting from \p L, for which at least 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(VL, [&](Value *V) { return L->isLoopInvariant(V); });
+ };
+ while (L && IsLoopInvariant(L, VL))
+ L = L->getParentLoop();
+ return L;
+}
+
+/// Get the loop nest for the given loop.
+static SmallVector<const Loop *> getLoopNest(const Loop *L) {
+ assert(L && "Expected valid loop");
+ SmallVector<const Loop *> LoopNest;
+ if (LoopAwareMinTripCount == 0)
+ return LoopNest;
+ while (L) {
+ LoopNest.push_back(L);
+ L = L->getParentLoop();
+ }
+ SmallVector<const Loop *> Res(LoopNest.rbegin(), LoopNest.rend());
+ return Res;
+}
+
BoUpSLP::TreeEntry::EntryState BoUpSLP::getScalarsVectorizationState(
const InstructionsState &S, ArrayRef<Value *> VL,
bool IsScatterVectorizeUserTE, OrdersType &CurrentOrder,
SmallVectorImpl<Value *> &PointerOps, StridedPtrInfo &SPtrInfo) {
assert(S.getMainOp() &&
"Expected instructions with same/alternate opcodes only.");
+ // Check the loop nest. Need to be sure, we handle single loop nest at the
+ // time to avoid incorrect cost estimation because of the loop aware cost
+ // model.
+ if (VectorizableTree.empty()) {
+ assert(LoopNest.empty() && "Expected empty loop nest");
+ // Process the first node? Initial fill of the loop nest.
+ BasicBlock *Parent = S.getMainOp()->getParent();
+ if (const Loop *L = LI->getLoopFor(Parent)) {
+ L = findInnermostNonInvariantLoop(L, VL);
+ if (L)
+ LoopNest = getLoopNest(L);
+ }
+ } else {
+ BasicBlock *Parent = S.getMainOp()->getParent();
+ if (const Loop *L = LI->getLoopFor(Parent)) {
+ // Check that the new loop nest is not involved.
+ // Otherwise, mark it as a gather node.
+ L = findInnermostNonInvariantLoop(L, VL);
+ if (L) {
+ SmallVector<const Loop *> NewLoopNest = getLoopNest(L);
+ for (const auto [L1, L2] : zip_longest(LoopNest, NewLoopNest)) {
----------------
alexey-bataev wrote:
Did exactly this!
https://github.com/llvm/llvm-project/pull/150450
More information about the llvm-commits
mailing list