[llvm] [VPlan] Consolidate VPIWithType and VPI (NFC) (PR #203019)
Ramkumar Ramachandra via llvm-commits
llvm-commits at lists.llvm.org
Thu Jun 25 07:50:05 PDT 2026
https://github.com/artagnon updated https://github.com/llvm/llvm-project/pull/203019
>From 8afa2ccc1d78a8afdad9be30be7e0f28ca903ee4 Mon Sep 17 00:00:00 2001
From: Ramkumar Ramachandra <artagnon at tenstorrent.com>
Date: Wed, 10 Jun 2026 16:25:40 +0100
Subject: [PATCH 1/3] [VPlan] Consolidate VPIWithType and VPI (NFC)
The extra ResultType has been absorbed into VPInstruction, and the
recipe classes can now be consolidated.
---
.../Vectorize/LoopVectorizationPlanner.h | 27 ++--
.../Transforms/Vectorize/LoopVectorize.cpp | 6 +-
llvm/lib/Transforms/Vectorize/VPlan.h | 77 +---------
.../Vectorize/VPlanConstruction.cpp | 2 +-
.../lib/Transforms/Vectorize/VPlanRecipes.cpp | 134 ++++++------------
llvm/lib/Transforms/Vectorize/VPlanUnroll.cpp | 2 +-
.../Transforms/Vectorize/VPDomTreeTest.cpp | 12 +-
.../Transforms/Vectorize/VPlanTest.cpp | 59 ++++----
8 files changed, 102 insertions(+), 217 deletions(-)
diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorizationPlanner.h b/llvm/lib/Transforms/Vectorize/LoopVectorizationPlanner.h
index b39ffdebf6179..640f8ba8cd22d 100644
--- a/llvm/lib/Transforms/Vectorize/LoopVectorizationPlanner.h
+++ b/llvm/lib/Transforms/Vectorize/LoopVectorizationPlanner.h
@@ -231,8 +231,8 @@ class VPBuilder {
Type *ResultTy, const VPIRFlags &Flags = {},
DebugLoc DL = DebugLoc::getUnknown(),
const Twine &Name = "") {
- return tryInsertInstruction(new VPInstructionWithType(
- Opcode, Operands, ResultTy, Flags, {}, DL, Name));
+ return tryInsertInstruction(
+ new VPInstruction(Opcode, Operands, Flags, {}, DL, Name, ResultTy));
}
VPInstruction *createFirstActiveLane(ArrayRef<VPValue *> Masks,
@@ -414,19 +414,18 @@ class VPBuilder {
new VPDerivedIVRecipe(Kind, FPBinOp, Start, Current, Step));
}
- VPInstructionWithType *createScalarLoad(Type *ResultTy, VPValue *Addr,
- DebugLoc DL,
- const VPIRMetadata &Metadata = {}) {
- return tryInsertInstruction(new VPInstructionWithType(
- Instruction::Load, Addr, ResultTy, {}, Metadata, DL));
+ VPInstruction *createScalarLoad(Type *ResultTy, VPValue *Addr, DebugLoc DL,
+ const VPIRMetadata &Metadata = {}) {
+ return tryInsertInstruction(new VPInstruction(Instruction::Load, Addr, {},
+ Metadata, DL, "", ResultTy));
}
VPInstruction *createScalarCast(Instruction::CastOps Opcode, VPValue *Op,
Type *ResultTy, DebugLoc DL,
const VPIRMetadata &Metadata = {}) {
- return tryInsertInstruction(new VPInstructionWithType(
- Opcode, Op, ResultTy, VPIRFlags::getDefaultFlags(Opcode), Metadata,
- DL));
+ return tryInsertInstruction(
+ new VPInstruction(Opcode, Op, VPIRFlags::getDefaultFlags(Opcode),
+ Metadata, DL, "", ResultTy));
}
VPInstruction *createScalarCast(Instruction::CastOps Opcode, VPValue *Op,
@@ -434,7 +433,7 @@ class VPBuilder {
const VPIRFlags &Flags,
const VPIRMetadata &Metadata = {}) {
return tryInsertInstruction(
- new VPInstructionWithType(Opcode, Op, ResultTy, Flags, Metadata, DL));
+ new VPInstruction(Opcode, Op, Flags, Metadata, DL, "", ResultTy));
}
VPValue *createScalarZExtOrTrunc(VPValue *Op, Type *ResultTy, Type *SrcTy,
@@ -480,8 +479,10 @@ class VPBuilder {
DebugLoc DL, Instruction *UV) {
if (Instruction::isCast(Opcode)) {
assert(!Mask && "Cast cannot be predicated");
- return new VPInstructionWithType(Opcode, Operands, UV->getType(), Flags,
- Metadata, DL, UV->getName(), UV);
+ auto *VPI = new VPInstruction(Opcode, Operands, Flags, Metadata, DL,
+ UV->getName(), UV->getType());
+ VPI->setUnderlyingValue(UV);
+ return VPI;
}
return new VPReplicateRecipe(UV, Operands, /*IsSingleScalar=*/true, Mask,
Flags, Metadata, DL);
diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
index 545fcba65d228..eaee6ced13e44 100644
--- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
+++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
@@ -6472,9 +6472,8 @@ VPRecipeBuilder::tryToCreateWidenNonPhiRecipe(VPSingleDefRecipe *R,
if (Instruction::isCast(VPI->getOpcode())) {
auto *CI = cast<CastInst>(Instr);
- auto *CastR = cast<VPInstructionWithType>(VPI);
return new VPWidenCastRecipe(CI->getOpcode(), VPI->getOperand(0),
- CastR->getResultType(), CI, *VPI, *VPI,
+ VPI->getScalarType(), CI, *VPI, *VPI,
VPI->getDebugLoc());
}
@@ -6739,8 +6738,7 @@ VPlanPtr LoopVectorizationPlanner::tryToBuildVPlan(VPlanPtr Plan,
VPReplicateRecipe, VPWidenLoadRecipe, VPWidenStoreRecipe,
VPWidenCallRecipe, VPWidenIntrinsicRecipe, VPVectorPointerRecipe,
VPVectorEndPointerRecipe, VPHistogramRecipe>(&R) ||
- (isa<VPInstructionWithType>(R) &&
- Instruction::isCast(cast<VPInstructionWithType>(R).getOpcode()) &&
+ (Instruction::isCast(cast<VPInstruction>(R).getOpcode()) &&
vputils::onlyFirstLaneUsed(R.getVPSingleValue())))
continue;
auto *VPI = cast<VPInstruction>(&R);
diff --git a/llvm/lib/Transforms/Vectorize/VPlan.h b/llvm/lib/Transforms/Vectorize/VPlan.h
index bd7f87dbb3a5d..2d1fc32578294 100644
--- a/llvm/lib/Transforms/Vectorize/VPlan.h
+++ b/llvm/lib/Transforms/Vectorize/VPlan.h
@@ -1505,6 +1505,11 @@ class LLVM_ABI_FOR_TEST VPInstruction : public VPRecipeWithIRFlags,
/// Returns true if the recipe only uses the first lane of operand \p Op.
bool usesFirstLaneOnly(const VPValue *Op) const override;
+ /// Returns true if the recipe only uses scalars of operand \p Op.
+ bool usesScalars(const VPValue *Op) const override {
+ return Instruction::isCast(getOpcode()) || usesFirstLaneOnly(Op);
+ }
+
/// Returns true if the recipe only uses the first part of operand \p Op.
bool usesFirstPartOnly(const VPValue *Op) const override;
@@ -1530,78 +1535,6 @@ class LLVM_ABI_FOR_TEST VPInstruction : public VPRecipeWithIRFlags,
#endif
};
-/// A specialization of VPInstruction augmenting it with a dedicated result
-/// type, to be used when the opcode and operands of the VPInstruction don't
-/// directly determine the result type. Note that there is no separate recipe ID
-/// for VPInstructionWithType; it shares the same ID as VPInstruction and is
-/// distinguished purely by the opcode.
-/// TODO: Merge with VPInstruction, now that VPRecipeValue provides the type.
-class VPInstructionWithType : public VPInstruction {
-public:
- VPInstructionWithType(unsigned Opcode, ArrayRef<VPValue *> Operands,
- Type *ResultTy, const VPIRFlags &Flags = {},
- const VPIRMetadata &Metadata = {},
- DebugLoc DL = DebugLoc::getUnknown(),
- const Twine &Name = "", Value *UV = nullptr)
- : VPInstruction(Opcode, Operands, Flags, Metadata, DL, Name, ResultTy) {
- setUnderlyingValue(UV);
- }
-
- static inline bool classof(const VPRecipeBase *R) {
- // VPInstructionWithType are VPInstructions with specific opcodes requiring
- // type information.
- auto *VPI = dyn_cast<VPInstruction>(R);
- if (!VPI)
- return false;
- unsigned Opc = VPI->getOpcode();
- if (Instruction::isCast(Opc))
- return true;
- switch (Opc) {
- case VPInstruction::WideIVStep:
- case VPInstruction::StepVector:
- case VPInstruction::VScale:
- case Instruction::Load:
- return true;
- default:
- return false;
- }
- }
-
- static inline bool classof(const VPUser *R) {
- return isa<VPInstructionWithType>(cast<VPRecipeBase>(R));
- }
-
- VPInstruction *clone() override {
- auto *New =
- new VPInstructionWithType(getOpcode(), operands(), getResultType(),
- *this, *this, getDebugLoc(), getName());
- New->setUnderlyingValue(getUnderlyingValue());
- return New;
- }
-
- void execute(VPTransformState &State) override;
-
- /// Return the cost of this VPInstruction.
- InstructionCost computeCost(ElementCount VF,
- VPCostContext &Ctx) const override;
-
- Type *getResultType() const { return getScalarType(); }
-
- /// Cast recipes always use scalars of their operand.
- bool usesScalars(const VPValue *Op) const override {
- if (Instruction::isCast(getOpcode()))
- return true;
- return VPInstruction::usesScalars(Op);
- }
-
-protected:
-#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
- /// Print the recipe.
- void printRecipe(raw_ostream &O, const Twine &Indent,
- VPSlotTracker &SlotTracker) const override;
-#endif
-};
-
/// Helper type to provide functions to access incoming values and blocks for
/// phi-like recipes.
class VPPhiAccessors {
diff --git a/llvm/lib/Transforms/Vectorize/VPlanConstruction.cpp b/llvm/lib/Transforms/Vectorize/VPlanConstruction.cpp
index 619fea8c10b4d..a60c9e59a24d1 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanConstruction.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanConstruction.cpp
@@ -1226,7 +1226,7 @@ static bool areAllLoadsDereferenceable(VPBasicBlock *HeaderVPBB, Loop *TheLoop,
const DataLayout &DL = TheLoop->getHeader()->getDataLayout();
for (VPBasicBlock *VPBB : vp_rpo_plain_cfg_loop_body(HeaderVPBB)) {
for (VPRecipeBase &R : *VPBB) {
- auto *VPI = dyn_cast<VPInstructionWithType>(&R);
+ auto *VPI = dyn_cast<VPInstruction>(&R);
if (!VPI || VPI->getOpcode() != Instruction::Load) {
assert(!R.mayReadFromMemory() && "unexpected recipe reading memory");
continue;
diff --git a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
index f45b9e4f6c35b..6e2cdb6683587 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
@@ -738,6 +738,16 @@ Value *VPInstruction::generate(VPTransformState &State) {
applyFlags(*I);
return Res;
}
+ if (Instruction::isCast(getOpcode())) {
+ Value *Op = State.get(getOperand(0), VPLane(0));
+ Value *Res = State.Builder.CreateCast(Instruction::CastOps(getOpcode()), Op,
+ getScalarType());
+ if (auto *CastOp = dyn_cast<Instruction>(Res)) {
+ applyFlags(*CastOp);
+ applyMetadata(*CastOp);
+ }
+ return Res;
+ }
switch (getOpcode()) {
case VPInstruction::Not: {
@@ -1103,6 +1113,11 @@ Value *VPInstruction::generate(VPTransformState &State) {
return Result;
}
+ case VPInstruction::StepVector:
+ return State.Builder.CreateStepVector(
+ VectorType::get(getScalarType(), State.VF));
+ case VPInstruction::VScale:
+ return State.Builder.CreateVScale(getScalarType());
default:
llvm_unreachable("Unsupported opcode for instruction");
}
@@ -1313,6 +1328,13 @@ InstructionCost VPRecipeWithIRFlags::getCostForRecipeWithOpcode(
InstructionCost VPInstruction::computeCost(ElementCount VF,
VPCostContext &Ctx) const {
+ // NOTE: At the moment it seems only possible to expose this path for
+ // the trunc, zext and sext opcodes. However, isScalarCast also covers
+ // int<>fp conversions, bitcasts, ptr<>int conversions, etc.
+ if (Instruction::isCast(getOpcode()))
+ return getCostForRecipeWithOpcode(getOpcode(), ElementCount::getFixed(1),
+ Ctx);
+
if (Instruction::isBinaryOp(getOpcode())) {
if (!getUnderlyingValue() && getOpcode() != Instruction::FMul) {
// TODO: Compute cost for VPInstructions without underlying values once
@@ -1475,6 +1497,18 @@ InstructionCost VPInstruction::computeCost(ElementCount VF,
CmpInst::makeCmpResultType(ValTy),
CmpInst::ICMP_EQ, Ctx.CostKind);
}
+ case VPInstruction::VScale: {
+ IntrinsicCostAttributes Attrs(Intrinsic::vscale, getScalarType(),
+ ArrayRef<Type *>());
+ return Ctx.TTI.getIntrinsicInstrCost(Attrs, Ctx.CostKind);
+ }
+ case VPInstruction::StepVector:
+ // TODO: This isn't quite right since even if the step-vector is hoisted
+ // out of the loop it has a non-zero cost in the middle block, etc.
+ // Once the stepvector is correctly hoisted out of the vector loop by the
+ // licm transform we can add the cost here so that it doesn't incorrectly
+ // affect the choice of VF.
+ return 0;
case Instruction::FCmp:
case Instruction::ICmp:
return getCostForRecipeWithOpcode(
@@ -1837,108 +1871,26 @@ void VPInstruction::printRecipe(raw_ostream &O, const Twine &Indent,
case VPInstruction::NumActiveLanes:
O << "num-active-lanes";
break;
- default:
- O << Instruction::getOpcodeName(getOpcode());
- }
-
- printFlags(O);
- printOperands(O, SlotTracker);
-}
-#endif
-
-void VPInstructionWithType::execute(VPTransformState &State) {
- Type *ResultTy = getResultType();
- if (Instruction::isCast(getOpcode())) {
- Value *Op = State.get(getOperand(0), VPLane(0));
- Value *Cast = State.Builder.CreateCast(Instruction::CastOps(getOpcode()),
- Op, ResultTy);
- if (auto *CastOp = dyn_cast<Instruction>(Cast)) {
- applyFlags(*CastOp);
- applyMetadata(*CastOp);
- }
- State.set(this, Cast, VPLane(0));
- return;
- }
- switch (getOpcode()) {
- case VPInstruction::StepVector: {
- Value *StepVector =
- State.Builder.CreateStepVector(VectorType::get(ResultTy, State.VF));
- State.set(this, StepVector);
- break;
- }
- case VPInstruction::VScale: {
- Value *VScale = State.Builder.CreateVScale(ResultTy);
- State.set(this, VScale, true);
- break;
- }
-
- default:
- llvm_unreachable("opcode not implemented yet");
- }
-}
-
-InstructionCost VPInstructionWithType::computeCost(ElementCount VF,
- VPCostContext &Ctx) const {
- // NOTE: At the moment it seems only possible to expose this path for
- // the trunc, zext and sext opcodes. However, isScalarCast also covers
- // int<>fp conversions, bitcasts, ptr<>int conversions, etc.
- if (Instruction::isCast(getOpcode()))
- return getCostForRecipeWithOpcode(getOpcode(), ElementCount::getFixed(1),
- Ctx);
-
- switch (getOpcode()) {
- case VPInstruction::VScale: {
- Type *Ty = this->getScalarType();
- ArrayRef<Type *> Tys;
- IntrinsicCostAttributes Attrs(Intrinsic::vscale, Ty, Tys);
- return Ctx.TTI.getIntrinsicInstrCost(Attrs, Ctx.CostKind);
- }
- case VPInstruction::StepVector:
- // TODO: This isn't quite right since even if the step-vector is hoisted
- // out of the loop it has a non-zero cost in the middle block, etc.
- // Once the stepvector is correctly hoisted out of the vector loop by the
- // licm transform we can add the cost here so that it doesn't incorrectly
- // affect the choice of VF.
- return 0;
- default:
- // Although VPInstructionWithType is also used for
- // VPInstruction::WideIVStep it isn't currently possible to expose cases
- // where the cost is queried.
- llvm_unreachable("Unhandled opcode");
- }
- return 0;
-}
-
-#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
-void VPInstructionWithType::printRecipe(raw_ostream &O, const Twine &Indent,
- VPSlotTracker &SlotTracker) const {
- O << Indent << "EMIT" << (isSingleScalar() ? "-SCALAR" : "") << " ";
- printAsOperand(O, SlotTracker);
- O << " = ";
-
- Type *ResultTy = getResultType();
- switch (getOpcode()) {
case VPInstruction::WideIVStep:
- O << "wide-iv-step ";
- printOperands(O, SlotTracker);
+ O << "wide-iv-step";
break;
case VPInstruction::StepVector:
- O << "step-vector " << *ResultTy;
+ O << "step-vector " << *getScalarType();
break;
case VPInstruction::VScale:
- O << "vscale " << *ResultTy;
+ O << "vscale " << *getScalarType();
break;
case Instruction::Load:
- O << "load ";
- printOperands(O, SlotTracker);
+ O << "load";
break;
default:
- assert(Instruction::isCast(getOpcode()) && "unhandled opcode");
O << Instruction::getOpcodeName(getOpcode());
- printFlags(O);
- printOperands(O, SlotTracker);
- O << " to " << *ResultTy;
}
+
+ printFlags(O);
+ printOperands(O, SlotTracker);
+ if (Instruction::isCast(getOpcode()))
+ O << " to " << *getScalarType();
}
#endif
diff --git a/llvm/lib/Transforms/Vectorize/VPlanUnroll.cpp b/llvm/lib/Transforms/Vectorize/VPlanUnroll.cpp
index bcd17a54a3e31..5b0cd0751266d 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanUnroll.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanUnroll.cpp
@@ -965,7 +965,7 @@ void VPlanTransforms::replicateByVF(VPlan &Plan, ElementCount VF) {
DefR->replaceUsesWithIf(LaneDefs[0], [DefR](VPUser &U, unsigned) {
if (U.usesFirstLaneOnly(DefR))
return true;
- auto *VPI = dyn_cast<VPInstructionWithType>(&U);
+ auto *VPI = dyn_cast<VPInstruction>(&U);
return VPI && Instruction::isCast(VPI->getOpcode());
});
diff --git a/llvm/unittests/Transforms/Vectorize/VPDomTreeTest.cpp b/llvm/unittests/Transforms/Vectorize/VPDomTreeTest.cpp
index de49dd6b57e61..f00f131b66190 100644
--- a/llvm/unittests/Transforms/Vectorize/VPDomTreeTest.cpp
+++ b/llvm/unittests/Transforms/Vectorize/VPDomTreeTest.cpp
@@ -239,29 +239,29 @@ TEST_F(VPDominatorTreeTest, DominanceRegionsTest) {
IntegerType *Int32 = IntegerType::get(C, 32);
VPBasicBlock *R1BB1 = Plan.createVPBasicBlock("R1BB1");
VPInstruction *R1BB1I =
- new VPInstructionWithType(VPInstruction::VScale, {}, Int32);
+ new VPInstruction(VPInstruction::VScale, {}, {}, {}, {}, "", Int32);
R1BB1->appendRecipe(R1BB1I);
VPBasicBlock *R1BB2 = Plan.createVPBasicBlock("R1BB2");
VPInstruction *R1BB2I =
- new VPInstructionWithType(VPInstruction::VScale, {}, Int32);
+ new VPInstruction(VPInstruction::VScale, {}, {}, {}, {}, {}, Int32);
R1BB2->appendRecipe(R1BB2I);
VPBasicBlock *R1BB3 = Plan.createVPBasicBlock("R1BB3");
VPInstruction *R1BB3I =
- new VPInstructionWithType(VPInstruction::VScale, {}, Int32);
+ new VPInstruction(VPInstruction::VScale, {}, {}, {}, {}, {}, Int32);
R1BB3->appendRecipe(R1BB3I);
VPRegionBlock *R1 = Plan.createReplicateRegion(R1BB1, R1BB3, "R1");
VPBasicBlock *R2BB1 = Plan.createVPBasicBlock("R2BB1");
VPInstruction *R2BB1I =
- new VPInstructionWithType(VPInstruction::VScale, {}, Int32);
+ new VPInstruction(VPInstruction::VScale, {}, {}, {}, {}, {}, Int32);
R2BB1->appendRecipe(R2BB1I);
VPBasicBlock *R2BB2 = Plan.createVPBasicBlock("R2BB2");
VPInstruction *R2BB2I =
- new VPInstructionWithType(VPInstruction::VScale, {}, Int32);
+ new VPInstruction(VPInstruction::VScale, {}, {}, {}, {}, {}, Int32);
R2BB2->appendRecipe(R2BB2I);
VPBasicBlock *R2BB3 = Plan.createVPBasicBlock("R2BB3");
VPInstruction *R2BB3I =
- new VPInstructionWithType(VPInstruction::VScale, {}, Int32);
+ new VPInstruction(VPInstruction::VScale, {}, {}, {}, {}, {}, Int32);
R2BB3->appendRecipe(R2BB3I);
VPRegionBlock *R2 = Plan.createReplicateRegion(R2BB1, R2BB3, "R2");
R2BB2->setParent(R2);
diff --git a/llvm/unittests/Transforms/Vectorize/VPlanTest.cpp b/llvm/unittests/Transforms/Vectorize/VPlanTest.cpp
index 2deb7c6c864b0..ea81631226a33 100644
--- a/llvm/unittests/Transforms/Vectorize/VPlanTest.cpp
+++ b/llvm/unittests/Transforms/Vectorize/VPlanTest.cpp
@@ -75,11 +75,11 @@ define void @f(i32 %x) {
TEST_F(VPInstructionTest, insertBefore) {
IntegerType *Int32 = IntegerType::get(C, 32);
VPInstruction *I1 =
- new VPInstructionWithType(VPInstruction::StepVector, {}, Int32);
+ new VPInstruction(VPInstruction::StepVector, {}, {}, {}, {}, {}, Int32);
VPInstruction *I2 =
- new VPInstructionWithType(VPInstruction::VScale, {}, Int32);
+ new VPInstruction(VPInstruction::VScale, {}, {}, {}, {}, {}, Int32);
VPInstruction *I3 =
- new VPInstructionWithType(VPInstruction::StepVector, {}, Int32);
+ new VPInstruction(VPInstruction::StepVector, {}, {}, {}, {}, {}, Int32);
VPBasicBlock &VPBB1 = *getPlan().createVPBasicBlock("");
VPBB1.appendRecipe(I1);
@@ -94,11 +94,11 @@ TEST_F(VPInstructionTest, insertBefore) {
TEST_F(VPInstructionTest, eraseFromParent) {
IntegerType *Int32 = IntegerType::get(C, 32);
VPInstruction *I1 =
- new VPInstructionWithType(VPInstruction::StepVector, {}, Int32);
+ new VPInstruction(VPInstruction::StepVector, {}, {}, {}, {}, {}, Int32);
VPInstruction *I2 =
- new VPInstructionWithType(VPInstruction::VScale, {}, Int32);
+ new VPInstruction(VPInstruction::VScale, {}, {}, {}, {}, {}, Int32);
VPInstruction *I3 =
- new VPInstructionWithType(VPInstruction::StepVector, {}, Int32);
+ new VPInstruction(VPInstruction::StepVector, {}, {}, {}, {}, {}, Int32);
VPBasicBlock &VPBB1 = *getPlan().createVPBasicBlock("");
VPBB1.appendRecipe(I1);
@@ -118,11 +118,11 @@ TEST_F(VPInstructionTest, eraseFromParent) {
TEST_F(VPInstructionTest, moveAfter) {
IntegerType *Int32 = IntegerType::get(C, 32);
VPInstruction *I1 =
- new VPInstructionWithType(VPInstruction::StepVector, {}, Int32);
+ new VPInstruction(VPInstruction::StepVector, {}, {}, {}, {}, {}, Int32);
VPInstruction *I2 =
- new VPInstructionWithType(VPInstruction::VScale, {}, Int32);
+ new VPInstruction(VPInstruction::VScale, {}, {}, {}, {}, {}, Int32);
VPInstruction *I3 =
- new VPInstructionWithType(VPInstruction::StepVector, {}, Int32);
+ new VPInstruction(VPInstruction::StepVector, {}, {}, {}, {}, {}, Int32);
VPBasicBlock &VPBB1 = *getPlan().createVPBasicBlock("");
VPBB1.appendRecipe(I1);
@@ -134,9 +134,9 @@ TEST_F(VPInstructionTest, moveAfter) {
CHECK_ITERATOR(VPBB1, I2, I1, I3);
VPInstruction *I4 =
- new VPInstructionWithType(VPInstruction::VScale, {}, Int32);
+ new VPInstruction(VPInstruction::VScale, {}, {}, {}, {}, {}, Int32);
VPInstruction *I5 =
- new VPInstructionWithType(VPInstruction::StepVector, {}, Int32);
+ new VPInstruction(VPInstruction::StepVector, {}, {}, {}, {}, {}, Int32);
VPBasicBlock &VPBB2 = *getPlan().createVPBasicBlock("");
VPBB2.appendRecipe(I4);
VPBB2.appendRecipe(I5);
@@ -151,11 +151,11 @@ TEST_F(VPInstructionTest, moveAfter) {
TEST_F(VPInstructionTest, moveBefore) {
IntegerType *Int32 = IntegerType::get(C, 32);
VPInstruction *I1 =
- new VPInstructionWithType(VPInstruction::StepVector, {}, Int32);
+ new VPInstruction(VPInstruction::StepVector, {}, {}, {}, {}, {}, Int32);
VPInstruction *I2 =
- new VPInstructionWithType(VPInstruction::VScale, {}, Int32);
+ new VPInstruction(VPInstruction::VScale, {}, {}, {}, {}, {}, Int32);
VPInstruction *I3 =
- new VPInstructionWithType(VPInstruction::StepVector, {}, Int32);
+ new VPInstruction(VPInstruction::StepVector, {}, {}, {}, {}, {}, Int32);
VPBasicBlock &VPBB1 = *getPlan().createVPBasicBlock("");
VPBB1.appendRecipe(I1);
@@ -167,9 +167,9 @@ TEST_F(VPInstructionTest, moveBefore) {
CHECK_ITERATOR(VPBB1, I2, I1, I3);
VPInstruction *I4 =
- new VPInstructionWithType(VPInstruction::VScale, {}, Int32);
+ new VPInstruction(VPInstruction::VScale, {}, {}, {}, {}, {}, Int32);
VPInstruction *I5 =
- new VPInstructionWithType(VPInstruction::StepVector, {}, Int32);
+ new VPInstruction(VPInstruction::StepVector, {}, {}, {}, {}, {}, Int32);
VPBasicBlock &VPBB2 = *getPlan().createVPBasicBlock("");
VPBB2.appendRecipe(I4);
VPBB2.appendRecipe(I5);
@@ -814,8 +814,8 @@ TEST_F(VPBasicBlockTest, reassociateBlocks) {
TEST_F(VPBasicBlockTest, splitAtEnd) {
VPlan &Plan = getPlan();
- VPInstruction *VPI = new VPInstructionWithType(VPInstruction::StepVector, {},
- IntegerType::get(C, 32));
+ VPInstruction *VPI = new VPInstruction(VPInstruction::StepVector, {}, {}, {},
+ {}, {}, IntegerType::get(C, 32));
VPBasicBlock *VPBB = Plan.createVPBasicBlock("VPBB1", VPI);
VPBlockUtils::connectBlocks(Plan.getEntry(), VPBB);
VPBlockUtils::connectBlocks(VPBB, Plan.getScalarHeader());
@@ -1785,8 +1785,8 @@ TEST(VPDoubleValueDefTest, traverseUseLists) {
// Create a new VPRecipeBase which defines 2 values and has 2 operands.
LLVMContext C;
IntegerType *Int32 = IntegerType::get(C, 32);
- VPInstructionWithType Op0(VPInstruction::StepVector, {}, Int32);
- VPInstructionWithType Op1(VPInstruction::VScale, {}, Int32);
+ VPInstruction Op0(VPInstruction::StepVector, {}, {}, {}, {}, {}, Int32);
+ VPInstruction Op1(VPInstruction::VScale, {}, {}, {}, {}, {}, Int32);
VPDoubleValueDef DoubleValueDef({&Op0, &Op1}, IntegerType::get(C, 32));
// Create a new users of the defined values.
@@ -1860,8 +1860,8 @@ TEST_F(VPUtilsTest, IsUniformAcrossVFsAndUFsForSingleScalarOpcodes) {
VPlan &Plan = getPlan();
// isSingleScalar opcode without operands.
- std::unique_ptr<VPInstruction> VScale(new VPInstructionWithType(
- VPInstruction::VScale, {}, IntegerType::get(C, 32)));
+ std::unique_ptr<VPInstruction> VScale(new VPInstruction(
+ VPInstruction::VScale, {}, {}, {}, {}, {}, IntegerType::get(C, 32)));
EXPECT_TRUE(vputils::isUniformAcrossVFsAndUFs(VScale.get()));
// isSingleScalar opcode with a uniform operand.
@@ -1871,14 +1871,14 @@ TEST_F(VPUtilsTest, IsUniformAcrossVFsAndUFsForSingleScalarOpcodes) {
// isVectorToScalar opcode with a uniform operand.
std::unique_ptr<VPInstruction> FirstActiveLane(
- new VPInstructionWithType(VPInstruction::FirstActiveLane, {&Plan.getVF()},
- IntegerType::get(C, 32)));
+ new VPInstruction(VPInstruction::FirstActiveLane, {&Plan.getVF()}, {}, {},
+ {}, {}, IntegerType::get(C, 32)));
EXPECT_TRUE(vputils::isUniformAcrossVFsAndUFs(FirstActiveLane.get()));
// StepVector produces a distinct value per lane and is non-uniform; use it
// as the non-single-scalar operand in the negative cases below.
- std::unique_ptr<VPInstruction> StepVector(new VPInstructionWithType(
- VPInstruction::StepVector, {}, IntegerType::get(C, 32)));
+ std::unique_ptr<VPInstruction> StepVector(new VPInstruction(
+ VPInstruction::StepVector, {}, {}, {}, {}, {}, IntegerType::get(C, 32)));
EXPECT_FALSE(vputils::isUniformAcrossVFsAndUFs(StepVector.get()));
// isSingleScalar opcode with a non-single-scalar operand.
@@ -1888,8 +1888,8 @@ TEST_F(VPUtilsTest, IsUniformAcrossVFsAndUFsForSingleScalarOpcodes) {
// isVectorToScalar opcode with a non-single-scalar operand.
std::unique_ptr<VPInstruction> FirstActiveLaneNonUniform(
- new VPInstructionWithType(VPInstruction::FirstActiveLane,
- {StepVector.get()}, IntegerType::get(C, 32)));
+ new VPInstruction(VPInstruction::FirstActiveLane, {StepVector.get()}, {},
+ {}, {}, {}, IntegerType::get(C, 32)));
EXPECT_FALSE(
vputils::isUniformAcrossVFsAndUFs(FirstActiveLaneNonUniform.get()));
}
@@ -1938,7 +1938,8 @@ TEST_F(VPRecipeTest, UFVScaleUserBeforeMaterialization) {
VPBlockUtils::connectBlocks(Plan.getEntry(), LoopRegion);
VPBlockUtils::connectBlocks(LoopRegion, Plan.getScalarHeader());
- auto *VScale = new VPInstructionWithType(VPInstruction::VScale, {}, IVTy);
+ auto *VScale =
+ new VPInstruction(VPInstruction::VScale, {}, {}, {}, {}, {}, IVTy);
Plan.getVectorPreheader()->appendRecipe(VScale);
auto *Step = new VPInstruction(Instruction::Mul, {VScale, UF},
>From 0318c6b23b3165a822de06bed775c03d36307aad Mon Sep 17 00:00:00 2001
From: Ramkumar Ramachandra <artagnon at tenstorrent.com>
Date: Thu, 25 Jun 2026 14:45:08 +0100
Subject: [PATCH 2/3] [VPlan] Make couple of improvements from Luke's review
---
llvm/lib/Transforms/Vectorize/VPlan.h | 2 +-
llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp | 12 +++++-------
2 files changed, 6 insertions(+), 8 deletions(-)
diff --git a/llvm/lib/Transforms/Vectorize/VPlan.h b/llvm/lib/Transforms/Vectorize/VPlan.h
index 2d1fc32578294..dc444c89a48db 100644
--- a/llvm/lib/Transforms/Vectorize/VPlan.h
+++ b/llvm/lib/Transforms/Vectorize/VPlan.h
@@ -1507,7 +1507,7 @@ class LLVM_ABI_FOR_TEST VPInstruction : public VPRecipeWithIRFlags,
/// Returns true if the recipe only uses scalars of operand \p Op.
bool usesScalars(const VPValue *Op) const override {
- return Instruction::isCast(getOpcode()) || usesFirstLaneOnly(Op);
+ return isSingleScalar() || usesFirstLaneOnly(Op);
}
/// Returns true if the recipe only uses the first part of operand \p Op.
diff --git a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
index 6e2cdb6683587..d28c6ac41fd12 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
@@ -1331,14 +1331,12 @@ InstructionCost VPInstruction::computeCost(ElementCount VF,
// NOTE: At the moment it seems only possible to expose this path for
// the trunc, zext and sext opcodes. However, isScalarCast also covers
// int<>fp conversions, bitcasts, ptr<>int conversions, etc.
- if (Instruction::isCast(getOpcode()))
- return getCostForRecipeWithOpcode(getOpcode(), ElementCount::getFixed(1),
- Ctx);
+ if (Instruction::isBinaryOp(getOpcode()) ||
+ Instruction::isCast(getOpcode())) {
- if (Instruction::isBinaryOp(getOpcode())) {
- if (!getUnderlyingValue() && getOpcode() != Instruction::FMul) {
- // TODO: Compute cost for VPInstructions without underlying values once
- // the legacy cost model has been retired.
+ // TODO: Strip this, now that legacy costing is retired.
+ if (Instruction::isBinaryOp(getOpcode()) && !getUnderlyingValue() &&
+ getOpcode() != Instruction::FMul) {
return 0;
}
>From 6f15d472794d08ea24922f22a760666639b1e62e Mon Sep 17 00:00:00 2001
From: Ramkumar Ramachandra <artagnon at tenstorrent.com>
Date: Thu, 25 Jun 2026 15:49:40 +0100
Subject: [PATCH 3/3] [VPlan] Strip stale comment
---
llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp | 3 ---
1 file changed, 3 deletions(-)
diff --git a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
index d28c6ac41fd12..c69ec9c6927ac 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
@@ -1328,9 +1328,6 @@ InstructionCost VPRecipeWithIRFlags::getCostForRecipeWithOpcode(
InstructionCost VPInstruction::computeCost(ElementCount VF,
VPCostContext &Ctx) const {
- // NOTE: At the moment it seems only possible to expose this path for
- // the trunc, zext and sext opcodes. However, isScalarCast also covers
- // int<>fp conversions, bitcasts, ptr<>int conversions, etc.
if (Instruction::isBinaryOp(getOpcode()) ||
Instruction::isCast(getOpcode())) {
More information about the llvm-commits
mailing list