Initial support for SPV_KHR_integer_dot_product (#4327)

* Initial support for SPV_KHR_integer_dot_product

- Adds new operand types for packed-vector-format
- Moves ray tracing enums to the end

- PackedVectorFormat is a new optional operand type, so it requires
  special handling in grammar table generation.

- Add SPV_KHR_integer_dot_product to optimizer whitelists.

- Pass-through validation: valid cases pass validation
  Validation errors are not checked.

- Update SPIRV-Headers

Patch by David Neto <dneto@google.com>
Rebase and minor tweaks by Kevin Petit <kevin.petit@arm.com>

Signed-off-by: David Neto <dneto@google.com>
Signed-off-by: Kevin Petit <kevin.petit@arm.com>
Change-Id: Icb41741cb7f0f1063e5541ce25e5ba6c02266d2c

* format fixes

Change-Id: I35c82ec27bded3d1b62373fa6daec3ffd91105a3
This commit is contained in:
Kévin Petit 2021-06-23 18:32:24 +01:00 committed by GitHub
parent e992c96c89
commit e065c482c6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 1453 additions and 17 deletions

2
DEPS
View File

@ -6,7 +6,7 @@ vars = {
'effcee_revision': '2ec8f8738118cc483b67c04a759fee53496c5659', 'effcee_revision': '2ec8f8738118cc483b67c04a759fee53496c5659',
'googletest_revision': 'b7d472f1225c5a64943821d8483fecb469d3f382', 'googletest_revision': 'b7d472f1225c5a64943821d8483fecb469d3f382',
're2_revision': 'f8e389f3acdc2517562924239e2a188037393683', 're2_revision': 'f8e389f3acdc2517562924239e2a188037393683',
'spirv_headers_revision': '07f259e68af3a540038fa32df522554e74f53ed5', 'spirv_headers_revision': 'f95c3b3761ee1b1903f54ae69b526ed6f0edc3b9',
} }
deps = { deps = {

View File

@ -113,6 +113,9 @@ typedef enum spv_endianness_t {
// Sometimes we also need to be able to express the fact that an operand // Sometimes we also need to be able to express the fact that an operand
// is a member of an optional tuple of values. In that case the first member // is a member of an optional tuple of values. In that case the first member
// would be optional, and the subsequent members would be required. // would be optional, and the subsequent members would be required.
//
// NOTE: Although we don't promise binary compatibility, as a courtesy, please
// add new enum values at the end.
typedef enum spv_operand_type_t { typedef enum spv_operand_type_t {
// A sentinel value. // A sentinel value.
SPV_OPERAND_TYPE_NONE = 0, SPV_OPERAND_TYPE_NONE = 0,
@ -167,12 +170,8 @@ typedef enum spv_operand_type_t {
SPV_OPERAND_TYPE_KERNEL_ENQ_FLAGS, // SPIR-V Sec 3.29 SPV_OPERAND_TYPE_KERNEL_ENQ_FLAGS, // SPIR-V Sec 3.29
SPV_OPERAND_TYPE_KERNEL_PROFILING_INFO, // SPIR-V Sec 3.30 SPV_OPERAND_TYPE_KERNEL_PROFILING_INFO, // SPIR-V Sec 3.30
SPV_OPERAND_TYPE_CAPABILITY, // SPIR-V Sec 3.31 SPV_OPERAND_TYPE_CAPABILITY, // SPIR-V Sec 3.31
SPV_OPERAND_TYPE_RAY_FLAGS, // SPIR-V Sec 3.RF
SPV_OPERAND_TYPE_RAY_QUERY_INTERSECTION, // SPIR-V Sec 3.RQIntersection // NOTE: New concrete enum values should be added at the end.
SPV_OPERAND_TYPE_RAY_QUERY_COMMITTED_INTERSECTION_TYPE, // SPIR-V Sec
// 3.RQCommitted
SPV_OPERAND_TYPE_RAY_QUERY_CANDIDATE_INTERSECTION_TYPE, // SPIR-V Sec
// 3.RQCandidate
// Set 5: Operands that are a single word bitmask. // Set 5: Operands that are a single word bitmask.
// Sometimes a set bit indicates the instruction requires still more operands. // Sometimes a set bit indicates the instruction requires still more operands.
@ -184,7 +183,10 @@ typedef enum spv_operand_type_t {
SPV_OPERAND_TYPE_MEMORY_ACCESS, // SPIR-V Sec 3.26 SPV_OPERAND_TYPE_MEMORY_ACCESS, // SPIR-V Sec 3.26
SPV_OPERAND_TYPE_FRAGMENT_SHADING_RATE, // SPIR-V Sec 3.FSR SPV_OPERAND_TYPE_FRAGMENT_SHADING_RATE, // SPIR-V Sec 3.FSR
// The remaining operand types are only used internally by the assembler. // NOTE: New concrete enum values should be added at the end.
// The "optional" and "variable" operand types are only used internally by
// the assembler and the binary parser.
// There are two categories: // There are two categories:
// Optional : expands to 0 or 1 operand, like ? in regular expressions. // Optional : expands to 0 or 1 operand, like ? in regular expressions.
// Variable : expands to 0, 1 or many operands or pairs of operands. // Variable : expands to 0, 1 or many operands or pairs of operands.
@ -269,6 +271,20 @@ typedef enum spv_operand_type_t {
// A value enum from https://github.com/KhronosGroup/SPIRV-Headers/pull/177 // A value enum from https://github.com/KhronosGroup/SPIRV-Headers/pull/177
SPV_OPERAND_TYPE_OVERFLOW_MODES, SPV_OPERAND_TYPE_OVERFLOW_MODES,
// Concrete operand types for the provisional Vulkan ray tracing feature.
SPV_OPERAND_TYPE_RAY_FLAGS, // SPIR-V Sec 3.RF
SPV_OPERAND_TYPE_RAY_QUERY_INTERSECTION, // SPIR-V Sec 3.RQIntersection
SPV_OPERAND_TYPE_RAY_QUERY_COMMITTED_INTERSECTION_TYPE, // SPIR-V Sec
// 3.RQCommitted
SPV_OPERAND_TYPE_RAY_QUERY_CANDIDATE_INTERSECTION_TYPE, // SPIR-V Sec
// 3.RQCandidate
// Concrete operand types for integer dot product.
// Packed vector format
SPV_OPERAND_TYPE_PACKED_VECTOR_FORMAT, // SPIR-V Sec 3.x
// An optional packed vector format
SPV_OPERAND_TYPE_OPTIONAL_PACKED_VECTOR_FORMAT,
// This is a sentinel value, and does not represent an operand type. // This is a sentinel value, and does not represent an operand type.
// It should come last. // It should come last.
SPV_OPERAND_TYPE_NUM_OPERAND_TYPES, SPV_OPERAND_TYPE_NUM_OPERAND_TYPES,

View File

@ -659,12 +659,16 @@ spv_result_t Parser::parseOperand(size_t inst_offset,
case SPV_OPERAND_TYPE_FPDENORM_MODE: case SPV_OPERAND_TYPE_FPDENORM_MODE:
case SPV_OPERAND_TYPE_FPOPERATION_MODE: case SPV_OPERAND_TYPE_FPOPERATION_MODE:
case SPV_OPERAND_TYPE_QUANTIZATION_MODES: case SPV_OPERAND_TYPE_QUANTIZATION_MODES:
case SPV_OPERAND_TYPE_OVERFLOW_MODES: { case SPV_OPERAND_TYPE_OVERFLOW_MODES:
case SPV_OPERAND_TYPE_PACKED_VECTOR_FORMAT:
case SPV_OPERAND_TYPE_OPTIONAL_PACKED_VECTOR_FORMAT: {
// A single word that is a plain enum value. // A single word that is a plain enum value.
// Map an optional operand type to its corresponding concrete type. // Map an optional operand type to its corresponding concrete type.
if (type == SPV_OPERAND_TYPE_OPTIONAL_ACCESS_QUALIFIER) if (type == SPV_OPERAND_TYPE_OPTIONAL_ACCESS_QUALIFIER)
parsed_operand.type = SPV_OPERAND_TYPE_ACCESS_QUALIFIER; parsed_operand.type = SPV_OPERAND_TYPE_ACCESS_QUALIFIER;
if (type == SPV_OPERAND_TYPE_OPTIONAL_PACKED_VECTOR_FORMAT)
parsed_operand.type = SPV_OPERAND_TYPE_PACKED_VECTOR_FORMAT;
spv_operand_desc entry; spv_operand_desc entry;
if (grammar_.lookupOperand(type, word, &entry)) { if (grammar_.lookupOperand(type, word, &entry)) {

View File

@ -347,7 +347,17 @@ void Disassembler::EmitOperand(const spv_parsed_instruction_t& inst,
EmitMaskOperand(operand.type, word); EmitMaskOperand(operand.type, word);
break; break;
default: default:
assert(false && "unhandled or invalid case"); if (spvOperandIsConcreteMask(operand.type)) {
EmitMaskOperand(operand.type, word);
} else if (spvOperandIsConcrete(operand.type)) {
spv_operand_desc entry;
if (grammar_.lookupOperand(operand.type, word, &entry))
assert(false && "should have caught this earlier");
stream_ << entry->name;
} else {
assert(false && "unhandled or invalid case");
}
break;
} }
ResetColor(); ResetColor();
} }

View File

@ -229,6 +229,9 @@ const char* spvOperandTypeStr(spv_operand_type_t type) {
return "ray query committed intersection type"; return "ray query committed intersection type";
case SPV_OPERAND_TYPE_RAY_QUERY_CANDIDATE_INTERSECTION_TYPE: case SPV_OPERAND_TYPE_RAY_QUERY_CANDIDATE_INTERSECTION_TYPE:
return "ray query candidate intersection type"; return "ray query candidate intersection type";
case SPV_OPERAND_TYPE_PACKED_VECTOR_FORMAT:
case SPV_OPERAND_TYPE_OPTIONAL_PACKED_VECTOR_FORMAT:
return "packed vector format";
case SPV_OPERAND_TYPE_IMAGE: case SPV_OPERAND_TYPE_IMAGE:
case SPV_OPERAND_TYPE_OPTIONAL_IMAGE: case SPV_OPERAND_TYPE_OPTIONAL_IMAGE:
return "image"; return "image";
@ -361,6 +364,7 @@ bool spvOperandIsConcrete(spv_operand_type_t type) {
case SPV_OPERAND_TYPE_FPOPERATION_MODE: case SPV_OPERAND_TYPE_FPOPERATION_MODE:
case SPV_OPERAND_TYPE_QUANTIZATION_MODES: case SPV_OPERAND_TYPE_QUANTIZATION_MODES:
case SPV_OPERAND_TYPE_OVERFLOW_MODES: case SPV_OPERAND_TYPE_OVERFLOW_MODES:
case SPV_OPERAND_TYPE_PACKED_VECTOR_FORMAT:
return true; return true;
default: default:
break; break;
@ -396,6 +400,7 @@ bool spvOperandIsOptional(spv_operand_type_t type) {
case SPV_OPERAND_TYPE_OPTIONAL_TYPED_LITERAL_INTEGER: case SPV_OPERAND_TYPE_OPTIONAL_TYPED_LITERAL_INTEGER:
case SPV_OPERAND_TYPE_OPTIONAL_LITERAL_STRING: case SPV_OPERAND_TYPE_OPTIONAL_LITERAL_STRING:
case SPV_OPERAND_TYPE_OPTIONAL_ACCESS_QUALIFIER: case SPV_OPERAND_TYPE_OPTIONAL_ACCESS_QUALIFIER:
case SPV_OPERAND_TYPE_OPTIONAL_PACKED_VECTOR_FORMAT:
case SPV_OPERAND_TYPE_OPTIONAL_CIV: case SPV_OPERAND_TYPE_OPTIONAL_CIV:
return true; return true;
default: default:

View File

@ -998,6 +998,7 @@ void AggressiveDCEPass::InitExtensions() {
"SPV_KHR_shader_clock", "SPV_KHR_shader_clock",
"SPV_KHR_vulkan_memory_model", "SPV_KHR_vulkan_memory_model",
"SPV_KHR_subgroup_uniform_control_flow", "SPV_KHR_subgroup_uniform_control_flow",
"SPV_KHR_integer_dot_product",
}); });
} }

View File

@ -419,6 +419,7 @@ void LocalAccessChainConvertPass::InitExtensions() {
"SPV_EXT_fragment_invocation_density", "SPV_EXT_fragment_invocation_density",
"SPV_KHR_terminate_invocation", "SPV_KHR_terminate_invocation",
"SPV_KHR_subgroup_uniform_control_flow", "SPV_KHR_subgroup_uniform_control_flow",
"SPV_KHR_integer_dot_product",
}); });
} }

View File

@ -271,6 +271,7 @@ void LocalSingleBlockLoadStoreElimPass::InitExtensions() {
"SPV_EXT_physical_storage_buffer", "SPV_EXT_physical_storage_buffer",
"SPV_KHR_terminate_invocation", "SPV_KHR_terminate_invocation",
"SPV_KHR_subgroup_uniform_control_flow", "SPV_KHR_subgroup_uniform_control_flow",
"SPV_KHR_integer_dot_product",
}); });
} }

View File

@ -124,6 +124,7 @@ void LocalSingleStoreElimPass::InitExtensionAllowList() {
"SPV_EXT_physical_storage_buffer", "SPV_EXT_physical_storage_buffer",
"SPV_KHR_terminate_invocation", "SPV_KHR_terminate_invocation",
"SPV_KHR_subgroup_uniform_control_flow", "SPV_KHR_subgroup_uniform_control_flow",
"SPV_KHR_integer_dot_product",
}); });
} }
bool LocalSingleStoreElimPass::ProcessVariable(Instruction* var_inst) { bool LocalSingleStoreElimPass::ProcessVariable(Instruction* var_inst) {

View File

@ -952,5 +952,71 @@ INSTANTIATE_TEST_SUITE_P(
{1, SpvExecutionModeSubgroupUniformControlFlowKHR})}, {1, SpvExecutionModeSubgroupUniformControlFlowKHR})},
}))); })));
// SPV_KHR_integer_dot_product
INSTANTIATE_TEST_SUITE_P(
SPV_KHR_integer_dot_product, ExtensionRoundTripTest,
Combine(
Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_5, SPV_ENV_VULKAN_1_0,
SPV_ENV_VULKAN_1_1, SPV_ENV_VULKAN_1_2),
ValuesIn(std::vector<AssemblyCase>{
{"OpExtension \"SPV_KHR_integer_dot_product\"\n",
MakeInstruction(SpvOpExtension,
MakeVector("SPV_KHR_integer_dot_product"))},
{"OpCapability DotProductInputAllKHR\n",
MakeInstruction(SpvOpCapability,
{SpvCapabilityDotProductInputAllKHR})},
{"OpCapability DotProductInput4x8BitKHR\n",
MakeInstruction(SpvOpCapability,
{SpvCapabilityDotProductInput4x8BitKHR})},
{"OpCapability DotProductInput4x8BitPackedKHR\n",
MakeInstruction(SpvOpCapability,
{SpvCapabilityDotProductInput4x8BitPackedKHR})},
{"OpCapability DotProductKHR\n",
MakeInstruction(SpvOpCapability, {SpvCapabilityDotProductKHR})},
{"%2 = OpSDotKHR %1 %3 %4\n",
MakeInstruction(SpvOpSDotKHR, {1, 2, 3, 4})},
{"%2 = OpSDotKHR %1 %3 %4 PackedVectorFormat4x8BitKHR\n",
MakeInstruction(
SpvOpSDotKHR,
{1, 2, 3, 4,
SpvPackedVectorFormatPackedVectorFormat4x8BitKHR})},
{"%2 = OpUDotKHR %1 %3 %4\n",
MakeInstruction(SpvOpUDotKHR, {1, 2, 3, 4})},
{"%2 = OpUDotKHR %1 %3 %4 PackedVectorFormat4x8BitKHR\n",
MakeInstruction(
SpvOpUDotKHR,
{1, 2, 3, 4,
SpvPackedVectorFormatPackedVectorFormat4x8BitKHR})},
{"%2 = OpSUDotKHR %1 %3 %4\n",
MakeInstruction(SpvOpSUDotKHR, {1, 2, 3, 4})},
{"%2 = OpSUDotKHR %1 %3 %4 PackedVectorFormat4x8BitKHR\n",
MakeInstruction(
SpvOpSUDotKHR,
{1, 2, 3, 4,
SpvPackedVectorFormatPackedVectorFormat4x8BitKHR})},
{"%2 = OpSDotAccSatKHR %1 %3 %4 %5\n",
MakeInstruction(SpvOpSDotAccSatKHR, {1, 2, 3, 4, 5})},
{"%2 = OpSDotAccSatKHR %1 %3 %4 %5 PackedVectorFormat4x8BitKHR\n",
MakeInstruction(
SpvOpSDotAccSatKHR,
{1, 2, 3, 4, 5,
SpvPackedVectorFormatPackedVectorFormat4x8BitKHR})},
{"%2 = OpUDotAccSatKHR %1 %3 %4 %5\n",
MakeInstruction(SpvOpUDotAccSatKHR, {1, 2, 3, 4, 5})},
{"%2 = OpUDotAccSatKHR %1 %3 %4 %5 PackedVectorFormat4x8BitKHR\n",
MakeInstruction(
SpvOpUDotAccSatKHR,
{1, 2, 3, 4, 5,
SpvPackedVectorFormatPackedVectorFormat4x8BitKHR})},
{"%2 = OpSUDotAccSatKHR %1 %3 %4 %5\n",
MakeInstruction(SpvOpSUDotAccSatKHR, {1, 2, 3, 4, 5})},
{"%2 = OpSUDotAccSatKHR %1 %3 %4 %5 PackedVectorFormat4x8BitKHR\n",
MakeInstruction(
SpvOpSUDotAccSatKHR,
{1, 2, 3, 4, 5,
SpvPackedVectorFormatPackedVectorFormat4x8BitKHR})},
})));
} // namespace } // namespace
} // namespace spvtools } // namespace spvtools

View File

@ -41,6 +41,7 @@ add_spvtools_unittest(TARGET val_abcde
val_extension_spv_khr_expect_assume.cpp val_extension_spv_khr_expect_assume.cpp
val_extension_spv_khr_linkonce_odr.cpp val_extension_spv_khr_linkonce_odr.cpp
val_extension_spv_khr_subgroup_uniform_control_flow.cpp val_extension_spv_khr_subgroup_uniform_control_flow.cpp
val_extension_spv_khr_integer_dot_product.cpp
val_extension_spv_khr_terminate_invocation.cpp val_extension_spv_khr_terminate_invocation.cpp
val_ext_inst_test.cpp val_ext_inst_test.cpp
${VAL_TEST_COMMON_SRCS} ${VAL_TEST_COMMON_SRCS}

File diff suppressed because it is too large Load Diff

View File

@ -523,17 +523,17 @@ def generate_operand_kind_table(enums):
enums = [generate_enum_operand_kind(e, exts) for e in enums] enums = [generate_enum_operand_kind(e, exts) for e in enums]
exts_arrays = generate_extension_arrays(exts) exts_arrays = generate_extension_arrays(exts)
# We have three operand kinds that requires their optional counterpart to # We have a few operand kinds that require their optional counterpart to
# exist in the operand info table. # exist in the operand info table.
three_optional_enums = ['ImageOperands', 'AccessQualifier', 'MemoryAccess'] optional_enums = ['ImageOperands', 'AccessQualifier', 'MemoryAccess', 'PackedVectorFormat']
three_optional_enums = [e for e in enums if e[0] in three_optional_enums] optional_enums = [e for e in enums if e[0] in optional_enums]
enums.extend(three_optional_enums) enums.extend(optional_enums)
enum_kinds, enum_names, enum_entries = zip(*enums) enum_kinds, enum_names, enum_entries = zip(*enums)
# Mark the last three as optional ones. # Mark the last few as optional ones.
enum_quantifiers = [''] * (len(enums) - 3) + ['?'] * 3 enum_quantifiers = [''] * (len(enums) - len(optional_enums)) + ['?'] * len(optional_enums)
# And we don't want redefinition of them. # And we don't want redefinition of them.
enum_entries = enum_entries[:-3] enum_entries = enum_entries[:-len(optional_enums)]
enum_kinds = [convert_operand_kind(e) enum_kinds = [convert_operand_kind(e)
for e in zip(enum_kinds, enum_quantifiers)] for e in zip(enum_kinds, enum_quantifiers)]
table_entries = zip(enum_kinds, enum_names, enum_names) table_entries = zip(enum_kinds, enum_names, enum_names)