586 lines · plain
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 %s2 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 %s4 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 %s6 7// RUN: mlir-opt -transform-interpreter %s | FileCheck --check-prefix=CHECK32 %s8 9// Same below, but using the `ConvertToLLVMPatternInterface` entry point10// and the generic `convert-to-llvm` pass.11// RUN: mlir-opt --convert-to-llvm="filter-dialects=arith,cf,func,math" %s | FileCheck %s12// RUN: mlir-opt --convert-to-llvm="filter-dialects=arith,cf,func,math allow-pattern-rollback=0" %s | FileCheck %s13 14// CHECK-LABEL: func @empty() {15// CHECK-NEXT: llvm.return16// CHECK-NEXT: }17func.func @empty() {18^bb0:19 return20}21 22// CHECK-LABEL: llvm.func @body(i64)23func.func private @body(index)24 25// CHECK-LABEL: func @simple_loop() {26// CHECK32-LABEL: func @simple_loop() {27func.func @simple_loop() {28^bb0:29// CHECK-NEXT: llvm.br ^bb130// CHECK32-NEXT: llvm.br ^bb131 cf.br ^bb132 33// CHECK-NEXT: ^bb1: // pred: ^bb034// CHECK-NEXT: {{.*}} = llvm.mlir.constant(1 : index) : i6435// CHECK-NEXT: {{.*}} = llvm.mlir.constant(42 : index) : i6436// CHECK-NEXT: llvm.br ^bb2({{.*}} : i64)37// CHECK32-NEXT: ^bb1: // pred: ^bb038// CHECK32-NEXT: {{.*}} = llvm.mlir.constant(1 : index) : i3239// CHECK32-NEXT: {{.*}} = llvm.mlir.constant(42 : index) : i3240// CHECK32-NEXT: llvm.br ^bb2({{.*}} : i32)41^bb1: // pred: ^bb042 %c1 = arith.constant 1 : index43 %c42 = arith.constant 42 : index44 cf.br ^bb2(%c1 : index)45 46// CHECK: ^bb2({{.*}}: i64): // 2 preds: ^bb1, ^bb347// CHECK-NEXT: {{.*}} = llvm.icmp "slt" {{.*}}, {{.*}} : i6448// CHECK-NEXT: llvm.cond_br {{.*}}, ^bb3, ^bb449// CHECK32: ^bb2({{.*}}: i32): // 2 preds: ^bb1, ^bb350// CHECK32-NEXT: {{.*}} = llvm.icmp "slt" {{.*}}, {{.*}} : i3251// CHECK32-NEXT: llvm.cond_br {{.*}}, ^bb3, ^bb452^bb2(%0: index): // 2 preds: ^bb1, ^bb353 %1 = arith.cmpi slt, %0, %c42 : index54 cf.cond_br %1, ^bb3, ^bb455 56// CHECK: ^bb3: // pred: ^bb257// CHECK-NEXT: llvm.call @body({{.*}}) : (i64) -> ()58// CHECK-NEXT: {{.*}} = llvm.mlir.constant(1 : index) : i6459// CHECK-NEXT: {{.*}} = llvm.add {{.*}}, {{.*}} : i6460// CHECK-NEXT: llvm.br ^bb2({{.*}} : i64)61// CHECK32: ^bb3: // pred: ^bb262// CHECK32-NEXT: llvm.call @body({{.*}}) : (i32) -> ()63// CHECK32-NEXT: {{.*}} = llvm.mlir.constant(1 : index) : i3264// CHECK32-NEXT: {{.*}} = llvm.add {{.*}}, {{.*}} : i3265// CHECK32-NEXT: llvm.br ^bb2({{.*}} : i32)66^bb3: // pred: ^bb267 call @body(%0) : (index) -> ()68 %c1_0 = arith.constant 1 : index69 %2 = arith.addi %0, %c1_0 : index70 cf.br ^bb2(%2 : index)71 72// CHECK: ^bb4: // pred: ^bb273// CHECK-NEXT: llvm.return74^bb4: // pred: ^bb275 return76}77 78// CHECK-LABEL: func @simple_caller() {79// CHECK-NEXT: llvm.call @simple_loop() : () -> ()80// CHECK-NEXT: llvm.return81// CHECK-NEXT: }82func.func @simple_caller() {83^bb0:84 call @simple_loop() : () -> ()85 return86}87 88// Check that function call attributes persist during conversion.89// CHECK-LABEL: @call_with_attributes90func.func @call_with_attributes() {91 // CHECK: llvm.call @simple_loop() {baz = [1, 2, 3, 4], foo = "bar"} : () -> ()92 call @simple_loop() {foo="bar", baz=[1,2,3,4]} : () -> ()93 return94}95 96// CHECK-LABEL: func @ml_caller() {97// CHECK-NEXT: llvm.call @simple_loop() : () -> ()98// CHECK-NEXT: llvm.call @more_imperfectly_nested_loops() : () -> ()99// CHECK-NEXT: llvm.return100// CHECK-NEXT: }101func.func @ml_caller() {102^bb0:103 call @simple_loop() : () -> ()104 call @more_imperfectly_nested_loops() : () -> ()105 return106}107 108// CHECK-LABEL: llvm.func @body_args(i64) -> i64109// CHECK32-LABEL: llvm.func @body_args(i32) -> i32110// CHECK-NO-CF-LABEL: llvm.func @body_args(i64) -> i64111func.func private @body_args(index) -> index112// CHECK-LABEL: llvm.func @other(i64, i32) -> i32113// CHECK32-LABEL: llvm.func @other(i32, i32) -> i32114func.func private @other(index, i32) -> i32115 116// CHECK-LABEL: func @func_args(%arg0: i32, %arg1: i32) -> i32 {117// CHECK-NEXT: {{.*}} = llvm.mlir.constant(0 : i32) : i32118// CHECK-NEXT: llvm.br ^bb1119// CHECK32-LABEL: func @func_args(%arg0: i32, %arg1: i32) -> i32 {120// CHECK32-NEXT: {{.*}} = llvm.mlir.constant(0 : i32) : i32121// CHECK32-NEXT: llvm.br ^bb1122func.func @func_args(i32, i32) -> i32 {123^bb0(%arg0: i32, %arg1: i32):124 %c0_i32 = arith.constant 0 : i32125 cf.br ^bb1126 127// CHECK-NEXT: ^bb1: // pred: ^bb0128// CHECK-NEXT: {{.*}} = llvm.mlir.constant(0 : index) : i64129// CHECK-NEXT: {{.*}} = llvm.mlir.constant(42 : index) : i64130// CHECK-NEXT: llvm.br ^bb2({{.*}} : i64)131// CHECK32-NEXT: ^bb1: // pred: ^bb0132// CHECK32-NEXT: {{.*}} = llvm.mlir.constant(0 : index) : i32133// CHECK32-NEXT: {{.*}} = llvm.mlir.constant(42 : index) : i32134// CHECK32-NEXT: llvm.br ^bb2({{.*}} : i32)135^bb1: // pred: ^bb0136 %c0 = arith.constant 0 : index137 %c42 = arith.constant 42 : index138 cf.br ^bb2(%c0 : index)139 140// CHECK-NEXT: ^bb2({{.*}}: i64): // 2 preds: ^bb1, ^bb3141// CHECK-NEXT: {{.*}} = llvm.icmp "slt" {{.*}}, {{.*}} : i64142// CHECK-NEXT: llvm.cond_br {{.*}}, ^bb3, ^bb4143// CHECK32-NEXT: ^bb2({{.*}}: i32): // 2 preds: ^bb1, ^bb3144// CHECK32-NEXT: {{.*}} = llvm.icmp "slt" {{.*}}, {{.*}} : i32145// CHECK32-NEXT: llvm.cond_br {{.*}}, ^bb3, ^bb4146^bb2(%0: index): // 2 preds: ^bb1, ^bb3147 %1 = arith.cmpi slt, %0, %c42 : index148 cf.cond_br %1, ^bb3, ^bb4149 150// CHECK-NEXT: ^bb3: // pred: ^bb2151// CHECK-NEXT: {{.*}} = llvm.call @body_args({{.*}}) : (i64) -> i64152// CHECK-NEXT: {{.*}} = llvm.call @other({{.*}}, %arg0) : (i64, i32) -> i32153// CHECK-NEXT: {{.*}} = llvm.call @other({{.*}}, {{.*}}) : (i64, i32) -> i32154// CHECK-NEXT: {{.*}} = llvm.call @other({{.*}}, %arg1) : (i64, i32) -> i32155// CHECK-NEXT: {{.*}} = llvm.mlir.constant(1 : index) : i64156// CHECK-NEXT: {{.*}} = llvm.add {{.*}}, {{.*}} : i64157// CHECK-NEXT: llvm.br ^bb2({{.*}} : i64)158// CHECK32-NEXT: ^bb3: // pred: ^bb2159// CHECK32-NEXT: {{.*}} = llvm.call @body_args({{.*}}) : (i32) -> i32160// CHECK32-NEXT: {{.*}} = llvm.call @other({{.*}}, %arg0) : (i32, i32) -> i32161// CHECK32-NEXT: {{.*}} = llvm.call @other({{.*}}, {{.*}}) : (i32, i32) -> i32162// CHECK32-NEXT: {{.*}} = llvm.call @other({{.*}}, %arg1) : (i32, i32) -> i32163// CHECK32-NEXT: {{.*}} = llvm.mlir.constant(1 : index) : i32164// CHECK32-NEXT: {{.*}} = llvm.add {{.*}}, {{.*}} : i32165// CHECK32-NEXT: llvm.br ^bb2({{.*}} : i32)166^bb3: // pred: ^bb2167 %2 = call @body_args(%0) : (index) -> index168 %3 = call @other(%2, %arg0) : (index, i32) -> i32169 %4 = call @other(%2, %3) : (index, i32) -> i32170 %5 = call @other(%2, %arg1) : (index, i32) -> i32171 %c1 = arith.constant 1 : index172 %6 = arith.addi %0, %c1 : index173 cf.br ^bb2(%6 : index)174 175// CHECK-NEXT: ^bb4: // pred: ^bb2176// CHECK-NEXT: {{.*}} = llvm.mlir.constant(0 : index) : i64177// CHECK-NEXT: {{.*}} = llvm.call @other({{.*}}, {{.*}}) : (i64, i32) -> i32178// CHECK-NEXT: llvm.return {{.*}} : i32179// CHECK32-NEXT: ^bb4: // pred: ^bb2180// CHECK32-NEXT: {{.*}} = llvm.mlir.constant(0 : index) : i32181// CHECK32-NEXT: {{.*}} = llvm.call @other({{.*}}, {{.*}}) : (i32, i32) -> i32182// CHECK32-NEXT: llvm.return {{.*}} : i32183^bb4: // pred: ^bb2184 %c0_0 = arith.constant 0 : index185 %7 = call @other(%c0_0, %c0_i32) : (index, i32) -> i32186 return %7 : i32187}188 189// CHECK-LABEL: llvm.func @pre(i64)190// CHECK32-LABEL: llvm.func @pre(i32)191func.func private @pre(index)192 193// CHECK-LABEL: llvm.func @body2(i64, i64)194// CHECK32-LABEL: llvm.func @body2(i32, i32)195func.func private @body2(index, index)196 197// CHECK-LABEL: llvm.func @post(i64)198// CHECK32-LABEL: llvm.func @post(i32)199func.func private @post(index)200 201// CHECK-LABEL: func @imperfectly_nested_loops() {202// CHECK-NEXT: llvm.br ^bb1203func.func @imperfectly_nested_loops() {204^bb0:205 cf.br ^bb1206 207// CHECK-NEXT: ^bb1: // pred: ^bb0208// CHECK-NEXT: {{.*}} = llvm.mlir.constant(0 : index) : i64209// CHECK-NEXT: {{.*}} = llvm.mlir.constant(42 : index) : i64210// CHECK-NEXT: llvm.br ^bb2({{.*}} : i64)211^bb1: // pred: ^bb0212 %c0 = arith.constant 0 : index213 %c42 = arith.constant 42 : index214 cf.br ^bb2(%c0 : index)215 216// CHECK-NEXT: ^bb2({{.*}}: i64): // 2 preds: ^bb1, ^bb7217// CHECK-NEXT: {{.*}} = llvm.icmp "slt" {{.*}}, {{.*}} : i64218// CHECK-NEXT: llvm.cond_br {{.*}}, ^bb3, ^bb8219^bb2(%0: index): // 2 preds: ^bb1, ^bb7220 %1 = arith.cmpi slt, %0, %c42 : index221 cf.cond_br %1, ^bb3, ^bb8222 223// CHECK-NEXT: ^bb3:224// CHECK-NEXT: llvm.call @pre({{.*}}) : (i64) -> ()225// CHECK-NEXT: llvm.br ^bb4226^bb3: // pred: ^bb2227 call @pre(%0) : (index) -> ()228 cf.br ^bb4229 230// CHECK-NEXT: ^bb4: // pred: ^bb3231// CHECK-NEXT: {{.*}} = llvm.mlir.constant(7 : index) : i64232// CHECK-NEXT: {{.*}} = llvm.mlir.constant(56 : index) : i64233// CHECK-NEXT: llvm.br ^bb5({{.*}} : i64)234^bb4: // pred: ^bb3235 %c7 = arith.constant 7 : index236 %c56 = arith.constant 56 : index237 cf.br ^bb5(%c7 : index)238 239// CHECK-NEXT: ^bb5({{.*}}: i64): // 2 preds: ^bb4, ^bb6240// CHECK-NEXT: {{.*}} = llvm.icmp "slt" {{.*}}, {{.*}} : i64241// CHECK-NEXT: llvm.cond_br {{.*}}, ^bb6, ^bb7242^bb5(%2: index): // 2 preds: ^bb4, ^bb6243 %3 = arith.cmpi slt, %2, %c56 : index244 cf.cond_br %3, ^bb6, ^bb7245 246// CHECK-NEXT: ^bb6: // pred: ^bb5247// CHECK-NEXT: llvm.call @body2({{.*}}, {{.*}}) : (i64, i64) -> ()248// CHECK-NEXT: {{.*}} = llvm.mlir.constant(2 : index) : i64249// CHECK-NEXT: {{.*}} = llvm.add {{.*}}, {{.*}} : i64250// CHECK-NEXT: llvm.br ^bb5({{.*}} : i64)251^bb6: // pred: ^bb5252 call @body2(%0, %2) : (index, index) -> ()253 %c2 = arith.constant 2 : index254 %4 = arith.addi %2, %c2 : index255 cf.br ^bb5(%4 : index)256 257// CHECK-NEXT: ^bb7: // pred: ^bb5258// CHECK-NEXT: llvm.call @post({{.*}}) : (i64) -> ()259// CHECK-NEXT: {{.*}} = llvm.mlir.constant(1 : index) : i64260// CHECK-NEXT: {{.*}} = llvm.add {{.*}}, {{.*}} : i64261// CHECK-NEXT: llvm.br ^bb2({{.*}} : i64)262^bb7: // pred: ^bb5263 call @post(%0) : (index) -> ()264 %c1 = arith.constant 1 : index265 %5 = arith.addi %0, %c1 : index266 cf.br ^bb2(%5 : index)267 268// CHECK-NEXT: ^bb8: // pred: ^bb2269// CHECK-NEXT: llvm.return270^bb8: // pred: ^bb2271 return272}273 274// CHECK-LABEL: llvm.func @mid(i64)275func.func private @mid(index)276 277// CHECK-LABEL: llvm.func @body3(i64, i64)278func.func private @body3(index, index)279 280// A complete function transformation check.281// CHECK-LABEL: func @more_imperfectly_nested_loops() {282// CHECK-NEXT: llvm.br ^bb1283// CHECK-NEXT:^bb1: // pred: ^bb0284// CHECK-NEXT: {{.*}} = llvm.mlir.constant(0 : index) : i64285// CHECK-NEXT: {{.*}} = llvm.mlir.constant(42 : index) : i64286// CHECK-NEXT: llvm.br ^bb2({{.*}} : i64)287// CHECK-NEXT:^bb2({{.*}}: i64): // 2 preds: ^bb1, ^bb11288// CHECK-NEXT: {{.*}} = llvm.icmp "slt" {{.*}}, {{.*}} : i64289// CHECK-NEXT: llvm.cond_br {{.*}}, ^bb3, ^bb12290// CHECK-NEXT:^bb3: // pred: ^bb2291// CHECK-NEXT: llvm.call @pre({{.*}}) : (i64) -> ()292// CHECK-NEXT: llvm.br ^bb4293// CHECK-NEXT:^bb4: // pred: ^bb3294// CHECK-NEXT: {{.*}} = llvm.mlir.constant(7 : index) : i64295// CHECK-NEXT: {{.*}} = llvm.mlir.constant(56 : index) : i64296// CHECK-NEXT: llvm.br ^bb5({{.*}} : i64)297// CHECK-NEXT:^bb5({{.*}}: i64): // 2 preds: ^bb4, ^bb6298// CHECK-NEXT: {{.*}} = llvm.icmp "slt" {{.*}}, {{.*}} : i64299// CHECK-NEXT: llvm.cond_br {{.*}}, ^bb6, ^bb7300// CHECK-NEXT:^bb6: // pred: ^bb5301// CHECK-NEXT: llvm.call @body2({{.*}}, {{.*}}) : (i64, i64) -> ()302// CHECK-NEXT: {{.*}} = llvm.mlir.constant(2 : index) : i64303// CHECK-NEXT: {{.*}} = llvm.add {{.*}}, {{.*}} : i64304// CHECK-NEXT: llvm.br ^bb5({{.*}} : i64)305// CHECK-NEXT:^bb7: // pred: ^bb5306// CHECK-NEXT: llvm.call @mid({{.*}}) : (i64) -> ()307// CHECK-NEXT: llvm.br ^bb8308// CHECK-NEXT:^bb8: // pred: ^bb7309// CHECK-NEXT: {{.*}} = llvm.mlir.constant(18 : index) : i64310// CHECK-NEXT: {{.*}} = llvm.mlir.constant(37 : index) : i64311// CHECK-NEXT: llvm.br ^bb9({{.*}} : i64)312// CHECK-NEXT:^bb9({{.*}}: i64): // 2 preds: ^bb8, ^bb10313// CHECK-NEXT: {{.*}} = llvm.icmp "slt" {{.*}}, {{.*}} : i64314// CHECK-NEXT: llvm.cond_br {{.*}}, ^bb10, ^bb11315// CHECK-NEXT:^bb10: // pred: ^bb9316// CHECK-NEXT: llvm.call @body3({{.*}}, {{.*}}) : (i64, i64) -> ()317// CHECK-NEXT: {{.*}} = llvm.mlir.constant(3 : index) : i64318// CHECK-NEXT: {{.*}} = llvm.add {{.*}}, {{.*}} : i64319// CHECK-NEXT: llvm.br ^bb9({{.*}} : i64)320// CHECK-NEXT:^bb11: // pred: ^bb9321// CHECK-NEXT: llvm.call @post({{.*}}) : (i64) -> ()322// CHECK-NEXT: {{.*}} = llvm.mlir.constant(1 : index) : i64323// CHECK-NEXT: {{.*}} = llvm.add {{.*}}, {{.*}} : i64324// CHECK-NEXT: llvm.br ^bb2({{.*}} : i64)325// CHECK-NEXT:^bb12: // pred: ^bb2326// CHECK-NEXT: llvm.return327// CHECK-NEXT: }328func.func @more_imperfectly_nested_loops() {329^bb0:330 cf.br ^bb1331^bb1: // pred: ^bb0332 %c0 = arith.constant 0 : index333 %c42 = arith.constant 42 : index334 cf.br ^bb2(%c0 : index)335^bb2(%0: index): // 2 preds: ^bb1, ^bb11336 %1 = arith.cmpi slt, %0, %c42 : index337 cf.cond_br %1, ^bb3, ^bb12338^bb3: // pred: ^bb2339 call @pre(%0) : (index) -> ()340 cf.br ^bb4341^bb4: // pred: ^bb3342 %c7 = arith.constant 7 : index343 %c56 = arith.constant 56 : index344 cf.br ^bb5(%c7 : index)345^bb5(%2: index): // 2 preds: ^bb4, ^bb6346 %3 = arith.cmpi slt, %2, %c56 : index347 cf.cond_br %3, ^bb6, ^bb7348^bb6: // pred: ^bb5349 call @body2(%0, %2) : (index, index) -> ()350 %c2 = arith.constant 2 : index351 %4 = arith.addi %2, %c2 : index352 cf.br ^bb5(%4 : index)353^bb7: // pred: ^bb5354 call @mid(%0) : (index) -> ()355 cf.br ^bb8356^bb8: // pred: ^bb7357 %c18 = arith.constant 18 : index358 %c37 = arith.constant 37 : index359 cf.br ^bb9(%c18 : index)360^bb9(%5: index): // 2 preds: ^bb8, ^bb10361 %6 = arith.cmpi slt, %5, %c37 : index362 cf.cond_br %6, ^bb10, ^bb11363^bb10: // pred: ^bb9364 call @body3(%0, %5) : (index, index) -> ()365 %c3 = arith.constant 3 : index366 %7 = arith.addi %5, %c3 : index367 cf.br ^bb9(%7 : index)368^bb11: // pred: ^bb9369 call @post(%0) : (index) -> ()370 %c1 = arith.constant 1 : index371 %8 = arith.addi %0, %c1 : index372 cf.br ^bb2(%8 : index)373^bb12: // pred: ^bb2374 return375}376 377// CHECK-LABEL: llvm.func @get_i64() -> i64378func.func private @get_i64() -> (i64)379// CHECK-LABEL: llvm.func @get_f32() -> f32380func.func private @get_f32() -> (f32)381// CHECK-LABEL: llvm.func @get_c16() -> !llvm.struct<(f16, f16)>382func.func private @get_c16() -> (complex<f16>)383// CHECK-LABEL: llvm.func @get_c32() -> !llvm.struct<(f32, f32)>384func.func private @get_c32() -> (complex<f32>)385// CHECK-LABEL: llvm.func @get_c64() -> !llvm.struct<(f64, f64)>386func.func private @get_c64() -> (complex<f64>)387// CHECK-LABEL: llvm.func @get_memref() -> !llvm.struct<(ptr, ptr, i64, array<4 x i64>, array<4 x i64>)>388// CHECK32-LABEL: llvm.func @get_memref() -> !llvm.struct<(ptr, ptr, i32, array<4 x i32>, array<4 x i32>)>389func.func private @get_memref() -> (memref<42x?x10x?xf32>)390 391// CHECK-LABEL: llvm.func @multireturn() -> !llvm.struct<(i64, f32, struct<(ptr, ptr, i64, array<4 x i64>, array<4 x i64>)>)> {392// CHECK32-LABEL: llvm.func @multireturn() -> !llvm.struct<(i64, f32, struct<(ptr, ptr, i32, array<4 x i32>, array<4 x i32>)>)> {393func.func @multireturn() -> (i64, f32, memref<42x?x10x?xf32>) {394^bb0:395// CHECK-NEXT: {{.*}} = llvm.call @get_i64() : () -> i64396// CHECK-NEXT: {{.*}} = llvm.call @get_f32() : () -> f32397// CHECK-NEXT: {{.*}} = llvm.call @get_memref() : () -> !llvm.struct<(ptr, ptr, i64, array<4 x i64>, array<4 x i64>)>398// CHECK32-NEXT: {{.*}} = llvm.call @get_i64() : () -> i64399// CHECK32-NEXT: {{.*}} = llvm.call @get_f32() : () -> f32400// CHECK32-NEXT: {{.*}} = llvm.call @get_memref() : () -> !llvm.struct<(ptr, ptr, i32, array<4 x i32>, array<4 x i32>)>401 %0 = call @get_i64() : () -> (i64)402 %1 = call @get_f32() : () -> (f32)403 %2 = call @get_memref() : () -> (memref<42x?x10x?xf32>)404// CHECK-NEXT: {{.*}} = llvm.mlir.poison : !llvm.struct<(i64, f32, struct<(ptr, ptr, i64, array<4 x i64>, array<4 x i64>)>)>405// CHECK-NEXT: {{.*}} = llvm.insertvalue {{.*}}, {{.*}}[0] : !llvm.struct<(i64, f32, struct<(ptr, ptr, i64, array<4 x i64>, array<4 x i64>)>)>406// CHECK-NEXT: {{.*}} = llvm.insertvalue {{.*}}, {{.*}}[1] : !llvm.struct<(i64, f32, struct<(ptr, ptr, i64, array<4 x i64>, array<4 x i64>)>)>407// CHECK-NEXT: {{.*}} = llvm.insertvalue {{.*}}, {{.*}}[2] : !llvm.struct<(i64, f32, struct<(ptr, ptr, i64, array<4 x i64>, array<4 x i64>)>)>408// CHECK-NEXT: llvm.return {{.*}} : !llvm.struct<(i64, f32, struct<(ptr, ptr, i64, array<4 x i64>, array<4 x i64>)>)>409// CHECK32-NEXT: {{.*}} = llvm.mlir.poison : !llvm.struct<(i64, f32, struct<(ptr, ptr, i32, array<4 x i32>, array<4 x i32>)>)>410// CHECK32-NEXT: {{.*}} = llvm.insertvalue {{.*}}, {{.*}}[0] : !llvm.struct<(i64, f32, struct<(ptr, ptr, i32, array<4 x i32>, array<4 x i32>)>)>411// CHECK32-NEXT: {{.*}} = llvm.insertvalue {{.*}}, {{.*}}[1] : !llvm.struct<(i64, f32, struct<(ptr, ptr, i32, array<4 x i32>, array<4 x i32>)>)>412// CHECK32-NEXT: {{.*}} = llvm.insertvalue {{.*}}, {{.*}}[2] : !llvm.struct<(i64, f32, struct<(ptr, ptr, i32, array<4 x i32>, array<4 x i32>)>)>413// CHECK32-NEXT: llvm.return {{.*}} : !llvm.struct<(i64, f32, struct<(ptr, ptr, i32, array<4 x i32>, array<4 x i32>)>)>414 return %0, %1, %2 : i64, f32, memref<42x?x10x?xf32>415}416 417 418// CHECK-LABEL: llvm.func @multireturn_caller() {419// CHECK32-LABEL: llvm.func @multireturn_caller() {420func.func @multireturn_caller() {421^bb0:422// CHECK-NEXT: {{.*}} = llvm.call @multireturn() : () -> !llvm.struct<(i64, f32, struct<(ptr, ptr, i64, array<4 x i64>, array<4 x i64>)>)>423// CHECK-NEXT: {{.*}} = llvm.extractvalue {{.*}}[0] : !llvm.struct<(i64, f32, struct<(ptr, ptr, i64, array<4 x i64>, array<4 x i64>)>)>424// CHECK-NEXT: {{.*}} = llvm.extractvalue {{.*}}[1] : !llvm.struct<(i64, f32, struct<(ptr, ptr, i64, array<4 x i64>, array<4 x i64>)>)>425// CHECK-NEXT: {{.*}} = llvm.extractvalue {{.*}}[2] : !llvm.struct<(i64, f32, struct<(ptr, ptr, i64, array<4 x i64>, array<4 x i64>)>)>426// CHECK32-NEXT: {{.*}} = llvm.call @multireturn() : () -> !llvm.struct<(i64, f32, struct<(ptr, ptr, i32, array<4 x i32>, array<4 x i32>)>)>427// CHECK32-NEXT: {{.*}} = llvm.extractvalue {{.*}}[0] : !llvm.struct<(i64, f32, struct<(ptr, ptr, i32, array<4 x i32>, array<4 x i32>)>)>428// CHECK32-NEXT: {{.*}} = llvm.extractvalue {{.*}}[1] : !llvm.struct<(i64, f32, struct<(ptr, ptr, i32, array<4 x i32>, array<4 x i32>)>)>429// CHECK32-NEXT: {{.*}} = llvm.extractvalue {{.*}}[2] : !llvm.struct<(i64, f32, struct<(ptr, ptr, i32, array<4 x i32>, array<4 x i32>)>)>430 %0:3 = call @multireturn() : () -> (i64, f32, memref<42x?x10x?xf32>)431 %1 = arith.constant 42 : i64432// CHECK: {{.*}} = llvm.add {{.*}}, {{.*}} : i64433 %2 = arith.addi %0#0, %1 : i64434 %3 = arith.constant 42.0 : f32435// CHECK: {{.*}} = llvm.fadd {{.*}}, {{.*}} : f32436 %4 = arith.addf %0#1, %3 : f32437 %5 = arith.constant 0 : index438 return439}440 441// CHECK-LABEL: @dfs_block_order442func.func @dfs_block_order(%arg0: i32) -> (i32) {443// CHECK-NEXT: %[[CST:.*]] = llvm.mlir.constant(42 : i32) : i32444 %0 = arith.constant 42 : i32445// CHECK-NEXT: llvm.br ^bb2446 cf.br ^bb2447 448// CHECK-NEXT: ^bb1:449// CHECK-NEXT: %[[ADD:.*]] = llvm.add %arg0, %[[CST]] : i32450// CHECK-NEXT: llvm.return %[[ADD]] : i32451^bb1:452 %2 = arith.addi %arg0, %0 : i32453 return %2 : i32454 455// CHECK-NEXT: ^bb2:456^bb2:457// CHECK-NEXT: llvm.br ^bb1458 cf.br ^bb1459}460 461// CHECK-LABEL: func @ceilf(462// CHECK-SAME: f32463func.func @ceilf(%arg0 : f32) {464 // CHECK: llvm.intr.ceil(%arg0) : (f32) -> f32465 %0 = math.ceil %arg0 : f32466 func.return467}468 469// CHECK-LABEL: func @floorf(470// CHECK-SAME: f32471func.func @floorf(%arg0 : f32) {472 // CHECK: llvm.intr.floor(%arg0) : (f32) -> f32473 %0 = math.floor %arg0 : f32474 func.return475}476 477// Wrap the following tests in a module to control the place where478// `llvm.func @abort()` is produced.479module {480// Lowers `cf.assert` to a function call to `abort` if the assertion is violated.481// CHECK: llvm.func @abort()482// CHECK-LABEL: @assert_test_function483// CHECK-SAME: (%[[ARG:.*]]: i1)484func.func @assert_test_function(%arg : i1) {485 // CHECK: llvm.cond_br %[[ARG]], ^[[CONTINUATION_BLOCK:.*]], ^[[FAILURE_BLOCK:.*]]486 // CHECK: ^[[CONTINUATION_BLOCK]]:487 // CHECK: llvm.return488 // CHECK: ^[[FAILURE_BLOCK]]:489 // CHECK: llvm.call @abort() : () -> ()490 // CHECK: llvm.unreachable491 cf.assert %arg, "Computer says no"492 return493}494}495 496// This should not trigger an assertion by creating an LLVM::CallOp with a497// nullptr result type.498 499// CHECK-LABEL: @call_zero_result_func500func.func @call_zero_result_func() {501 // CHECK: call @zero_result_func502 call @zero_result_func() : () -> ()503 return504}505func.func private @zero_result_func()506 507// CHECK-LABEL: func @fmaf(508// CHECK-SAME: %[[ARG0:.*]]: f32509// CHECK-SAME: %[[ARG1:.*]]: vector<4xf32>510func.func @fmaf(%arg0: f32, %arg1: vector<4xf32>) {511 // CHECK: %[[S:.*]] = llvm.intr.fma(%[[ARG0]], %[[ARG0]], %[[ARG0]]) : (f32, f32, f32) -> f32512 %0 = math.fma %arg0, %arg0, %arg0 : f32513 // CHECK: %[[V:.*]] = llvm.intr.fma(%[[ARG1]], %[[ARG1]], %[[ARG1]]) : (vector<4xf32>, vector<4xf32>, vector<4xf32>) -> vector<4xf32>514 %1 = math.fma %arg1, %arg1, %arg1 : vector<4xf32>515 func.return516}517 518// CHECK-LABEL: func @switchi8(519func.func @switchi8(%arg0 : i8) -> i32 {520 cf.switch %arg0 : i8, [521 default: ^bb1,522 42: ^bb1,523 43: ^bb3524 ]525^bb1:526 %c_1 = arith.constant 1 : i32527 func.return %c_1 : i32528^bb3:529 %c_42 = arith.constant 42 : i32530 func.return %c_42: i32531}532// CHECK: llvm.switch %arg0 : i8, ^bb1 [533// CHECK-NEXT: 42: ^bb1,534// CHECK-NEXT: 43: ^bb2535// CHECK-NEXT: ]536// CHECK: ^bb1: // 2 preds: ^bb0, ^bb0537// CHECK-NEXT: %[[E0:.+]] = llvm.mlir.constant(1 : i32) : i32538// CHECK-NEXT: llvm.return %[[E0]] : i32539// CHECK: ^bb2: // pred: ^bb0540// CHECK-NEXT: %[[E1:.+]] = llvm.mlir.constant(42 : i32) : i32541// CHECK-NEXT: llvm.return %[[E1]] : i32542// CHECK-NEXT: }543 544// Convert the entry block but not the unstructured control flow.545 546// CHECK-NO-CF-LABEL: llvm.func @index_arg(547// CHECK-NO-CF-SAME: %[[arg0:.*]]: i64) -> i64 {548// CHECK-NO-CF: %[[cast:.*]] = builtin.unrealized_conversion_cast %[[arg0]] : i64 to index549// CHECK-NO-CF: cf.br ^[[bb1:.*]](%[[cast]] : index)550// CHECK-NO-CF: ^[[bb1]](%[[arg1:.*]]: index):551// CHECK-NO-CF: %[[cast2:.*]] = builtin.unrealized_conversion_cast %[[arg1]] : index to i64552// CHECK-NO-CF: llvm.return %[[cast2]] : i64553func.func @index_arg(%arg0: index) -> index {554 cf.br ^bb1(%arg0 : index)555^bb1(%arg1: index):556 return %arg1 : index557}558 559// There is no type conversion rule for tf32, so vector<1xtf32> and, therefore,560// the func op cannot be converted.561// CHECK: func.func @non_convertible_arg_type({{.*}}: vector<1xtf32>)562// CHECK: llvm.return563func.func @non_convertible_arg_type(%arg: vector<1xtf32>) {564 return565}566 567module attributes {transform.with_named_sequence} {568 transform.named_sequence @__transform_main(%toplevel_module: !transform.any_op {transform.readonly}) {569 %func = transform.structured.match ops{["func.func"]} in %toplevel_module570 : (!transform.any_op) -> !transform.any_op571 transform.apply_conversion_patterns to %func {572 transform.apply_conversion_patterns.dialect_to_llvm "math"573 transform.apply_conversion_patterns.dialect_to_llvm "arith"574 transform.apply_conversion_patterns.dialect_to_llvm "cf"575 transform.apply_conversion_patterns.func.func_to_llvm576 } with type_converter {577 transform.apply_conversion_patterns.memref.memref_to_llvm_type_converter578 {index_bitwidth = 32, use_opaque_pointers = true}579 } {580 legal_dialects = ["llvm"],581 partial_conversion582 } : !transform.any_op583 transform.yield584 }585}586