spirv-val: Add OpSpecConstantOp for Arithmetics and Bitwise (#6582)
another chunk of https://github.com/KhronosGroup/SPIRV-Tools/issues/6564
adds `ArithmeticsPass` and `BitwisePass`
diff --git a/source/val/validate_arithmetics.cpp b/source/val/validate_arithmetics.cpp
index 38ef9e6..03697c6 100644
--- a/source/val/validate_arithmetics.cpp
+++ b/source/val/validate_arithmetics.cpp
@@ -24,7 +24,8 @@
namespace spvtools {
namespace val {
-spv_result_t ValidateFloat(ValidationState_t& _, const Instruction* inst) {
+spv_result_t ValidateFloat(ValidationState_t& _, const Instruction* inst,
+ uint32_t starting_index = 2) {
const spv::Op opcode = inst->opcode();
const uint32_t result_type = inst->type_id();
bool supportsCoopMat =
@@ -42,8 +43,8 @@
<< "Expected floating scalar or vector type as Result Type: "
<< spvOpcodeString(opcode);
- for (size_t operand_index = 2; operand_index < inst->operands().size();
- ++operand_index) {
+ for (size_t operand_index = starting_index;
+ operand_index < inst->operands().size(); ++operand_index) {
if (supportsCoopVec && _.IsCooperativeVectorNVType(result_type)) {
const uint32_t type_id = _.GetOperandTypeId(inst, operand_index);
if (!_.IsCooperativeVectorNVType(type_id)) {
@@ -73,8 +74,8 @@
return SPV_SUCCESS;
}
-spv_result_t ValidateUnsignedInt(ValidationState_t& _,
- const Instruction* inst) {
+spv_result_t ValidateUnsignedInt(ValidationState_t& _, const Instruction* inst,
+ uint32_t starting_index = 2) {
const spv::Op opcode = inst->opcode();
const uint32_t result_type = inst->type_id();
bool supportsCoopMat = (opcode == spv::Op::OpUDiv);
@@ -87,8 +88,8 @@
<< "Expected unsigned int scalar or vector type as Result Type: "
<< spvOpcodeString(opcode);
- for (size_t operand_index = 2; operand_index < inst->operands().size();
- ++operand_index) {
+ for (size_t operand_index = starting_index;
+ operand_index < inst->operands().size(); ++operand_index) {
if (supportsCoopVec && _.IsCooperativeVectorNVType(result_type)) {
const uint32_t type_id = _.GetOperandTypeId(inst, operand_index);
if (!_.IsCooperativeVectorNVType(type_id)) {
@@ -119,7 +120,8 @@
return SPV_SUCCESS;
}
-spv_result_t ValidateSignedInt(ValidationState_t& _, const Instruction* inst) {
+spv_result_t ValidateSignedInt(ValidationState_t& _, const Instruction* inst,
+ uint32_t starting_index = 2) {
const spv::Op opcode = inst->opcode();
const uint32_t result_type = inst->type_id();
bool supportsCoopMat =
@@ -140,8 +142,8 @@
const uint32_t dimension = _.GetDimension(result_type);
const uint32_t bit_width = _.GetBitWidth(result_type);
- for (size_t operand_index = 2; operand_index < inst->operands().size();
- ++operand_index) {
+ for (size_t operand_index = starting_index;
+ operand_index < inst->operands().size(); ++operand_index) {
const uint32_t type_id = _.GetOperandTypeId(inst, operand_index);
if (supportsCoopVec && _.IsCooperativeVectorNVType(result_type)) {
@@ -884,6 +886,33 @@
return ValidateCooperativeMatrixMulAddKHR(_, inst);
case spv::Op::OpCooperativeMatrixReduceNV:
return ValidateCooperativeMatrixReduceNV(_, inst);
+
+ case spv::Op::OpSpecConstantOp: {
+ switch (inst->GetOperandAs<spv::Op>(2u)) {
+ case spv::Op::OpFAdd:
+ case spv::Op::OpFSub:
+ case spv::Op::OpFMul:
+ case spv::Op::OpFDiv:
+ case spv::Op::OpFRem:
+ case spv::Op::OpFMod:
+ case spv::Op::OpFNegate:
+ return ValidateFloat(_, inst, 3);
+ case spv::Op::OpUDiv:
+ case spv::Op::OpUMod:
+ return ValidateUnsignedInt(_, inst, 3);
+ case spv::Op::OpISub:
+ case spv::Op::OpIAdd:
+ case spv::Op::OpIMul:
+ case spv::Op::OpSDiv:
+ case spv::Op::OpSMod:
+ case spv::Op::OpSRem:
+ case spv::Op::OpSNegate:
+ return ValidateSignedInt(_, inst, 3);
+ default:
+ break;
+ }
+ break;
+ }
default:
break;
}
diff --git a/source/val/validate_bitwise.cpp b/source/val/validate_bitwise.cpp
index a34b75a..f038617 100644
--- a/source/val/validate_bitwise.cpp
+++ b/source/val/validate_bitwise.cpp
@@ -57,7 +57,8 @@
return SPV_SUCCESS;
}
-spv_result_t ValidateShift(ValidationState_t& _, const Instruction* inst) {
+spv_result_t ValidateShift(ValidationState_t& _, const Instruction* inst,
+ uint32_t starting_index = 2) {
const spv::Op opcode = inst->opcode();
const uint32_t result_type = inst->type_id();
if (!_.IsIntScalarType(result_type) && !_.IsIntVectorType(result_type) &&
@@ -67,8 +68,8 @@
<< spvOpcodeString(opcode);
const uint32_t result_dimension = _.GetDimension(result_type);
- const uint32_t base_type = _.GetOperandTypeId(inst, 2);
- const uint32_t shift_type = _.GetOperandTypeId(inst, 3);
+ const uint32_t base_type = _.GetOperandTypeId(inst, starting_index);
+ const uint32_t shift_type = _.GetOperandTypeId(inst, starting_index + 1);
if (!base_type ||
(!_.IsIntScalarType(base_type) && !_.IsIntVectorType(base_type) &&
@@ -101,7 +102,8 @@
return SPV_SUCCESS;
}
-spv_result_t ValidateBitwise(ValidationState_t& _, const Instruction* inst) {
+spv_result_t ValidateBitwise(ValidationState_t& _, const Instruction* inst,
+ uint32_t starting_index = 2) {
const spv::Op opcode = inst->opcode();
const uint32_t result_type = inst->type_id();
if (!_.IsIntScalarType(result_type) && !_.IsIntVectorType(result_type) &&
@@ -113,8 +115,8 @@
const uint32_t result_dimension = _.GetDimension(result_type);
const uint32_t result_bit_width = _.GetBitWidth(result_type);
- for (size_t operand_index = 2; operand_index < inst->operands().size();
- ++operand_index) {
+ for (size_t operand_index = starting_index;
+ operand_index < inst->operands().size(); ++operand_index) {
const uint32_t type_id = _.GetOperandTypeId(inst, operand_index);
if (!type_id ||
(!_.IsIntScalarType(type_id) && !_.IsIntVectorType(type_id) &&
@@ -245,6 +247,24 @@
return ValidateBitReverse(_, inst);
case spv::Op::OpBitCount:
return ValidateBitCount(_, inst);
+
+ case spv::Op::OpSpecConstantOp: {
+ switch (inst->GetOperandAs<spv::Op>(2u)) {
+ case spv::Op::OpShiftRightLogical:
+ case spv::Op::OpShiftRightArithmetic:
+ case spv::Op::OpShiftLeftLogical:
+ return ValidateShift(_, inst, 3);
+ case spv::Op::OpBitwiseOr:
+ case spv::Op::OpBitwiseXor:
+ case spv::Op::OpBitwiseAnd:
+ case spv::Op::OpNot:
+ return ValidateBitwise(_, inst, 3);
+ default:
+ break;
+ }
+ break;
+ }
+
default:
break;
}
diff --git a/test/val/val_constants_test.cpp b/test/val/val_constants_test.cpp
index 88750b9..b6b118a 100644
--- a/test/val/val_constants_test.cpp
+++ b/test/val/val_constants_test.cpp
@@ -584,6 +584,142 @@
"Expected float scalar or vector type as Result Type"),
BAD_KERNEL_OPERANDS("%v = OpSpecConstantOp %float ConvertUToF %float_0",
"Expected input to be int scalar or vector"),
+
+ BAD_KERNEL_OPERANDS(
+ "%v = OpSpecConstantOp %float UDiv %uint_0 %uint_0",
+ "Expected unsigned int scalar or vector type as Result Type"),
+ BAD_KERNEL_OPERANDS(
+ "%v = OpSpecConstantOp %uint UDiv %uint_0 %float_0",
+ "Expected arithmetic operands to be of Result Type"),
+
+ BAD_KERNEL_OPERANDS(
+ "%v = OpSpecConstantOp %float UMod %uint_0 %uint_0",
+ "Expected unsigned int scalar or vector type as Result Type"),
+ BAD_KERNEL_OPERANDS(
+ "%v = OpSpecConstantOp %uint UMod %uint_0 %float_0",
+ "Expected arithmetic operands to be of Result Type"),
+
+ BAD_KERNEL_OPERANDS(
+ "%v = OpSpecConstantOp %float ISub %uint_0 %uint_0",
+ "Expected int scalar or vector type as Result Type"),
+ BAD_KERNEL_OPERANDS("%v = OpSpecConstantOp %uint ISub %uint_0 %float_0",
+ "Expected int scalar or vector type as operand"),
+
+ BAD_KERNEL_OPERANDS(
+ "%v = OpSpecConstantOp %float IAdd %uint_0 %uint_0",
+ "Expected int scalar or vector type as Result Type"),
+ BAD_KERNEL_OPERANDS("%v = OpSpecConstantOp %uint IAdd %uint_0 %float_0",
+ "Expected int scalar or vector type as operand"),
+
+ BAD_KERNEL_OPERANDS(
+ "%v = OpSpecConstantOp %float IMul %uint_0 %uint_0",
+ "Expected int scalar or vector type as Result Type"),
+ BAD_KERNEL_OPERANDS("%v = OpSpecConstantOp %uint IMul %uint_0 %float_0",
+ "Expected int scalar or vector type as operand"),
+
+ BAD_KERNEL_OPERANDS(
+ "%v = OpSpecConstantOp %float SDiv %uint_0 %uint_0",
+ "Expected int scalar or vector type as Result Type"),
+ BAD_KERNEL_OPERANDS("%v = OpSpecConstantOp %uint SDiv %uint_0 %float_0",
+ "Expected int scalar or vector type as operand"),
+
+ BAD_KERNEL_OPERANDS(
+ "%v = OpSpecConstantOp %float SRem %uint_0 %uint_0",
+ "Expected int scalar or vector type as Result Type"),
+ BAD_KERNEL_OPERANDS("%v = OpSpecConstantOp %uint SRem %uint_0 %float_0",
+ "Expected int scalar or vector type as operand"),
+
+ BAD_KERNEL_OPERANDS(
+ "%v = OpSpecConstantOp %float SMod %uint_0 %uint_0",
+ "Expected int scalar or vector type as Result Type"),
+ BAD_KERNEL_OPERANDS("%v = OpSpecConstantOp %uint SMod %uint_0 %float_0",
+ "Expected int scalar or vector type as operand"),
+
+ BAD_KERNEL_OPERANDS(
+ "%v = OpSpecConstantOp %float SNegate %uint_0",
+ "Expected int scalar or vector type as Result Type"),
+ BAD_KERNEL_OPERANDS("%v = OpSpecConstantOp %uint SNegate %float_0",
+ "Expected int scalar or vector type as operand"),
+
+ BAD_KERNEL_OPERANDS(
+ "%v = OpSpecConstantOp %uint FAdd %float_0 %float_0",
+ "Expected floating scalar or vector type as Result Type"),
+ BAD_KERNEL_OPERANDS(
+ "%v = OpSpecConstantOp %float FAdd %float_0 %uint_0",
+ "Expected arithmetic operands to be of Result Type"),
+ BAD_KERNEL_OPERANDS(
+ "%v = OpSpecConstantOp %uint FSub %float_0 %float_0",
+ "Expected floating scalar or vector type as Result Type"),
+ BAD_KERNEL_OPERANDS(
+ "%v = OpSpecConstantOp %float FSub %float_0 %uint_0",
+ "Expected arithmetic operands to be of Result Type"),
+ BAD_KERNEL_OPERANDS(
+ "%v = OpSpecConstantOp %uint FMul %float_0 %float_0",
+ "Expected floating scalar or vector type as Result Type"),
+ BAD_KERNEL_OPERANDS(
+ "%v = OpSpecConstantOp %float FMul %float_0 %uint_0",
+ "Expected arithmetic operands to be of Result Type"),
+ BAD_KERNEL_OPERANDS(
+ "%v = OpSpecConstantOp %uint FDiv %float_0 %float_0",
+ "Expected floating scalar or vector type as Result Type"),
+ BAD_KERNEL_OPERANDS(
+ "%v = OpSpecConstantOp %float FDiv %float_0 %uint_0",
+ "Expected arithmetic operands to be of Result Type"),
+ BAD_KERNEL_OPERANDS(
+ "%v = OpSpecConstantOp %uint FRem %float_0 %float_0",
+ "Expected floating scalar or vector type as Result Type"),
+ BAD_KERNEL_OPERANDS(
+ "%v = OpSpecConstantOp %float FRem %float_0 %uint_0",
+ "Expected arithmetic operands to be of Result Type"),
+ BAD_KERNEL_OPERANDS(
+ "%v = OpSpecConstantOp %uint FMod %float_0 %float_0",
+ "Expected floating scalar or vector type as Result Type"),
+ BAD_KERNEL_OPERANDS(
+ "%v = OpSpecConstantOp %float FMod %float_0 %uint_0",
+ "Expected arithmetic operands to be of Result Type"),
+
+ BAD_KERNEL_OPERANDS(
+ "%v = OpSpecConstantOp %float ShiftRightLogical %uint_0 %uint_0",
+ "Expected int scalar or vector type as Result Type"),
+ BAD_KERNEL_OPERANDS(
+ "%v = OpSpecConstantOp %uint ShiftRightLogical %uint_0 %float_0",
+ "Expected Shift to be int scalar or vector"),
+ BAD_KERNEL_OPERANDS(
+ "%v = OpSpecConstantOp %float ShiftRightArithmetic %uint_0 %uint_0",
+ "Expected int scalar or vector type as Result Type"),
+ BAD_KERNEL_OPERANDS(
+ "%v = OpSpecConstantOp %uint ShiftRightArithmetic %uint_0 %float_0",
+ "Expected Shift to be int scalar or vector"),
+ BAD_KERNEL_OPERANDS(
+ "%v = OpSpecConstantOp %float ShiftLeftLogical %uint_0 %uint_0",
+ "Expected int scalar or vector type as Result Type"),
+ BAD_KERNEL_OPERANDS(
+ "%v = OpSpecConstantOp %uint ShiftLeftLogical %uint_0 %float_0",
+ "Expected Shift to be int scalar or vector"),
+
+ BAD_KERNEL_OPERANDS(
+ "%v = OpSpecConstantOp %float BitwiseOr %uint_0 %uint_0",
+ "Expected int scalar or vector type as Result Type"),
+ BAD_KERNEL_OPERANDS(
+ "%v = OpSpecConstantOp %uint BitwiseOr %uint_0 %float_0",
+ "Expected int scalar or vector as operand"),
+ BAD_KERNEL_OPERANDS(
+ "%v = OpSpecConstantOp %float BitwiseXor %uint_0 %uint_0",
+ "Expected int scalar or vector type as Result Type"),
+ BAD_KERNEL_OPERANDS(
+ "%v = OpSpecConstantOp %uint BitwiseXor %uint_0 %float_0",
+ "Expected int scalar or vector as operand"),
+ BAD_KERNEL_OPERANDS(
+ "%v = OpSpecConstantOp %float BitwiseAnd %uint_0 %uint_0",
+ "Expected int scalar or vector type as Result Type"),
+ BAD_KERNEL_OPERANDS(
+ "%v = OpSpecConstantOp %uint BitwiseAnd %uint_0 %float_0",
+ "Expected int scalar or vector as operand"),
+ BAD_KERNEL_OPERANDS(
+ "%v = OpSpecConstantOp %float Not %uint_0",
+ "Expected int scalar or vector type as Result Type"),
+ BAD_KERNEL_OPERANDS("%v = OpSpecConstantOp %uint Not %float_0",
+ "Expected int scalar or vector as operand"),
}));
} // namespace