[llvm] [VPlan] Relax type of DerivedIV start value (NFC) (PR #206464)
Ramkumar Ramachandra via llvm-commits
llvm-commits at lists.llvm.org
Fri Jul 10 02:06:21 PDT 2026
https://github.com/artagnon updated https://github.com/llvm/llvm-project/pull/206464
>From d384241fd1d9fda0c8b4fd47e72069ff00eb6215 Mon Sep 17 00:00:00 2001
From: Ramkumar Ramachandra <artagnon at tenstorrent.com>
Date: Mon, 29 Jun 2026 12:20:47 +0100
Subject: [PATCH 1/4] [VPlan] Relax type of DerivedIV start value (NFC)
Change it from VPIRValue -> VPValue, as several usecases require it.
---
llvm/lib/Transforms/Vectorize/LoopVectorizationPlanner.h | 2 +-
llvm/lib/Transforms/Vectorize/VPlan.h | 6 +++---
llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp | 2 +-
3 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorizationPlanner.h b/llvm/lib/Transforms/Vectorize/LoopVectorizationPlanner.h
index e4cfdecfb1acf..cd02ced2942d1 100644
--- a/llvm/lib/Transforms/Vectorize/LoopVectorizationPlanner.h
+++ b/llvm/lib/Transforms/Vectorize/LoopVectorizationPlanner.h
@@ -406,7 +406,7 @@ class VPBuilder {
/// induction with \p Start and \p Step values, using \p Start + \p Current *
/// \p Step.
VPDerivedIVRecipe *createDerivedIV(InductionDescriptor::InductionKind Kind,
- FPMathOperator *FPBinOp, VPIRValue *Start,
+ FPMathOperator *FPBinOp, VPValue *Start,
VPValue *Current, VPValue *Step) {
return tryInsertInstruction(
new VPDerivedIVRecipe(Kind, FPBinOp, Start, Current, Step));
diff --git a/llvm/lib/Transforms/Vectorize/VPlan.h b/llvm/lib/Transforms/Vectorize/VPlan.h
index eefe02b3e41ad..1ce5786793c49 100644
--- a/llvm/lib/Transforms/Vectorize/VPlan.h
+++ b/llvm/lib/Transforms/Vectorize/VPlan.h
@@ -4181,8 +4181,8 @@ class VPDerivedIVRecipe : public VPSingleDefRecipe {
public:
VPDerivedIVRecipe(InductionDescriptor::InductionKind Kind,
- const FPMathOperator *FPBinOp, VPIRValue *Start,
- VPValue *IV, VPValue *Step)
+ const FPMathOperator *FPBinOp, VPValue *Start, VPValue *IV,
+ VPValue *Step)
: VPSingleDefRecipe(VPRecipeBase::VPDerivedIVSC, {Start, IV, Step},
Start->getScalarType(), nullptr),
Kind(Kind), FPBinOp(FPBinOp) {}
@@ -4204,7 +4204,7 @@ class VPDerivedIVRecipe : public VPSingleDefRecipe {
InstructionCost computeCost(ElementCount VF,
VPCostContext &Ctx) const override;
- VPIRValue *getStartValue() const { return cast<VPIRValue>(getOperand(0)); }
+ VPValue *getStartValue() const { return getOperand(0); }
VPValue *getIndex() const { return getOperand(1); }
VPValue *getStepValue() const { return getOperand(2); }
const FPMathOperator *getFPBinOp() const { return FPBinOp; }
diff --git a/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp b/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
index 343ee02007966..8d047d2120cb2 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
@@ -4086,7 +4086,7 @@ static void expandVPWidenPointerInduction(VPWidenPointerInductionRecipe *R) {
/// Expand a VPDerivedIVRecipe into executable recipes.
static void expandVPDerivedIV(VPDerivedIVRecipe *R) {
VPBuilder Builder(R);
- VPIRValue *Start = R->getStartValue();
+ VPValue *Start = R->getStartValue();
VPValue *Step = R->getStepValue();
VPValue *Index = R->getIndex();
Type *StepTy = Step->getScalarType();
>From a851259ca806b8d186045e1d8eb50d801ec39609 Mon Sep 17 00:00:00 2001
From: Ramkumar Ramachandra <artagnon at tenstorrent.com>
Date: Fri, 3 Jul 2026 13:00:07 +0100
Subject: [PATCH 2/4] [VPlan] Add verifier rule for DIV start value
---
llvm/lib/Transforms/Vectorize/VPlanVerifier.cpp | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/llvm/lib/Transforms/Vectorize/VPlanVerifier.cpp b/llvm/lib/Transforms/Vectorize/VPlanVerifier.cpp
index 656a5f25878df..a4d6cc0ecb480 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanVerifier.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanVerifier.cpp
@@ -334,6 +334,13 @@ bool VPlanVerifier::verifyVPBasicBlock(const VPBasicBlock *VPBB) {
break;
}
}
+ if (const auto *DIV = dyn_cast<VPDerivedIVRecipe>(&R)) {
+ if (!DIV->getStartValue()->isDefinedOutsideLoopRegions()) {
+ errs() << "VPDerivedIVRecipe must have start value defined outside "
+ "loop regions\n";
+ return false;
+ }
+ }
if (const auto *ScalarIVSteps = dyn_cast<VPScalarIVStepsRecipe>(&R)) {
unsigned NumOps = ScalarIVSteps->getNumOperands();
if (NumOps != 3 && NumOps != 4) {
>From 67176f7149fd3a85b2c89a4c799898dd75037a77 Mon Sep 17 00:00:00 2001
From: Ramkumar Ramachandra <artagnon at tenstorrent.com>
Date: Thu, 9 Jul 2026 09:35:27 +0100
Subject: [PATCH 3/4] [VPlan] Add verifier test
---
.../Vectorize/VPlanVerifierTest.cpp | 35 +++++++++++++++++++
1 file changed, 35 insertions(+)
diff --git a/llvm/unittests/Transforms/Vectorize/VPlanVerifierTest.cpp b/llvm/unittests/Transforms/Vectorize/VPlanVerifierTest.cpp
index 64101278c08bf..3fba8536582e9 100644
--- a/llvm/unittests/Transforms/Vectorize/VPlanVerifierTest.cpp
+++ b/llvm/unittests/Transforms/Vectorize/VPlanVerifierTest.cpp
@@ -330,6 +330,41 @@ TEST_F(VPVerifierTest, NonHeaderPHIInHeader) {
delete PHINode;
}
+TEST_F(VPVerifierTest, DerivedIVWithStartInLoopRegions) {
+ VPlan &Plan = getPlan();
+ auto *I32Ty = Type::getInt32Ty(C);
+ VPBasicBlock *Entry = Plan.getEntry();
+ VPBasicBlock *Latch = Plan.createVPBasicBlock("latch");
+ VPInstruction *DefI = new VPInstruction(
+ Instruction::Add, {Plan.getPoison(I32Ty), Plan.getPoison(I32Ty)},
+ VPIRFlags::getDefaultFlags(Instruction::Add));
+ Entry->appendRecipe(DefI);
+
+ auto *Start = new VPInstruction(VPInstruction::Not, Plan.getPoison(I32Ty));
+ Latch->appendRecipe(Start);
+ auto *DIV = new VPDerivedIVRecipe(InductionDescriptor::IK_IntInduction,
+ nullptr, Start, Plan.getPoison(I32Ty),
+ Plan.getPoison(I32Ty));
+ Latch->appendRecipe(DIV);
+ Latch->appendRecipe(
+ new VPInstruction(VPInstruction::BranchOnCond, Plan.getTrue()));
+
+ VPRegionBlock *LoopR = Plan.createLoopRegion(I32Ty, DebugLoc::getUnknown(),
+ "loop", Latch, Latch);
+ VPBlockUtils::connectBlocks(Entry, LoopR);
+ VPBlockUtils::connectBlocks(LoopR, Plan.getScalarHeader());
+
+#if GTEST_HAS_STREAM_REDIRECTION
+ ::testing::internal::CaptureStderr();
+#endif
+ EXPECT_FALSE(verifyVPlanIsValid(Plan));
+#if GTEST_HAS_STREAM_REDIRECTION
+ EXPECT_STREQ(
+ "VPDerivedIVRecipe must have start value defined outside loop regions\n",
+ ::testing::internal::GetCapturedStderr().c_str());
+#endif
+}
+
TEST_F(VPVerifierTest, testRUN_VPLAN_PASS) {
VPlan &Plan = getPlan();
VPIRValue *Zero = Plan.getConstantInt(32, 0);
>From 689eace02c62b8a96738fa82d3ca040df81bdf34 Mon Sep 17 00:00:00 2001
From: Ramkumar Ramachandra <artagnon at tenstorrent.com>
Date: Fri, 10 Jul 2026 09:49:28 +0100
Subject: [PATCH 4/4] [VPlan] Improve verifier test; use VPBuilder
---
.../Vectorize/VPlanVerifierTest.cpp | 21 +++++++------------
1 file changed, 7 insertions(+), 14 deletions(-)
diff --git a/llvm/unittests/Transforms/Vectorize/VPlanVerifierTest.cpp b/llvm/unittests/Transforms/Vectorize/VPlanVerifierTest.cpp
index 3fba8536582e9..ebf7a0942ae2c 100644
--- a/llvm/unittests/Transforms/Vectorize/VPlanVerifierTest.cpp
+++ b/llvm/unittests/Transforms/Vectorize/VPlanVerifierTest.cpp
@@ -7,8 +7,8 @@
//===----------------------------------------------------------------------===//
#include "../lib/Transforms/Vectorize/VPlanVerifier.h"
+#include "../lib/Transforms/Vectorize/LoopVectorizationPlanner.h"
#include "../lib/Transforms/Vectorize/VPlan.h"
-#include "../lib/Transforms/Vectorize/VPlanCFG.h"
#include "VPlanTestBase.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
@@ -335,19 +335,12 @@ TEST_F(VPVerifierTest, DerivedIVWithStartInLoopRegions) {
auto *I32Ty = Type::getInt32Ty(C);
VPBasicBlock *Entry = Plan.getEntry();
VPBasicBlock *Latch = Plan.createVPBasicBlock("latch");
- VPInstruction *DefI = new VPInstruction(
- Instruction::Add, {Plan.getPoison(I32Ty), Plan.getPoison(I32Ty)},
- VPIRFlags::getDefaultFlags(Instruction::Add));
- Entry->appendRecipe(DefI);
-
- auto *Start = new VPInstruction(VPInstruction::Not, Plan.getPoison(I32Ty));
- Latch->appendRecipe(Start);
- auto *DIV = new VPDerivedIVRecipe(InductionDescriptor::IK_IntInduction,
- nullptr, Start, Plan.getPoison(I32Ty),
- Plan.getPoison(I32Ty));
- Latch->appendRecipe(DIV);
- Latch->appendRecipe(
- new VPInstruction(VPInstruction::BranchOnCond, Plan.getTrue()));
+
+ VPBuilder Builder(Latch);
+ VPValue *Start = Builder.createNot(Plan.getPoison(I32Ty));
+ Builder.createDerivedIV(InductionDescriptor::IK_IntInduction, nullptr, Start,
+ Plan.getPoison(I32Ty), Plan.getPoison(I32Ty));
+ Builder.createNaryOp(VPInstruction::BranchOnCond, Plan.getTrue());
VPRegionBlock *LoopR = Plan.createLoopRegion(I32Ty, DebugLoc::getUnknown(),
"loop", Latch, Latch);
More information about the llvm-commits
mailing list