[llvm] [VPlan] Re-use VPSlotTracker when printing recipes for costs (NFC). (PR #203386)
Florian Hahn via llvm-commits
llvm-commits at lists.llvm.org
Mon Jul 6 03:02:10 PDT 2026
https://github.com/fhahn updated https://github.com/llvm/llvm-project/pull/203386
>From 9612e877d8397a6cd977b71f3c99075adc77a5bb Mon Sep 17 00:00:00 2001
From: Florian Hahn <flo at fhahn.com>
Date: Thu, 11 Jun 2026 20:11:08 +0200
Subject: [PATCH 1/3] [VPlan] Re-use VPSlotTracker when printing recipes for
costs (NFC).
VPRecipeBase::dump() constructs a fresh VPSlotTracker instance on each
call. VPSlotTracker construction requires iterating over all recipes in
the plan, to number all VPValues.
To avoid doing lots of unnecessary work when printing VPlan costs,
construct a shared VPSlotTracker in VPCostContext, re-used by all
prints.
---
llvm/lib/Transforms/Vectorize/VPlan.cpp | 8 ++++++++
llvm/lib/Transforms/Vectorize/VPlanHelpers.h | 20 ++++++++++++++++++-
.../lib/Transforms/Vectorize/VPlanRecipes.cpp | 3 ++-
3 files changed, 29 insertions(+), 2 deletions(-)
diff --git a/llvm/lib/Transforms/Vectorize/VPlan.cpp b/llvm/lib/Transforms/Vectorize/VPlan.cpp
index 292e3e85da9d5..8a56c0c7566f0 100644
--- a/llvm/lib/Transforms/Vectorize/VPlan.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlan.cpp
@@ -1866,6 +1866,14 @@ VPCostContext::getOperandInfo(VPValue *V) const {
return {};
}
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+VPSlotTracker &VPCostContext::getSlotTracker() {
+ if (!SlotTracker)
+ SlotTracker = std::make_unique<VPSlotTracker>(&Plan);
+ return *SlotTracker;
+}
+#endif
+
InstructionCost VPCostContext::getScalarizationOverhead(
Type *ResultTy, ArrayRef<const VPValue *> Operands, ElementCount VF,
TTI::VectorInstrContext VIC, bool AlwaysIncludeReplicatingR) {
diff --git a/llvm/lib/Transforms/Vectorize/VPlanHelpers.h b/llvm/lib/Transforms/Vectorize/VPlanHelpers.h
index 5ea0208e416ed..4e0090435552f 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanHelpers.h
+++ b/llvm/lib/Transforms/Vectorize/VPlanHelpers.h
@@ -40,6 +40,7 @@ class Type;
class VPBasicBlock;
class VPRegionBlock;
class VPlan;
+class VPSlotTracker;
class Value;
namespace Intrinsic {
@@ -337,7 +338,7 @@ struct VPCostContext {
TargetTransformInfo::TargetCostKind CostKind,
PredicatedScalarEvolution &PSE, const Loop *L)
: TTI(TTI), TLI(TLI), LLVMCtx(Plan.getContext()), CM(CM),
- CostKind(CostKind), PSE(PSE), L(L) {}
+ CostKind(CostKind), PSE(PSE), L(L), Plan(Plan) {}
/// Return the cost for \p UI with \p VF using the legacy cost model as
/// fallback until computing the cost of all recipes migrates to VPlan.
@@ -382,6 +383,23 @@ struct VPCostContext {
/// Returns true if \p ID is a pseudo intrinsic that is dropped via
/// scalarization rather than widened.
static bool isFreeScalarIntrinsic(Intrinsic::ID ID);
+
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+ /// Return a VPSlotTracker for \p Plan, shared across all recipe cost
+ /// printing, so names are assigned once instead of per-recipe.
+ VPSlotTracker &getSlotTracker();
+#endif
+
+private:
+ /// The VPlan whose cost is being computed. Used to lazily construct the
+ /// shared VPSlotTracker for recipe cost printing; only read in dump-enabled
+ /// builds.
+ [[maybe_unused]] const VPlan &Plan;
+
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+ /// Lazily created slot tracker, reused while printing recipe costs.
+ std::unique_ptr<VPSlotTracker> SlotTracker;
+#endif
};
/// This class can be used to assign names to VPValues. For VPValues without
diff --git a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
index 258ca7296006b..aea5ff2df0c6a 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
@@ -331,7 +331,8 @@ InstructionCost VPRecipeBase::cost(ElementCount VF, VPCostContext &Ctx) {
LLVM_DEBUG({
dbgs() << "Cost of " << RecipeCost << " for VF " << VF << ": ";
- dump();
+ print(dbgs(), "", Ctx.getSlotTracker());
+ dbgs() << "\n";
});
return RecipeCost;
}
>From 0ef30c05e9396ab28e90821baa6dc0917d451562 Mon Sep 17 00:00:00 2001
From: Florian Hahn <flo at fhahn.com>
Date: Mon, 15 Jun 2026 20:32:42 +0200
Subject: [PATCH 2/3] !fixup wrap VPlan member in ifdef.
---
llvm/lib/Transforms/Vectorize/VPlanHelpers.h | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/llvm/lib/Transforms/Vectorize/VPlanHelpers.h b/llvm/lib/Transforms/Vectorize/VPlanHelpers.h
index 4e0090435552f..230eab609aad3 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanHelpers.h
+++ b/llvm/lib/Transforms/Vectorize/VPlanHelpers.h
@@ -338,7 +338,13 @@ struct VPCostContext {
TargetTransformInfo::TargetCostKind CostKind,
PredicatedScalarEvolution &PSE, const Loop *L)
: TTI(TTI), TLI(TLI), LLVMCtx(Plan.getContext()), CM(CM),
- CostKind(CostKind), PSE(PSE), L(L), Plan(Plan) {}
+ CostKind(CostKind), PSE(PSE), L(L)
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+ ,
+ Plan(Plan)
+#endif
+ {
+ }
/// Return the cost for \p UI with \p VF using the legacy cost model as
/// fallback until computing the cost of all recipes migrates to VPlan.
@@ -388,15 +394,13 @@ struct VPCostContext {
/// Return a VPSlotTracker for \p Plan, shared across all recipe cost
/// printing, so names are assigned once instead of per-recipe.
VPSlotTracker &getSlotTracker();
-#endif
private:
/// The VPlan whose cost is being computed. Used to lazily construct the
/// shared VPSlotTracker for recipe cost printing; only read in dump-enabled
/// builds.
- [[maybe_unused]] const VPlan &Plan;
+ const VPlan &Plan;
-#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
/// Lazily created slot tracker, reused while printing recipe costs.
std::unique_ptr<VPSlotTracker> SlotTracker;
#endif
>From 0e3f0a54f89f71cdbc481750f9999fdb6143115b Mon Sep 17 00:00:00 2001
From: Florian Hahn <flo at fhahn.com>
Date: Mon, 6 Jul 2026 11:01:12 +0100
Subject: [PATCH 3/3] !fixup add new Ctor taking slot tracker explicitly.
---
.../Transforms/Vectorize/LoopVectorize.cpp | 5 ++--
llvm/lib/Transforms/Vectorize/VPlan.cpp | 8 -------
llvm/lib/Transforms/Vectorize/VPlanHelpers.h | 24 ++++++++++---------
.../lib/Transforms/Vectorize/VPlanRecipes.cpp | 8 +++++--
4 files changed, 22 insertions(+), 23 deletions(-)
diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
index 6bb68d1f7bb19..e27709102134c 100644
--- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
+++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
@@ -3156,7 +3156,8 @@ void LoopVectorizationPlanner::emitInvalidCostRemarks(
continue;
VPCostContext CostCtx(CM.TTI, *CM.TLI, *Plan, CM, Config.CostKind, CM.PSE,
- OrigLoop);
+ OrigLoop,
+ std::make_unique<VPSlotTracker>(Plan.get()));
precomputeCosts(*Plan, VF, CostCtx);
auto Iter = vp_depth_first_deep(Plan->getVectorLoopRegion()->getEntry());
for (VPBasicBlock *VPBB : VPBlockUtils::blocksOnly<VPBasicBlock>(Iter)) {
@@ -5750,7 +5751,7 @@ LoopVectorizationPlanner::precomputeCosts(VPlan &Plan, ElementCount VF,
InstructionCost LoopVectorizationPlanner::cost(VPlan &Plan, ElementCount VF,
VPRegisterUsage *RU) const {
VPCostContext CostCtx(CM.TTI, *CM.TLI, Plan, CM, Config.CostKind, PSE,
- OrigLoop);
+ OrigLoop, std::make_unique<VPSlotTracker>(&Plan));
InstructionCost Cost = precomputeCosts(Plan, VF, CostCtx);
// Now compute and add the VPlan-based cost.
diff --git a/llvm/lib/Transforms/Vectorize/VPlan.cpp b/llvm/lib/Transforms/Vectorize/VPlan.cpp
index 8a56c0c7566f0..292e3e85da9d5 100644
--- a/llvm/lib/Transforms/Vectorize/VPlan.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlan.cpp
@@ -1866,14 +1866,6 @@ VPCostContext::getOperandInfo(VPValue *V) const {
return {};
}
-#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
-VPSlotTracker &VPCostContext::getSlotTracker() {
- if (!SlotTracker)
- SlotTracker = std::make_unique<VPSlotTracker>(&Plan);
- return *SlotTracker;
-}
-#endif
-
InstructionCost VPCostContext::getScalarizationOverhead(
Type *ResultTy, ArrayRef<const VPValue *> Operands, ElementCount VF,
TTI::VectorInstrContext VIC, bool AlwaysIncludeReplicatingR) {
diff --git a/llvm/lib/Transforms/Vectorize/VPlanHelpers.h b/llvm/lib/Transforms/Vectorize/VPlanHelpers.h
index 230eab609aad3..eff17c3667899 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanHelpers.h
+++ b/llvm/lib/Transforms/Vectorize/VPlanHelpers.h
@@ -337,11 +337,19 @@ struct VPCostContext {
const VPlan &Plan, LoopVectorizationCostModel &CM,
TargetTransformInfo::TargetCostKind CostKind,
PredicatedScalarEvolution &PSE, const Loop *L)
+ : TTI(TTI), TLI(TLI), LLVMCtx(Plan.getContext()), CM(CM),
+ CostKind(CostKind), PSE(PSE), L(L) {}
+
+ VPCostContext(const TargetTransformInfo &TTI, const TargetLibraryInfo &TLI,
+ const VPlan &Plan, LoopVectorizationCostModel &CM,
+ TargetTransformInfo::TargetCostKind CostKind,
+ PredicatedScalarEvolution &PSE, const Loop *L,
+ std::unique_ptr<VPSlotTracker> SlotTracker)
: TTI(TTI), TLI(TLI), LLVMCtx(Plan.getContext()), CM(CM),
CostKind(CostKind), PSE(PSE), L(L)
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
,
- Plan(Plan)
+ SlotTracker(std::move(SlotTracker))
#endif
{
}
@@ -391,18 +399,12 @@ struct VPCostContext {
static bool isFreeScalarIntrinsic(Intrinsic::ID ID);
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
- /// Return a VPSlotTracker for \p Plan, shared across all recipe cost
- /// printing, so names are assigned once instead of per-recipe.
- VPSlotTracker &getSlotTracker();
+ /// Return SlotTracker to re-use for printing, if set.
+ VPSlotTracker *getSlotTracker() const { return SlotTracker.get(); }
private:
- /// The VPlan whose cost is being computed. Used to lazily construct the
- /// shared VPSlotTracker for recipe cost printing; only read in dump-enabled
- /// builds.
- const VPlan &Plan;
-
- /// Lazily created slot tracker, reused while printing recipe costs.
- std::unique_ptr<VPSlotTracker> SlotTracker;
+ /// SlotTracker to re-use when printing.
+ const std::unique_ptr<VPSlotTracker> SlotTracker = nullptr;
#endif
};
diff --git a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
index aea5ff2df0c6a..1bff973b8d070 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
@@ -331,8 +331,12 @@ InstructionCost VPRecipeBase::cost(ElementCount VF, VPCostContext &Ctx) {
LLVM_DEBUG({
dbgs() << "Cost of " << RecipeCost << " for VF " << VF << ": ";
- print(dbgs(), "", Ctx.getSlotTracker());
- dbgs() << "\n";
+ if (auto SlotTracker = Ctx.getSlotTracker()) {
+ print(dbgs(), "", *SlotTracker);
+ dbgs() << "\n";
+ } else {
+ dump();
+ }
});
return RecipeCost;
}
More information about the llvm-commits
mailing list