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
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}}
44 //===----------------------------------------------------------------------===//
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<>>
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)
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<>>
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)
66 //===----------------------------------------------------------------------===//
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<>>
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<>>
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 //===----------------------------------------------------------------------===//
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<>>
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)
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<>>
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)
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<>>
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<>>
123 // CHECK: spirv.BitReverse
124 %0 = "test.convert_to_bit_reverse_op"(%operand): (i32) -> (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<>>
132 // CHECK: spirv.BitReverse
133 %0 = "test.convert_to_bit_reverse_op"(%operand): (i32) -> (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<>>
143 %0 = "test.convert_to_sdot_op"(%operand, %operand) {format = #spirv.packed_vector_format<PackedVectorFormat4x8Bit>}: (i32, i32) -> (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<>>
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)
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<>>
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)
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<>>
172 // CHECK: spirv.SUDot
173 %0 = "test.convert_to_sudot_op"(%operand, %operand): (vector<4xi8>, vector<4xi8>) -> (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<>>
182 // CHECK: test.convert_to_sudot_op
183 %0 = "test.convert_to_sudot_op"(%operand, %operand): (vector<4xi8>, vector<4xi8>) -> (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<>>
192 // CHECK: test.convert_to_sudot_op
193 %0 = "test.convert_to_sudot_op"(%operand, %operand): (vector<4xi8>, vector<4xi8>) -> (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<>>
203 %0 = "test.convert_to_udot_op"(%operand, %operand): (vector<4xi16>, vector<4xi16>) -> (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<>>
212 // CHECK: test.convert_to_udot_op
213 %0 = "test.convert_to_udot_op"(%operand, %operand): (vector<4xi16>, vector<4xi16>) -> (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<>>
222 // CHECK: test.convert_to_udot_op
223 %0 = "test.convert_to_udot_op"(%operand, %operand): (vector<4xi16>, vector<4xi16>) -> (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<>>
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)
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<>>
243 // CHECK: spirv.SUDotAccSat
244 %0 = "test.convert_to_sudot_acc_sat_op"(%operand, %operand, %acc): (vector<4xi8>, vector<4xi8>, i32) -> (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<>>
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)
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<>>
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)
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<>>
273 // CHECK: spirv.UDotAccSat
274 %0 = "test.convert_to_udot_acc_sat_op"(%operand, %operand, %acc): (vector<4xi16>, vector<4xi16>, i64) -> (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<>>
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)
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<>>
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)
298 //===----------------------------------------------------------------------===//
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<>>
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<>>
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<>>
324 // CHECK: spirv.module PhysicalStorageBuffer64 Vulkan
325 "test.convert_to_module_op"() : () ->()
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<>>
333 // CHECK: spirv.module PhysicalStorageBuffer64 Vulkan
334 "test.convert_to_module_op"() : () -> ()
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<>>
342 // CHECK: test.convert_to_module_op
343 "test.convert_to_module_op"() : () -> ()
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<>>
351 // CHECK: test.convert_to_module_op
352 "test.convert_to_module_op"() : () -> ()
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<>>
361 // CHECK: spirv.module PhysicalStorageBuffer64 Vulkan
362 "test.convert_to_module_op"() : () -> ()
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<>>
373 %0 = "test.convert_to_udot_op"(%operand, %operand): (vector<4xi16>, vector<4xi16>) -> (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<>>
383 // CHECK: test.convert_to_udot_op
384 %0 = "test.convert_to_udot_op"(%operand, %operand): (vector<4xi16>, vector<4xi16>) -> (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<>>
394 // CHECK: spirv.SDotAccSat
395 %0 = "test.convert_to_sdot_acc_sat_op"(%operand, %operand, %acc): (vector<4xi16>, vector<4xi16>, i64) -> (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<>>
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)