xref: /llvm-project/mlir/test/Conversion/FuncToLLVM/func-to-llvm.mlir (revision 6422546e996c769dda39a681da090fe28870a376)
1// RUN: mlir-opt -pass-pipeline="builtin.module(func.func(convert-math-to-llvm,convert-arith-to-llvm),convert-func-to-llvm,convert-cf-to-llvm,reconcile-unrealized-casts)" %s | FileCheck %s
2
3// RUN: mlir-opt -pass-pipeline="builtin.module(func.func(convert-math-to-llvm,convert-arith-to-llvm{index-bitwidth=32}),convert-func-to-llvm{index-bitwidth=32},convert-cf-to-llvm{index-bitwidth=32},reconcile-unrealized-casts)" %s | FileCheck --check-prefix=CHECK32 %s
4
5// RUN: mlir-opt -pass-pipeline="builtin.module(func.func(convert-math-to-llvm,convert-arith-to-llvm),convert-func-to-llvm,reconcile-unrealized-casts)" %s | FileCheck --check-prefix=CHECK-NO-CF %s
6
7// RUN: mlir-opt -transform-interpreter %s | FileCheck --check-prefix=CHECK32 %s
8
9// Same below, but using the `ConvertToLLVMPatternInterface` entry point
10// and the generic `convert-to-llvm` pass.
11// RUN: mlir-opt --convert-to-llvm="filter-dialects=arith,cf,func,math" %s | FileCheck %s
12
13// CHECK-LABEL: func @empty() {
14// CHECK-NEXT:  llvm.return
15// CHECK-NEXT: }
16func.func @empty() {
17^bb0:
18  return
19}
20
21// CHECK-LABEL: llvm.func @body(i64)
22func.func private @body(index)
23
24// CHECK-LABEL: func @simple_loop() {
25// CHECK32-LABEL: func @simple_loop() {
26func.func @simple_loop() {
27^bb0:
28// CHECK-NEXT:  llvm.br ^bb1
29// CHECK32-NEXT:  llvm.br ^bb1
30  cf.br ^bb1
31
32// CHECK-NEXT: ^bb1:	// pred: ^bb0
33// CHECK-NEXT:  {{.*}} = llvm.mlir.constant(1 : index) : i64
34// CHECK-NEXT:  {{.*}} = llvm.mlir.constant(42 : index) : i64
35// CHECK-NEXT:  llvm.br ^bb2({{.*}} : i64)
36// CHECK32-NEXT: ^bb1:	// pred: ^bb0
37// CHECK32-NEXT:  {{.*}} = llvm.mlir.constant(1 : index) : i32
38// CHECK32-NEXT:  {{.*}} = llvm.mlir.constant(42 : index) : i32
39// CHECK32-NEXT:  llvm.br ^bb2({{.*}} : i32)
40^bb1:	// pred: ^bb0
41  %c1 = arith.constant 1 : index
42  %c42 = arith.constant 42 : index
43  cf.br ^bb2(%c1 : index)
44
45// CHECK:      ^bb2({{.*}}: i64):	// 2 preds: ^bb1, ^bb3
46// CHECK-NEXT:  {{.*}} = llvm.icmp "slt" {{.*}}, {{.*}} : i64
47// CHECK-NEXT:  llvm.cond_br {{.*}}, ^bb3, ^bb4
48// CHECK32:      ^bb2({{.*}}: i32):	// 2 preds: ^bb1, ^bb3
49// CHECK32-NEXT:  {{.*}} = llvm.icmp "slt" {{.*}}, {{.*}} : i32
50// CHECK32-NEXT:  llvm.cond_br {{.*}}, ^bb3, ^bb4
51^bb2(%0: index):	// 2 preds: ^bb1, ^bb3
52  %1 = arith.cmpi slt, %0, %c42 : index
53  cf.cond_br %1, ^bb3, ^bb4
54
55// CHECK:      ^bb3:	// pred: ^bb2
56// CHECK-NEXT:  llvm.call @body({{.*}}) : (i64) -> ()
57// CHECK-NEXT:  {{.*}} = llvm.mlir.constant(1 : index) : i64
58// CHECK-NEXT:  {{.*}} = llvm.add {{.*}}, {{.*}} : i64
59// CHECK-NEXT:  llvm.br ^bb2({{.*}} : i64)
60// CHECK32:      ^bb3:	// pred: ^bb2
61// CHECK32-NEXT:  llvm.call @body({{.*}}) : (i32) -> ()
62// CHECK32-NEXT:  {{.*}} = llvm.mlir.constant(1 : index) : i32
63// CHECK32-NEXT:  {{.*}} = llvm.add {{.*}}, {{.*}} : i32
64// CHECK32-NEXT:  llvm.br ^bb2({{.*}} : i32)
65^bb3:	// pred: ^bb2
66  call @body(%0) : (index) -> ()
67  %c1_0 = arith.constant 1 : index
68  %2 = arith.addi %0, %c1_0 : index
69  cf.br ^bb2(%2 : index)
70
71// CHECK:      ^bb4:	// pred: ^bb2
72// CHECK-NEXT:  llvm.return
73^bb4:	// pred: ^bb2
74  return
75}
76
77// CHECK-LABEL: func @simple_caller() {
78// CHECK-NEXT:  llvm.call @simple_loop() : () -> ()
79// CHECK-NEXT:  llvm.return
80// CHECK-NEXT: }
81func.func @simple_caller() {
82^bb0:
83  call @simple_loop() : () -> ()
84  return
85}
86
87// Check that function call attributes persist during conversion.
88// CHECK-LABEL: @call_with_attributes
89func.func @call_with_attributes() {
90  // CHECK: llvm.call @simple_loop() {baz = [1, 2, 3, 4], foo = "bar"} : () -> ()
91  call @simple_loop() {foo="bar", baz=[1,2,3,4]} : () -> ()
92  return
93}
94
95// CHECK-LABEL: func @ml_caller() {
96// CHECK-NEXT:  llvm.call @simple_loop() : () -> ()
97// CHECK-NEXT:  llvm.call @more_imperfectly_nested_loops() : () -> ()
98// CHECK-NEXT:  llvm.return
99// CHECK-NEXT: }
100func.func @ml_caller() {
101^bb0:
102  call @simple_loop() : () -> ()
103  call @more_imperfectly_nested_loops() : () -> ()
104  return
105}
106
107// CHECK-LABEL: llvm.func @body_args(i64) -> i64
108// CHECK32-LABEL: llvm.func @body_args(i32) -> i32
109// CHECK-NO-CF-LABEL: llvm.func @body_args(i64) -> i64
110func.func private @body_args(index) -> index
111// CHECK-LABEL: llvm.func @other(i64, i32) -> i32
112// CHECK32-LABEL: llvm.func @other(i32, i32) -> i32
113func.func private @other(index, i32) -> i32
114
115// CHECK-LABEL: func @func_args(%arg0: i32, %arg1: i32) -> i32 {
116// CHECK-NEXT:  {{.*}} = llvm.mlir.constant(0 : i32) : i32
117// CHECK-NEXT:  llvm.br ^bb1
118// CHECK32-LABEL: func @func_args(%arg0: i32, %arg1: i32) -> i32 {
119// CHECK32-NEXT:  {{.*}} = llvm.mlir.constant(0 : i32) : i32
120// CHECK32-NEXT:  llvm.br ^bb1
121func.func @func_args(i32, i32) -> i32 {
122^bb0(%arg0: i32, %arg1: i32):
123  %c0_i32 = arith.constant 0 : i32
124  cf.br ^bb1
125
126// CHECK-NEXT: ^bb1:	// pred: ^bb0
127// CHECK-NEXT:  {{.*}} = llvm.mlir.constant(0 : index) : i64
128// CHECK-NEXT:  {{.*}} = llvm.mlir.constant(42 : index) : i64
129// CHECK-NEXT:  llvm.br ^bb2({{.*}} : i64)
130// CHECK32-NEXT: ^bb1:	// pred: ^bb0
131// CHECK32-NEXT:  {{.*}} = llvm.mlir.constant(0 : index) : i32
132// CHECK32-NEXT:  {{.*}} = llvm.mlir.constant(42 : index) : i32
133// CHECK32-NEXT:  llvm.br ^bb2({{.*}} : i32)
134^bb1:	// pred: ^bb0
135  %c0 = arith.constant 0 : index
136  %c42 = arith.constant 42 : index
137  cf.br ^bb2(%c0 : index)
138
139// CHECK-NEXT: ^bb2({{.*}}: i64):	// 2 preds: ^bb1, ^bb3
140// CHECK-NEXT:  {{.*}} = llvm.icmp "slt" {{.*}}, {{.*}} : i64
141// CHECK-NEXT:  llvm.cond_br {{.*}}, ^bb3, ^bb4
142// CHECK32-NEXT: ^bb2({{.*}}: i32):	// 2 preds: ^bb1, ^bb3
143// CHECK32-NEXT:  {{.*}} = llvm.icmp "slt" {{.*}}, {{.*}} : i32
144// CHECK32-NEXT:  llvm.cond_br {{.*}}, ^bb3, ^bb4
145^bb2(%0: index):	// 2 preds: ^bb1, ^bb3
146  %1 = arith.cmpi slt, %0, %c42 : index
147  cf.cond_br %1, ^bb3, ^bb4
148
149// CHECK-NEXT: ^bb3:	// pred: ^bb2
150// CHECK-NEXT:  {{.*}} = llvm.call @body_args({{.*}}) : (i64) -> i64
151// CHECK-NEXT:  {{.*}} = llvm.call @other({{.*}}, %arg0) : (i64, i32) -> i32
152// CHECK-NEXT:  {{.*}} = llvm.call @other({{.*}}, {{.*}}) : (i64, i32) -> i32
153// CHECK-NEXT:  {{.*}} = llvm.call @other({{.*}}, %arg1) : (i64, i32) -> i32
154// CHECK-NEXT:  {{.*}} = llvm.mlir.constant(1 : index) : i64
155// CHECK-NEXT:  {{.*}} = llvm.add {{.*}}, {{.*}} : i64
156// CHECK-NEXT:  llvm.br ^bb2({{.*}} : i64)
157// CHECK32-NEXT: ^bb3:	// pred: ^bb2
158// CHECK32-NEXT:  {{.*}} = llvm.call @body_args({{.*}}) : (i32) -> i32
159// CHECK32-NEXT:  {{.*}} = llvm.call @other({{.*}}, %arg0) : (i32, i32) -> i32
160// CHECK32-NEXT:  {{.*}} = llvm.call @other({{.*}}, {{.*}}) : (i32, i32) -> i32
161// CHECK32-NEXT:  {{.*}} = llvm.call @other({{.*}}, %arg1) : (i32, i32) -> i32
162// CHECK32-NEXT:  {{.*}} = llvm.mlir.constant(1 : index) : i32
163// CHECK32-NEXT:  {{.*}} = llvm.add {{.*}}, {{.*}} : i32
164// CHECK32-NEXT:  llvm.br ^bb2({{.*}} : i32)
165^bb3:	// pred: ^bb2
166  %2 = call @body_args(%0) : (index) -> index
167  %3 = call @other(%2, %arg0) : (index, i32) -> i32
168  %4 = call @other(%2, %3) : (index, i32) -> i32
169  %5 = call @other(%2, %arg1) : (index, i32) -> i32
170  %c1 = arith.constant 1 : index
171  %6 = arith.addi %0, %c1 : index
172  cf.br ^bb2(%6 : index)
173
174// CHECK-NEXT: ^bb4:	// pred: ^bb2
175// CHECK-NEXT:  {{.*}} = llvm.mlir.constant(0 : index) : i64
176// CHECK-NEXT:  {{.*}} = llvm.call @other({{.*}}, {{.*}}) : (i64, i32) -> i32
177// CHECK-NEXT:  llvm.return {{.*}} : i32
178// CHECK32-NEXT: ^bb4:	// pred: ^bb2
179// CHECK32-NEXT:  {{.*}} = llvm.mlir.constant(0 : index) : i32
180// CHECK32-NEXT:  {{.*}} = llvm.call @other({{.*}}, {{.*}}) : (i32, i32) -> i32
181// CHECK32-NEXT:  llvm.return {{.*}} : i32
182^bb4:	// pred: ^bb2
183  %c0_0 = arith.constant 0 : index
184  %7 = call @other(%c0_0, %c0_i32) : (index, i32) -> i32
185  return %7 : i32
186}
187
188// CHECK-LABEL: llvm.func @pre(i64)
189// CHECK32-LABEL: llvm.func @pre(i32)
190func.func private @pre(index)
191
192// CHECK-LABEL: llvm.func @body2(i64, i64)
193// CHECK32-LABEL: llvm.func @body2(i32, i32)
194func.func private @body2(index, index)
195
196// CHECK-LABEL: llvm.func @post(i64)
197// CHECK32-LABEL: llvm.func @post(i32)
198func.func private @post(index)
199
200// CHECK-LABEL: func @imperfectly_nested_loops() {
201// CHECK-NEXT:  llvm.br ^bb1
202func.func @imperfectly_nested_loops() {
203^bb0:
204  cf.br ^bb1
205
206// CHECK-NEXT: ^bb1:	// pred: ^bb0
207// CHECK-NEXT:  {{.*}} = llvm.mlir.constant(0 : index) : i64
208// CHECK-NEXT:  {{.*}} = llvm.mlir.constant(42 : index) : i64
209// CHECK-NEXT:  llvm.br ^bb2({{.*}} : i64)
210^bb1:	// pred: ^bb0
211  %c0 = arith.constant 0 : index
212  %c42 = arith.constant 42 : index
213  cf.br ^bb2(%c0 : index)
214
215// CHECK-NEXT: ^bb2({{.*}}: i64):	// 2 preds: ^bb1, ^bb7
216// CHECK-NEXT:  {{.*}} = llvm.icmp "slt" {{.*}}, {{.*}} : i64
217// CHECK-NEXT:  llvm.cond_br {{.*}}, ^bb3, ^bb8
218^bb2(%0: index):	// 2 preds: ^bb1, ^bb7
219  %1 = arith.cmpi slt, %0, %c42 : index
220  cf.cond_br %1, ^bb3, ^bb8
221
222// CHECK-NEXT: ^bb3:
223// CHECK-NEXT:  llvm.call @pre({{.*}}) : (i64) -> ()
224// CHECK-NEXT:  llvm.br ^bb4
225^bb3:	// pred: ^bb2
226  call @pre(%0) : (index) -> ()
227  cf.br ^bb4
228
229// CHECK-NEXT: ^bb4:	// pred: ^bb3
230// CHECK-NEXT:  {{.*}} = llvm.mlir.constant(7 : index) : i64
231// CHECK-NEXT:  {{.*}} = llvm.mlir.constant(56 : index) : i64
232// CHECK-NEXT:  llvm.br ^bb5({{.*}} : i64)
233^bb4:	// pred: ^bb3
234  %c7 = arith.constant 7 : index
235  %c56 = arith.constant 56 : index
236  cf.br ^bb5(%c7 : index)
237
238// CHECK-NEXT: ^bb5({{.*}}: i64):	// 2 preds: ^bb4, ^bb6
239// CHECK-NEXT:  {{.*}} = llvm.icmp "slt" {{.*}}, {{.*}} : i64
240// CHECK-NEXT:  llvm.cond_br {{.*}}, ^bb6, ^bb7
241^bb5(%2: index):	// 2 preds: ^bb4, ^bb6
242  %3 = arith.cmpi slt, %2, %c56 : index
243  cf.cond_br %3, ^bb6, ^bb7
244
245// CHECK-NEXT: ^bb6:	// pred: ^bb5
246// CHECK-NEXT:  llvm.call @body2({{.*}}, {{.*}}) : (i64, i64) -> ()
247// CHECK-NEXT:  {{.*}} = llvm.mlir.constant(2 : index) : i64
248// CHECK-NEXT:  {{.*}} = llvm.add {{.*}}, {{.*}} : i64
249// CHECK-NEXT:  llvm.br ^bb5({{.*}} : i64)
250^bb6:	// pred: ^bb5
251  call @body2(%0, %2) : (index, index) -> ()
252  %c2 = arith.constant 2 : index
253  %4 = arith.addi %2, %c2 : index
254  cf.br ^bb5(%4 : index)
255
256// CHECK-NEXT: ^bb7:	// pred: ^bb5
257// CHECK-NEXT:  llvm.call @post({{.*}}) : (i64) -> ()
258// CHECK-NEXT:  {{.*}} = llvm.mlir.constant(1 : index) : i64
259// CHECK-NEXT:  {{.*}} = llvm.add {{.*}}, {{.*}} : i64
260// CHECK-NEXT:  llvm.br ^bb2({{.*}} : i64)
261^bb7:	// pred: ^bb5
262  call @post(%0) : (index) -> ()
263  %c1 = arith.constant 1 : index
264  %5 = arith.addi %0, %c1 : index
265  cf.br ^bb2(%5 : index)
266
267// CHECK-NEXT: ^bb8:	// pred: ^bb2
268// CHECK-NEXT:  llvm.return
269^bb8:	// pred: ^bb2
270  return
271}
272
273// CHECK-LABEL: llvm.func @mid(i64)
274func.func private @mid(index)
275
276// CHECK-LABEL: llvm.func @body3(i64, i64)
277func.func private @body3(index, index)
278
279// A complete function transformation check.
280// CHECK-LABEL: func @more_imperfectly_nested_loops() {
281// CHECK-NEXT:  llvm.br ^bb1
282// CHECK-NEXT:^bb1:	// pred: ^bb0
283// CHECK-NEXT:  {{.*}} = llvm.mlir.constant(0 : index) : i64
284// CHECK-NEXT:  {{.*}} = llvm.mlir.constant(42 : index) : i64
285// CHECK-NEXT:  llvm.br ^bb2({{.*}} : i64)
286// CHECK-NEXT:^bb2({{.*}}: i64):	// 2 preds: ^bb1, ^bb11
287// CHECK-NEXT:  {{.*}} = llvm.icmp "slt" {{.*}}, {{.*}} : i64
288// CHECK-NEXT:  llvm.cond_br {{.*}}, ^bb3, ^bb12
289// CHECK-NEXT:^bb3:	// pred: ^bb2
290// CHECK-NEXT:  llvm.call @pre({{.*}}) : (i64) -> ()
291// CHECK-NEXT:  llvm.br ^bb4
292// CHECK-NEXT:^bb4:	// pred: ^bb3
293// CHECK-NEXT:  {{.*}} = llvm.mlir.constant(7 : index) : i64
294// CHECK-NEXT:  {{.*}} = llvm.mlir.constant(56 : index) : i64
295// CHECK-NEXT:  llvm.br ^bb5({{.*}} : i64)
296// CHECK-NEXT:^bb5({{.*}}: i64):	// 2 preds: ^bb4, ^bb6
297// CHECK-NEXT:  {{.*}} = llvm.icmp "slt" {{.*}}, {{.*}} : i64
298// CHECK-NEXT:  llvm.cond_br {{.*}}, ^bb6, ^bb7
299// CHECK-NEXT:^bb6:	// pred: ^bb5
300// CHECK-NEXT:  llvm.call @body2({{.*}}, {{.*}}) : (i64, i64) -> ()
301// CHECK-NEXT:  {{.*}} = llvm.mlir.constant(2 : index) : i64
302// CHECK-NEXT:  {{.*}} = llvm.add {{.*}}, {{.*}} : i64
303// CHECK-NEXT:  llvm.br ^bb5({{.*}} : i64)
304// CHECK-NEXT:^bb7:	// pred: ^bb5
305// CHECK-NEXT:  llvm.call @mid({{.*}}) : (i64) -> ()
306// CHECK-NEXT:  llvm.br ^bb8
307// CHECK-NEXT:^bb8:	// pred: ^bb7
308// CHECK-NEXT:  {{.*}} = llvm.mlir.constant(18 : index) : i64
309// CHECK-NEXT:  {{.*}} = llvm.mlir.constant(37 : index) : i64
310// CHECK-NEXT:  llvm.br ^bb9({{.*}} : i64)
311// CHECK-NEXT:^bb9({{.*}}: i64):	// 2 preds: ^bb8, ^bb10
312// CHECK-NEXT:  {{.*}} = llvm.icmp "slt" {{.*}}, {{.*}} : i64
313// CHECK-NEXT:  llvm.cond_br {{.*}}, ^bb10, ^bb11
314// CHECK-NEXT:^bb10:	// pred: ^bb9
315// CHECK-NEXT:  llvm.call @body3({{.*}}, {{.*}}) : (i64, i64) -> ()
316// CHECK-NEXT:  {{.*}} = llvm.mlir.constant(3 : index) : i64
317// CHECK-NEXT:  {{.*}} = llvm.add {{.*}}, {{.*}} : i64
318// CHECK-NEXT:  llvm.br ^bb9({{.*}} : i64)
319// CHECK-NEXT:^bb11:	// pred: ^bb9
320// CHECK-NEXT:  llvm.call @post({{.*}}) : (i64) -> ()
321// CHECK-NEXT:  {{.*}} = llvm.mlir.constant(1 : index) : i64
322// CHECK-NEXT:  {{.*}} = llvm.add {{.*}}, {{.*}} : i64
323// CHECK-NEXT:  llvm.br ^bb2({{.*}} : i64)
324// CHECK-NEXT:^bb12:	// pred: ^bb2
325// CHECK-NEXT:  llvm.return
326// CHECK-NEXT: }
327func.func @more_imperfectly_nested_loops() {
328^bb0:
329  cf.br ^bb1
330^bb1:	// pred: ^bb0
331  %c0 = arith.constant 0 : index
332  %c42 = arith.constant 42 : index
333  cf.br ^bb2(%c0 : index)
334^bb2(%0: index):	// 2 preds: ^bb1, ^bb11
335  %1 = arith.cmpi slt, %0, %c42 : index
336  cf.cond_br %1, ^bb3, ^bb12
337^bb3:	// pred: ^bb2
338  call @pre(%0) : (index) -> ()
339  cf.br ^bb4
340^bb4:	// pred: ^bb3
341  %c7 = arith.constant 7 : index
342  %c56 = arith.constant 56 : index
343  cf.br ^bb5(%c7 : index)
344^bb5(%2: index):	// 2 preds: ^bb4, ^bb6
345  %3 = arith.cmpi slt, %2, %c56 : index
346  cf.cond_br %3, ^bb6, ^bb7
347^bb6:	// pred: ^bb5
348  call @body2(%0, %2) : (index, index) -> ()
349  %c2 = arith.constant 2 : index
350  %4 = arith.addi %2, %c2 : index
351  cf.br ^bb5(%4 : index)
352^bb7:	// pred: ^bb5
353  call @mid(%0) : (index) -> ()
354  cf.br ^bb8
355^bb8:	// pred: ^bb7
356  %c18 = arith.constant 18 : index
357  %c37 = arith.constant 37 : index
358  cf.br ^bb9(%c18 : index)
359^bb9(%5: index):	// 2 preds: ^bb8, ^bb10
360  %6 = arith.cmpi slt, %5, %c37 : index
361  cf.cond_br %6, ^bb10, ^bb11
362^bb10:	// pred: ^bb9
363  call @body3(%0, %5) : (index, index) -> ()
364  %c3 = arith.constant 3 : index
365  %7 = arith.addi %5, %c3 : index
366  cf.br ^bb9(%7 : index)
367^bb11:	// pred: ^bb9
368  call @post(%0) : (index) -> ()
369  %c1 = arith.constant 1 : index
370  %8 = arith.addi %0, %c1 : index
371  cf.br ^bb2(%8 : index)
372^bb12:	// pred: ^bb2
373  return
374}
375
376// CHECK-LABEL: llvm.func @get_i64() -> i64
377func.func private @get_i64() -> (i64)
378// CHECK-LABEL: llvm.func @get_f32() -> f32
379func.func private @get_f32() -> (f32)
380// CHECK-LABEL: llvm.func @get_c16() -> !llvm.struct<(f16, f16)>
381func.func private @get_c16() -> (complex<f16>)
382// CHECK-LABEL: llvm.func @get_c32() -> !llvm.struct<(f32, f32)>
383func.func private @get_c32() -> (complex<f32>)
384// CHECK-LABEL: llvm.func @get_c64() -> !llvm.struct<(f64, f64)>
385func.func private @get_c64() -> (complex<f64>)
386// CHECK-LABEL: llvm.func @get_memref() -> !llvm.struct<(ptr, ptr, i64, array<4 x i64>, array<4 x i64>)>
387// CHECK32-LABEL: llvm.func @get_memref() -> !llvm.struct<(ptr, ptr, i32, array<4 x i32>, array<4 x i32>)>
388func.func private @get_memref() -> (memref<42x?x10x?xf32>)
389
390// CHECK-LABEL: llvm.func @multireturn() -> !llvm.struct<(i64, f32, struct<(ptr, ptr, i64, array<4 x i64>, array<4 x i64>)>)> {
391// CHECK32-LABEL: llvm.func @multireturn() -> !llvm.struct<(i64, f32, struct<(ptr, ptr, i32, array<4 x i32>, array<4 x i32>)>)> {
392func.func @multireturn() -> (i64, f32, memref<42x?x10x?xf32>) {
393^bb0:
394// CHECK-NEXT:  {{.*}} = llvm.call @get_i64() : () -> i64
395// CHECK-NEXT:  {{.*}} = llvm.call @get_f32() : () -> f32
396// CHECK-NEXT:  {{.*}} = llvm.call @get_memref() : () -> !llvm.struct<(ptr, ptr, i64, array<4 x i64>, array<4 x i64>)>
397// CHECK32-NEXT:  {{.*}} = llvm.call @get_i64() : () -> i64
398// CHECK32-NEXT:  {{.*}} = llvm.call @get_f32() : () -> f32
399// CHECK32-NEXT:  {{.*}} = llvm.call @get_memref() : () -> !llvm.struct<(ptr, ptr, i32, array<4 x i32>, array<4 x i32>)>
400  %0 = call @get_i64() : () -> (i64)
401  %1 = call @get_f32() : () -> (f32)
402  %2 = call @get_memref() : () -> (memref<42x?x10x?xf32>)
403// CHECK-NEXT:  {{.*}} = llvm.mlir.undef : !llvm.struct<(i64, f32, struct<(ptr, ptr, i64, array<4 x i64>, array<4 x i64>)>)>
404// CHECK-NEXT:  {{.*}} = llvm.insertvalue {{.*}}, {{.*}}[0] : !llvm.struct<(i64, f32, struct<(ptr, ptr, i64, array<4 x i64>, array<4 x i64>)>)>
405// CHECK-NEXT:  {{.*}} = llvm.insertvalue {{.*}}, {{.*}}[1] : !llvm.struct<(i64, f32, struct<(ptr, ptr, i64, array<4 x i64>, array<4 x i64>)>)>
406// CHECK-NEXT:  {{.*}} = llvm.insertvalue {{.*}}, {{.*}}[2] : !llvm.struct<(i64, f32, struct<(ptr, ptr, i64, array<4 x i64>, array<4 x i64>)>)>
407// CHECK-NEXT:  llvm.return {{.*}} : !llvm.struct<(i64, f32, struct<(ptr, ptr, i64, array<4 x i64>, array<4 x i64>)>)>
408// CHECK32-NEXT:  {{.*}} = llvm.mlir.undef : !llvm.struct<(i64, f32, struct<(ptr, ptr, i32, array<4 x i32>, array<4 x i32>)>)>
409// CHECK32-NEXT:  {{.*}} = llvm.insertvalue {{.*}}, {{.*}}[0] : !llvm.struct<(i64, f32, struct<(ptr, ptr, i32, array<4 x i32>, array<4 x i32>)>)>
410// CHECK32-NEXT:  {{.*}} = llvm.insertvalue {{.*}}, {{.*}}[1] : !llvm.struct<(i64, f32, struct<(ptr, ptr, i32, array<4 x i32>, array<4 x i32>)>)>
411// CHECK32-NEXT:  {{.*}} = llvm.insertvalue {{.*}}, {{.*}}[2] : !llvm.struct<(i64, f32, struct<(ptr, ptr, i32, array<4 x i32>, array<4 x i32>)>)>
412// CHECK32-NEXT:  llvm.return {{.*}} : !llvm.struct<(i64, f32, struct<(ptr, ptr, i32, array<4 x i32>, array<4 x i32>)>)>
413  return %0, %1, %2 : i64, f32, memref<42x?x10x?xf32>
414}
415
416
417// CHECK-LABEL: llvm.func @multireturn_caller() {
418// CHECK32-LABEL: llvm.func @multireturn_caller() {
419func.func @multireturn_caller() {
420^bb0:
421// CHECK-NEXT:  {{.*}} = llvm.call @multireturn() : () -> !llvm.struct<(i64, f32, struct<(ptr, ptr, i64, array<4 x i64>, array<4 x i64>)>)>
422// CHECK-NEXT:  {{.*}} = llvm.extractvalue {{.*}}[0] : !llvm.struct<(i64, f32, struct<(ptr, ptr, i64, array<4 x i64>, array<4 x i64>)>)>
423// CHECK-NEXT:  {{.*}} = llvm.extractvalue {{.*}}[1] : !llvm.struct<(i64, f32, struct<(ptr, ptr, i64, array<4 x i64>, array<4 x i64>)>)>
424// CHECK-NEXT:  {{.*}} = llvm.extractvalue {{.*}}[2] : !llvm.struct<(i64, f32, struct<(ptr, ptr, i64, array<4 x i64>, array<4 x i64>)>)>
425// CHECK32-NEXT:  {{.*}} = llvm.call @multireturn() : () -> !llvm.struct<(i64, f32, struct<(ptr, ptr, i32, array<4 x i32>, array<4 x i32>)>)>
426// CHECK32-NEXT:  {{.*}} = llvm.extractvalue {{.*}}[0] : !llvm.struct<(i64, f32, struct<(ptr, ptr, i32, array<4 x i32>, array<4 x i32>)>)>
427// CHECK32-NEXT:  {{.*}} = llvm.extractvalue {{.*}}[1] : !llvm.struct<(i64, f32, struct<(ptr, ptr, i32, array<4 x i32>, array<4 x i32>)>)>
428// CHECK32-NEXT:  {{.*}} = llvm.extractvalue {{.*}}[2] : !llvm.struct<(i64, f32, struct<(ptr, ptr, i32, array<4 x i32>, array<4 x i32>)>)>
429  %0:3 = call @multireturn() : () -> (i64, f32, memref<42x?x10x?xf32>)
430  %1 = arith.constant 42 : i64
431// CHECK:       {{.*}} = llvm.add {{.*}}, {{.*}} : i64
432  %2 = arith.addi %0#0, %1 : i64
433  %3 = arith.constant 42.0 : f32
434// CHECK:       {{.*}} = llvm.fadd {{.*}}, {{.*}} : f32
435  %4 = arith.addf %0#1, %3 : f32
436  %5 = arith.constant 0 : index
437  return
438}
439
440// CHECK-LABEL: @dfs_block_order
441func.func @dfs_block_order(%arg0: i32) -> (i32) {
442// CHECK-NEXT:  %[[CST:.*]] = llvm.mlir.constant(42 : i32) : i32
443  %0 = arith.constant 42 : i32
444// CHECK-NEXT:  llvm.br ^bb2
445  cf.br ^bb2
446
447// CHECK-NEXT: ^bb1:
448// CHECK-NEXT:  %[[ADD:.*]] = llvm.add %arg0, %[[CST]] : i32
449// CHECK-NEXT:  llvm.return %[[ADD]] : i32
450^bb1:
451  %2 = arith.addi %arg0, %0 : i32
452  return %2 : i32
453
454// CHECK-NEXT: ^bb2:
455^bb2:
456// CHECK-NEXT:  llvm.br ^bb1
457  cf.br ^bb1
458}
459
460// CHECK-LABEL: func @ceilf(
461// CHECK-SAME: f32
462func.func @ceilf(%arg0 : f32) {
463  // CHECK: llvm.intr.ceil(%arg0) : (f32) -> f32
464  %0 = math.ceil %arg0 : f32
465  func.return
466}
467
468// CHECK-LABEL: func @floorf(
469// CHECK-SAME: f32
470func.func @floorf(%arg0 : f32) {
471  // CHECK: llvm.intr.floor(%arg0) : (f32) -> f32
472  %0 = math.floor %arg0 : f32
473  func.return
474}
475
476// Wrap the following tests in a module to control the place where
477// `llvm.func @abort()` is produced.
478module {
479// Lowers `cf.assert` to a function call to `abort` if the assertion is violated.
480// CHECK: llvm.func @abort()
481// CHECK-LABEL: @assert_test_function
482// CHECK-SAME:  (%[[ARG:.*]]: i1)
483func.func @assert_test_function(%arg : i1) {
484  // CHECK: llvm.cond_br %[[ARG]], ^[[CONTINUATION_BLOCK:.*]], ^[[FAILURE_BLOCK:.*]]
485  // CHECK: ^[[CONTINUATION_BLOCK]]:
486  // CHECK: llvm.return
487  // CHECK: ^[[FAILURE_BLOCK]]:
488  // CHECK: llvm.call @abort() : () -> ()
489  // CHECK: llvm.unreachable
490  cf.assert %arg, "Computer says no"
491  return
492}
493}
494
495// This should not trigger an assertion by creating an LLVM::CallOp with a
496// nullptr result type.
497
498// CHECK-LABEL: @call_zero_result_func
499func.func @call_zero_result_func() {
500  // CHECK: call @zero_result_func
501  call @zero_result_func() : () -> ()
502  return
503}
504func.func private @zero_result_func()
505
506// CHECK-LABEL: func @fmaf(
507// CHECK-SAME: %[[ARG0:.*]]: f32
508// CHECK-SAME: %[[ARG1:.*]]: vector<4xf32>
509func.func @fmaf(%arg0: f32, %arg1: vector<4xf32>) {
510  // CHECK: %[[S:.*]] = llvm.intr.fma(%[[ARG0]], %[[ARG0]], %[[ARG0]]) : (f32, f32, f32) -> f32
511  %0 = math.fma %arg0, %arg0, %arg0 : f32
512  // CHECK: %[[V:.*]] = llvm.intr.fma(%[[ARG1]], %[[ARG1]], %[[ARG1]]) : (vector<4xf32>, vector<4xf32>, vector<4xf32>) -> vector<4xf32>
513  %1 = math.fma %arg1, %arg1, %arg1 : vector<4xf32>
514  func.return
515}
516
517// CHECK-LABEL: func @switchi8(
518func.func @switchi8(%arg0 : i8) -> i32 {
519  cf.switch %arg0 : i8, [
520    default: ^bb1,
521    42: ^bb1,
522    43: ^bb3
523  ]
524^bb1:
525  %c_1 = arith.constant 1 : i32
526  func.return %c_1 : i32
527^bb3:
528  %c_42 = arith.constant 42 : i32
529  func.return %c_42: i32
530}
531// CHECK:     llvm.switch %arg0 : i8, ^bb1 [
532// CHECK-NEXT:       42: ^bb1,
533// CHECK-NEXT:       43: ^bb2
534// CHECK-NEXT:     ]
535// CHECK:   ^bb1:  // 2 preds: ^bb0, ^bb0
536// CHECK-NEXT:     %[[E0:.+]] = llvm.mlir.constant(1 : i32) : i32
537// CHECK-NEXT:     llvm.return %[[E0]] : i32
538// CHECK:   ^bb2:  // pred: ^bb0
539// CHECK-NEXT:     %[[E1:.+]] = llvm.mlir.constant(42 : i32) : i32
540// CHECK-NEXT:     llvm.return %[[E1]] : i32
541// CHECK-NEXT:   }
542
543// Convert the entry block but not the unstructured control flow.
544
545// CHECK-NO-CF-LABEL: llvm.func @index_arg(
546//  CHECK-NO-CF-SAME:     %[[arg0:.*]]: i64) -> i64 {
547//       CHECK-NO-CF:   %[[cast:.*]] = builtin.unrealized_conversion_cast %[[arg0]] : i64 to index
548//       CHECK-NO-CF:   cf.br ^[[bb1:.*]](%[[cast]] : index)
549//       CHECK-NO-CF: ^[[bb1]](%[[arg1:.*]]: index):
550//       CHECK-NO-CF:   %[[cast2:.*]] = builtin.unrealized_conversion_cast %[[arg1]] : index to i64
551//       CHECK-NO-CF:   llvm.return %[[cast2]] : i64
552func.func @index_arg(%arg0: index) -> index {
553  cf.br ^bb1(%arg0 : index)
554^bb1(%arg1: index):
555  return %arg1 : index
556}
557
558// There is no type conversion rule for tf32, so vector<1xtf32> and, therefore,
559// the func op cannot be converted.
560// CHECK: func.func @non_convertible_arg_type({{.*}}: vector<1xtf32>)
561// CHECK:   llvm.return
562func.func @non_convertible_arg_type(%arg: vector<1xtf32>) {
563  return
564}
565
566module attributes {transform.with_named_sequence} {
567  transform.named_sequence @__transform_main(%toplevel_module: !transform.any_op {transform.readonly}) {
568    %func = transform.structured.match ops{["func.func"]} in %toplevel_module
569      : (!transform.any_op) -> !transform.any_op
570    transform.apply_conversion_patterns to %func {
571      transform.apply_conversion_patterns.dialect_to_llvm "math"
572      transform.apply_conversion_patterns.dialect_to_llvm "arith"
573      transform.apply_conversion_patterns.dialect_to_llvm "cf"
574      transform.apply_conversion_patterns.func.func_to_llvm
575    } with type_converter {
576      transform.apply_conversion_patterns.memref.memref_to_llvm_type_converter
577        {index_bitwidth = 32, use_opaque_pointers = true}
578    } {
579      legal_dialects = ["llvm"],
580      partial_conversion
581    } : !transform.any_op
582    transform.yield
583  }
584}
585