[llvm] [VPlan] Check operand types of more VPInstruction on construction (NFC). (PR #203777)

via llvm-commits llvm-commits at lists.llvm.org
Sun Jun 14 11:11:45 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-transforms

Author: Florian Hahn (fhahn)

<details>
<summary>Changes</summary>

Follow-up to earlier PRs, tighten VPInstruction operand type checks at construction: restrict operand types for various opcodes, and support missing opcodes.

---
Full diff: https://github.com/llvm/llvm-project/pull/203777.diff


2 Files Affected:

- (modified) llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp (+55-6) 
- (modified) llvm/unittests/Transforms/Vectorize/VPlanVerifierTest.cpp (+9-9) 


``````````diff
diff --git a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
index 17b90c733a817..e4ec0a2d535ab 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
@@ -459,37 +459,88 @@ Type *llvm::computeScalarTypeForInstruction(unsigned Opcode,
   LLVMContext &Ctx = Op0Ty->getContext();
   switch (Opcode) {
   case VPInstruction::BranchOnCond:
+    assert(Op0Ty->isIntegerTy(1) && "expected bool condition");
+    return Type::getVoidTy(Ctx);
   case VPInstruction::BranchOnTwoConds:
+    assert(Op0Ty->isIntegerTy(1) && "expected bool condition");
+    AssertOperandType(1, IntegerType::get(Ctx, 1));
+    return Type::getVoidTy(Ctx);
   case VPInstruction::BranchOnCount:
-  case Instruction::Store:
+    assert(Op0Ty->isIntegerTy() && "expected integer operand");
+    AssertOperandType(1, Op0Ty);
+    return Type::getVoidTy(Ctx);
+  case VPInstruction::CalculateTripCountMinusVF:
+  case VPInstruction::CanonicalIVIncrementForPart:
+    assert(Op0Ty->isIntegerTy() && "expected integer operand");
+    for (unsigned Idx = 1; Idx != Operands.size(); ++Idx)
+      AssertOperandType(Idx, Op0Ty);
+    return Op0Ty;
   case Instruction::Switch:
+    for (unsigned Idx = 1; Idx != Operands.size(); ++Idx)
+      AssertOperandType(Idx, Op0Ty);
+    return Type::getVoidTy(Ctx);
+  case Instruction::Store:
     return Type::getVoidTy(Ctx);
   case Instruction::ICmp:
+    assert(Op0Ty->isIntOrPtrTy() && "expected integer or pointer operand");
+    AssertOperandType(1, Op0Ty);
+    return IntegerType::get(Ctx, 1);
   case Instruction::FCmp:
+    assert(Op0Ty->isFloatingPointTy() && "expected floating-point operand");
+    AssertOperandType(1, Op0Ty);
+    return IntegerType::get(Ctx, 1);
   case VPInstruction::ActiveLaneMask:
+    assert(Op0Ty->isIntegerTy() && "expected integer operand");
     AssertOperandType(1, Op0Ty);
     return IntegerType::get(Ctx, 1);
+  case VPInstruction::MaskedCond:
+    assert(Op0Ty->isIntegerTy(1) && "expected bool operand");
+    return IntegerType::get(Ctx, 1);
   case VPInstruction::LogicalAnd:
   case VPInstruction::LogicalOr:
-  case VPInstruction::MaskedCond:
-    assert((!Op0Ty || Op0Ty->isIntegerTy(1)) && "expected bool operand");
+    assert(Op0Ty->isIntegerTy(1) && "expected bool operand");
     AssertOperandType(1, Op0Ty);
     return IntegerType::get(Ctx, 1);
+  case VPInstruction::AnyOf:
+    assert(Op0Ty->isIntegerTy(1) && "expected bool operand");
+    for (unsigned Idx = 1; Idx != Operands.size(); ++Idx)
+      AssertOperandType(Idx, Op0Ty);
+    return IntegerType::get(Ctx, 1);
   case VPInstruction::ExplicitVectorLength:
+    assert(Op0Ty->isIntegerTy() && "expected integer operand");
     return IntegerType::get(Ctx, 32);
   case Instruction::Select: {
+    assert((!Op0Ty || Op0Ty->isIntegerTy(1)) &&
+           "select condition must be bool");
     Type *Op1Ty = Operands[1]->getScalarType();
     AssertOperandType(2, Op1Ty);
     return Op1Ty;
   }
+  case Instruction::InsertElement:
+    // The inserted scalar (operand 1) must match the vector element type;
+    // operand 2 is the index and may have a different type.
+    AssertOperandType(1, Op0Ty);
+    return Op0Ty;
+  case VPInstruction::ReductionStartVector:
+    // The start value and the identity value (operands 0 and 1) fill the same
+    // vector and must match in type; operand 2 is the scaling factor.
+    AssertOperandType(1, Op0Ty);
+    return Op0Ty;
   case VPInstruction::ExtractLane: {
     assert(Operands.size() >= 2 && "ExtractLane requires a lane operand and "
                                    "at least one source vector operand");
+    // Operand 0 is the lane index, used for integer arithmetic.
+    assert(Op0Ty->isIntegerTy() && "expected integer operand");
     Type *Op1Ty = Operands[1]->getScalarType();
     for (unsigned Idx = 2; Idx != Operands.size(); ++Idx)
       AssertOperandType(Idx, Op1Ty);
     return Op1Ty;
   }
+  case VPInstruction::PtrAdd:
+  case VPInstruction::WidePtrAdd:
+    assert(Operands[1]->getScalarType()->isIntegerTy() &&
+           "expected integer operand");
+    return Op0Ty;
   case Instruction::ExtractValue: {
     assert(Operands.size() == 2 && "expected single level extractvalue");
     auto *StructTy = cast<StructType>(Op0Ty);
@@ -514,9 +565,7 @@ Type *llvm::computeScalarTypeForInstruction(unsigned Opcode,
   bool AllOperandsSameType =
       Instruction::isBinaryOp(Opcode) ||
       is_contained({VPInstruction::FirstOrderRecurrenceSplice,
-                    VPInstruction::CalculateTripCountMinusVF,
-                    VPInstruction::CanonicalIVIncrementForPart,
-                    VPInstruction::AnyOf, VPInstruction::BuildVector,
+                    VPInstruction::BuildVector,
                     VPInstruction::BuildStructVector},
                    Opcode);
   if (AllOperandsSameType)
diff --git a/llvm/unittests/Transforms/Vectorize/VPlanVerifierTest.cpp b/llvm/unittests/Transforms/Vectorize/VPlanVerifierTest.cpp
index 638a875df86ea..64101278c08bf 100644
--- a/llvm/unittests/Transforms/Vectorize/VPlanVerifierTest.cpp
+++ b/llvm/unittests/Transforms/Vectorize/VPlanVerifierTest.cpp
@@ -76,7 +76,7 @@ TEST_F(VPVerifierTest, VPInstructionUseBeforeDefDifferentBB) {
       new VPInstruction(Instruction::Sub, {DefI, Zero},
                         VPIRFlags::getDefaultFlags(Instruction::Sub));
   VPInstruction *BranchOnCond =
-      new VPInstruction(VPInstruction::BranchOnCond, {UseI});
+      new VPInstruction(VPInstruction::BranchOnCond, {Plan.getFalse()});
 
   VPBasicBlock *VPBB1 = Plan.getEntry();
   VPBasicBlock *VPBB2 = Plan.createVPBasicBlock("");
@@ -118,7 +118,7 @@ TEST_F(VPVerifierTest, VPBlendUseBeforeDefDifferentBB) {
       new VPInstruction(Instruction::Add, {Zero, Zero},
                         VPIRFlags::getDefaultFlags(Instruction::Add));
   VPInstruction *BranchOnCond =
-      new VPInstruction(VPInstruction::BranchOnCond, {DefI});
+      new VPInstruction(VPInstruction::BranchOnCond, {Plan.getFalse()});
   auto *Blend = new VPBlendRecipe(Phi, {DefI, Plan.getTrue()}, {}, {});
 
   VPBasicBlock *VPBB1 = Plan.getEntry();
@@ -206,9 +206,9 @@ TEST_F(VPVerifierTest, DuplicateSuccessorsOutsideRegion) {
       new VPInstruction(Instruction::Add, {Zero, Zero},
                         VPIRFlags::getDefaultFlags(Instruction::Add));
   VPInstruction *BranchOnCond =
-      new VPInstruction(VPInstruction::BranchOnCond, {I1});
+      new VPInstruction(VPInstruction::BranchOnCond, {Plan.getFalse()});
   VPInstruction *BranchOnCond2 =
-      new VPInstruction(VPInstruction::BranchOnCond, {I1});
+      new VPInstruction(VPInstruction::BranchOnCond, {Plan.getFalse()});
 
   VPBasicBlock *VPBB1 = Plan.getEntry();
   VPBasicBlock *VPBB2 = Plan.createVPBasicBlock("");
@@ -235,9 +235,9 @@ TEST_F(VPVerifierTest, DuplicateSuccessorsInsideRegion) {
       new VPInstruction(Instruction::Add, {Zero, Zero},
                         VPIRFlags::getDefaultFlags(Instruction::Add));
   VPInstruction *BranchOnCond =
-      new VPInstruction(VPInstruction::BranchOnCond, {I1});
+      new VPInstruction(VPInstruction::BranchOnCond, {Plan.getFalse()});
   VPInstruction *BranchOnCond2 =
-      new VPInstruction(VPInstruction::BranchOnCond, {I1});
+      new VPInstruction(VPInstruction::BranchOnCond, {Plan.getFalse()});
 
   VPBasicBlock *VPBB1 = Plan.getEntry();
   VPBasicBlock *VPBB2 = Plan.createVPBasicBlock("");
@@ -272,7 +272,7 @@ TEST_F(VPVerifierTest, BlockOutsideRegionWithParent) {
       new VPInstruction(Instruction::Add, {Zero, Zero},
                         VPIRFlags::getDefaultFlags(Instruction::Add));
   VPInstruction *BranchOnCond =
-      new VPInstruction(VPInstruction::BranchOnCond, {DefI});
+      new VPInstruction(VPInstruction::BranchOnCond, {Plan.getFalse()});
 
   VPBB1->appendRecipe(DefI);
   VPBB2->appendRecipe(BranchOnCond);
@@ -296,8 +296,8 @@ TEST_F(VPVerifierTest, BlockOutsideRegionWithParent) {
 
 TEST_F(VPVerifierTest, NonHeaderPHIInHeader) {
   VPlan &Plan = getPlan();
-  VPValue *Zero = Plan.getConstantInt(32, 0);
-  auto *BranchOnCond = new VPInstruction(VPInstruction::BranchOnCond, {Zero});
+  auto *BranchOnCond =
+      new VPInstruction(VPInstruction::BranchOnCond, {Plan.getFalse()});
 
   VPBasicBlock *VPBB1 = Plan.getEntry();
   VPBasicBlock *VPBB2 = Plan.createVPBasicBlock("header");

``````````

</details>


https://github.com/llvm/llvm-project/pull/203777


More information about the llvm-commits mailing list