[llvm] [VPlan] Fix issues around scalar-cast VPInstructions (PR #195629)
Ramkumar Ramachandra via llvm-commits
llvm-commits at lists.llvm.org
Mon May 4 04:44:50 PDT 2026
https://github.com/artagnon updated https://github.com/llvm/llvm-project/pull/195629
>From e32f9ac243057f3f293503e3cf252bcf090fcc3e Mon Sep 17 00:00:00 2001
From: Ramkumar Ramachandra <artagnon at tenstorrent.com>
Date: Mon, 4 May 2026 11:03:20 +0100
Subject: [PATCH] [VPlan] Fix issues around scalar-cast VPInstructions
Compute a cost for them, mark them alwaysUnmasked, and apply flags when
executing them. While at it, strip VPRecipeBase::isScalarCast.
---
.../Transforms/Vectorize/LoopVectorize.cpp | 3 ++-
llvm/lib/Transforms/Vectorize/VPlan.h | 15 ++++----------
.../lib/Transforms/Vectorize/VPlanRecipes.cpp | 20 ++++++++++++-------
3 files changed, 19 insertions(+), 19 deletions(-)
diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
index 78163b5fe35d5..afbdb88d7640e 100644
--- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
+++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
@@ -7845,7 +7845,8 @@ static SmallVector<Instruction *> preparePlanForEpilogueVectorLoop(
[](const VPUser *U) {
return isa<VPScalarIVStepsRecipe>(U) ||
isa<VPDerivedIVRecipe>(U) ||
- cast<VPRecipeBase>(U)->isScalarCast() ||
+ Instruction::isCast(
+ cast<VPInstruction>(U)->getOpcode()) ||
cast<VPInstruction>(U)->getOpcode() ==
Instruction::Add;
}) &&
diff --git a/llvm/lib/Transforms/Vectorize/VPlan.h b/llvm/lib/Transforms/Vectorize/VPlan.h
index 4a5420185224b..8f04357da099c 100644
--- a/llvm/lib/Transforms/Vectorize/VPlan.h
+++ b/llvm/lib/Transforms/Vectorize/VPlan.h
@@ -552,9 +552,6 @@ class LLVM_ABI_FOR_TEST VPRecipeBase
/// Returns the debug location of the recipe.
DebugLoc getDebugLoc() const { return DL; }
- /// Return true if the recipe is a scalar cast.
- bool isScalarCast() const;
-
/// Set the recipe's debug location to \p NewDL.
void setDebugLoc(DebugLoc NewDL) { DL = NewDL; }
@@ -1376,7 +1373,8 @@ class LLVM_ABI_FOR_TEST VPInstruction : public VPRecipeWithIRFlags,
if (!getUnderlyingValue())
return true;
- return Opcode == Instruction::PHI || Opcode == Instruction::GetElementPtr;
+ return Instruction::isCast(Opcode) || Opcode == Instruction::PHI ||
+ Opcode == Instruction::GetElementPtr;
}
public:
@@ -1524,8 +1522,6 @@ class VPInstructionWithType : public VPInstruction {
static inline bool classof(const VPRecipeBase *R) {
// VPInstructionWithType are VPInstructions with specific opcodes requiring
// type information.
- if (R->isScalarCast())
- return true;
auto *VPI = dyn_cast<VPInstruction>(R);
if (!VPI)
return false;
@@ -1536,7 +1532,7 @@ class VPInstructionWithType : public VPInstruction {
case Instruction::Load:
return true;
default:
- return false;
+ return Instruction::isCast(VPI->getOpcode());
}
}
@@ -1556,10 +1552,7 @@ class VPInstructionWithType : public VPInstruction {
/// Return the cost of this VPInstruction.
InstructionCost computeCost(ElementCount VF,
- VPCostContext &Ctx) const override {
- // TODO: Compute accurate cost after retiring the legacy cost model.
- return 0;
- }
+ VPCostContext &Ctx) const override;
Type *getResultType() const { return ResultTy; }
diff --git a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
index 2225dfa310c6c..41102932fd930 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
@@ -312,11 +312,6 @@ bool VPRecipeBase::isPhi() const {
isa<VPPhi, VPIRPhi>(this);
}
-bool VPRecipeBase::isScalarCast() const {
- auto *VPI = dyn_cast<VPInstruction>(this);
- return VPI && Instruction::isCast(VPI->getOpcode());
-}
-
void VPIRFlags::intersectFlags(const VPIRFlags &Other) {
assert(OpType == Other.OpType && "OpType must match");
switch (OpType) {
@@ -1306,7 +1301,7 @@ bool VPInstruction::isSingleScalar() const {
case VPInstruction::VScale:
return true;
default:
- return isScalarCast();
+ return Instruction::isCast(getOpcode());
}
}
@@ -1589,10 +1584,14 @@ void VPInstruction::printRecipe(raw_ostream &O, const Twine &Indent,
void VPInstructionWithType::execute(VPTransformState &State) {
State.setDebugLocFrom(getDebugLoc());
- if (isScalarCast()) {
+ 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;
}
@@ -1614,6 +1613,13 @@ void VPInstructionWithType::execute(VPTransformState &State) {
}
}
+InstructionCost VPInstructionWithType::computeCost(ElementCount VF,
+ VPCostContext &Ctx) const {
+ if (!getUnderlyingValue())
+ return 0;
+ return getCostForRecipeWithOpcode(getOpcode(), VF, Ctx);
+}
+
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
void VPInstructionWithType::printRecipe(raw_ostream &O, const Twine &Indent,
VPSlotTracker &SlotTracker) const {
More information about the llvm-commits
mailing list