1 // RUN: mlir-opt -split-input-file -convert-std-to-spirv -verify-diagnostics %s | FileCheck %s
3 //===----------------------------------------------------------------------===//
5 //===----------------------------------------------------------------------===//
8 spv.target_env = #spv.target_env<
9 #spv.vce<v1.0, [Int8, Int16, Int64, Float16, Float64, Shader], []>, {}>
12 // Check integer operation conversions.
13 // CHECK-LABEL: @int32_scalar
14 func @int32_scalar(%lhs: i32, %rhs: i32) {
15 // CHECK: spv.IAdd %{{.*}}, %{{.*}}: i32
16 %0 = arith.addi %lhs, %rhs: i32
17 // CHECK: spv.ISub %{{.*}}, %{{.*}}: i32
18 %1 = arith.subi %lhs, %rhs: i32
19 // CHECK: spv.IMul %{{.*}}, %{{.*}}: i32
20 %2 = arith.muli %lhs, %rhs: i32
21 // CHECK: spv.SDiv %{{.*}}, %{{.*}}: i32
22 %3 = arith.divsi %lhs, %rhs: i32
23 // CHECK: spv.UDiv %{{.*}}, %{{.*}}: i32
24 %4 = arith.divui %lhs, %rhs: i32
25 // CHECK: spv.UMod %{{.*}}, %{{.*}}: i32
26 %5 = arith.remui %lhs, %rhs: i32
30 // CHECK-LABEL: @scalar_srem
31 // CHECK-SAME: (%[[LHS:.+]]: i32, %[[RHS:.+]]: i32)
32 func @scalar_srem(%lhs: i32, %rhs: i32) {
33 // CHECK: %[[LABS:.+]] = spv.GLSL.SAbs %[[LHS]] : i32
34 // CHECK: %[[RABS:.+]] = spv.GLSL.SAbs %[[RHS]] : i32
35 // CHECK: %[[ABS:.+]] = spv.UMod %[[LABS]], %[[RABS]] : i32
36 // CHECK: %[[POS:.+]] = spv.IEqual %[[LHS]], %[[LABS]] : i32
37 // CHECK: %[[NEG:.+]] = spv.SNegate %[[ABS]] : i32
38 // CHECK: %{{.+}} = spv.Select %[[POS]], %[[ABS]], %[[NEG]] : i1, i32
39 %0 = arith.remsi %lhs, %rhs: i32
43 // Check float unary operation conversions.
44 // CHECK-LABEL: @float32_unary_scalar
45 func @float32_unary_scalar(%arg0: f32) {
46 // CHECK: spv.FNegate %{{.*}}: f32
47 %0 = arith.negf %arg0 : f32
51 // Check float binary operation conversions.
52 // CHECK-LABEL: @float32_binary_scalar
53 func @float32_binary_scalar(%lhs: f32, %rhs: f32) {
54 // CHECK: spv.FAdd %{{.*}}, %{{.*}}: f32
55 %0 = arith.addf %lhs, %rhs: f32
56 // CHECK: spv.FSub %{{.*}}, %{{.*}}: f32
57 %1 = arith.subf %lhs, %rhs: f32
58 // CHECK: spv.FMul %{{.*}}, %{{.*}}: f32
59 %2 = arith.mulf %lhs, %rhs: f32
60 // CHECK: spv.FDiv %{{.*}}, %{{.*}}: f32
61 %3 = arith.divf %lhs, %rhs: f32
62 // CHECK: spv.FRem %{{.*}}, %{{.*}}: f32
63 %4 = arith.remf %lhs, %rhs: f32
67 // Check int vector types.
68 // CHECK-LABEL: @int_vector234
69 func @int_vector234(%arg0: vector<2xi8>, %arg1: vector<4xi64>) {
70 // CHECK: spv.SDiv %{{.*}}, %{{.*}}: vector<2xi8>
71 %0 = arith.divsi %arg0, %arg0: vector<2xi8>
72 // CHECK: spv.UDiv %{{.*}}, %{{.*}}: vector<4xi64>
73 %1 = arith.divui %arg1, %arg1: vector<4xi64>
77 // CHECK-LABEL: @vector_srem
78 // CHECK-SAME: (%[[LHS:.+]]: vector<3xi16>, %[[RHS:.+]]: vector<3xi16>)
79 func @vector_srem(%arg0: vector<3xi16>, %arg1: vector<3xi16>) {
80 // CHECK: %[[LABS:.+]] = spv.GLSL.SAbs %[[LHS]] : vector<3xi16>
81 // CHECK: %[[RABS:.+]] = spv.GLSL.SAbs %[[RHS]] : vector<3xi16>
82 // CHECK: %[[ABS:.+]] = spv.UMod %[[LABS]], %[[RABS]] : vector<3xi16>
83 // CHECK: %[[POS:.+]] = spv.IEqual %[[LHS]], %[[LABS]] : vector<3xi16>
84 // CHECK: %[[NEG:.+]] = spv.SNegate %[[ABS]] : vector<3xi16>
85 // CHECK: %{{.+}} = spv.Select %[[POS]], %[[ABS]], %[[NEG]] : vector<3xi1>, vector<3xi16>
86 %0 = arith.remsi %arg0, %arg1: vector<3xi16>
90 // Check float vector types.
91 // CHECK-LABEL: @float_vector234
92 func @float_vector234(%arg0: vector<2xf16>, %arg1: vector<3xf64>) {
93 // CHECK: spv.FAdd %{{.*}}, %{{.*}}: vector<2xf16>
94 %0 = arith.addf %arg0, %arg0: vector<2xf16>
95 // CHECK: spv.FMul %{{.*}}, %{{.*}}: vector<3xf64>
96 %1 = arith.mulf %arg1, %arg1: vector<3xf64>
100 // CHECK-LABEL: @one_elem_vector
101 func @one_elem_vector(%arg0: vector<1xi32>) {
102 // CHECK: spv.IAdd %{{.+}}, %{{.+}}: i32
103 %0 = arith.addi %arg0, %arg0: vector<1xi32>
107 // CHECK-LABEL: @unsupported_5elem_vector
108 func @unsupported_5elem_vector(%arg0: vector<5xi32>) {
110 %1 = arith.subi %arg0, %arg0: vector<5xi32>
114 // CHECK-LABEL: @unsupported_2x2elem_vector
115 func @unsupported_2x2elem_vector(%arg0: vector<2x2xi32>) {
117 %2 = arith.muli %arg0, %arg0: vector<2x2xi32>
125 // Check that types are converted to 32-bit when no special capabilities.
127 spv.target_env = #spv.target_env<#spv.vce<v1.0, [], []>, {}>
130 // CHECK-LABEL: @int_vector23
131 func @int_vector23(%arg0: vector<2xi8>, %arg1: vector<3xi16>) {
132 // CHECK: spv.SDiv %{{.*}}, %{{.*}}: vector<2xi32>
133 %0 = arith.divsi %arg0, %arg0: vector<2xi8>
134 // CHECK: spv.SDiv %{{.*}}, %{{.*}}: vector<3xi32>
135 %1 = arith.divsi %arg1, %arg1: vector<3xi16>
139 // CHECK-LABEL: @float_scalar
140 func @float_scalar(%arg0: f16, %arg1: f64) {
141 // CHECK: spv.FAdd %{{.*}}, %{{.*}}: f32
142 %0 = arith.addf %arg0, %arg0: f16
143 // CHECK: spv.FMul %{{.*}}, %{{.*}}: f32
144 %1 = arith.mulf %arg1, %arg1: f64
152 // Check that types are converted to 32-bit when no special capabilities that
153 // are not supported.
155 spv.target_env = #spv.target_env<#spv.vce<v1.0, [], []>, {}>
158 // expected-error @+1 {{failed to materialize conversion for block argument #0 that remained live after conversion, type was 'vector<4xi64>', with target type 'vector<4xi32>'}}
159 func @int_vector4_invalid(%arg0: vector<4xi64>) {
160 // expected-error @+2 {{bitwidth emulation is not implemented yet on unsigned op}}
161 // expected-note @+1 {{see existing live user here}}
162 %0 = arith.divui %arg0, %arg0: vector<4xi64>
170 //===----------------------------------------------------------------------===//
172 //===----------------------------------------------------------------------===//
175 spv.target_env = #spv.target_env<#spv.vce<v1.0, [], []>, {}>
178 // CHECK-LABEL: @bitwise_scalar
179 func @bitwise_scalar(%arg0 : i32, %arg1 : i32) {
180 // CHECK: spv.BitwiseAnd
181 %0 = arith.andi %arg0, %arg1 : i32
182 // CHECK: spv.BitwiseOr
183 %1 = arith.ori %arg0, %arg1 : i32
184 // CHECK: spv.BitwiseXor
185 %2 = arith.xori %arg0, %arg1 : i32
189 // CHECK-LABEL: @bitwise_vector
190 func @bitwise_vector(%arg0 : vector<4xi32>, %arg1 : vector<4xi32>) {
191 // CHECK: spv.BitwiseAnd
192 %0 = arith.andi %arg0, %arg1 : vector<4xi32>
193 // CHECK: spv.BitwiseOr
194 %1 = arith.ori %arg0, %arg1 : vector<4xi32>
195 // CHECK: spv.BitwiseXor
196 %2 = arith.xori %arg0, %arg1 : vector<4xi32>
200 // CHECK-LABEL: @logical_scalar
201 func @logical_scalar(%arg0 : i1, %arg1 : i1) {
202 // CHECK: spv.LogicalAnd
203 %0 = arith.andi %arg0, %arg1 : i1
204 // CHECK: spv.LogicalOr
205 %1 = arith.ori %arg0, %arg1 : i1
206 // CHECK: spv.LogicalNotEqual
207 %2 = arith.xori %arg0, %arg1 : i1
211 // CHECK-LABEL: @logical_vector
212 func @logical_vector(%arg0 : vector<4xi1>, %arg1 : vector<4xi1>) {
213 // CHECK: spv.LogicalAnd
214 %0 = arith.andi %arg0, %arg1 : vector<4xi1>
215 // CHECK: spv.LogicalOr
216 %1 = arith.ori %arg0, %arg1 : vector<4xi1>
217 // CHECK: spv.LogicalNotEqual
218 %2 = arith.xori %arg0, %arg1 : vector<4xi1>
222 // CHECK-LABEL: @shift_scalar
223 func @shift_scalar(%arg0 : i32, %arg1 : i32) {
224 // CHECK: spv.ShiftLeftLogical
225 %0 = arith.shli %arg0, %arg1 : i32
226 // CHECK: spv.ShiftRightArithmetic
227 %1 = arith.shrsi %arg0, %arg1 : i32
228 // CHECK: spv.ShiftRightLogical
229 %2 = arith.shrui %arg0, %arg1 : i32
233 // CHECK-LABEL: @shift_vector
234 func @shift_vector(%arg0 : vector<4xi32>, %arg1 : vector<4xi32>) {
235 // CHECK: spv.ShiftLeftLogical
236 %0 = arith.shli %arg0, %arg1 : vector<4xi32>
237 // CHECK: spv.ShiftRightArithmetic
238 %1 = arith.shrsi %arg0, %arg1 : vector<4xi32>
239 // CHECK: spv.ShiftRightLogical
240 %2 = arith.shrui %arg0, %arg1 : vector<4xi32>
248 //===----------------------------------------------------------------------===//
250 //===----------------------------------------------------------------------===//
253 spv.target_env = #spv.target_env<#spv.vce<v1.0, [], []>, {}>
256 // CHECK-LABEL: @cmpf
257 func @cmpf(%arg0 : f32, %arg1 : f32) {
258 // CHECK: spv.FOrdEqual
259 %1 = arith.cmpf oeq, %arg0, %arg1 : f32
260 // CHECK: spv.FOrdGreaterThan
261 %2 = arith.cmpf ogt, %arg0, %arg1 : f32
262 // CHECK: spv.FOrdGreaterThanEqual
263 %3 = arith.cmpf oge, %arg0, %arg1 : f32
264 // CHECK: spv.FOrdLessThan
265 %4 = arith.cmpf olt, %arg0, %arg1 : f32
266 // CHECK: spv.FOrdLessThanEqual
267 %5 = arith.cmpf ole, %arg0, %arg1 : f32
268 // CHECK: spv.FOrdNotEqual
269 %6 = arith.cmpf one, %arg0, %arg1 : f32
270 // CHECK: spv.FUnordEqual
271 %7 = arith.cmpf ueq, %arg0, %arg1 : f32
272 // CHECK: spv.FUnordGreaterThan
273 %8 = arith.cmpf ugt, %arg0, %arg1 : f32
274 // CHECK: spv.FUnordGreaterThanEqual
275 %9 = arith.cmpf uge, %arg0, %arg1 : f32
276 // CHECK: spv.FUnordLessThan
277 %10 = arith.cmpf ult, %arg0, %arg1 : f32
278 // CHECK: FUnordLessThanEqual
279 %11 = arith.cmpf ule, %arg0, %arg1 : f32
280 // CHECK: spv.FUnordNotEqual
281 %12 = arith.cmpf une, %arg0, %arg1 : f32
289 // With Kernel capability, we can convert NaN check to spv.Ordered/spv.Unordered.
291 spv.target_env = #spv.target_env<#spv.vce<v1.0, [Kernel], []>, {}>
294 // CHECK-LABEL: @cmpf
295 func @cmpf(%arg0 : f32, %arg1 : f32) {
296 // CHECK: spv.Ordered
297 %0 = arith.cmpf ord, %arg0, %arg1 : f32
298 // CHECK: spv.Unordered
299 %1 = arith.cmpf uno, %arg0, %arg1 : f32
307 // Without Kernel capability, we need to convert NaN check to spv.IsNan.
309 spv.target_env = #spv.target_env<#spv.vce<v1.0, [], []>, {}>
312 // CHECK-LABEL: @cmpf
313 // CHECK-SAME: %[[LHS:.+]]: f32, %[[RHS:.+]]: f32
314 func @cmpf(%arg0 : f32, %arg1 : f32) {
315 // CHECK: %[[LHS_NAN:.+]] = spv.IsNan %[[LHS]] : f32
316 // CHECK-NEXT: %[[RHS_NAN:.+]] = spv.IsNan %[[RHS]] : f32
317 // CHECK-NEXT: %[[OR:.+]] = spv.LogicalOr %[[LHS_NAN]], %[[RHS_NAN]] : i1
318 // CHECK-NEXT: %{{.+}} = spv.LogicalNot %[[OR]] : i1
319 %0 = arith.cmpf ord, %arg0, %arg1 : f32
321 // CHECK-NEXT: %[[LHS_NAN:.+]] = spv.IsNan %[[LHS]] : f32
322 // CHECK-NEXT: %[[RHS_NAN:.+]] = spv.IsNan %[[RHS]] : f32
323 // CHECK-NEXT: %{{.+}} = spv.LogicalOr %[[LHS_NAN]], %[[RHS_NAN]] : i1
324 %1 = arith.cmpf uno, %arg0, %arg1 : f32
332 //===----------------------------------------------------------------------===//
334 //===----------------------------------------------------------------------===//
337 spv.target_env = #spv.target_env<#spv.vce<v1.0, [], []>, {}>
340 // CHECK-LABEL: @cmpi
341 func @cmpi(%arg0 : i32, %arg1 : i32) {
343 %0 = arith.cmpi eq, %arg0, %arg1 : i32
344 // CHECK: spv.INotEqual
345 %1 = arith.cmpi ne, %arg0, %arg1 : i32
346 // CHECK: spv.SLessThan
347 %2 = arith.cmpi slt, %arg0, %arg1 : i32
348 // CHECK: spv.SLessThanEqual
349 %3 = arith.cmpi sle, %arg0, %arg1 : i32
350 // CHECK: spv.SGreaterThan
351 %4 = arith.cmpi sgt, %arg0, %arg1 : i32
352 // CHECK: spv.SGreaterThanEqual
353 %5 = arith.cmpi sge, %arg0, %arg1 : i32
354 // CHECK: spv.ULessThan
355 %6 = arith.cmpi ult, %arg0, %arg1 : i32
356 // CHECK: spv.ULessThanEqual
357 %7 = arith.cmpi ule, %arg0, %arg1 : i32
358 // CHECK: spv.UGreaterThan
359 %8 = arith.cmpi ugt, %arg0, %arg1 : i32
360 // CHECK: spv.UGreaterThanEqual
361 %9 = arith.cmpi uge, %arg0, %arg1 : i32
365 // CHECK-LABEL: @boolcmpi
366 func @boolcmpi(%arg0 : i1, %arg1 : i1) {
367 // CHECK: spv.LogicalEqual
368 %0 = arith.cmpi eq, %arg0, %arg1 : i1
369 // CHECK: spv.LogicalNotEqual
370 %1 = arith.cmpi ne, %arg0, %arg1 : i1
374 // CHECK-LABEL: @vecboolcmpi
375 func @vecboolcmpi(%arg0 : vector<4xi1>, %arg1 : vector<4xi1>) {
376 // CHECK: spv.LogicalEqual
377 %0 = arith.cmpi eq, %arg0, %arg1 : vector<4xi1>
378 // CHECK: spv.LogicalNotEqual
379 %1 = arith.cmpi ne, %arg0, %arg1 : vector<4xi1>
387 //===----------------------------------------------------------------------===//
389 //===----------------------------------------------------------------------===//
392 spv.target_env = #spv.target_env<
393 #spv.vce<v1.0, [Int8, Int16, Int64, Float16, Float64], []>, {}>
396 // CHECK-LABEL: @constant
398 // CHECK: spv.Constant true
399 %0 = arith.constant true
400 // CHECK: spv.Constant 42 : i32
401 %1 = arith.constant 42 : i32
402 // CHECK: spv.Constant 5.000000e-01 : f32
403 %2 = arith.constant 0.5 : f32
404 // CHECK: spv.Constant dense<[2, 3]> : vector<2xi32>
405 %3 = arith.constant dense<[2, 3]> : vector<2xi32>
406 // CHECK: spv.Constant 1 : i32
407 %4 = arith.constant 1 : index
408 // CHECK: spv.Constant dense<1> : tensor<6xi32> : !spv.array<6 x i32, stride=4>
409 %5 = arith.constant dense<1> : tensor<2x3xi32>
410 // CHECK: spv.Constant dense<1.000000e+00> : tensor<6xf32> : !spv.array<6 x f32, stride=4>
411 %6 = arith.constant dense<1.0> : tensor<2x3xf32>
412 // CHECK: spv.Constant dense<{{\[}}1.000000e+00, 2.000000e+00, 3.000000e+00, 4.000000e+00, 5.000000e+00, 6.000000e+00]> : tensor<6xf32> : !spv.array<6 x f32, stride=4>
413 %7 = arith.constant dense<[[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]> : tensor<2x3xf32>
414 // CHECK: spv.Constant dense<{{\[}}1, 2, 3, 4, 5, 6]> : tensor<6xi32> : !spv.array<6 x i32, stride=4>
415 %8 = arith.constant dense<[[1, 2, 3], [4, 5, 6]]> : tensor<2x3xi32>
416 // CHECK: spv.Constant dense<{{\[}}1, 2, 3, 4, 5, 6]> : tensor<6xi32> : !spv.array<6 x i32, stride=4>
417 %9 = arith.constant dense<[[1, 2], [3, 4], [5, 6]]> : tensor<3x2xi32>
418 // CHECK: spv.Constant dense<{{\[}}1, 2, 3, 4, 5, 6]> : tensor<6xi32> : !spv.array<6 x i32, stride=4>
419 %10 = arith.constant dense<[1, 2, 3, 4, 5, 6]> : tensor<6xi32>
423 // CHECK-LABEL: @constant_16bit
424 func @constant_16bit() {
425 // CHECK: spv.Constant 4 : i16
426 %0 = arith.constant 4 : i16
427 // CHECK: spv.Constant 5.000000e+00 : f16
428 %1 = arith.constant 5.0 : f16
429 // CHECK: spv.Constant dense<[2, 3]> : vector<2xi16>
430 %2 = arith.constant dense<[2, 3]> : vector<2xi16>
431 // CHECK: spv.Constant dense<4.000000e+00> : tensor<5xf16> : !spv.array<5 x f16, stride=2>
432 %3 = arith.constant dense<4.0> : tensor<5xf16>
436 // CHECK-LABEL: @constant_64bit
437 func @constant_64bit() {
438 // CHECK: spv.Constant 4 : i64
439 %0 = arith.constant 4 : i64
440 // CHECK: spv.Constant 5.000000e+00 : f64
441 %1 = arith.constant 5.0 : f64
442 // CHECK: spv.Constant dense<[2, 3]> : vector<2xi64>
443 %2 = arith.constant dense<[2, 3]> : vector<2xi64>
444 // CHECK: spv.Constant dense<4.000000e+00> : tensor<5xf64> : !spv.array<5 x f64, stride=8>
445 %3 = arith.constant dense<4.0> : tensor<5xf64>
449 // CHECK-LABEL: @constant_size1
450 func @constant_size1() {
451 // CHECK: spv.Constant true
452 %0 = arith.constant dense<true> : tensor<1xi1>
453 // CHECK: spv.Constant 4 : i64
454 %1 = arith.constant dense<4> : vector<1xi64>
455 // CHECK: spv.Constant 5.000000e+00 : f64
456 %2 = arith.constant dense<5.0> : tensor<1xf64>
464 // Check that constants are converted to 32-bit when no special capability.
466 spv.target_env = #spv.target_env<#spv.vce<v1.0, [], []>, {}>
469 // CHECK-LABEL: @constant_16bit
470 func @constant_16bit() {
471 // CHECK: spv.Constant 4 : i32
472 %0 = arith.constant 4 : i16
473 // CHECK: spv.Constant 5.000000e+00 : f32
474 %1 = arith.constant 5.0 : f16
475 // CHECK: spv.Constant dense<[2, 3]> : vector<2xi32>
476 %2 = arith.constant dense<[2, 3]> : vector<2xi16>
477 // CHECK: spv.Constant dense<4.000000e+00> : tensor<5xf32> : !spv.array<5 x f32, stride=4>
478 %3 = arith.constant dense<4.0> : tensor<5xf16>
479 // CHECK: spv.Constant dense<[1.000000e+00, 2.000000e+00, 3.000000e+00, 4.000000e+00]> : tensor<4xf32> : !spv.array<4 x f32, stride=4>
480 %4 = arith.constant dense<[[1.0, 2.0], [3.0, 4.0]]> : tensor<2x2xf16>
484 // CHECK-LABEL: @constant_64bit
485 func @constant_64bit() {
486 // CHECK: spv.Constant 4 : i32
487 %0 = arith.constant 4 : i64
488 // CHECK: spv.Constant 5.000000e+00 : f32
489 %1 = arith.constant 5.0 : f64
490 // CHECK: spv.Constant dense<[2, 3]> : vector<2xi32>
491 %2 = arith.constant dense<[2, 3]> : vector<2xi64>
492 // CHECK: spv.Constant dense<4.000000e+00> : tensor<5xf32> : !spv.array<5 x f32, stride=4>
493 %3 = arith.constant dense<4.0> : tensor<5xf64>
494 // CHECK: spv.Constant dense<[1.000000e+00, 2.000000e+00, 3.000000e+00, 4.000000e+00]> : tensor<4xf32> : !spv.array<4 x f32, stride=4>
495 %4 = arith.constant dense<[[1.0, 2.0], [3.0, 4.0]]> : tensor<2x2xf16>
499 // CHECK-LABEL: @constant_size1
500 func @constant_size1() {
501 // CHECK: spv.Constant 4 : i32
502 %0 = arith.constant dense<4> : vector<1xi64>
503 // CHECK: spv.Constant 5.000000e+00 : f32
504 %1 = arith.constant dense<5.0> : tensor<1xf64>
508 // CHECK-LABEL: @corner_cases
509 func @corner_cases() {
510 // CHECK: %{{.*}} = spv.Constant -1 : i32
511 %0 = arith.constant 4294967295 : i64 // 2^32 - 1
512 // CHECK: %{{.*}} = spv.Constant 2147483647 : i32
513 %1 = arith.constant 2147483647 : i64 // 2^31 - 1
514 // CHECK: %{{.*}} = spv.Constant -2147483648 : i32
515 %2 = arith.constant 2147483648 : i64 // 2^31
516 // CHECK: %{{.*}} = spv.Constant -2147483648 : i32
517 %3 = arith.constant -2147483648 : i64 // -2^31
519 // CHECK: %{{.*}} = spv.Constant -1 : i32
520 %5 = arith.constant -1 : i64
521 // CHECK: %{{.*}} = spv.Constant -2 : i32
522 %6 = arith.constant -2 : i64
523 // CHECK: %{{.*}} = spv.Constant -1 : i32
524 %7 = arith.constant -1 : index
525 // CHECK: %{{.*}} = spv.Constant -2 : i32
526 %8 = arith.constant -2 : index
529 // CHECK: spv.Constant false
530 %9 = arith.constant false
531 // CHECK: spv.Constant true
532 %10 = arith.constant true
537 // CHECK-LABEL: @unsupported_cases
538 func @unsupported_cases() {
539 // CHECK: %{{.*}} = arith.constant 4294967296 : i64
540 %0 = arith.constant 4294967296 : i64 // 2^32
541 // CHECK: %{{.*}} = arith.constant -2147483649 : i64
542 %1 = arith.constant -2147483649 : i64 // -2^31 - 1
543 // CHECK: %{{.*}} = arith.constant 1.0000000000000002 : f64
544 %2 = arith.constant 0x3FF0000000000001 : f64 // smallest number > 1
552 //===----------------------------------------------------------------------===//
554 //===----------------------------------------------------------------------===//
557 spv.target_env = #spv.target_env<
558 #spv.vce<v1.0, [Int8, Int16, Int64, Float16, Float64], []>, {}>
561 // CHECK-LABEL: index_cast1
562 func @index_cast1(%arg0: i16) {
563 // CHECK: spv.SConvert %{{.+}} : i16 to i32
564 %0 = arith.index_cast %arg0 : i16 to index
568 // CHECK-LABEL: index_cast2
569 func @index_cast2(%arg0: index) {
570 // CHECK: spv.SConvert %{{.+}} : i32 to i16
571 %0 = arith.index_cast %arg0 : index to i16
575 // CHECK-LABEL: index_cast3
576 func @index_cast3(%arg0: i32) {
577 // CHECK-NOT: spv.SConvert
578 %0 = arith.index_cast %arg0 : i32 to index
582 // CHECK-LABEL: index_cast4
583 func @index_cast4(%arg0: index) {
584 // CHECK-NOT: spv.SConvert
585 %0 = arith.index_cast %arg0 : index to i32
589 // CHECK-LABEL: @bit_cast
590 func @bit_cast(%arg0: vector<2xf32>, %arg1: i64) {
591 // CHECK: spv.Bitcast %{{.+}} : vector<2xf32> to vector<2xi32>
592 %0 = arith.bitcast %arg0 : vector<2xf32> to vector<2xi32>
593 // CHECK: spv.Bitcast %{{.+}} : i64 to f64
594 %1 = arith.bitcast %arg1 : i64 to f64
598 // CHECK-LABEL: @fpext1
599 func @fpext1(%arg0: f16) -> f64 {
600 // CHECK: spv.FConvert %{{.*}} : f16 to f64
601 %0 = arith.extf %arg0 : f16 to f64
605 // CHECK-LABEL: @fpext2
606 func @fpext2(%arg0 : f32) -> f64 {
607 // CHECK: spv.FConvert %{{.*}} : f32 to f64
608 %0 = arith.extf %arg0 : f32 to f64
612 // CHECK-LABEL: @fptrunc1
613 func @fptrunc1(%arg0 : f64) -> f16 {
614 // CHECK: spv.FConvert %{{.*}} : f64 to f16
615 %0 = arith.truncf %arg0 : f64 to f16
619 // CHECK-LABEL: @fptrunc2
620 func @fptrunc2(%arg0: f32) -> f16 {
621 // CHECK: spv.FConvert %{{.*}} : f32 to f16
622 %0 = arith.truncf %arg0 : f32 to f16
626 // CHECK-LABEL: @sitofp1
627 func @sitofp1(%arg0 : i32) -> f32 {
628 // CHECK: spv.ConvertSToF %{{.*}} : i32 to f32
629 %0 = arith.sitofp %arg0 : i32 to f32
633 // CHECK-LABEL: @sitofp2
634 func @sitofp2(%arg0 : i64) -> f64 {
635 // CHECK: spv.ConvertSToF %{{.*}} : i64 to f64
636 %0 = arith.sitofp %arg0 : i64 to f64
640 // CHECK-LABEL: @uitofp_i16_f32
641 func @uitofp_i16_f32(%arg0: i16) -> f32 {
642 // CHECK: spv.ConvertUToF %{{.*}} : i16 to f32
643 %0 = arith.uitofp %arg0 : i16 to f32
647 // CHECK-LABEL: @uitofp_i32_f32
648 func @uitofp_i32_f32(%arg0 : i32) -> f32 {
649 // CHECK: spv.ConvertUToF %{{.*}} : i32 to f32
650 %0 = arith.uitofp %arg0 : i32 to f32
654 // CHECK-LABEL: @uitofp_i1_f32
655 func @uitofp_i1_f32(%arg0 : i1) -> f32 {
656 // CHECK: %[[ZERO:.+]] = spv.Constant 0.000000e+00 : f32
657 // CHECK: %[[ONE:.+]] = spv.Constant 1.000000e+00 : f32
658 // CHECK: spv.Select %{{.*}}, %[[ONE]], %[[ZERO]] : i1, f32
659 %0 = arith.uitofp %arg0 : i1 to f32
663 // CHECK-LABEL: @uitofp_i1_f64
664 func @uitofp_i1_f64(%arg0 : i1) -> f64 {
665 // CHECK: %[[ZERO:.+]] = spv.Constant 0.000000e+00 : f64
666 // CHECK: %[[ONE:.+]] = spv.Constant 1.000000e+00 : f64
667 // CHECK: spv.Select %{{.*}}, %[[ONE]], %[[ZERO]] : i1, f64
668 %0 = arith.uitofp %arg0 : i1 to f64
672 // CHECK-LABEL: @uitofp_vec_i1_f32
673 func @uitofp_vec_i1_f32(%arg0 : vector<4xi1>) -> vector<4xf32> {
674 // CHECK: %[[ZERO:.+]] = spv.Constant dense<0.000000e+00> : vector<4xf32>
675 // CHECK: %[[ONE:.+]] = spv.Constant dense<1.000000e+00> : vector<4xf32>
676 // CHECK: spv.Select %{{.*}}, %[[ONE]], %[[ZERO]] : vector<4xi1>, vector<4xf32>
677 %0 = arith.uitofp %arg0 : vector<4xi1> to vector<4xf32>
678 return %0 : vector<4xf32>
681 // CHECK-LABEL: @uitofp_vec_i1_f64
682 spv.func @uitofp_vec_i1_f64(%arg0: vector<4xi1>) -> vector<4xf64> "None" {
683 // CHECK: %[[ZERO:.+]] = spv.Constant dense<0.000000e+00> : vector<4xf64>
684 // CHECK: %[[ONE:.+]] = spv.Constant dense<1.000000e+00> : vector<4xf64>
685 // CHECK: spv.Select %{{.*}}, %[[ONE]], %[[ZERO]] : vector<4xi1>, vector<4xf64>
686 %0 = spv.Constant dense<0.000000e+00> : vector<4xf64>
687 %1 = spv.Constant dense<1.000000e+00> : vector<4xf64>
688 %2 = spv.Select %arg0, %1, %0 : vector<4xi1>, vector<4xf64>
689 spv.ReturnValue %2 : vector<4xf64>
692 // CHECK-LABEL: @sexti1
693 func @sexti1(%arg0: i16) -> i64 {
694 // CHECK: spv.SConvert %{{.*}} : i16 to i64
695 %0 = arith.extsi %arg0 : i16 to i64
699 // CHECK-LABEL: @sexti2
700 func @sexti2(%arg0 : i32) -> i64 {
701 // CHECK: spv.SConvert %{{.*}} : i32 to i64
702 %0 = arith.extsi %arg0 : i32 to i64
706 // CHECK-LABEL: @zexti1
707 func @zexti1(%arg0: i16) -> i64 {
708 // CHECK: spv.UConvert %{{.*}} : i16 to i64
709 %0 = arith.extui %arg0 : i16 to i64
713 // CHECK-LABEL: @zexti2
714 func @zexti2(%arg0 : i32) -> i64 {
715 // CHECK: spv.UConvert %{{.*}} : i32 to i64
716 %0 = arith.extui %arg0 : i32 to i64
720 // CHECK-LABEL: @zexti3
721 func @zexti3(%arg0 : i1) -> i32 {
722 // CHECK: %[[ZERO:.+]] = spv.Constant 0 : i32
723 // CHECK: %[[ONE:.+]] = spv.Constant 1 : i32
724 // CHECK: spv.Select %{{.*}}, %[[ONE]], %[[ZERO]] : i1, i32
725 %0 = arith.extui %arg0 : i1 to i32
729 // CHECK-LABEL: @zexti4
730 func @zexti4(%arg0 : vector<4xi1>) -> vector<4xi32> {
731 // CHECK: %[[ZERO:.+]] = spv.Constant dense<0> : vector<4xi32>
732 // CHECK: %[[ONE:.+]] = spv.Constant dense<1> : vector<4xi32>
733 // CHECK: spv.Select %{{.*}}, %[[ONE]], %[[ZERO]] : vector<4xi1>, vector<4xi32>
734 %0 = arith.extui %arg0 : vector<4xi1> to vector<4xi32>
735 return %0 : vector<4xi32>
738 // CHECK-LABEL: @zexti5
739 func @zexti5(%arg0 : vector<4xi1>) -> vector<4xi64> {
740 // CHECK: %[[ZERO:.+]] = spv.Constant dense<0> : vector<4xi64>
741 // CHECK: %[[ONE:.+]] = spv.Constant dense<1> : vector<4xi64>
742 // CHECK: spv.Select %{{.*}}, %[[ONE]], %[[ZERO]] : vector<4xi1>, vector<4xi64>
743 %0 = arith.extui %arg0 : vector<4xi1> to vector<4xi64>
744 return %0 : vector<4xi64>
747 // CHECK-LABEL: @trunci1
748 func @trunci1(%arg0 : i64) -> i16 {
749 // CHECK: spv.SConvert %{{.*}} : i64 to i16
750 %0 = arith.trunci %arg0 : i64 to i16
754 // CHECK-LABEL: @trunci2
755 func @trunci2(%arg0: i32) -> i16 {
756 // CHECK: spv.SConvert %{{.*}} : i32 to i16
757 %0 = arith.trunci %arg0 : i32 to i16
761 // CHECK-LABEL: @trunc_to_i1
762 func @trunc_to_i1(%arg0: i32) -> i1 {
763 // CHECK: %[[MASK:.*]] = spv.Constant 1 : i32
764 // CHECK: %[[MASKED_SRC:.*]] = spv.BitwiseAnd %{{.*}}, %[[MASK]] : i32
765 // CHECK: %[[IS_ONE:.*]] = spv.IEqual %[[MASKED_SRC]], %[[MASK]] : i32
766 // CHECK-DAG: %[[TRUE:.*]] = spv.Constant true
767 // CHECK-DAG: %[[FALSE:.*]] = spv.Constant false
768 // CHECK: spv.Select %[[IS_ONE]], %[[TRUE]], %[[FALSE]] : i1, i1
769 %0 = arith.trunci %arg0 : i32 to i1
773 // CHECK-LABEL: @trunc_to_veci1
774 func @trunc_to_veci1(%arg0: vector<4xi32>) -> vector<4xi1> {
775 // CHECK: %[[MASK:.*]] = spv.Constant dense<1> : vector<4xi32>
776 // CHECK: %[[MASKED_SRC:.*]] = spv.BitwiseAnd %{{.*}}, %[[MASK]] : vector<4xi32>
777 // CHECK: %[[IS_ONE:.*]] = spv.IEqual %[[MASKED_SRC]], %[[MASK]] : vector<4xi32>
778 // CHECK-DAG: %[[TRUE:.*]] = spv.Constant dense<true> : vector<4xi1>
779 // CHECK-DAG: %[[FALSE:.*]] = spv.Constant dense<false> : vector<4xi1>
780 // CHECK: spv.Select %[[IS_ONE]], %[[TRUE]], %[[FALSE]] : vector<4xi1>, vector<4xi1>
781 %0 = arith.trunci %arg0 : vector<4xi32> to vector<4xi1>
782 return %0 : vector<4xi1>
785 // CHECK-LABEL: @fptosi1
786 func @fptosi1(%arg0 : f32) -> i32 {
787 // CHECK: spv.ConvertFToS %{{.*}} : f32 to i32
788 %0 = arith.fptosi %arg0 : f32 to i32
792 // CHECK-LABEL: @fptosi2
793 func @fptosi2(%arg0 : f16) -> i16 {
794 // CHECK: spv.ConvertFToS %{{.*}} : f16 to i16
795 %0 = arith.fptosi %arg0 : f16 to i16
803 // Checks that cast types will be adjusted when missing special capabilities for
804 // certain non-32-bit scalar types.
806 spv.target_env = #spv.target_env<#spv.vce<v1.0, [Float64], []>, {}>
809 // CHECK-LABEL: @fpext1
810 // CHECK-SAME: %[[ARG:.*]]: f32
811 func @fpext1(%arg0: f16) -> f64 {
812 // CHECK-NEXT: spv.FConvert %[[ARG]] : f32 to f64
813 %0 = arith.extf %arg0 : f16 to f64
817 // CHECK-LABEL: @fpext2
818 // CHECK-SAME: %[[ARG:.*]]: f32
819 func @fpext2(%arg0 : f32) -> f64 {
820 // CHECK-NEXT: spv.FConvert %[[ARG]] : f32 to f64
821 %0 = arith.extf %arg0 : f32 to f64
829 // Checks that cast types will be adjusted when missing special capabilities for
830 // certain non-32-bit scalar types.
832 spv.target_env = #spv.target_env<#spv.vce<v1.0, [Float16], []>, {}>
835 // CHECK-LABEL: @fptrunc1
836 // CHECK-SAME: %[[ARG:.*]]: f32
837 func @fptrunc1(%arg0 : f64) -> f16 {
838 // CHECK-NEXT: spv.FConvert %[[ARG]] : f32 to f16
839 %0 = arith.truncf %arg0 : f64 to f16
843 // CHECK-LABEL: @fptrunc2
844 // CHECK-SAME: %[[ARG:.*]]: f32
845 func @fptrunc2(%arg0: f32) -> f16 {
846 // CHECK-NEXT: spv.FConvert %[[ARG]] : f32 to f16
847 %0 = arith.truncf %arg0 : f32 to f16
851 // CHECK-LABEL: @sitofp
852 func @sitofp(%arg0 : i64) -> f64 {
853 // CHECK: spv.ConvertSToF %{{.*}} : i32 to f32
854 %0 = arith.sitofp %arg0 : i64 to f64
862 // Check OpenCL lowering of arith.remsi
864 spv.target_env = #spv.target_env<
865 #spv.vce<v1.0, [Int16, Kernel], []>, {}>
868 // CHECK-LABEL: @scalar_srem
869 // CHECK-SAME: (%[[LHS:.+]]: i32, %[[RHS:.+]]: i32)
870 func @scalar_srem(%lhs: i32, %rhs: i32) {
871 // CHECK: %[[LABS:.+]] = spv.OCL.s_abs %[[LHS]] : i32
872 // CHECK: %[[RABS:.+]] = spv.OCL.s_abs %[[RHS]] : i32
873 // CHECK: %[[ABS:.+]] = spv.UMod %[[LABS]], %[[RABS]] : i32
874 // CHECK: %[[POS:.+]] = spv.IEqual %[[LHS]], %[[LABS]] : i32
875 // CHECK: %[[NEG:.+]] = spv.SNegate %[[ABS]] : i32
876 // CHECK: %{{.+}} = spv.Select %[[POS]], %[[ABS]], %[[NEG]] : i1, i32
877 %0 = arith.remsi %lhs, %rhs: i32
881 // CHECK-LABEL: @vector_srem
882 // CHECK-SAME: (%[[LHS:.+]]: vector<3xi16>, %[[RHS:.+]]: vector<3xi16>)
883 func @vector_srem(%arg0: vector<3xi16>, %arg1: vector<3xi16>) {
884 // CHECK: %[[LABS:.+]] = spv.OCL.s_abs %[[LHS]] : vector<3xi16>
885 // CHECK: %[[RABS:.+]] = spv.OCL.s_abs %[[RHS]] : vector<3xi16>
886 // CHECK: %[[ABS:.+]] = spv.UMod %[[LABS]], %[[RABS]] : vector<3xi16>
887 // CHECK: %[[POS:.+]] = spv.IEqual %[[LHS]], %[[LABS]] : vector<3xi16>
888 // CHECK: %[[NEG:.+]] = spv.SNegate %[[ABS]] : vector<3xi16>
889 // CHECK: %{{.+}} = spv.Select %[[POS]], %[[ABS]], %[[NEG]] : vector<3xi1>, vector<3xi16>
890 %0 = arith.remsi %arg0, %arg1: vector<3xi16>