spirv-val: Add validation for 4-bit integer types (#6644)
Allow 4-bit integers with Int4TypeINTEL
Required for test in LLVM tree:
https://github.com/llvm/llvm-project/blob/6b0d268fe544b25fd1f82aad4e246f8a74e260ed/llvm/test/CodeGen/SPIRV/legalization/icmp_extended_int.ll
Extension ref:
https://github.com/KhronosGroup/SPIRV-Registry/blob/main/extensions/INTEL/SPV_INTEL_int4.asciidoc
diff --git a/source/val/validate_type.cpp b/source/val/validate_type.cpp
index 9ed0eab..ce8fc75 100644
--- a/source/val/validate_type.cpp
+++ b/source/val/validate_type.cpp
@@ -60,7 +60,15 @@
// integers, respectively.
auto num_bits = inst->GetOperandAs<const uint32_t>(1);
if (num_bits != 32) {
- if (num_bits == 8) {
+ if (num_bits == 4) {
+ if (_.HasCapability(spv::Capability::Int4TypeINTEL) ||
+ _.HasCapability(spv::Capability::ArbitraryPrecisionIntegersINTEL)) {
+ return SPV_SUCCESS;
+ }
+ return _.diag(SPV_ERROR_INVALID_DATA, inst)
+ << "Using a 4-bit integer type requires the Int4TypeINTEL "
+ "or ArbitraryPrecisionIntegersINTEL capability.";
+ } else if (num_bits == 8) {
if (_.features().declare_int8_type) {
return SPV_SUCCESS;
}
diff --git a/test/val/val_data_test.cpp b/test/val/val_data_test.cpp
index 5b3e543..210e1d1 100644
--- a/test/val/val_data_test.cpp
+++ b/test/val/val_data_test.cpp
@@ -143,6 +143,9 @@
std::string missing_cap_error =
"requires the Vector16 or LongVectorEXT capability";
std::string missing_int8_cap_error = "requires the Int8 capability";
+std::string missing_int4_cap_error =
+ "Using a 4-bit integer type requires the Int4TypeINTEL "
+ "or ArbitraryPrecisionIntegersINTEL capability.";
std::string missing_int16_cap_error =
"requires the Int16 capability,"
" or an extension that explicitly enables 16-bit integers.";
@@ -298,6 +301,33 @@
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()) << getDiagnosticString();
}
+TEST_F(ValidateData, int4_bad) {
+ std::string str = header + "%2 = OpTypeInt 4 0";
+ CompileSuccessfully(str.c_str());
+ ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
+ EXPECT_THAT(getDiagnosticString(), HasSubstr(missing_int4_cap_error));
+}
+
+TEST_F(ValidateData, int4_with_arbitrary_precision_good) {
+ std::string str =
+ HeaderWith(
+ "ArbitraryPrecisionIntegersINTEL "
+ "OpExtension \"SPV_INTEL_arbitrary_precision_integers\"") +
+ " %2 = OpTypeInt 4 0";
+ CompileSuccessfully(str.c_str());
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()) << getDiagnosticString();
+}
+
+TEST_F(ValidateData, int4_signed_with_arbitrary_precision_good) {
+ std::string str =
+ HeaderWith(
+ "ArbitraryPrecisionIntegersINTEL "
+ "OpExtension \"SPV_INTEL_arbitrary_precision_integers\"") +
+ " %2 = OpTypeInt 4 1";
+ CompileSuccessfully(str.c_str());
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()) << getDiagnosticString();
+}
+
TEST_F(ValidateData, int16_good) {
std::string str = header_with_int16 + "%2 = OpTypeInt 16 1";
CompileSuccessfully(str.c_str());