[llvm] [VPlan] Check operand types of more VPInstruction on construction (NFC). (PR #203777)
Florian Hahn via llvm-commits
llvm-commits at lists.llvm.org
Sun Jun 14 11:11:06 PDT 2026
https://github.com/fhahn created https://github.com/llvm/llvm-project/pull/203777
Follow-up to earlier PRs, tighten VPInstruction operand type checks at construction: restrict operand types for various opcodes, and support missing opcodes.
>From 6eb8bd14e712dd3506889be2021f737c8859db9f Mon Sep 17 00:00:00 2001
From: Florian Hahn <flo at fhahn.com>
Date: Sat, 13 Jun 2026 21:46:40 +0200
Subject: [PATCH] [VPlan] Check operand types of more VPInstruction on
construction (NFC).
Follow-up to earlier PRs, tighten VPInstruction operand type checks at
construction: restrict operand types for various opcodes, and support
missing opcodes.
---
.../lib/Transforms/Vectorize/VPlanRecipes.cpp | 61 +++++++++++++++++--
.../Vectorize/VPlanVerifierTest.cpp | 18 +++---
2 files changed, 64 insertions(+), 15 deletions(-)
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");
More information about the llvm-commits
mailing list