[clang-tidy][NFC]remove deps of clang in clang tidy test (#116588)
[llvm-project.git] / mlir / test / Dialect / SPIRV / IR / target-env.mlir
blob273aa33e15eae2103413ade824063e2f127cfecf
1 // RUN: mlir-opt --split-input-file --verify-diagnostics --mlir-disable-threading \
2 // RUN:   --test-spirv-target-env %s | FileCheck %s
4 // Note: The following tests check that a spirv.target_env can properly control
5 // the conversion target and filter unavailable ops during the conversion.
6 // We don't care about the op argument consistency too much; so certain enum
7 // values for enum attributes may not make much sense for the test op.
9 // spirv.AtomicCompareExchangeWeak is available from SPIR-V 1.0 to 1.3 under
10 // Kernel capability.
11 // spirv.AtomicCompareExchangeWeak has two memory semantics enum attribute,
12 // whose value, if containing AtomicCounterMemory bit, additionally requires
13 // AtomicStorage capability.
15 // spirv.BitReverse is available in all SPIR-V versions under Shader capability.
17 // spirv.GroupNonUniformBallot is available starting from SPIR-V 1.3 under
18 // GroupNonUniform capability.
20 // spirv.KHR.SubgroupBallot is available under in all SPIR-V versions under
21 // SubgroupBallotKHR capability and SPV_KHR_shader_ballot extension.
23 // Integer Dot Product ops (spirv.*Dot*) require the
24 // SPV_KHR_integer_dot_product extension and a number of related capabilities.
26 // The GeometryPointSize capability implies the Geometry capability, which
27 // implies the Shader capability.
29 // PhysicalStorageBuffer64 addressing model is available via extension
30 // SPV_EXT_physical_storage_buffer or SPV_KHR_physical_storage_buffer;
31 // both extensions are incorporated into SPIR-V 1.5.
33 // Vulkan memory model is available via extension SPV_KHR_vulkan_memory_model,
34 // which extensions are incorporated into SPIR-V 1.5.
37 // expected-error @+1 {{missing 'spirv.target_env' attribute}}
38 func.func @main() {
39   return
42 // -----
44 //===----------------------------------------------------------------------===//
45 // MaxVersion
46 //===----------------------------------------------------------------------===//
48 // CHECK-LABEL: @cmp_exchange_weak_suitable_version_capabilities
49 func.func @cmp_exchange_weak_suitable_version_capabilities(%ptr: !spirv.ptr<i32, Workgroup>, %value: i32, %comparator: i32) -> i32 attributes {
50   spirv.target_env = #spirv.target_env<#spirv.vce<v1.1, [Kernel, AtomicStorage], []>, #spirv.resource_limits<>>
51 } {
52   // CHECK: spirv.AtomicCompareExchangeWeak <Workgroup> <AcquireRelease|AtomicCounterMemory> <Acquire>
53   %0 = "test.convert_to_atomic_compare_exchange_weak_op"(%ptr, %value, %comparator): (!spirv.ptr<i32, Workgroup>, i32, i32) -> (i32)
54   return %0: i32
57 // CHECK-LABEL: @cmp_exchange_weak_unsupported_version
58 func.func @cmp_exchange_weak_unsupported_version(%ptr: !spirv.ptr<i32, Workgroup>, %value: i32, %comparator: i32) -> i32 attributes {
59   spirv.target_env = #spirv.target_env<#spirv.vce<v1.4, [Kernel, AtomicStorage], []>, #spirv.resource_limits<>>
60 } {
61   // CHECK: test.convert_to_atomic_compare_exchange_weak_op
62   %0 = "test.convert_to_atomic_compare_exchange_weak_op"(%ptr, %value, %comparator): (!spirv.ptr<i32, Workgroup>, i32, i32) -> (i32)
63   return %0: i32
66 //===----------------------------------------------------------------------===//
67 // MinVersion
68 //===----------------------------------------------------------------------===//
70 // CHECK-LABEL: @group_non_uniform_ballot_suitable_version
71 func.func @group_non_uniform_ballot_suitable_version(%predicate: i1) -> vector<4xi32> attributes {
72   spirv.target_env = #spirv.target_env<#spirv.vce<v1.4, [GroupNonUniformBallot], []>, #spirv.resource_limits<>>
73 } {
74   // CHECK: spirv.GroupNonUniformBallot <Workgroup>
75   %0 = "test.convert_to_group_non_uniform_ballot_op"(%predicate): (i1) -> (vector<4xi32>)
76   return %0: vector<4xi32>
79 // CHECK-LABEL: @group_non_uniform_ballot_unsupported_version
80 func.func @group_non_uniform_ballot_unsupported_version(%predicate: i1) -> vector<4xi32> attributes {
81   spirv.target_env = #spirv.target_env<#spirv.vce<v1.1, [GroupNonUniformBallot], []>, #spirv.resource_limits<>>
82 } {
83   // CHECK: test.convert_to_group_non_uniform_ballot_op
84   %0 = "test.convert_to_group_non_uniform_ballot_op"(%predicate): (i1) -> (vector<4xi32>)
85   return %0: vector<4xi32>
88 //===----------------------------------------------------------------------===//
89 // Capability
90 //===----------------------------------------------------------------------===//
92 // CHECK-LABEL: @cmp_exchange_weak_missing_capability_kernel
93 func.func @cmp_exchange_weak_missing_capability_kernel(%ptr: !spirv.ptr<i32, Workgroup>, %value: i32, %comparator: i32) -> i32 attributes {
94   spirv.target_env = #spirv.target_env<#spirv.vce<v1.3, [AtomicStorage], []>, #spirv.resource_limits<>>
95 } {
96   // CHECK: test.convert_to_atomic_compare_exchange_weak_op
97   %0 = "test.convert_to_atomic_compare_exchange_weak_op"(%ptr, %value, %comparator): (!spirv.ptr<i32, Workgroup>, i32, i32) -> (i32)
98   return %0: i32
101 // CHECK-LABEL: @cmp_exchange_weak_missing_capability_atomic_storage
102 func.func @cmp_exchange_weak_missing_capability_atomic_storage(%ptr: !spirv.ptr<i32, Workgroup>, %value: i32, %comparator: i32) -> i32 attributes {
103   spirv.target_env = #spirv.target_env<#spirv.vce<v1.3, [Kernel], []>, #spirv.resource_limits<>>
104 } {
105   // CHECK: test.convert_to_atomic_compare_exchange_weak_op
106   %0 = "test.convert_to_atomic_compare_exchange_weak_op"(%ptr, %value, %comparator): (!spirv.ptr<i32, Workgroup>, i32, i32) -> (i32)
107   return %0: i32
110 // CHECK-LABEL: @subgroup_ballot_missing_capability
111 func.func @subgroup_ballot_missing_capability(%predicate: i1) -> vector<4xi32> attributes {
112   spirv.target_env = #spirv.target_env<#spirv.vce<v1.4, [], [SPV_KHR_shader_ballot]>, #spirv.resource_limits<>>
113 } {
114   // CHECK: test.convert_to_subgroup_ballot_op
115   %0 = "test.convert_to_subgroup_ballot_op"(%predicate): (i1) -> (vector<4xi32>)
116   return %0: vector<4xi32>
119 // CHECK-LABEL: @bit_reverse_directly_implied_capability
120 func.func @bit_reverse_directly_implied_capability(%operand: i32) -> i32 attributes {
121   spirv.target_env = #spirv.target_env<#spirv.vce<v1.0, [Geometry], []>, #spirv.resource_limits<>>
122 } {
123   // CHECK: spirv.BitReverse
124   %0 = "test.convert_to_bit_reverse_op"(%operand): (i32) -> (i32)
125   return %0: i32
128 // CHECK-LABEL: @bit_reverse_recursively_implied_capability
129 func.func @bit_reverse_recursively_implied_capability(%operand: i32) -> i32 attributes {
130   spirv.target_env = #spirv.target_env<#spirv.vce<v1.0, [GeometryPointSize], []>, #spirv.resource_limits<>>
131 } {
132   // CHECK: spirv.BitReverse
133   %0 = "test.convert_to_bit_reverse_op"(%operand): (i32) -> (i32)
134   return %0: i32
137 // CHECK-LABEL: @sdot_scalar_i32_i32_capabilities
138 func.func @sdot_scalar_i32_i32_capabilities(%operand: i32) -> i32 attributes {
139   spirv.target_env = #spirv.target_env<#spirv.vce<v1.0,
140     [DotProduct, DotProductInput4x8BitPacked], [SPV_KHR_integer_dot_product]>, #spirv.resource_limits<>>
141 } {
142   // CHECK: spirv.SDot
143   %0 = "test.convert_to_sdot_op"(%operand, %operand) {format = #spirv.packed_vector_format<PackedVectorFormat4x8Bit>}: (i32, i32) -> (i32)
144   return %0: i32
147 // CHECK-LABEL: @sdot_scalar_i32_i32_missing_capability1
148 func.func @sdot_scalar_i32_i32_missing_capability1(%operand: i32) -> i32 attributes {
149   spirv.target_env = #spirv.target_env<#spirv.vce<v1.0,
150     [DotProduct], [SPV_KHR_integer_dot_product]>, #spirv.resource_limits<>>
151 } {
152   // CHECK: test.convert_to_sdot_op
153   %0 = "test.convert_to_sdot_op"(%operand, %operand) {format = #spirv.packed_vector_format<PackedVectorFormat4x8Bit>}: (i32, i32) -> (i32)
154   return %0: i32
157 // CHECK-LABEL: @sdot_scalar_i32_i32_missing_capability2
158 func.func @sdot_scalar_i32_i32_missing_capability2(%operand: i32) -> i32 attributes {
159   spirv.target_env = #spirv.target_env<#spirv.vce<v1.0,
160     [DotProductInput4x8BitPacked], [SPV_KHR_integer_dot_product]>, #spirv.resource_limits<>>
161 } {
162   // CHECK: test.convert_to_sdot_op
163   %0 = "test.convert_to_sdot_op"(%operand, %operand) {format = #spirv.packed_vector_format<PackedVectorFormat4x8Bit>}: (i32, i32) -> (i32)
164   return %0: i32
167 // CHECK-LABEL: @sudot_vector_4xi8_i32_capabilities
168 func.func @sudot_vector_4xi8_i32_capabilities(%operand: vector<4xi8>) -> i32 attributes {
169   spirv.target_env = #spirv.target_env<#spirv.vce<v1.0,
170     [DotProduct, DotProductInput4x8Bit], [SPV_KHR_integer_dot_product]>, #spirv.resource_limits<>>
171 } {
172   // CHECK: spirv.SUDot
173   %0 = "test.convert_to_sudot_op"(%operand, %operand): (vector<4xi8>, vector<4xi8>) -> (i32)
174   return %0: i32
177 // CHECK-LABEL: @sudot_vector_4xi8_i32_missing_capability1
178 func.func @sudot_vector_4xi8_i32_missing_capability1(%operand: vector<4xi8>) -> i32 attributes {
179   spirv.target_env = #spirv.target_env<#spirv.vce<v1.0,
180     [DotProduct], [SPV_KHR_integer_dot_product]>, #spirv.resource_limits<>>
181 } {
182   // CHECK: test.convert_to_sudot_op
183   %0 = "test.convert_to_sudot_op"(%operand, %operand): (vector<4xi8>, vector<4xi8>) -> (i32)
184   return %0: i32
187 // CHECK-LABEL: @sudot_vector_4xi8_i32_missing_capability2
188 func.func @sudot_vector_4xi8_i32_missing_capability2(%operand: vector<4xi8>) -> i32 attributes {
189   spirv.target_env = #spirv.target_env<#spirv.vce<v1.0,
190     [DotProductInput4x8Bit], [SPV_KHR_integer_dot_product]>, #spirv.resource_limits<>>
191 } {
192   // CHECK: test.convert_to_sudot_op
193   %0 = "test.convert_to_sudot_op"(%operand, %operand): (vector<4xi8>, vector<4xi8>) -> (i32)
194   return %0: i32
197 // CHECK-LABEL: @udot_vector_4xi16_i64_capabilities
198 func.func @udot_vector_4xi16_i64_capabilities(%operand: vector<4xi16>) -> i64 attributes {
199   spirv.target_env = #spirv.target_env<#spirv.vce<v1.0,
200     [DotProduct, DotProductInputAll, Int16, Int64], [SPV_KHR_integer_dot_product]>, #spirv.resource_limits<>>
201 } {
202   // CHECK: spirv.UDot
203   %0 = "test.convert_to_udot_op"(%operand, %operand): (vector<4xi16>, vector<4xi16>) -> (i64)
204   return %0: i64
207 // CHECK-LABEL: @udot_vector_4xi16_i64_missing_capability1
208 func.func @udot_vector_4xi16_i64_missing_capability1(%operand: vector<4xi16>) -> i64 attributes {
209   spirv.target_env = #spirv.target_env<#spirv.vce<v1.0,
210     [DotProduct, Int16, Int64], [SPV_KHR_integer_dot_product]>, #spirv.resource_limits<>>
211 } {
212   // CHECK: test.convert_to_udot_op
213   %0 = "test.convert_to_udot_op"(%operand, %operand): (vector<4xi16>, vector<4xi16>) -> (i64)
214   return %0: i64
217 // CHECK-LABEL: @udot_vector_4xi16_i64_missing_capability2
218 func.func @udot_vector_4xi16_i64_missing_capability2(%operand: vector<4xi16>) -> i64 attributes {
219   spirv.target_env = #spirv.target_env<#spirv.vce<v1.0,
220     [DotProductInputAll, Int16, Int64], [SPV_KHR_integer_dot_product]>, #spirv.resource_limits<>>
221 } {
222   // CHECK: test.convert_to_udot_op
223   %0 = "test.convert_to_udot_op"(%operand, %operand): (vector<4xi16>, vector<4xi16>) -> (i64)
224   return %0 : i64
227 // CHECK-LABEL: @sdot_acc_sat_scalar_i32_i32_capabilities
228 func.func @sdot_acc_sat_scalar_i32_i32_capabilities(%operand: i32) -> i32 attributes {
229   spirv.target_env = #spirv.target_env<#spirv.vce<v1.0,
230     [DotProduct, DotProductInput4x8BitPacked], [SPV_KHR_integer_dot_product]>, #spirv.resource_limits<>>
231 } {
232   // CHECK: spirv.SDotAccSat
233   %0 = "test.convert_to_sdot_acc_sat_op"(%operand, %operand, %operand)
234          {format = #spirv.packed_vector_format<PackedVectorFormat4x8Bit>}: (i32, i32, i32) -> (i32)
235   return %0: i32
238 // CHECK-LABEL: @sudot_acc_sat_vector_4xi8_i32_capabilities
239 func.func @sudot_acc_sat_vector_4xi8_i32_capabilities(%operand: vector<4xi8>, %acc: i32) -> i32 attributes {
240   spirv.target_env = #spirv.target_env<#spirv.vce<v1.0,
241     [DotProduct, DotProductInput4x8Bit], [SPV_KHR_integer_dot_product]>, #spirv.resource_limits<>>
242 } {
243   // CHECK: spirv.SUDotAccSat
244   %0 = "test.convert_to_sudot_acc_sat_op"(%operand, %operand, %acc): (vector<4xi8>, vector<4xi8>, i32) -> (i32)
245   return %0: i32
248 // CHECK-LABEL: @udot_acc_sat_vector_4xi8_i32_missing_capability1
249 func.func @udot_acc_sat_vector_4xi8_i32_missing_capability1(%operand: vector<4xi8>, %acc: i32) -> i32 attributes {
250   spirv.target_env = #spirv.target_env<#spirv.vce<v1.0,
251     [DotProduct, DotProductInputAll, Int16, Int64], [SPV_KHR_integer_dot_product]>, #spirv.resource_limits<>>
252 } {
253   // CHECK: test.convert_to_udot_acc_sat_op
254   %0 = "test.convert_to_udot_acc_sat_op"(%operand, %operand, %acc): (vector<4xi8>, vector<4xi8>, i32) -> (i32)
255   return %0: i32
258 // CHECK-LABEL: @udot_acc_sat_vector_4xi8_i32_missing_capability2
259 func.func @udot_acc_sat_vector_4xi8_i32_missing_capability2(%operand: vector<4xi8>, %acc: i32) -> i32 attributes {
260   spirv.target_env = #spirv.target_env<#spirv.vce<v1.0,
261     [DotProductInputAll, DotProductInput4x8Bit, Int16, Int64], [SPV_KHR_integer_dot_product]>, #spirv.resource_limits<>>
262 } {
263   // CHECK: test.convert_to_udot_acc_sat_op
264   %0 = "test.convert_to_udot_acc_sat_op"(%operand, %operand, %acc): (vector<4xi8>, vector<4xi8>, i32) -> (i32)
265   return %0: i32
268 // CHECK-LABEL: @udot_acc_sat_vector_4xi16_i64_capabilities
269 func.func @udot_acc_sat_vector_4xi16_i64_capabilities(%operand: vector<4xi16>, %acc: i64) -> i64 attributes {
270   spirv.target_env = #spirv.target_env<#spirv.vce<v1.0,
271     [DotProduct, DotProductInputAll, Int16, Int64], [SPV_KHR_integer_dot_product]>, #spirv.resource_limits<>>
272 } {
273   // CHECK: spirv.UDotAccSat
274   %0 = "test.convert_to_udot_acc_sat_op"(%operand, %operand, %acc): (vector<4xi16>, vector<4xi16>, i64) -> (i64)
275   return %0: i64
278 // CHECK-LABEL: @udot_acc_sat_vector_4xi16_i64_missing_capability1
279 func.func @udot_acc_sat_vector_4xi16_i64_missing_capability1(%operand: vector<4xi16>, %acc: i64) -> i64 attributes {
280   spirv.target_env = #spirv.target_env<#spirv.vce<v1.0,
281     [DotProductInputAll, Int16, Int64], [SPV_KHR_integer_dot_product]>, #spirv.resource_limits<>>
282 } {
283   // CHECK: test.convert_to_udot_acc_sat_op
284   %0 = "test.convert_to_udot_acc_sat_op"(%operand, %operand, %acc): (vector<4xi16>, vector<4xi16>, i64) -> (i64)
285   return %0: i64
288 // CHECK-LABEL: @udot_acc_sat_vector_4xi16_i64_missing_capability2
289 func.func @udot_acc_sat_vector_4xi16_i64_missing_capability2(%operand: vector<4xi16>, %acc: i64) -> i64 attributes {
290   spirv.target_env = #spirv.target_env<#spirv.vce<v1.0,
291     [DotProduct, Int16, Int64], [SPV_KHR_integer_dot_product]>, #spirv.resource_limits<>>
292 } {
293   // CHECK: test.convert_to_udot_acc_sat_op
294   %0 = "test.convert_to_udot_acc_sat_op"(%operand, %operand, %acc): (vector<4xi16>, vector<4xi16>, i64) -> (i64)
295   return %0: i64
298 //===----------------------------------------------------------------------===//
299 // Extension
300 //===----------------------------------------------------------------------===//
302 // CHECK-LABEL: @subgroup_ballot_suitable_extension
303 func.func @subgroup_ballot_suitable_extension(%predicate: i1) -> vector<4xi32> attributes {
304   spirv.target_env = #spirv.target_env<#spirv.vce<v1.4, [SubgroupBallotKHR], [SPV_KHR_shader_ballot]>, #spirv.resource_limits<>>
305 } {
306   // CHECK: spirv.KHR.SubgroupBallot
307   %0 = "test.convert_to_subgroup_ballot_op"(%predicate): (i1) -> (vector<4xi32>)
308   return %0: vector<4xi32>
311 // CHECK-LABEL: @subgroup_ballot_missing_extension
312 func.func @subgroup_ballot_missing_extension(%predicate: i1) -> vector<4xi32> attributes {
313   spirv.target_env = #spirv.target_env<#spirv.vce<v1.4, [SubgroupBallotKHR], []>, #spirv.resource_limits<>>
314 } {
315   // CHECK: test.convert_to_subgroup_ballot_op
316   %0 = "test.convert_to_subgroup_ballot_op"(%predicate): (i1) -> (vector<4xi32>)
317   return %0: vector<4xi32>
320 // CHECK-LABEL: @module_suitable_extension1
321 func.func @module_suitable_extension1() attributes {
322   spirv.target_env = #spirv.target_env<#spirv.vce<v1.0, [VulkanMemoryModel, PhysicalStorageBufferAddresses], [SPV_KHR_vulkan_memory_model, SPV_EXT_physical_storage_buffer]>, #spirv.resource_limits<>>
323 } {
324   // CHECK: spirv.module PhysicalStorageBuffer64 Vulkan
325   "test.convert_to_module_op"() : () ->()
326   return
329 // CHECK-LABEL: @module_suitable_extension2
330 func.func @module_suitable_extension2() attributes {
331   spirv.target_env = #spirv.target_env<#spirv.vce<v1.0, [VulkanMemoryModel, PhysicalStorageBufferAddresses], [SPV_KHR_vulkan_memory_model, SPV_KHR_physical_storage_buffer]>, #spirv.resource_limits<>>
332 } {
333   // CHECK: spirv.module PhysicalStorageBuffer64 Vulkan
334   "test.convert_to_module_op"() : () -> ()
335   return
338 // CHECK-LABEL: @module_missing_extension_mm
339 func.func @module_missing_extension_mm() attributes {
340   spirv.target_env = #spirv.target_env<#spirv.vce<v1.0, [VulkanMemoryModel, PhysicalStorageBufferAddresses], [SPV_KHR_physical_storage_buffer]>, #spirv.resource_limits<>>
341 } {
342   // CHECK: test.convert_to_module_op
343   "test.convert_to_module_op"() : () -> ()
344   return
347 // CHECK-LABEL: @module_missing_extension_am
348 func.func @module_missing_extension_am() attributes {
349   spirv.target_env = #spirv.target_env<#spirv.vce<v1.0, [VulkanMemoryModel, PhysicalStorageBufferAddresses], [SPV_KHR_vulkan_memory_model]>, #spirv.resource_limits<>>
350 } {
351   // CHECK: test.convert_to_module_op
352   "test.convert_to_module_op"() : () -> ()
353   return
356 // CHECK-LABEL: @module_implied_extension
357 func.func @module_implied_extension() attributes {
358   // Version 1.5 implies SPV_KHR_vulkan_memory_model and SPV_KHR_physical_storage_buffer.
359   spirv.target_env = #spirv.target_env<#spirv.vce<v1.5, [VulkanMemoryModel, PhysicalStorageBufferAddresses], []>, #spirv.resource_limits<>>
360 } {
361   // CHECK: spirv.module PhysicalStorageBuffer64 Vulkan
362   "test.convert_to_module_op"() : () -> ()
363   return
366 // CHECK-LABEL: @udot_vector_4xi16_i64_implied_extension
367 func.func @udot_vector_4xi16_i64_implied_extension(%operand: vector<4xi16>) -> i64 attributes {
368   // Version 1.6 implies SPV_KHR_integer_to_product.
369   spirv.target_env = #spirv.target_env<#spirv.vce<v1.6,
370     [DotProduct, DotProductInputAll, Int16, Int64], []>, #spirv.resource_limits<>>
371 } {
372   // CHECK: spirv.UDot
373   %0 = "test.convert_to_udot_op"(%operand, %operand): (vector<4xi16>, vector<4xi16>) -> (i64)
374   return %0: i64
377 // CHECK-LABEL: @udot_vector_4xi16_i64_missing_extension
378 func.func @udot_vector_4xi16_i64_missing_extension(%operand: vector<4xi16>) -> i64 attributes {
379   // Version 1.5 does not imply SPV_KHR_integer_to_product.
380   spirv.target_env = #spirv.target_env<#spirv.vce<v1.5,
381     [DotProduct, DotProductInputAll, Int16, Int64], []>, #spirv.resource_limits<>>
382 } {
383   // CHECK: test.convert_to_udot_op
384   %0 = "test.convert_to_udot_op"(%operand, %operand): (vector<4xi16>, vector<4xi16>) -> (i64)
385   return %0: i64
388 // CHECK-LABEL: @sdot_acc_sat_vector_4xi16_i64_implied_extension
389 func.func @sdot_acc_sat_vector_4xi16_i64_implied_extension(%operand: vector<4xi16>, %acc: i64) -> i64 attributes {
390   // Version 1.6 implies SPV_KHR_integer_to_product.
391   spirv.target_env = #spirv.target_env<#spirv.vce<v1.6,
392     [DotProduct, DotProductInputAll, Int16, Int64], []>, #spirv.resource_limits<>>
393 } {
394   // CHECK: spirv.SDotAccSat
395   %0 = "test.convert_to_sdot_acc_sat_op"(%operand, %operand, %acc): (vector<4xi16>, vector<4xi16>, i64) -> (i64)
396   return %0: i64
399 // CHECK-LABEL: @sdot_acc_sat_vector_4xi16_i64_missing_extension
400 func.func @sdot_acc_sat_vector_4xi16_i64_missing_extension(%operand: vector<4xi16>, %acc: i64) -> i64 attributes {
401   // Version 1.5 does not imply SPV_KHR_integer_to_product.
402   spirv.target_env = #spirv.target_env<#spirv.vce<v1.5,
403     [DotProduct, DotProductInputAll, Int16, Int64], []>, #spirv.resource_limits<>>
404 } {
405   // CHECK: test.convert_to_sdot_acc_sat_op
406   %0 = "test.convert_to_sdot_acc_sat_op"(%operand, %operand, %acc): (vector<4xi16>, vector<4xi16>, i64) -> (i64)
407   return %0: i64