1 // RUN: mlir-opt -convert-math-to-llvm -convert-arith-to-llvm -convert-std-to-llvm -reconcile-unrealized-casts %s -split-input-file | FileCheck %s
2 // RUN: mlir-opt -convert-math-to-llvm -convert-arith-to-llvm='index-bitwidth=32' -convert-std-to-llvm='index-bitwidth=32' -reconcile-unrealized-casts %s -split-input-file | FileCheck --check-prefix=CHECK32 %s
4 // CHECK-LABEL: func @empty() {
5 // CHECK-NEXT: llvm.return
12 // CHECK-LABEL: llvm.func @body(i64)
13 func private @body(index)
15 // CHECK-LABEL: func @simple_loop() {
16 // CHECK32-LABEL: func @simple_loop() {
19 // CHECK-NEXT: llvm.br ^bb1
20 // CHECK32-NEXT: llvm.br ^bb1
23 // CHECK-NEXT: ^bb1: // pred: ^bb0
24 // CHECK-NEXT: {{.*}} = llvm.mlir.constant(1 : index) : i64
25 // CHECK-NEXT: {{.*}} = llvm.mlir.constant(42 : index) : i64
26 // CHECK-NEXT: llvm.br ^bb2({{.*}} : i64)
27 // CHECK32-NEXT: ^bb1: // pred: ^bb0
28 // CHECK32-NEXT: {{.*}} = llvm.mlir.constant(1 : index) : i32
29 // CHECK32-NEXT: {{.*}} = llvm.mlir.constant(42 : index) : i32
30 // CHECK32-NEXT: llvm.br ^bb2({{.*}} : i32)
32 %c1 = arith.constant 1 : index
33 %c42 = arith.constant 42 : index
36 // CHECK: ^bb2({{.*}}: i64): // 2 preds: ^bb1, ^bb3
37 // CHECK-NEXT: {{.*}} = llvm.icmp "slt" {{.*}}, {{.*}} : i64
38 // CHECK-NEXT: llvm.cond_br {{.*}}, ^bb3, ^bb4
39 // CHECK32: ^bb2({{.*}}: i32): // 2 preds: ^bb1, ^bb3
40 // CHECK32-NEXT: {{.*}} = llvm.icmp "slt" {{.*}}, {{.*}} : i32
41 // CHECK32-NEXT: llvm.cond_br {{.*}}, ^bb3, ^bb4
42 ^bb2(%0: index): // 2 preds: ^bb1, ^bb3
43 %1 = arith.cmpi slt, %0, %c42 : index
44 cond_br %1, ^bb3, ^bb4
46 // CHECK: ^bb3: // pred: ^bb2
47 // CHECK-NEXT: llvm.call @body({{.*}}) : (i64) -> ()
48 // CHECK-NEXT: {{.*}} = llvm.mlir.constant(1 : index) : i64
49 // CHECK-NEXT: {{.*}} = llvm.add {{.*}}, {{.*}} : i64
50 // CHECK-NEXT: llvm.br ^bb2({{.*}} : i64)
51 // CHECK32: ^bb3: // pred: ^bb2
52 // CHECK32-NEXT: llvm.call @body({{.*}}) : (i32) -> ()
53 // CHECK32-NEXT: {{.*}} = llvm.mlir.constant(1 : index) : i32
54 // CHECK32-NEXT: {{.*}} = llvm.add {{.*}}, {{.*}} : i32
55 // CHECK32-NEXT: llvm.br ^bb2({{.*}} : i32)
57 call @body(%0) : (index) -> ()
58 %c1_0 = arith.constant 1 : index
59 %2 = arith.addi %0, %c1_0 : index
62 // CHECK: ^bb4: // pred: ^bb2
63 // CHECK-NEXT: llvm.return
68 // CHECK-LABEL: func @simple_caller() {
69 // CHECK-NEXT: llvm.call @simple_loop() : () -> ()
70 // CHECK-NEXT: llvm.return
72 func @simple_caller() {
74 call @simple_loop() : () -> ()
78 // Check that function call attributes persist during conversion.
79 // CHECK-LABEL: @call_with_attributes
80 func @call_with_attributes() {
81 // CHECK: llvm.call @simple_loop() {baz = [1, 2, 3, 4], foo = "bar"} : () -> ()
82 call @simple_loop() {foo="bar", baz=[1,2,3,4]} : () -> ()
86 // CHECK-LABEL: func @ml_caller() {
87 // CHECK-NEXT: llvm.call @simple_loop() : () -> ()
88 // CHECK-NEXT: llvm.call @more_imperfectly_nested_loops() : () -> ()
89 // CHECK-NEXT: llvm.return
93 call @simple_loop() : () -> ()
94 call @more_imperfectly_nested_loops() : () -> ()
98 // CHECK-LABEL: llvm.func @body_args(i64) -> i64
99 // CHECK32-LABEL: llvm.func @body_args(i32) -> i32
100 func private @body_args(index) -> index
101 // CHECK-LABEL: llvm.func @other(i64, i32) -> i32
102 // CHECK32-LABEL: llvm.func @other(i32, i32) -> i32
103 func private @other(index, i32) -> i32
105 // CHECK-LABEL: func @func_args(%arg0: i32, %arg1: i32) -> i32 {
106 // CHECK-NEXT: {{.*}} = llvm.mlir.constant(0 : i32) : i32
107 // CHECK-NEXT: llvm.br ^bb1
108 // CHECK32-LABEL: func @func_args(%arg0: i32, %arg1: i32) -> i32 {
109 // CHECK32-NEXT: {{.*}} = llvm.mlir.constant(0 : i32) : i32
110 // CHECK32-NEXT: llvm.br ^bb1
111 func @func_args(i32, i32) -> i32 {
112 ^bb0(%arg0: i32, %arg1: i32):
113 %c0_i32 = arith.constant 0 : i32
116 // CHECK-NEXT: ^bb1: // pred: ^bb0
117 // CHECK-NEXT: {{.*}} = llvm.mlir.constant(0 : index) : i64
118 // CHECK-NEXT: {{.*}} = llvm.mlir.constant(42 : index) : i64
119 // CHECK-NEXT: llvm.br ^bb2({{.*}} : i64)
120 // CHECK32-NEXT: ^bb1: // pred: ^bb0
121 // CHECK32-NEXT: {{.*}} = llvm.mlir.constant(0 : index) : i32
122 // CHECK32-NEXT: {{.*}} = llvm.mlir.constant(42 : index) : i32
123 // CHECK32-NEXT: llvm.br ^bb2({{.*}} : i32)
125 %c0 = arith.constant 0 : index
126 %c42 = arith.constant 42 : index
129 // CHECK-NEXT: ^bb2({{.*}}: i64): // 2 preds: ^bb1, ^bb3
130 // CHECK-NEXT: {{.*}} = llvm.icmp "slt" {{.*}}, {{.*}} : i64
131 // CHECK-NEXT: llvm.cond_br {{.*}}, ^bb3, ^bb4
132 // CHECK32-NEXT: ^bb2({{.*}}: i32): // 2 preds: ^bb1, ^bb3
133 // CHECK32-NEXT: {{.*}} = llvm.icmp "slt" {{.*}}, {{.*}} : i32
134 // CHECK32-NEXT: llvm.cond_br {{.*}}, ^bb3, ^bb4
135 ^bb2(%0: index): // 2 preds: ^bb1, ^bb3
136 %1 = arith.cmpi slt, %0, %c42 : index
137 cond_br %1, ^bb3, ^bb4
139 // CHECK-NEXT: ^bb3: // pred: ^bb2
140 // CHECK-NEXT: {{.*}} = llvm.call @body_args({{.*}}) : (i64) -> i64
141 // CHECK-NEXT: {{.*}} = llvm.call @other({{.*}}, %arg0) : (i64, i32) -> i32
142 // CHECK-NEXT: {{.*}} = llvm.call @other({{.*}}, {{.*}}) : (i64, i32) -> i32
143 // CHECK-NEXT: {{.*}} = llvm.call @other({{.*}}, %arg1) : (i64, i32) -> i32
144 // CHECK-NEXT: {{.*}} = llvm.mlir.constant(1 : index) : i64
145 // CHECK-NEXT: {{.*}} = llvm.add {{.*}}, {{.*}} : i64
146 // CHECK-NEXT: llvm.br ^bb2({{.*}} : i64)
147 // CHECK32-NEXT: ^bb3: // pred: ^bb2
148 // CHECK32-NEXT: {{.*}} = llvm.call @body_args({{.*}}) : (i32) -> i32
149 // CHECK32-NEXT: {{.*}} = llvm.call @other({{.*}}, %arg0) : (i32, i32) -> i32
150 // CHECK32-NEXT: {{.*}} = llvm.call @other({{.*}}, {{.*}}) : (i32, i32) -> i32
151 // CHECK32-NEXT: {{.*}} = llvm.call @other({{.*}}, %arg1) : (i32, i32) -> i32
152 // CHECK32-NEXT: {{.*}} = llvm.mlir.constant(1 : index) : i32
153 // CHECK32-NEXT: {{.*}} = llvm.add {{.*}}, {{.*}} : i32
154 // CHECK32-NEXT: llvm.br ^bb2({{.*}} : i32)
156 %2 = call @body_args(%0) : (index) -> index
157 %3 = call @other(%2, %arg0) : (index, i32) -> i32
158 %4 = call @other(%2, %3) : (index, i32) -> i32
159 %5 = call @other(%2, %arg1) : (index, i32) -> i32
160 %c1 = arith.constant 1 : index
161 %6 = arith.addi %0, %c1 : index
164 // CHECK-NEXT: ^bb4: // pred: ^bb2
165 // CHECK-NEXT: {{.*}} = llvm.mlir.constant(0 : index) : i64
166 // CHECK-NEXT: {{.*}} = llvm.call @other({{.*}}, {{.*}}) : (i64, i32) -> i32
167 // CHECK-NEXT: llvm.return {{.*}} : i32
168 // CHECK32-NEXT: ^bb4: // pred: ^bb2
169 // CHECK32-NEXT: {{.*}} = llvm.mlir.constant(0 : index) : i32
170 // CHECK32-NEXT: {{.*}} = llvm.call @other({{.*}}, {{.*}}) : (i32, i32) -> i32
171 // CHECK32-NEXT: llvm.return {{.*}} : i32
173 %c0_0 = arith.constant 0 : index
174 %7 = call @other(%c0_0, %c0_i32) : (index, i32) -> i32
178 // CHECK-LABEL: llvm.func @pre(i64)
179 // CHECK32-LABEL: llvm.func @pre(i32)
180 func private @pre(index)
182 // CHECK-LABEL: llvm.func @body2(i64, i64)
183 // CHECK32-LABEL: llvm.func @body2(i32, i32)
184 func private @body2(index, index)
186 // CHECK-LABEL: llvm.func @post(i64)
187 // CHECK32-LABEL: llvm.func @post(i32)
188 func private @post(index)
190 // CHECK-LABEL: func @imperfectly_nested_loops() {
191 // CHECK-NEXT: llvm.br ^bb1
192 func @imperfectly_nested_loops() {
196 // CHECK-NEXT: ^bb1: // pred: ^bb0
197 // CHECK-NEXT: {{.*}} = llvm.mlir.constant(0 : index) : i64
198 // CHECK-NEXT: {{.*}} = llvm.mlir.constant(42 : index) : i64
199 // CHECK-NEXT: llvm.br ^bb2({{.*}} : i64)
201 %c0 = arith.constant 0 : index
202 %c42 = arith.constant 42 : index
205 // CHECK-NEXT: ^bb2({{.*}}: i64): // 2 preds: ^bb1, ^bb7
206 // CHECK-NEXT: {{.*}} = llvm.icmp "slt" {{.*}}, {{.*}} : i64
207 // CHECK-NEXT: llvm.cond_br {{.*}}, ^bb3, ^bb8
208 ^bb2(%0: index): // 2 preds: ^bb1, ^bb7
209 %1 = arith.cmpi slt, %0, %c42 : index
210 cond_br %1, ^bb3, ^bb8
213 // CHECK-NEXT: llvm.call @pre({{.*}}) : (i64) -> ()
214 // CHECK-NEXT: llvm.br ^bb4
216 call @pre(%0) : (index) -> ()
219 // CHECK-NEXT: ^bb4: // pred: ^bb3
220 // CHECK-NEXT: {{.*}} = llvm.mlir.constant(7 : index) : i64
221 // CHECK-NEXT: {{.*}} = llvm.mlir.constant(56 : index) : i64
222 // CHECK-NEXT: llvm.br ^bb5({{.*}} : i64)
224 %c7 = arith.constant 7 : index
225 %c56 = arith.constant 56 : index
228 // CHECK-NEXT: ^bb5({{.*}}: i64): // 2 preds: ^bb4, ^bb6
229 // CHECK-NEXT: {{.*}} = llvm.icmp "slt" {{.*}}, {{.*}} : i64
230 // CHECK-NEXT: llvm.cond_br {{.*}}, ^bb6, ^bb7
231 ^bb5(%2: index): // 2 preds: ^bb4, ^bb6
232 %3 = arith.cmpi slt, %2, %c56 : index
233 cond_br %3, ^bb6, ^bb7
235 // CHECK-NEXT: ^bb6: // pred: ^bb5
236 // CHECK-NEXT: llvm.call @body2({{.*}}, {{.*}}) : (i64, i64) -> ()
237 // CHECK-NEXT: {{.*}} = llvm.mlir.constant(2 : index) : i64
238 // CHECK-NEXT: {{.*}} = llvm.add {{.*}}, {{.*}} : i64
239 // CHECK-NEXT: llvm.br ^bb5({{.*}} : i64)
241 call @body2(%0, %2) : (index, index) -> ()
242 %c2 = arith.constant 2 : index
243 %4 = arith.addi %2, %c2 : index
246 // CHECK-NEXT: ^bb7: // pred: ^bb5
247 // CHECK-NEXT: llvm.call @post({{.*}}) : (i64) -> ()
248 // CHECK-NEXT: {{.*}} = llvm.mlir.constant(1 : index) : i64
249 // CHECK-NEXT: {{.*}} = llvm.add {{.*}}, {{.*}} : i64
250 // CHECK-NEXT: llvm.br ^bb2({{.*}} : i64)
252 call @post(%0) : (index) -> ()
253 %c1 = arith.constant 1 : index
254 %5 = arith.addi %0, %c1 : index
257 // CHECK-NEXT: ^bb8: // pred: ^bb2
258 // CHECK-NEXT: llvm.return
263 // CHECK-LABEL: llvm.func @mid(i64)
264 func private @mid(index)
266 // CHECK-LABEL: llvm.func @body3(i64, i64)
267 func private @body3(index, index)
269 // A complete function transformation check.
270 // CHECK-LABEL: func @more_imperfectly_nested_loops() {
271 // CHECK-NEXT: llvm.br ^bb1
272 // CHECK-NEXT:^bb1: // pred: ^bb0
273 // CHECK-NEXT: {{.*}} = llvm.mlir.constant(0 : index) : i64
274 // CHECK-NEXT: {{.*}} = llvm.mlir.constant(42 : index) : i64
275 // CHECK-NEXT: llvm.br ^bb2({{.*}} : i64)
276 // CHECK-NEXT:^bb2({{.*}}: i64): // 2 preds: ^bb1, ^bb11
277 // CHECK-NEXT: {{.*}} = llvm.icmp "slt" {{.*}}, {{.*}} : i64
278 // CHECK-NEXT: llvm.cond_br {{.*}}, ^bb3, ^bb12
279 // CHECK-NEXT:^bb3: // pred: ^bb2
280 // CHECK-NEXT: llvm.call @pre({{.*}}) : (i64) -> ()
281 // CHECK-NEXT: llvm.br ^bb4
282 // CHECK-NEXT:^bb4: // pred: ^bb3
283 // CHECK-NEXT: {{.*}} = llvm.mlir.constant(7 : index) : i64
284 // CHECK-NEXT: {{.*}} = llvm.mlir.constant(56 : index) : i64
285 // CHECK-NEXT: llvm.br ^bb5({{.*}} : i64)
286 // CHECK-NEXT:^bb5({{.*}}: i64): // 2 preds: ^bb4, ^bb6
287 // CHECK-NEXT: {{.*}} = llvm.icmp "slt" {{.*}}, {{.*}} : i64
288 // CHECK-NEXT: llvm.cond_br {{.*}}, ^bb6, ^bb7
289 // CHECK-NEXT:^bb6: // pred: ^bb5
290 // CHECK-NEXT: llvm.call @body2({{.*}}, {{.*}}) : (i64, i64) -> ()
291 // CHECK-NEXT: {{.*}} = llvm.mlir.constant(2 : index) : i64
292 // CHECK-NEXT: {{.*}} = llvm.add {{.*}}, {{.*}} : i64
293 // CHECK-NEXT: llvm.br ^bb5({{.*}} : i64)
294 // CHECK-NEXT:^bb7: // pred: ^bb5
295 // CHECK-NEXT: llvm.call @mid({{.*}}) : (i64) -> ()
296 // CHECK-NEXT: llvm.br ^bb8
297 // CHECK-NEXT:^bb8: // pred: ^bb7
298 // CHECK-NEXT: {{.*}} = llvm.mlir.constant(18 : index) : i64
299 // CHECK-NEXT: {{.*}} = llvm.mlir.constant(37 : index) : i64
300 // CHECK-NEXT: llvm.br ^bb9({{.*}} : i64)
301 // CHECK-NEXT:^bb9({{.*}}: i64): // 2 preds: ^bb8, ^bb10
302 // CHECK-NEXT: {{.*}} = llvm.icmp "slt" {{.*}}, {{.*}} : i64
303 // CHECK-NEXT: llvm.cond_br {{.*}}, ^bb10, ^bb11
304 // CHECK-NEXT:^bb10: // pred: ^bb9
305 // CHECK-NEXT: llvm.call @body3({{.*}}, {{.*}}) : (i64, i64) -> ()
306 // CHECK-NEXT: {{.*}} = llvm.mlir.constant(3 : index) : i64
307 // CHECK-NEXT: {{.*}} = llvm.add {{.*}}, {{.*}} : i64
308 // CHECK-NEXT: llvm.br ^bb9({{.*}} : i64)
309 // CHECK-NEXT:^bb11: // pred: ^bb9
310 // CHECK-NEXT: llvm.call @post({{.*}}) : (i64) -> ()
311 // CHECK-NEXT: {{.*}} = llvm.mlir.constant(1 : index) : i64
312 // CHECK-NEXT: {{.*}} = llvm.add {{.*}}, {{.*}} : i64
313 // CHECK-NEXT: llvm.br ^bb2({{.*}} : i64)
314 // CHECK-NEXT:^bb12: // pred: ^bb2
315 // CHECK-NEXT: llvm.return
317 func @more_imperfectly_nested_loops() {
321 %c0 = arith.constant 0 : index
322 %c42 = arith.constant 42 : index
324 ^bb2(%0: index): // 2 preds: ^bb1, ^bb11
325 %1 = arith.cmpi slt, %0, %c42 : index
326 cond_br %1, ^bb3, ^bb12
328 call @pre(%0) : (index) -> ()
331 %c7 = arith.constant 7 : index
332 %c56 = arith.constant 56 : index
334 ^bb5(%2: index): // 2 preds: ^bb4, ^bb6
335 %3 = arith.cmpi slt, %2, %c56 : index
336 cond_br %3, ^bb6, ^bb7
338 call @body2(%0, %2) : (index, index) -> ()
339 %c2 = arith.constant 2 : index
340 %4 = arith.addi %2, %c2 : index
343 call @mid(%0) : (index) -> ()
346 %c18 = arith.constant 18 : index
347 %c37 = arith.constant 37 : index
348 br ^bb9(%c18 : index)
349 ^bb9(%5: index): // 2 preds: ^bb8, ^bb10
350 %6 = arith.cmpi slt, %5, %c37 : index
351 cond_br %6, ^bb10, ^bb11
353 call @body3(%0, %5) : (index, index) -> ()
354 %c3 = arith.constant 3 : index
355 %7 = arith.addi %5, %c3 : index
358 call @post(%0) : (index) -> ()
359 %c1 = arith.constant 1 : index
360 %8 = arith.addi %0, %c1 : index
366 // CHECK-LABEL: llvm.func @get_i64() -> i64
367 func private @get_i64() -> (i64)
368 // CHECK-LABEL: llvm.func @get_f32() -> f32
369 func private @get_f32() -> (f32)
370 // CHECK-LABEL: llvm.func @get_c16() -> !llvm.struct<(f16, f16)>
371 func private @get_c16() -> (complex<f16>)
372 // CHECK-LABEL: llvm.func @get_c32() -> !llvm.struct<(f32, f32)>
373 func private @get_c32() -> (complex<f32>)
374 // CHECK-LABEL: llvm.func @get_c64() -> !llvm.struct<(f64, f64)>
375 func private @get_c64() -> (complex<f64>)
376 // CHECK-LABEL: llvm.func @get_memref() -> !llvm.struct<(ptr<f32>, ptr<f32>, i64, array<4 x i64>, array<4 x i64>)>
377 // CHECK32-LABEL: llvm.func @get_memref() -> !llvm.struct<(ptr<f32>, ptr<f32>, i32, array<4 x i32>, array<4 x i32>)>
378 func private @get_memref() -> (memref<42x?x10x?xf32>)
380 // CHECK-LABEL: llvm.func @multireturn() -> !llvm.struct<(i64, f32, struct<(ptr<f32>, ptr<f32>, i64, array<4 x i64>, array<4 x i64>)>)> {
381 // CHECK32-LABEL: llvm.func @multireturn() -> !llvm.struct<(i64, f32, struct<(ptr<f32>, ptr<f32>, i32, array<4 x i32>, array<4 x i32>)>)> {
382 func @multireturn() -> (i64, f32, memref<42x?x10x?xf32>) {
384 // CHECK-NEXT: {{.*}} = llvm.call @get_i64() : () -> i64
385 // CHECK-NEXT: {{.*}} = llvm.call @get_f32() : () -> f32
386 // CHECK-NEXT: {{.*}} = llvm.call @get_memref() : () -> !llvm.struct<(ptr<f32>, ptr<f32>, i64, array<4 x i64>, array<4 x i64>)>
387 // CHECK32-NEXT: {{.*}} = llvm.call @get_i64() : () -> i64
388 // CHECK32-NEXT: {{.*}} = llvm.call @get_f32() : () -> f32
389 // CHECK32-NEXT: {{.*}} = llvm.call @get_memref() : () -> !llvm.struct<(ptr<f32>, ptr<f32>, i32, array<4 x i32>, array<4 x i32>)>
390 %0 = call @get_i64() : () -> (i64)
391 %1 = call @get_f32() : () -> (f32)
392 %2 = call @get_memref() : () -> (memref<42x?x10x?xf32>)
393 // CHECK-NEXT: {{.*}} = llvm.mlir.undef : !llvm.struct<(i64, f32, struct<(ptr<f32>, ptr<f32>, i64, array<4 x i64>, array<4 x i64>)>)>
394 // CHECK-NEXT: {{.*}} = llvm.insertvalue {{.*}}, {{.*}}[0] : !llvm.struct<(i64, f32, struct<(ptr<f32>, ptr<f32>, i64, array<4 x i64>, array<4 x i64>)>)>
395 // CHECK-NEXT: {{.*}} = llvm.insertvalue {{.*}}, {{.*}}[1] : !llvm.struct<(i64, f32, struct<(ptr<f32>, ptr<f32>, i64, array<4 x i64>, array<4 x i64>)>)>
396 // CHECK-NEXT: {{.*}} = llvm.insertvalue {{.*}}, {{.*}}[2] : !llvm.struct<(i64, f32, struct<(ptr<f32>, ptr<f32>, i64, array<4 x i64>, array<4 x i64>)>)>
397 // CHECK-NEXT: llvm.return {{.*}} : !llvm.struct<(i64, f32, struct<(ptr<f32>, ptr<f32>, i64, array<4 x i64>, array<4 x i64>)>)>
398 // CHECK32-NEXT: {{.*}} = llvm.mlir.undef : !llvm.struct<(i64, f32, struct<(ptr<f32>, ptr<f32>, i32, array<4 x i32>, array<4 x i32>)>)>
399 // CHECK32-NEXT: {{.*}} = llvm.insertvalue {{.*}}, {{.*}}[0] : !llvm.struct<(i64, f32, struct<(ptr<f32>, ptr<f32>, i32, array<4 x i32>, array<4 x i32>)>)>
400 // CHECK32-NEXT: {{.*}} = llvm.insertvalue {{.*}}, {{.*}}[1] : !llvm.struct<(i64, f32, struct<(ptr<f32>, ptr<f32>, i32, array<4 x i32>, array<4 x i32>)>)>
401 // CHECK32-NEXT: {{.*}} = llvm.insertvalue {{.*}}, {{.*}}[2] : !llvm.struct<(i64, f32, struct<(ptr<f32>, ptr<f32>, i32, array<4 x i32>, array<4 x i32>)>)>
402 // CHECK32-NEXT: llvm.return {{.*}} : !llvm.struct<(i64, f32, struct<(ptr<f32>, ptr<f32>, i32, array<4 x i32>, array<4 x i32>)>)>
403 return %0, %1, %2 : i64, f32, memref<42x?x10x?xf32>
407 // CHECK-LABEL: llvm.func @multireturn_caller() {
408 // CHECK32-LABEL: llvm.func @multireturn_caller() {
409 func @multireturn_caller() {
411 // CHECK-NEXT: {{.*}} = llvm.call @multireturn() : () -> !llvm.struct<(i64, f32, struct<(ptr<f32>, ptr<f32>, i64, array<4 x i64>, array<4 x i64>)>)>
412 // CHECK-NEXT: {{.*}} = llvm.extractvalue {{.*}}[0] : !llvm.struct<(i64, f32, struct<(ptr<f32>, ptr<f32>, i64, array<4 x i64>, array<4 x i64>)>)>
413 // CHECK-NEXT: {{.*}} = llvm.extractvalue {{.*}}[1] : !llvm.struct<(i64, f32, struct<(ptr<f32>, ptr<f32>, i64, array<4 x i64>, array<4 x i64>)>)>
414 // CHECK-NEXT: {{.*}} = llvm.extractvalue {{.*}}[2] : !llvm.struct<(i64, f32, struct<(ptr<f32>, ptr<f32>, i64, array<4 x i64>, array<4 x i64>)>)>
415 // CHECK32-NEXT: {{.*}} = llvm.call @multireturn() : () -> !llvm.struct<(i64, f32, struct<(ptr<f32>, ptr<f32>, i32, array<4 x i32>, array<4 x i32>)>)>
416 // CHECK32-NEXT: {{.*}} = llvm.extractvalue {{.*}}[0] : !llvm.struct<(i64, f32, struct<(ptr<f32>, ptr<f32>, i32, array<4 x i32>, array<4 x i32>)>)>
417 // CHECK32-NEXT: {{.*}} = llvm.extractvalue {{.*}}[1] : !llvm.struct<(i64, f32, struct<(ptr<f32>, ptr<f32>, i32, array<4 x i32>, array<4 x i32>)>)>
418 // CHECK32-NEXT: {{.*}} = llvm.extractvalue {{.*}}[2] : !llvm.struct<(i64, f32, struct<(ptr<f32>, ptr<f32>, i32, array<4 x i32>, array<4 x i32>)>)>
419 %0:3 = call @multireturn() : () -> (i64, f32, memref<42x?x10x?xf32>)
420 %1 = arith.constant 42 : i64
421 // CHECK: {{.*}} = llvm.add {{.*}}, {{.*}} : i64
422 %2 = arith.addi %0#0, %1 : i64
423 %3 = arith.constant 42.0 : f32
424 // CHECK: {{.*}} = llvm.fadd {{.*}}, {{.*}} : f32
425 %4 = arith.addf %0#1, %3 : f32
426 %5 = arith.constant 0 : index
430 // CHECK-LABEL: @select
431 func @select(%arg0 : i1, %arg1 : i32, %arg2 : i32) -> i32 {
432 // CHECK: = llvm.select %arg0, %arg1, %arg2 : i1, i32
433 %0 = select %arg0, %arg1, %arg2 : i32
437 // CHECK-LABEL: @dfs_block_order
438 func @dfs_block_order(%arg0: i32) -> (i32) {
439 // CHECK-NEXT: %[[CST:.*]] = llvm.mlir.constant(42 : i32) : i32
440 %0 = arith.constant 42 : i32
441 // CHECK-NEXT: llvm.br ^bb2
445 // CHECK-NEXT: %[[ADD:.*]] = llvm.add %arg0, %[[CST]] : i32
446 // CHECK-NEXT: llvm.return %[[ADD]] : i32
448 %2 = arith.addi %arg0, %0 : i32
453 // CHECK-NEXT: llvm.br ^bb1
459 // CHECK-LABEL: @splat_0d
460 // CHECK-SAME: %[[ARG:.*]]: f32
461 func @splat_0d(%a: f32) -> vector<f32> {
462 %v = splat %a : vector<f32>
463 return %v : vector<f32>
465 // CHECK-NEXT: %[[UNDEF:[0-9]+]] = llvm.mlir.undef : vector<1xf32>
466 // CHECK-NEXT: %[[ZERO:[0-9]+]] = llvm.mlir.constant(0 : i32) : i32
467 // CHECK-NEXT: %[[V:[0-9]+]] = llvm.insertelement %[[ARG]], %[[UNDEF]][%[[ZERO]] : i32] : vector<1xf32>
468 // CHECK-NEXT: llvm.return %[[V]] : vector<1xf32>
472 // CHECK-LABEL: @splat
473 // CHECK-SAME: %[[A:arg[0-9]+]]: vector<4xf32>
474 // CHECK-SAME: %[[ELT:arg[0-9]+]]: f32
475 func @splat(%a: vector<4xf32>, %b: f32) -> vector<4xf32> {
476 %vb = splat %b : vector<4xf32>
477 %r = arith.mulf %a, %vb : vector<4xf32>
478 return %r : vector<4xf32>
480 // CHECK-NEXT: %[[UNDEF:[0-9]+]] = llvm.mlir.undef : vector<4xf32>
481 // CHECK-NEXT: %[[ZERO:[0-9]+]] = llvm.mlir.constant(0 : i32) : i32
482 // CHECK-NEXT: %[[V:[0-9]+]] = llvm.insertelement %[[ELT]], %[[UNDEF]][%[[ZERO]] : i32] : vector<4xf32>
483 // CHECK-NEXT: %[[SPLAT:[0-9]+]] = llvm.shufflevector %[[V]], %[[UNDEF]] [0 : i32, 0 : i32, 0 : i32, 0 : i32]
484 // CHECK-NEXT: %[[SCALE:[0-9]+]] = llvm.fmul %[[A]], %[[SPLAT]] : vector<4xf32>
485 // CHECK-NEXT: llvm.return %[[SCALE]] : vector<4xf32>
489 // CHECK-LABEL: func @generic_atomic_rmw
490 func @generic_atomic_rmw(%I : memref<10xi32>, %i : index) -> i32 {
491 %x = generic_atomic_rmw %I[%i] : memref<10xi32> {
492 ^bb0(%old_value : i32):
493 %c1 = arith.constant 1 : i32
494 atomic_yield %c1 : i32
496 // CHECK: [[init:%.*]] = llvm.load %{{.*}} : !llvm.ptr<i32>
497 // CHECK-NEXT: llvm.br ^bb1([[init]] : i32)
498 // CHECK-NEXT: ^bb1([[loaded:%.*]]: i32):
499 // CHECK-NEXT: [[c1:%.*]] = llvm.mlir.constant(1 : i32)
500 // CHECK-NEXT: [[pair:%.*]] = llvm.cmpxchg %{{.*}}, [[loaded]], [[c1]]
501 // CHECK-SAME: acq_rel monotonic : i32
502 // CHECK-NEXT: [[new:%.*]] = llvm.extractvalue [[pair]][0]
503 // CHECK-NEXT: [[ok:%.*]] = llvm.extractvalue [[pair]][1]
504 // CHECK-NEXT: llvm.cond_br [[ok]], ^bb2, ^bb1([[new]] : i32)
506 %c2 = arith.constant 2 : i32
507 %add = arith.addi %c2, %x : i32
509 // CHECK-NEXT: [[c2:%.*]] = llvm.mlir.constant(2 : i32)
510 // CHECK-NEXT: [[add:%.*]] = llvm.add [[c2]], [[new]] : i32
511 // CHECK-NEXT: llvm.return [[add]]
516 // CHECK-LABEL: func @ceilf(
518 func @ceilf(%arg0 : f32) {
519 // CHECK: "llvm.intr.ceil"(%arg0) : (f32) -> f32
520 %0 = math.ceil %arg0 : f32
526 // CHECK-LABEL: func @floorf(
528 func @floorf(%arg0 : f32) {
529 // CHECK: "llvm.intr.floor"(%arg0) : (f32) -> f32
530 %0 = math.floor %arg0 : f32
536 // Lowers `assert` to a function call to `abort` if the assertion is violated.
537 // CHECK: llvm.func @abort()
538 // CHECK-LABEL: @assert_test_function
539 // CHECK-SAME: (%[[ARG:.*]]: i1)
540 func @assert_test_function(%arg : i1) {
541 // CHECK: llvm.cond_br %[[ARG]], ^[[CONTINUATION_BLOCK:.*]], ^[[FAILURE_BLOCK:.*]]
542 // CHECK: ^[[CONTINUATION_BLOCK]]:
543 // CHECK: llvm.return
544 // CHECK: ^[[FAILURE_BLOCK]]:
545 // CHECK: llvm.call @abort() : () -> ()
546 // CHECK: llvm.unreachable
547 assert %arg, "Computer says no"
553 // This should not trigger an assertion by creating an LLVM::CallOp with a
554 // nullptr result type.
556 // CHECK-LABEL: @call_zero_result_func
557 func @call_zero_result_func() {
558 // CHECK: call @zero_result_func
559 call @zero_result_func() : () -> ()
562 func private @zero_result_func()
566 // CHECK-LABEL: func @fmaf(
567 // CHECK-SAME: %[[ARG0:.*]]: f32
568 // CHECK-SAME: %[[ARG1:.*]]: vector<4xf32>
569 func @fmaf(%arg0: f32, %arg1: vector<4xf32>) {
570 // CHECK: %[[S:.*]] = "llvm.intr.fma"(%[[ARG0]], %[[ARG0]], %[[ARG0]]) : (f32, f32, f32) -> f32
571 %0 = math.fma %arg0, %arg0, %arg0 : f32
572 // CHECK: %[[V:.*]] = "llvm.intr.fma"(%[[ARG1]], %[[ARG1]], %[[ARG1]]) : (vector<4xf32>, vector<4xf32>, vector<4xf32>) -> vector<4xf32>
573 %1 = math.fma %arg1, %arg1, %arg1 : vector<4xf32>
579 // CHECK-LABEL: func @select_2dvector(
580 func @select_2dvector(%arg0 : vector<4x3xi1>, %arg1 : vector<4x3xi32>, %arg2 : vector<4x3xi32>) {
581 // CHECK: %[[EXTRACT1:.*]] = llvm.extractvalue %arg0[0] : !llvm.array<4 x vector<3xi1>>
582 // CHECK: %[[EXTRACT2:.*]] = llvm.extractvalue %arg1[0] : !llvm.array<4 x vector<3xi32>>
583 // CHECK: %[[EXTRACT3:.*]] = llvm.extractvalue %arg2[0] : !llvm.array<4 x vector<3xi32>>
584 // CHECK: %[[SELECT:.*]] = llvm.select %[[EXTRACT1]], %[[EXTRACT2]], %[[EXTRACT3]] : vector<3xi1>, vector<3xi32>
585 // CHECK: %[[INSERT:.*]] = llvm.insertvalue %[[SELECT]], %0[0] : !llvm.array<4 x vector<3xi32>>
586 %0 = select %arg0, %arg1, %arg2 : vector<4x3xi1>, vector<4x3xi32>
592 // CHECK-LABEL: func @switchi8(
593 func @switchi8(%arg0 : i8) -> i32 {
600 %c_1 = arith.constant 1 : i32
601 std.return %c_1 : i32
603 %c_42 = arith.constant 42 : i32
604 std.return %c_42: i32
606 // CHECK: llvm.switch %arg0 : i8, ^bb1 [
607 // CHECK-NEXT: 42: ^bb1,
608 // CHECK-NEXT: 43: ^bb2
610 // CHECK: ^bb1: // 2 preds: ^bb0, ^bb0
611 // CHECK-NEXT: %[[E0:.+]] = llvm.mlir.constant(1 : i32) : i32
612 // CHECK-NEXT: llvm.return %[[E0]] : i32
613 // CHECK: ^bb2: // pred: ^bb0
614 // CHECK-NEXT: %[[E1:.+]] = llvm.mlir.constant(42 : i32) : i32
615 // CHECK-NEXT: llvm.return %[[E1]] : i32