[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