1 // RUN: mlir-opt %s -split-input-file -pass-pipeline='func(canonicalize)' | FileCheck %s
3 //===----------------------------------------------------------------------===//
5 //===----------------------------------------------------------------------===//
7 func @combine_full_access_chain() -> f32 {
8 // CHECK: %[[INDEX:.*]] = spv.constant 0
9 // CHECK-NEXT: %[[VAR:.*]] = spv.Variable
10 // CHECK-NEXT: %[[PTR:.*]] = spv.AccessChain %[[VAR]][%[[INDEX]], %[[INDEX]], %[[INDEX]]]
11 // CHECK-NEXT: spv.Load "Function" %[[PTR]]
12 %c0 = spv.constant 0: i32
13 %0 = spv.Variable : !spv.ptr<!spv.struct<(!spv.array<4x!spv.array<4xf32>>, !spv.array<4xi32>)>, Function>
14 %1 = spv.AccessChain %0[%c0] : !spv.ptr<!spv.struct<(!spv.array<4x!spv.array<4xf32>>, !spv.array<4xi32>)>, Function>, i32
15 %2 = spv.AccessChain %1[%c0, %c0] : !spv.ptr<!spv.array<4x!spv.array<4xf32>>, Function>, i32, i32
16 %3 = spv.Load "Function" %2 : f32
17 spv.ReturnValue %3 : f32
22 func @combine_access_chain_multi_use() -> !spv.array<4xf32> {
23 // CHECK: %[[INDEX:.*]] = spv.constant 0
24 // CHECK-NEXT: %[[VAR:.*]] = spv.Variable
25 // CHECK-NEXT: %[[PTR_0:.*]] = spv.AccessChain %[[VAR]][%[[INDEX]], %[[INDEX]]]
26 // CHECK-NEXT: %[[PTR_1:.*]] = spv.AccessChain %[[VAR]][%[[INDEX]], %[[INDEX]], %[[INDEX]]]
27 // CHECK-NEXT: spv.Load "Function" %[[PTR_0]]
28 // CHECK-NEXT: spv.Load "Function" %[[PTR_1]]
29 %c0 = spv.constant 0: i32
30 %0 = spv.Variable : !spv.ptr<!spv.struct<(!spv.array<4x!spv.array<4xf32>>, !spv.array<4xi32>)>, Function>
31 %1 = spv.AccessChain %0[%c0] : !spv.ptr<!spv.struct<(!spv.array<4x!spv.array<4xf32>>, !spv.array<4xi32>)>, Function>, i32
32 %2 = spv.AccessChain %1[%c0] : !spv.ptr<!spv.array<4x!spv.array<4xf32>>, Function>, i32
33 %3 = spv.AccessChain %2[%c0] : !spv.ptr<!spv.array<4xf32>, Function>, i32
34 %4 = spv.Load "Function" %2 : !spv.array<4xf32>
35 %5 = spv.Load "Function" %3 : f32
36 spv.ReturnValue %4: !spv.array<4xf32>
41 func @dont_combine_access_chain_without_common_base() -> !spv.array<4xi32> {
42 // CHECK: %[[INDEX:.*]] = spv.constant 1
43 // CHECK-NEXT: %[[VAR_0:.*]] = spv.Variable
44 // CHECK-NEXT: %[[VAR_1:.*]] = spv.Variable
45 // CHECK-NEXT: %[[VAR_0_PTR:.*]] = spv.AccessChain %[[VAR_0]][%[[INDEX]]]
46 // CHECK-NEXT: %[[VAR_1_PTR:.*]] = spv.AccessChain %[[VAR_1]][%[[INDEX]]]
47 // CHECK-NEXT: spv.Load "Function" %[[VAR_0_PTR]]
48 // CHECK-NEXT: spv.Load "Function" %[[VAR_1_PTR]]
49 %c1 = spv.constant 1: i32
50 %0 = spv.Variable : !spv.ptr<!spv.struct<(!spv.array<4x!spv.array<4xf32>>, !spv.array<4xi32>)>, Function>
51 %1 = spv.Variable : !spv.ptr<!spv.struct<(!spv.array<4x!spv.array<4xf32>>, !spv.array<4xi32>)>, Function>
52 %2 = spv.AccessChain %0[%c1] : !spv.ptr<!spv.struct<(!spv.array<4x!spv.array<4xf32>>, !spv.array<4xi32>)>, Function>, i32
53 %3 = spv.AccessChain %1[%c1] : !spv.ptr<!spv.struct<(!spv.array<4x!spv.array<4xf32>>, !spv.array<4xi32>)>, Function>, i32
54 %4 = spv.Load "Function" %2 : !spv.array<4xi32>
55 %5 = spv.Load "Function" %3 : !spv.array<4xi32>
56 spv.ReturnValue %4 : !spv.array<4xi32>
61 //===----------------------------------------------------------------------===//
63 //===----------------------------------------------------------------------===//
65 func @convert_bitcast_full(%arg0 : vector<2xf32>) -> f64 {
66 // CHECK: %[[RESULT:.*]] = spv.Bitcast {{%.*}} : vector<2xf32> to f64
67 // CHECK-NEXT: spv.ReturnValue %[[RESULT]]
68 %0 = spv.Bitcast %arg0 : vector<2xf32> to vector<2xi32>
69 %1 = spv.Bitcast %0 : vector<2xi32> to i64
70 %2 = spv.Bitcast %1 : i64 to f64
71 spv.ReturnValue %2 : f64
76 func @convert_bitcast_multi_use(%arg0 : vector<2xf32>, %arg1 : !spv.ptr<i64, Uniform>) -> f64 {
77 // CHECK: %[[RESULT_0:.*]] = spv.Bitcast {{%.*}} : vector<2xf32> to i64
78 // CHECK-NEXT: %[[RESULT_1:.*]] = spv.Bitcast {{%.*}} : vector<2xf32> to f64
79 // CHECK-NEXT: spv.Store {{".*"}} {{%.*}}, %[[RESULT_0]]
80 // CHECK-NEXT: spv.ReturnValue %[[RESULT_1]]
81 %0 = spv.Bitcast %arg0 : vector<2xf32> to i64
82 %1 = spv.Bitcast %0 : i64 to f64
83 spv.Store "Uniform" %arg1, %0 : i64
84 spv.ReturnValue %1 : f64
89 //===----------------------------------------------------------------------===//
90 // spv.CompositeExtract
91 //===----------------------------------------------------------------------===//
93 // CHECK-LABEL: extract_vector
94 func @extract_vector() -> (i32, i32, i32) {
95 // CHECK: spv.constant 42 : i32
96 // CHECK: spv.constant -33 : i32
97 // CHECK: spv.constant 6 : i32
98 %0 = spv.constant dense<[42, -33, 6]> : vector<3xi32>
99 %1 = spv.CompositeExtract %0[0 : i32] : vector<3xi32>
100 %2 = spv.CompositeExtract %0[1 : i32] : vector<3xi32>
101 %3 = spv.CompositeExtract %0[2 : i32] : vector<3xi32>
102 return %1, %2, %3 : i32, i32, i32
107 // CHECK-LABEL: extract_array_final
108 func @extract_array_final() -> (i32, i32) {
109 // CHECK: spv.constant 4 : i32
110 // CHECK: spv.constant -5 : i32
111 %0 = spv.constant [dense<[4, -5]> : vector<2xi32>] : !spv.array<1 x vector<2xi32>>
112 %1 = spv.CompositeExtract %0[0 : i32, 0 : i32] : !spv.array<1 x vector<2 x i32>>
113 %2 = spv.CompositeExtract %0[0 : i32, 1 : i32] : !spv.array<1 x vector<2 x i32>>
114 return %1, %2 : i32, i32
119 // CHECK-LABEL: extract_array_interm
120 func @extract_array_interm() -> (vector<2xi32>) {
121 // CHECK: spv.constant dense<[4, -5]> : vector<2xi32>
122 %0 = spv.constant [dense<[4, -5]> : vector<2xi32>] : !spv.array<1 x vector<2xi32>>
123 %1 = spv.CompositeExtract %0[0 : i32] : !spv.array<1 x vector<2 x i32>>
124 return %1 : vector<2xi32>
129 // CHECK-LABEL: extract_from_not_constant
130 func @extract_from_not_constant() -> i32 {
131 %0 = spv.Variable : !spv.ptr<vector<3xi32>, Function>
132 %1 = spv.Load "Function" %0 : vector<3xi32>
133 // CHECK: spv.CompositeExtract
134 %2 = spv.CompositeExtract %1[0 : i32] : vector<3xi32>
135 spv.ReturnValue %2 : i32
140 //===----------------------------------------------------------------------===//
142 //===----------------------------------------------------------------------===//
144 // TODO: test constants in different blocks
146 func @deduplicate_scalar_constant() -> (i32, i32) {
147 // CHECK: %[[CST:.*]] = spv.constant 42 : i32
148 %0 = spv.constant 42 : i32
149 %1 = spv.constant 42 : i32
150 // CHECK-NEXT: return %[[CST]], %[[CST]]
151 return %0, %1 : i32, i32
156 func @deduplicate_vector_constant() -> (vector<3xi32>, vector<3xi32>) {
157 // CHECK: %[[CST:.*]] = spv.constant dense<[1, 2, 3]> : vector<3xi32>
158 %0 = spv.constant dense<[1, 2, 3]> : vector<3xi32>
159 %1 = spv.constant dense<[1, 2, 3]> : vector<3xi32>
160 // CHECK-NEXT: return %[[CST]], %[[CST]]
161 return %0, %1 : vector<3xi32>, vector<3xi32>
166 func @deduplicate_composite_constant() -> (!spv.array<1 x vector<2xi32>>, !spv.array<1 x vector<2xi32>>) {
167 // CHECK: %[[CST:.*]] = spv.constant [dense<5> : vector<2xi32>] : !spv.array<1 x vector<2xi32>>
168 %0 = spv.constant [dense<5> : vector<2xi32>] : !spv.array<1 x vector<2xi32>>
169 %1 = spv.constant [dense<5> : vector<2xi32>] : !spv.array<1 x vector<2xi32>>
170 // CHECK-NEXT: return %[[CST]], %[[CST]]
171 return %0, %1 : !spv.array<1 x vector<2xi32>>, !spv.array<1 x vector<2xi32>>
176 //===----------------------------------------------------------------------===//
178 //===----------------------------------------------------------------------===//
180 // CHECK-LABEL: @iadd_zero
181 // CHECK-SAME: (%[[ARG:.*]]: i32)
182 func @iadd_zero(%arg0: i32) -> (i32, i32) {
183 %zero = spv.constant 0 : i32
184 %0 = spv.IAdd %arg0, %zero : i32
185 %1 = spv.IAdd %zero, %arg0 : i32
186 // CHECK: return %[[ARG]], %[[ARG]]
187 return %0, %1: i32, i32
190 // CHECK-LABEL: @const_fold_scalar_iadd_normal
191 func @const_fold_scalar_iadd_normal() -> (i32, i32, i32) {
192 %c5 = spv.constant 5 : i32
193 %cn8 = spv.constant -8 : i32
195 // CHECK: spv.constant 10
196 // CHECK: spv.constant -16
197 // CHECK: spv.constant -3
198 %0 = spv.IAdd %c5, %c5 : i32
199 %1 = spv.IAdd %cn8, %cn8 : i32
200 %2 = spv.IAdd %c5, %cn8 : i32
201 return %0, %1, %2: i32, i32, i32
204 // CHECK-LABEL: @const_fold_scalar_iadd_flow
205 func @const_fold_scalar_iadd_flow() -> (i32, i32, i32, i32) {
206 %c1 = spv.constant 1 : i32
207 %c2 = spv.constant 2 : i32
208 %c3 = spv.constant 4294967295 : i32 // 2^32 - 1: 0xffff ffff
209 %c4 = spv.constant -2147483648 : i32 // -2^31 : 0x8000 0000
210 %c5 = spv.constant -1 : i32 // : 0xffff ffff
211 %c6 = spv.constant -2 : i32 // : 0xffff fffe
213 // 0x0000 0001 + 0xffff ffff = 0x1 0000 0000 -> 0x0000 0000
214 // CHECK: spv.constant 0
215 %0 = spv.IAdd %c1, %c3 : i32
216 // 0x0000 0002 + 0xffff ffff = 0x1 0000 0001 -> 0x0000 0001
217 // CHECK: spv.constant 1
218 %1 = spv.IAdd %c2, %c3 : i32
219 // 0x8000 0000 + 0xffff ffff = 0x1 7fff ffff -> 0x7fff ffff
220 // CHECK: spv.constant 2147483647
221 %2 = spv.IAdd %c4, %c5 : i32
222 // 0x8000 0000 + 0xffff fffe = 0x1 7fff fffe -> 0x7fff fffe
223 // CHECK: spv.constant 2147483646
224 %3 = spv.IAdd %c4, %c6 : i32
225 return %0, %1, %2, %3: i32, i32, i32, i32
228 // CHECK-LABEL: @const_fold_vector_iadd
229 func @const_fold_vector_iadd() -> vector<3xi32> {
230 %vc1 = spv.constant dense<[42, -55, 127]> : vector<3xi32>
231 %vc2 = spv.constant dense<[-3, -15, 28]> : vector<3xi32>
233 // CHECK: spv.constant dense<[39, -70, 155]>
234 %0 = spv.IAdd %vc1, %vc2 : vector<3xi32>
235 return %0: vector<3xi32>
240 //===----------------------------------------------------------------------===//
242 //===----------------------------------------------------------------------===//
244 // CHECK-LABEL: @imul_zero_one
245 // CHECK-SAME: (%[[ARG:.*]]: i32)
246 func @imul_zero_one(%arg0: i32) -> (i32, i32) {
247 // CHECK: %[[ZERO:.*]] = spv.constant 0
248 %zero = spv.constant 0 : i32
249 %one = spv.constant 1: i32
250 %0 = spv.IMul %arg0, %zero : i32
251 %1 = spv.IMul %one, %arg0 : i32
252 // CHECK: return %[[ZERO]], %[[ARG]]
253 return %0, %1: i32, i32
256 // CHECK-LABEL: @const_fold_scalar_imul_normal
257 func @const_fold_scalar_imul_normal() -> (i32, i32, i32) {
258 %c5 = spv.constant 5 : i32
259 %cn8 = spv.constant -8 : i32
260 %c7 = spv.constant 7 : i32
262 // CHECK: spv.constant 35
263 // CHECK: spv.constant -40
264 // CHECK: spv.constant -56
265 %0 = spv.IMul %c7, %c5 : i32
266 %1 = spv.IMul %c5, %cn8 : i32
267 %2 = spv.IMul %cn8, %c7 : i32
268 return %0, %1, %2: i32, i32, i32
271 // CHECK-LABEL: @const_fold_scalar_imul_flow
272 func @const_fold_scalar_imul_flow() -> (i32, i32, i32) {
273 %c1 = spv.constant 2 : i32
274 %c2 = spv.constant 4 : i32
275 %c3 = spv.constant 4294967295 : i32 // 2^32 - 1 : 0xffff ffff
276 %c4 = spv.constant 2147483647 : i32 // 2^31 - 1 : 0x7fff ffff
278 // (0xffff ffff << 1) = 0x1 ffff fffe -> 0xffff fffe
279 // CHECK: %[[CST2:.*]] = spv.constant -2
280 %0 = spv.IMul %c1, %c3 : i32
281 // (0x7fff ffff << 1) = 0x0 ffff fffe -> 0xffff fffe
282 %1 = spv.IMul %c1, %c4 : i32
283 // (0x7fff ffff << 2) = 0x1 ffff fffc -> 0xffff fffc
284 // CHECK: %[[CST4:.*]] = spv.constant -4
285 %2 = spv.IMul %c4, %c2 : i32
286 // CHECK: return %[[CST2]], %[[CST2]], %[[CST4]]
287 return %0, %1, %2: i32, i32, i32
291 // CHECK-LABEL: @const_fold_vector_imul
292 func @const_fold_vector_imul() -> vector<3xi32> {
293 %vc1 = spv.constant dense<[42, -55, 127]> : vector<3xi32>
294 %vc2 = spv.constant dense<[-3, -15, 28]> : vector<3xi32>
296 // CHECK: spv.constant dense<[-126, 825, 3556]>
297 %0 = spv.IMul %vc1, %vc2 : vector<3xi32>
298 return %0: vector<3xi32>
303 //===----------------------------------------------------------------------===//
305 //===----------------------------------------------------------------------===//
307 // CHECK-LABEL: @isub_x_x
308 func @isub_x_x(%arg0: i32) -> i32 {
309 // CHECK: spv.constant 0
310 %0 = spv.ISub %arg0, %arg0: i32
314 // CHECK-LABEL: @const_fold_scalar_isub_normal
315 func @const_fold_scalar_isub_normal() -> (i32, i32, i32) {
316 %c5 = spv.constant 5 : i32
317 %cn8 = spv.constant -8 : i32
318 %c7 = spv.constant 7 : i32
320 // CHECK: spv.constant 2
321 // CHECK: spv.constant 13
322 // CHECK: spv.constant -15
323 %0 = spv.ISub %c7, %c5 : i32
324 %1 = spv.ISub %c5, %cn8 : i32
325 %2 = spv.ISub %cn8, %c7 : i32
326 return %0, %1, %2: i32, i32, i32
329 // CHECK-LABEL: @const_fold_scalar_isub_flow
330 func @const_fold_scalar_isub_flow() -> (i32, i32, i32, i32) {
331 %c1 = spv.constant 0 : i32
332 %c2 = spv.constant 1 : i32
333 %c3 = spv.constant 4294967295 : i32 // 2^32 - 1 : 0xffff ffff
334 %c4 = spv.constant 2147483647 : i32 // 2^31 : 0x7fff ffff
335 %c5 = spv.constant -1 : i32 // : 0xffff ffff
336 %c6 = spv.constant -2 : i32 // : 0xffff fffe
338 // 0x0000 0000 - 0xffff ffff -> 0x0000 0000 + 0x0000 0001 = 0x0000 0001
339 // CHECK: spv.constant 1
340 %0 = spv.ISub %c1, %c3 : i32
341 // 0x0000 0001 - 0xffff ffff -> 0x0000 0001 + 0x0000 0001 = 0x0000 0002
342 // CHECK: spv.constant 2
343 %1 = spv.ISub %c2, %c3 : i32
344 // 0xffff ffff - 0x7fff ffff -> 0xffff ffff + 0x8000 0001 = 0x1 8000 0000
345 // CHECK: spv.constant -2147483648
346 %2 = spv.ISub %c5, %c4 : i32
347 // 0xffff fffe - 0x7fff ffff -> 0xffff fffe + 0x8000 0001 = 0x1 7fff ffff
348 // CHECK: spv.constant 2147483647
349 %3 = spv.ISub %c6, %c4 : i32
350 return %0, %1, %2, %3: i32, i32, i32, i32
353 // CHECK-LABEL: @const_fold_vector_isub
354 func @const_fold_vector_isub() -> vector<3xi32> {
355 %vc1 = spv.constant dense<[42, -55, 127]> : vector<3xi32>
356 %vc2 = spv.constant dense<[-3, -15, 28]> : vector<3xi32>
358 // CHECK: spv.constant dense<[45, -40, 99]>
359 %0 = spv.ISub %vc1, %vc2 : vector<3xi32>
360 return %0: vector<3xi32>
365 //===----------------------------------------------------------------------===//
367 //===----------------------------------------------------------------------===//
369 // CHECK-LABEL: @convert_logical_and_true_false_scalar
370 // CHECK-SAME: %[[ARG:.+]]: i1
371 func @convert_logical_and_true_false_scalar(%arg: i1) -> (i1, i1) {
372 %true = spv.constant true
373 // CHECK: %[[FALSE:.+]] = spv.constant false
374 %false = spv.constant false
375 %0 = spv.LogicalAnd %true, %arg: i1
376 %1 = spv.LogicalAnd %arg, %false: i1
377 // CHECK: return %[[ARG]], %[[FALSE]]
378 return %0, %1: i1, i1
381 // CHECK-LABEL: @convert_logical_and_true_false_vector
382 // CHECK-SAME: %[[ARG:.+]]: vector<3xi1>
383 func @convert_logical_and_true_false_vector(%arg: vector<3xi1>) -> (vector<3xi1>, vector<3xi1>) {
384 %true = spv.constant dense<true> : vector<3xi1>
385 // CHECK: %[[FALSE:.+]] = spv.constant dense<false>
386 %false = spv.constant dense<false> : vector<3xi1>
387 %0 = spv.LogicalAnd %true, %arg: vector<3xi1>
388 %1 = spv.LogicalAnd %arg, %false: vector<3xi1>
389 // CHECK: return %[[ARG]], %[[FALSE]]
390 return %0, %1: vector<3xi1>, vector<3xi1>
395 //===----------------------------------------------------------------------===//
397 //===----------------------------------------------------------------------===//
399 func @convert_logical_not_to_not_equal(%arg0: vector<3xi64>, %arg1: vector<3xi64>) -> vector<3xi1> {
400 // CHECK: %[[RESULT:.*]] = spv.INotEqual {{%.*}}, {{%.*}} : vector<3xi64>
401 // CHECK-NEXT: spv.ReturnValue %[[RESULT]] : vector<3xi1>
402 %2 = spv.IEqual %arg0, %arg1 : vector<3xi64>
403 %3 = spv.LogicalNot %2 : vector<3xi1>
404 spv.ReturnValue %3 : vector<3xi1>
409 func @convert_logical_not_to_equal(%arg0: vector<3xi64>, %arg1: vector<3xi64>) -> vector<3xi1> {
410 // CHECK: %[[RESULT:.*]] = spv.IEqual {{%.*}}, {{%.*}} : vector<3xi64>
411 // CHECK-NEXT: spv.ReturnValue %[[RESULT]] : vector<3xi1>
412 %2 = spv.INotEqual %arg0, %arg1 : vector<3xi64>
413 %3 = spv.LogicalNot %2 : vector<3xi1>
414 spv.ReturnValue %3 : vector<3xi1>
419 func @convert_logical_not_parent_multi_use(%arg0: vector<3xi64>, %arg1: vector<3xi64>, %arg2: !spv.ptr<vector<3xi1>, Uniform>) -> vector<3xi1> {
420 // CHECK: %[[RESULT_0:.*]] = spv.INotEqual {{%.*}}, {{%.*}} : vector<3xi64>
421 // CHECK-NEXT: %[[RESULT_1:.*]] = spv.IEqual {{%.*}}, {{%.*}} : vector<3xi64>
422 // CHECK-NEXT: spv.Store "Uniform" {{%.*}}, %[[RESULT_0]]
423 // CHECK-NEXT: spv.ReturnValue %[[RESULT_1]]
424 %0 = spv.INotEqual %arg0, %arg1 : vector<3xi64>
425 %1 = spv.LogicalNot %0 : vector<3xi1>
426 spv.Store "Uniform" %arg2, %0 : vector<3xi1>
427 spv.ReturnValue %1 : vector<3xi1>
432 func @convert_logical_not_to_logical_not_equal(%arg0: vector<3xi1>, %arg1: vector<3xi1>) -> vector<3xi1> {
433 // CHECK: %[[RESULT:.*]] = spv.LogicalNotEqual {{%.*}}, {{%.*}} : vector<3xi1>
434 // CHECK-NEXT: spv.ReturnValue %[[RESULT]] : vector<3xi1>
435 %2 = spv.LogicalEqual %arg0, %arg1 : vector<3xi1>
436 %3 = spv.LogicalNot %2 : vector<3xi1>
437 spv.ReturnValue %3 : vector<3xi1>
442 func @convert_logical_not_to_logical_equal(%arg0: vector<3xi1>, %arg1: vector<3xi1>) -> vector<3xi1> {
443 // CHECK: %[[RESULT:.*]] = spv.LogicalEqual {{%.*}}, {{%.*}} : vector<3xi1>
444 // CHECK-NEXT: spv.ReturnValue %[[RESULT]] : vector<3xi1>
445 %2 = spv.LogicalNotEqual %arg0, %arg1 : vector<3xi1>
446 %3 = spv.LogicalNot %2 : vector<3xi1>
447 spv.ReturnValue %3 : vector<3xi1>
452 //===----------------------------------------------------------------------===//
454 //===----------------------------------------------------------------------===//
456 // CHECK-LABEL: @convert_logical_or_true_false_scalar
457 // CHECK-SAME: %[[ARG:.+]]: i1
458 func @convert_logical_or_true_false_scalar(%arg: i1) -> (i1, i1) {
459 // CHECK: %[[TRUE:.+]] = spv.constant true
460 %true = spv.constant true
461 %false = spv.constant false
462 %0 = spv.LogicalOr %true, %arg: i1
463 %1 = spv.LogicalOr %arg, %false: i1
464 // CHECK: return %[[TRUE]], %[[ARG]]
465 return %0, %1: i1, i1
468 // CHECK-LABEL: @convert_logical_or_true_false_vector
469 // CHECK-SAME: %[[ARG:.+]]: vector<3xi1>
470 func @convert_logical_or_true_false_vector(%arg: vector<3xi1>) -> (vector<3xi1>, vector<3xi1>) {
471 // CHECK: %[[TRUE:.+]] = spv.constant dense<true>
472 %true = spv.constant dense<true> : vector<3xi1>
473 %false = spv.constant dense<false> : vector<3xi1>
474 %0 = spv.LogicalOr %true, %arg: vector<3xi1>
475 %1 = spv.LogicalOr %arg, %false: vector<3xi1>
476 // CHECK: return %[[TRUE]], %[[ARG]]
477 return %0, %1: vector<3xi1>, vector<3xi1>
482 //===----------------------------------------------------------------------===//
484 //===----------------------------------------------------------------------===//
486 func @canonicalize_selection_op_scalar_type(%cond: i1) -> () {
487 %0 = spv.constant 0: i32
488 // CHECK: %[[TRUE_VALUE:.*]] = spv.constant 1 : i32
489 %1 = spv.constant 1: i32
490 // CHECK: %[[FALSE_VALUE:.*]] = spv.constant 2 : i32
491 %2 = spv.constant 2: i32
492 // CHECK: %[[DST_VAR:.*]] = spv.Variable init({{%.*}}) : !spv.ptr<i32, Function>
493 %3 = spv.Variable init(%0) : !spv.ptr<i32, Function>
495 // CHECK: %[[SRC_VALUE:.*]] = spv.Select {{%.*}}, %[[TRUE_VALUE]], %[[FALSE_VALUE]] : i1, i32
496 // CHECK-NEXT: spv.Store "Function" %[[DST_VAR]], %[[SRC_VALUE]] ["Aligned", 4] : i32
497 // CHECK-NEXT: spv.Return
499 spv.BranchConditional %cond, ^then, ^else
502 spv.Store "Function" %3, %2 ["Aligned", 4]: i32
506 spv.Store "Function" %3, %1 ["Aligned", 4]: i32
517 func @canonicalize_selection_op_vector_type(%cond: i1) -> () {
518 %0 = spv.constant dense<[0, 1, 2]> : vector<3xi32>
519 // CHECK: %[[TRUE_VALUE:.*]] = spv.constant dense<[1, 2, 3]> : vector<3xi32>
520 %1 = spv.constant dense<[1, 2, 3]> : vector<3xi32>
521 // CHECK: %[[FALSE_VALUE:.*]] = spv.constant dense<[2, 3, 4]> : vector<3xi32>
522 %2 = spv.constant dense<[2, 3, 4]> : vector<3xi32>
523 // CHECK: %[[DST_VAR:.*]] = spv.Variable init({{%.*}}) : !spv.ptr<vector<3xi32>, Function>
524 %3 = spv.Variable init(%0) : !spv.ptr<vector<3xi32>, Function>
526 // CHECK: %[[SRC_VALUE:.*]] = spv.Select {{%.*}}, %[[TRUE_VALUE]], %[[FALSE_VALUE]] : i1, vector<3xi32>
527 // CHECK-NEXT: spv.Store "Function" %[[DST_VAR]], %[[SRC_VALUE]] ["Aligned", 8] : vector<3xi32>
528 // CHECK-NEXT: spv.Return
530 spv.BranchConditional %cond, ^then, ^else
533 spv.Store "Function" %3, %1 ["Aligned", 8]: vector<3xi32>
537 spv.Store "Function" %3, %2 ["Aligned", 8] : vector<3xi32>
548 // Store to a different variables.
549 func @cannot_canonicalize_selection_op_0(%cond: i1) -> () {
550 %0 = spv.constant dense<[0, 1, 2]> : vector<3xi32>
551 // CHECK: %[[SRC_VALUE_0:.*]] = spv.constant dense<[1, 2, 3]> : vector<3xi32>
552 %1 = spv.constant dense<[1, 2, 3]> : vector<3xi32>
553 // CHECK: %[[SRC_VALUE_1:.*]] = spv.constant dense<[2, 3, 4]> : vector<3xi32>
554 %2 = spv.constant dense<[2, 3, 4]> : vector<3xi32>
555 // CHECK: %[[DST_VAR_0:.*]] = spv.Variable init({{%.*}}) : !spv.ptr<vector<3xi32>, Function>
556 %3 = spv.Variable init(%0) : !spv.ptr<vector<3xi32>, Function>
557 // CHECK: %[[DST_VAR_1:.*]] = spv.Variable init({{%.*}}) : !spv.ptr<vector<3xi32>, Function>
558 %4 = spv.Variable init(%0) : !spv.ptr<vector<3xi32>, Function>
560 // CHECK: spv.selection {
562 // CHECK: spv.BranchConditional
563 // CHECK-SAME: ^bb1(%[[DST_VAR_0]], %[[SRC_VALUE_0]]
564 // CHECK-SAME: ^bb1(%[[DST_VAR_1]], %[[SRC_VALUE_1]]
565 spv.BranchConditional %cond, ^then, ^else
568 // CHECK: ^bb1(%[[ARG0:.*]]: !spv.ptr<vector<3xi32>, Function>, %[[ARG1:.*]]: vector<3xi32>):
569 // CHECK: spv.Store "Function" %[[ARG0]], %[[ARG1]] ["Aligned", 8] : vector<3xi32>
570 spv.Store "Function" %3, %1 ["Aligned", 8]: vector<3xi32>
574 spv.Store "Function" %4, %2 ["Aligned", 8] : vector<3xi32>
585 // A conditional block consists of more than 2 operations.
586 func @cannot_canonicalize_selection_op_1(%cond: i1) -> () {
587 %0 = spv.constant dense<[0, 1, 2]> : vector<3xi32>
588 // CHECK: %[[SRC_VALUE_0:.*]] = spv.constant dense<[1, 2, 3]> : vector<3xi32>
589 %1 = spv.constant dense<[1, 2, 3]> : vector<3xi32>
590 // CHECK: %[[SRC_VALUE_1:.*]] = spv.constant dense<[2, 3, 4]> : vector<3xi32>
591 %2 = spv.constant dense<[2, 3, 4]> : vector<3xi32>
592 // CHECK: %[[DST_VAR_0:.*]] = spv.Variable init({{%.*}}) : !spv.ptr<vector<3xi32>, Function>
593 %3 = spv.Variable init(%0) : !spv.ptr<vector<3xi32>, Function>
594 // CHECK: %[[DST_VAR_1:.*]] = spv.Variable init({{%.*}}) : !spv.ptr<vector<3xi32>, Function>
595 %4 = spv.Variable init(%0) : !spv.ptr<vector<3xi32>, Function>
597 // CHECK: spv.selection {
599 spv.BranchConditional %cond, ^then, ^else
602 // CHECK: spv.Store "Function" %[[DST_VAR_0]], %[[SRC_VALUE_0]] ["Aligned", 8] : vector<3xi32>
603 spv.Store "Function" %3, %1 ["Aligned", 8] : vector<3xi32>
604 // CHECK: spv.Store "Function" %[[DST_VAR_1]], %[[SRC_VALUE_0]] ["Aligned", 8] : vector<3xi32>
605 spv.Store "Function" %4, %1 ["Aligned", 8]: vector<3xi32>
609 // CHECK: spv.Store "Function" %[[DST_VAR_1]], %[[SRC_VALUE_1]] ["Aligned", 8] : vector<3xi32>
610 spv.Store "Function" %4, %2 ["Aligned", 8] : vector<3xi32>
621 // A control-flow goes into `^then` block from `^else` block.
622 func @cannot_canonicalize_selection_op_2(%cond: i1) -> () {
623 %0 = spv.constant dense<[0, 1, 2]> : vector<3xi32>
624 // CHECK: %[[SRC_VALUE_0:.*]] = spv.constant dense<[1, 2, 3]> : vector<3xi32>
625 %1 = spv.constant dense<[1, 2, 3]> : vector<3xi32>
626 // CHECK: %[[SRC_VALUE_1:.*]] = spv.constant dense<[2, 3, 4]> : vector<3xi32>
627 %2 = spv.constant dense<[2, 3, 4]> : vector<3xi32>
628 // CHECK: %[[DST_VAR:.*]] = spv.Variable init({{%.*}}) : !spv.ptr<vector<3xi32>, Function>
629 %3 = spv.Variable init(%0) : !spv.ptr<vector<3xi32>, Function>
631 // CHECK: spv.selection {
633 spv.BranchConditional %cond, ^then, ^else
636 // CHECK: spv.Store "Function" %[[DST_VAR]], %[[SRC_VALUE_0]] ["Aligned", 8] : vector<3xi32>
637 spv.Store "Function" %3, %1 ["Aligned", 8]: vector<3xi32>
641 // CHECK: spv.Store "Function" %[[DST_VAR]], %[[SRC_VALUE_1]] ["Aligned", 8] : vector<3xi32>
642 spv.Store "Function" %3, %2 ["Aligned", 8] : vector<3xi32>
653 // `spv.Return` as a block terminator.
654 func @cannot_canonicalize_selection_op_3(%cond: i1) -> () {
655 %0 = spv.constant dense<[0, 1, 2]> : vector<3xi32>
656 // CHECK: %[[SRC_VALUE_0:.*]] = spv.constant dense<[1, 2, 3]> : vector<3xi32>
657 %1 = spv.constant dense<[1, 2, 3]> : vector<3xi32>
658 // CHECK: %[[SRC_VALUE_1:.*]] = spv.constant dense<[2, 3, 4]> : vector<3xi32>
659 %2 = spv.constant dense<[2, 3, 4]> : vector<3xi32>
660 // CHECK: %[[DST_VAR:.*]] = spv.Variable init({{%.*}}) : !spv.ptr<vector<3xi32>, Function>
661 %3 = spv.Variable init(%0) : !spv.ptr<vector<3xi32>, Function>
663 // CHECK: spv.selection {
665 spv.BranchConditional %cond, ^then, ^else
668 // CHECK: spv.Store "Function" %[[DST_VAR]], %[[SRC_VALUE_0]] ["Aligned", 8] : vector<3xi32>
669 spv.Store "Function" %3, %1 ["Aligned", 8]: vector<3xi32>
673 // CHECK: spv.Store "Function" %[[DST_VAR]], %[[SRC_VALUE_1]] ["Aligned", 8] : vector<3xi32>
674 spv.Store "Function" %3, %2 ["Aligned", 8] : vector<3xi32>
685 // Different memory access attributes.
686 func @cannot_canonicalize_selection_op_4(%cond: i1) -> () {
687 %0 = spv.constant dense<[0, 1, 2]> : vector<3xi32>
688 // CHECK: %[[SRC_VALUE_0:.*]] = spv.constant dense<[1, 2, 3]> : vector<3xi32>
689 %1 = spv.constant dense<[1, 2, 3]> : vector<3xi32>
690 // CHECK: %[[SRC_VALUE_1:.*]] = spv.constant dense<[2, 3, 4]> : vector<3xi32>
691 %2 = spv.constant dense<[2, 3, 4]> : vector<3xi32>
692 // CHECK: %[[DST_VAR:.*]] = spv.Variable init({{%.*}}) : !spv.ptr<vector<3xi32>, Function>
693 %3 = spv.Variable init(%0) : !spv.ptr<vector<3xi32>, Function>
695 // CHECK: spv.selection {
697 spv.BranchConditional %cond, ^then, ^else
700 // CHECK: spv.Store "Function" %[[DST_VAR]], %[[SRC_VALUE_0]] ["Aligned", 4] : vector<3xi32>
701 spv.Store "Function" %3, %1 ["Aligned", 4]: vector<3xi32>
705 // CHECK: spv.Store "Function" %[[DST_VAR]], %[[SRC_VALUE_1]] ["Aligned", 8] : vector<3xi32>
706 spv.Store "Function" %3, %2 ["Aligned", 8] : vector<3xi32>