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