[llvm] [VPlan] Add Type* and getType() to VPSymbolicValue (NFC) (PR #195183)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Apr 30 14:56:00 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-vectorizers
Author: Florian Hahn (fhahn)
<details>
<summary>Changes</summary>
Add a Type* field to VPSymbolicValue, along with a getType() methods to query the stored scalar type.
This makes it easier to retrieve the type of various symbolic values, and also simplifies VPTypeAnalysis construction.
---
Full diff: https://github.com/llvm/llvm-project/pull/195183.diff
7 Files Affected:
- (modified) llvm/lib/Transforms/Vectorize/VPlan.cpp (+6-3)
- (modified) llvm/lib/Transforms/Vectorize/VPlan.h (+9-5)
- (modified) llvm/lib/Transforms/Vectorize/VPlanAnalysis.cpp (+3-23)
- (modified) llvm/lib/Transforms/Vectorize/VPlanAnalysis.h (+2-6)
- (modified) llvm/lib/Transforms/Vectorize/VPlanConstruction.cpp (+4-3)
- (modified) llvm/lib/Transforms/Vectorize/VPlanUnroll.cpp (+1-1)
- (modified) llvm/lib/Transforms/Vectorize/VPlanValue.h (+8-1)
``````````diff
diff --git a/llvm/lib/Transforms/Vectorize/VPlan.cpp b/llvm/lib/Transforms/Vectorize/VPlan.cpp
index 197ef22dc7fc6..a53dc0efb9b06 100644
--- a/llvm/lib/Transforms/Vectorize/VPlan.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlan.cpp
@@ -894,7 +894,8 @@ VPInstruction *VPRegionBlock::getOrCreateCanonicalIVIncrement() {
CanIV->getDebugLoc(), "index.next");
}
-VPlan::VPlan(Loop *L) {
+VPlan::VPlan(Loop *L, Type *IdxTy)
+ : VectorTripCount(IdxTy), VF(IdxTy), UF(IdxTy), VFxUF(IdxTy) {
setEntry(createVPIRBasicBlock(L->getLoopPreheader()));
ScalarHeader = createVPIRBasicBlock(L->getHeader());
@@ -1257,7 +1258,8 @@ VPlan *VPlan::duplicate() {
NewScalarHeader = createVPIRBasicBlock(ScalarHeaderIRBB);
}
// Create VPlan, clone live-ins and remap operands in the cloned blocks.
- auto *NewPlan = new VPlan(cast<VPBasicBlock>(NewEntry), NewScalarHeader);
+ auto *NewPlan =
+ new VPlan(cast<VPBasicBlock>(NewEntry), NewScalarHeader, VF.getType());
DenseMap<VPValue *, VPValue *> Old2NewVPValues;
for (VPIRValue *OldLiveIn : getLiveIns())
Old2NewVPValues[OldLiveIn] = NewPlan->getOrAddLiveIn(OldLiveIn);
@@ -1279,7 +1281,8 @@ VPlan *VPlan::duplicate() {
"All VPSymbolicValues must be handled below");
if (BackedgeTakenCount)
- NewPlan->BackedgeTakenCount = new VPSymbolicValue();
+ NewPlan->BackedgeTakenCount =
+ new VPSymbolicValue(BackedgeTakenCount->getType());
// Map and propagate materialized state for symbolic values.
for (auto [OldSV, NewSV] :
diff --git a/llvm/lib/Transforms/Vectorize/VPlan.h b/llvm/lib/Transforms/Vectorize/VPlan.h
index ff056df396eb4..7b830fb408ec4 100644
--- a/llvm/lib/Transforms/Vectorize/VPlan.h
+++ b/llvm/lib/Transforms/Vectorize/VPlan.h
@@ -4568,8 +4568,10 @@ class VPlan {
/// Construct a VPlan with \p Entry to the plan and with \p ScalarHeader
/// wrapping the original header of the scalar loop.
- VPlan(VPBasicBlock *Entry, VPIRBasicBlock *ScalarHeader)
- : Entry(Entry), ScalarHeader(ScalarHeader) {
+ VPlan(VPBasicBlock *Entry, VPIRBasicBlock *ScalarHeader,
+ Type *IdxTy = nullptr)
+ : Entry(Entry), ScalarHeader(ScalarHeader), VectorTripCount(IdxTy),
+ VF(IdxTy), UF(IdxTy), VFxUF(IdxTy) {
Entry->setPlan(this);
assert(ScalarHeader->getNumSuccessors() == 0 &&
"scalar header must be a leaf node");
@@ -4579,11 +4581,12 @@ class VPlan {
/// Construct a VPlan for \p L. This will create VPIRBasicBlocks wrapping the
/// original preheader and scalar header of \p L, to be used as entry and
/// scalar header blocks of the new VPlan.
- VPlan(Loop *L);
+ VPlan(Loop *L, Type *IdxTy = nullptr);
/// Construct a VPlan with a new VPBasicBlock as entry, a VPIRBasicBlock
/// wrapping \p ScalarHeaderBB and a trip count of \p TC.
- VPlan(BasicBlock *ScalarHeaderBB) {
+ VPlan(BasicBlock *ScalarHeaderBB, Type *IdxTy = nullptr)
+ : VectorTripCount(IdxTy), VF(IdxTy), UF(IdxTy), VFxUF(IdxTy) {
setEntry(createVPBasicBlock("preheader"));
ScalarHeader = createVPIRBasicBlock(ScalarHeaderBB);
}
@@ -4682,8 +4685,9 @@ class VPlan {
/// The backedge taken count of the original loop.
VPValue *getOrCreateBackedgeTakenCount() {
+ // BTC shares the canonical IV type with VectorTripCount.
if (!BackedgeTakenCount)
- BackedgeTakenCount = new VPSymbolicValue();
+ BackedgeTakenCount = new VPSymbolicValue(VectorTripCount.getType());
return BackedgeTakenCount;
}
VPValue *getBackedgeTakenCount() const { return BackedgeTakenCount; }
diff --git a/llvm/lib/Transforms/Vectorize/VPlanAnalysis.cpp b/llvm/lib/Transforms/Vectorize/VPlanAnalysis.cpp
index 5697856559bc2..4fc0423a616fd 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanAnalysis.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanAnalysis.cpp
@@ -24,23 +24,6 @@ using namespace VPlanPatternMatch;
#define DEBUG_TYPE "vplan"
-VPTypeAnalysis::VPTypeAnalysis(const VPlan &Plan)
- : Ctx(Plan.getContext()), DL(Plan.getDataLayout()) {
- if (auto LoopRegion = Plan.getVectorLoopRegion()) {
- CanonicalIVTy = LoopRegion->getCanonicalIVType();
- return;
- }
-
- // If there's no loop region, retrieve the type from the trip count
- // expression.
- auto *TC = Plan.getTripCount();
- if (auto *TCIRV = dyn_cast<VPIRValue>(TC)) {
- CanonicalIVTy = TCIRV->getType();
- return;
- }
- CanonicalIVTy = cast<VPExpandSCEVRecipe>(TC)->getSCEV()->getType();
-}
-
Type *VPTypeAnalysis::inferScalarTypeForRecipe(const VPBlendRecipe *R) {
Type *ResTy = inferScalarType(R->getIncomingValue(0));
for (unsigned I = 1, E = R->getNumIncomingValues(); I != E; ++I) {
@@ -120,7 +103,7 @@ Type *VPTypeAnalysis::inferScalarTypeForRecipe(const VPInstruction *R) {
case VPInstruction::LastActiveLane:
// Assume that the maximum possible number of elements in a vector fits
// within the index type for the default address space.
- return DL.getIndexType(Ctx, 0);
+ return R->getParent()->getPlan()->getDataLayout().getIndexType(Ctx, 0);
case VPInstruction::LogicalAnd:
case VPInstruction::LogicalOr:
assert(inferScalarType(R->getOperand(0))->isIntegerTy(1) &&
@@ -278,11 +261,8 @@ Type *VPTypeAnalysis::inferScalarType(const VPValue *V) {
if (auto *IRV = dyn_cast<VPIRValue>(V))
return IRV->getType();
- if (isa<VPSymbolicValue>(V)) {
- // All VPValues without any underlying IR value (like the vector trip count
- // or the backedge-taken count) have the same type as the canonical IV.
- return CanonicalIVTy;
- }
+ if (auto *SymbolicV = dyn_cast<VPSymbolicValue>(V))
+ return SymbolicV->getType();
if (auto *RegionV = dyn_cast<VPRegionValue>(V))
return RegionV->getType();
diff --git a/llvm/lib/Transforms/Vectorize/VPlanAnalysis.h b/llvm/lib/Transforms/Vectorize/VPlanAnalysis.h
index 416c4d9dc2f3b..d53afad80a595 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanAnalysis.h
+++ b/llvm/lib/Transforms/Vectorize/VPlanAnalysis.h
@@ -9,6 +9,7 @@
#ifndef LLVM_TRANSFORMS_VECTORIZE_VPLANANALYSIS_H
#define LLVM_TRANSFORMS_VECTORIZE_VPLANANALYSIS_H
+#include "VPlan.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/MapVector.h"
@@ -46,12 +47,7 @@ struct VPCostContext;
/// of the previously inferred types.
class VPTypeAnalysis {
DenseMap<const VPValue *, Type *> CachedTypes;
- /// Type of the canonical induction variable. Used for all VPValues without
- /// any underlying IR value (like the vector trip count or the backedge-taken
- /// count).
- Type *CanonicalIVTy;
LLVMContext &Ctx;
- const DataLayout &DL;
Type *inferScalarTypeForRecipe(const VPBlendRecipe *R);
Type *inferScalarTypeForRecipe(const VPInstruction *R);
@@ -62,7 +58,7 @@ class VPTypeAnalysis {
Type *inferScalarTypeForRecipe(const VPReplicateRecipe *R);
public:
- VPTypeAnalysis(const VPlan &Plan);
+ VPTypeAnalysis(const VPlan &Plan) : Ctx(Plan.getContext()) {}
/// Infer the type of \p V. Returns the scalar type of \p V.
Type *inferScalarType(const VPValue *V);
diff --git a/llvm/lib/Transforms/Vectorize/VPlanConstruction.cpp b/llvm/lib/Transforms/Vectorize/VPlanConstruction.cpp
index 66b9c0e4bc0ec..282115d659da0 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanConstruction.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanConstruction.cpp
@@ -78,8 +78,9 @@ class PlainCFGBuilder {
void createVPInstructionsForVPBB(VPBasicBlock *VPBB, BasicBlock *BB);
public:
- PlainCFGBuilder(Loop *Lp, LoopInfo *LI, LoopVersioning *LVer)
- : TheLoop(Lp), LI(LI), LVer(LVer), Plan(std::make_unique<VPlan>(Lp)) {}
+ PlainCFGBuilder(Loop *Lp, LoopInfo *LI, LoopVersioning *LVer, Type *IdxTy)
+ : TheLoop(Lp), LI(LI), LVer(LVer),
+ Plan(std::make_unique<VPlan>(Lp, IdxTy)) {}
/// Build plain CFG for TheLoop and connect it to Plan's entry.
std::unique_ptr<VPlan> buildPlainCFG();
@@ -635,7 +636,7 @@ std::unique_ptr<VPlan>
VPlanTransforms::buildVPlan0(Loop *TheLoop, LoopInfo &LI, Type *InductionTy,
DebugLoc IVDL, PredicatedScalarEvolution &PSE,
LoopVersioning *LVer) {
- PlainCFGBuilder Builder(TheLoop, &LI, LVer);
+ PlainCFGBuilder Builder(TheLoop, &LI, LVer, InductionTy);
std::unique_ptr<VPlan> VPlan0 = Builder.buildPlainCFG();
addInitialSkeleton(*VPlan0, InductionTy, IVDL, PSE, TheLoop);
simplifyLiveInsWithSCEV(*VPlan0, PSE);
diff --git a/llvm/lib/Transforms/Vectorize/VPlanUnroll.cpp b/llvm/lib/Transforms/Vectorize/VPlanUnroll.cpp
index d5eb7e82b6f84..24539d340c23e 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanUnroll.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanUnroll.cpp
@@ -345,7 +345,7 @@ void UnrollState::unrollRecipeByUF(VPRecipeBase &R) {
VPBuilder Builder(VPR);
const DataLayout &DL = Plan.getDataLayout();
Type *IndexTy = DL.getIndexType(TypeInfo.inferScalarType(VPR));
- Type *VFTy = TypeInfo.inferScalarType(&Plan.getVF());
+ Type *VFTy = Plan.getVF().getType();
VPValue *VF = Builder.createScalarZExtOrTrunc(
&Plan.getVF(), IndexTy, VFTy, DebugLoc::getUnknown());
// VFxUF does not wrap, so VF * Part also cannot wrap.
diff --git a/llvm/lib/Transforms/Vectorize/VPlanValue.h b/llvm/lib/Transforms/Vectorize/VPlanValue.h
index 8f9806adf774e..1e79c48cc8f7c 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanValue.h
+++ b/llvm/lib/Transforms/Vectorize/VPlanValue.h
@@ -278,12 +278,16 @@ struct VPConstantInt : public VPIRValue {
/// A symbolic live-in VPValue, used for values like vector trip count, VF, and
/// VFxUF.
struct VPSymbolicValue : public VPValue {
- VPSymbolicValue() : VPValue(VPVSymbolicSC, nullptr) {}
+ VPSymbolicValue(Type *Ty = nullptr)
+ : VPValue(VPVSymbolicSC, nullptr), Ty(Ty) {}
static bool classof(const VPValue *V) {
return V->getVPValueID() == VPVSymbolicSC;
}
+ /// Returns the scalar type of this symbolic value.
+ Type *getType() const { return Ty; }
+
/// Returns true if this symbolic value has been materialized.
bool isMaterialized() const { return Materialized; }
@@ -294,6 +298,9 @@ struct VPSymbolicValue : public VPValue {
}
private:
+ /// The scalar type of this symbolic value.
+ Type *Ty;
+
/// Track whether this symbolic value has been materialized (replaced).
/// After materialization, accessing users should trigger an assertion.
bool Materialized = false;
``````````
</details>
https://github.com/llvm/llvm-project/pull/195183
More information about the llvm-commits
mailing list