brintos

brintos / llvm-project-archived public Read only

0
0
Text · 13.0 KiB · d8e10aa Raw
378 lines · plain
1// RUN: mlir-opt %s -inline='default-pipeline=''' | FileCheck %s2// RUN: mlir-opt %s --mlir-disable-threading -inline='default-pipeline=''' | FileCheck %s3// RUN: mlir-opt %s -inline='default-pipeline=''' -mlir-print-debuginfo -mlir-print-local-scope | FileCheck %s --check-prefix INLINE-LOC4// RUN: mlir-opt %s -inline | FileCheck %s --check-prefix INLINE_SIMPLIFY5// RUN: mlir-opt %s -inline='op-pipelines=func.func(canonicalize,cse)' | FileCheck %s --check-prefix INLINE_SIMPLIFY6 7// Inline a function that takes an argument.8func.func @func_with_arg(%arg0 : i32) -> i32 {9  %b = arith.addi %arg0, %arg0 : i3210  %c = builtin.unrealized_conversion_cast %b : i32 to i6411  %d = builtin.unrealized_conversion_cast %c : i64 to i3212  return %d : i3213}14 15// CHECK-LABEL: func @inline_with_arg16func.func @inline_with_arg(%arg0 : i32) -> i32 {17  // CHECK-NEXT: arith.addi18  // CHECK-NEXT: unrealized_conversion_cast19  // CHECK-NEXT: unrealized_conversion_cast20  // CHECK-NEXT: return21 22  %0 = call @func_with_arg(%arg0) : (i32) -> i3223  return %0 : i3224}25 26// CHECK-LABEL: func @noinline_with_arg27func.func @noinline_with_arg(%arg0 : i32) -> i32 {28  // CHECK-NEXT: func_with_arg29  // CHECK-NEXT: return30 31  %0 = call @func_with_arg(%arg0) {no_inline} : (i32) -> i3232  return %0 : i3233}34 35func.func @non_inlinable_func_with_arg(%c : i32) -> i32 attributes {no_inline} {36  %b = arith.addi %c, %c : i3237  return %b : i3238}39 40// CHECK-LABEL: func @noinline_with_func_arg41func.func @noinline_with_func_arg(%arg0 : i32) -> i32 {42  // CHECK-NEXT: non_inlinable_func_with_arg43  // CHECK-NEXT: return44 45  %0 = call @non_inlinable_func_with_arg(%arg0) : (i32) -> i3246  return %0 : i3247}48 49// Inline a function that has multiple return operations.50func.func @func_with_multi_return(%a : i1) -> (i32) {51  cf.cond_br %a, ^bb1, ^bb252 53^bb1:54  %const_0 = arith.constant 0 : i3255  return %const_0 : i3256 57^bb2:58  %const_55 = arith.constant 55 : i3259  return %const_55 : i3260}61 62// CHECK-LABEL: func @inline_with_multi_return() -> i3263func.func @inline_with_multi_return() -> i32 {64// CHECK-NEXT:    [[VAL_7:%.*]] = arith.constant false65// CHECK-NEXT:    cf.cond_br [[VAL_7]], ^bb1, ^bb266// CHECK:       ^bb1:67// CHECK-NEXT:    [[VAL_8:%.*]] = arith.constant 0 : i3268// CHECK-NEXT:    cf.br ^bb3([[VAL_8]] : i32)69// CHECK:       ^bb2:70// CHECK-NEXT:    [[VAL_9:%.*]] = arith.constant 55 : i3271// CHECK-NEXT:    cf.br ^bb3([[VAL_9]] : i32)72// CHECK:       ^bb3([[VAL_10:%.*]]: i32):73// CHECK-NEXT:    return [[VAL_10]] : i3274 75  %false = arith.constant false76  %x = call @func_with_multi_return(%false) : (i1) -> i3277  return %x : i3278}79 80// Check that location information is updated for inlined instructions.81 82#inline_stack1 = loc(callsite("mysource1.cc":10:8 at callsite("mysource2.cc":13:6 at "mysource3.cc":16:2)))83#inline_stack2 = loc(callsite("mysource4.cc":55:4 at callsite("mysource5.cc":25:8 at "mysource6.cc":32:4)))84 85// INLINE-LOC-LABEL: func @func_with_file_locations86func.func @func_with_file_locations(%c : i32) -> i32 {87  %b = arith.addi %c, %c : i32 loc("mysource.cc":10:8)88  return %b : i32 loc("mysource.cc":11:2)89}90 91// INLINE-LOC-LABEL: func @func_with_callsite_locations92func.func @func_with_callsite_locations(%c : i32) -> i32 {93  %b = arith.addi %c, %c : i32 loc(#inline_stack1)94  return %b : i32 loc(#inline_stack1)95}96 97// INLINE-LOC-LABEL: func @inline_func_with_file_locations98func.func @inline_func_with_file_locations(%arg0 : i32) -> i32 {99  // INLINE-LOC-NEXT: arith.addi %{{.*}}, %{{.*}} : i32 loc(callsite("mysource.cc":10:8 at "mysource.cc":55:14))100  %0 = call @func_with_file_locations(%arg0) : (i32) -> i32 loc("mysource.cc":55:14)101 102  // INLINE-LOC-NEXT: arith.addi %{{.*}}, %{{.*}} : i32103  // INLINE-LOC-SAME: loc(callsite("mysource.cc":10:8 at callsite("mysource1.cc":10:8 at callsite("mysource2.cc":13:6104  // INLINE-LOC-SAME: at "mysource3.cc":16:2))))105  %1 = call @func_with_file_locations(%0) : (i32) -> i32 loc(#inline_stack1)106 107  // INLINE-LOC-NEXT: return108  return %1 : i32109}110 111// INLINE-LOC-LABEL: func @inline_func_with_callsite_locations112func.func @inline_func_with_callsite_locations(%arg0 : i32) -> i32 {113  // INLINE-LOC-NEXT: arith.addi %{{.*}}, %{{.*}} : i32114  // INLINE-LOC-SAME: loc(callsite("mysource1.cc":10:8 at callsite("mysource2.cc":13:6 at callsite("mysource3.cc":16:2115  // INLINE-LOC-SAME: at "mysource.cc":10:8))))116  %0 = call @func_with_callsite_locations(%arg0) : (i32) -> i32 loc("mysource.cc":10:8)117 118  // INLINE-LOC-NEXT: arith.addi %{{.*}}, %{{.*}} : i32119  // INLINE-LOC-SAME: loc(callsite("mysource1.cc":10:8 at callsite("mysource2.cc":13:6 at callsite("mysource3.cc":16:2120  // INLINE-LOC-SAME: at callsite("mysource4.cc":55:4 at callsite("mysource5.cc":25:8 at "mysource6.cc":32:4))))))121  %1 = call @func_with_callsite_locations(%0) : (i32) -> i32 loc(#inline_stack2)122 123  // INLINE-LOC-NEXT: return124  return %1 : i32125}126 127// Check that external function declarations are not inlined.128func.func private @func_external()129 130// CHECK-LABEL: func @no_inline_external131func.func @no_inline_external() {132  // CHECK-NEXT: call @func_external()133  call @func_external() : () -> ()134  return135}136 137// Check that multiple levels of calls will be inlined.138func.func @multilevel_func_a() {139  return140}141func.func @multilevel_func_b() {142  call @multilevel_func_a() : () -> ()143  return144}145 146// CHECK-LABEL: func @inline_multilevel147func.func @inline_multilevel() {148  // CHECK-NOT: call149  %fn = "test.functional_region_op"() ({150    call @multilevel_func_b() : () -> ()151    "test.return"() : () -> ()152  }) : () -> (() -> ())153 154  call_indirect %fn() : () -> ()155  return156}157 158// Check that recursive calls are not inlined.159// CHECK-LABEL: func @no_inline_recursive160func.func @no_inline_recursive() {161  // CHECK: test.functional_region_op162  // CHECK-NOT: test.functional_region_op163  %fn = "test.functional_region_op"() ({164    call @no_inline_recursive() : () -> ()165    "test.return"() : () -> ()166  }) : () -> (() -> ())167  return168}169 170// Check that we can convert types for inputs and results as necessary.171func.func @convert_callee_fn(%arg : i32) -> i32 {172  return %arg : i32173}174func.func @convert_callee_fn_multi_arg(%a : i32, %b : i32) -> () {175  return176}177func.func @convert_callee_fn_multi_res() -> (i32, i32) {178  %res = arith.constant 0 : i32179  return %res, %res : i32, i32180}181 182// CHECK-LABEL: func @inline_convert_call183func.func @inline_convert_call() -> i16 {184  // CHECK: %[[INPUT:.*]] = arith.constant185  %test_input = arith.constant 0 : i16186 187  // CHECK: %[[CAST_INPUT:.*]] = "test.cast"(%[[INPUT]]) : (i16) -> i32188  // CHECK: %[[CAST_RESULT:.*]] = "test.cast"(%[[CAST_INPUT]]) : (i32) -> i16189  // CHECK-NEXT: return %[[CAST_RESULT]]190  %res = "test.conversion_call_op"(%test_input) { callee=@convert_callee_fn } : (i16) -> (i16)191  return %res : i16192}193 194func.func @convert_callee_fn_multiblock() -> i32 {195  cf.br ^bb0196^bb0:197  %0 = arith.constant 0 : i32198  return %0 : i32199}200 201// CHECK-LABEL: func @inline_convert_result_multiblock202func.func @inline_convert_result_multiblock() -> i16 {203// CHECK:   cf.br ^bb1 {inlined_conversion}204// CHECK: ^bb1:205// CHECK:   %[[C:.+]] = arith.constant {inlined_conversion} 0 : i32206// CHECK:   cf.br ^bb2(%[[C]] : i32)207// CHECK: ^bb2(%[[BBARG:.+]]: i32):208// CHECK:   %[[CAST_RESULT:.+]] = "test.cast"(%[[BBARG]]) : (i32) -> i16209// CHECK:   return %[[CAST_RESULT]] : i16210 211  %res = "test.conversion_call_op"() { callee=@convert_callee_fn_multiblock } : () -> (i16)212  return %res : i16213}214 215// CHECK-LABEL: func @no_inline_convert_call216func.func @no_inline_convert_call() {217  // CHECK: "test.conversion_call_op"218  %test_input_i16 = arith.constant 0 : i16219  %test_input_i64 = arith.constant 0 : i64220  "test.conversion_call_op"(%test_input_i16, %test_input_i64) { callee=@convert_callee_fn_multi_arg } : (i16, i64) -> ()221 222  // CHECK: "test.conversion_call_op"223  %res_2:2 = "test.conversion_call_op"() { callee=@convert_callee_fn_multi_res } : () -> (i16, i64)224  return225}226 227// Check that we properly simplify when inlining.228func.func @simplify_return_constant() -> i32 {229  %res = arith.constant 0 : i32230  return %res : i32231}232 233func.func @simplify_return_reference() -> (() -> i32) {234  %res = constant @simplify_return_constant : () -> i32235  return %res : () -> i32236}237 238// INLINE_SIMPLIFY-LABEL: func @inline_simplify239func.func @inline_simplify() -> i32 {240  // INLINE_SIMPLIFY-NEXT: %[[CST:.*]] = arith.constant 0 : i32241  // INLINE_SIMPLIFY-NEXT: return %[[CST]]242  %fn = call @simplify_return_reference() : () -> (() -> i32)243  %res = call_indirect %fn() : () -> i32244  return %res : i32245}246 247// CHECK-LABEL: func @no_inline_invalid_call248func.func @no_inline_invalid_call() -> i32 {249  %res = "test.conversion_call_op"() { callee=@convert_callee_fn_multiblock, noinline } : () -> (i32)250  return %res : i32251}252 253func.func @gpu_alloc() -> memref<1024xf32> {254  %m = gpu.alloc [] () : memref<1024xf32>255  return %m : memref<1024xf32>256}257 258// CHECK-LABEL: func @inline_gpu_ops259func.func @inline_gpu_ops() -> memref<1024xf32> {260  // CHECK-NEXT: gpu.alloc261  %m = call @gpu_alloc() : () -> memref<1024xf32>262  return %m : memref<1024xf32>263}264 265// Test block arguments location propagation.266// Use two call-sites to force cloning.267func.func @func_with_block_args_location(%arg0 : i32) {268  cf.br ^bb1(%arg0 : i32)269^bb1(%x : i32 loc("foo")):270  "test.foo" (%x) : (i32) -> () loc("bar")271  return272}273 274// INLINE-LOC-LABEL: func @func_with_block_args_location_callee1275// INLINE-LOC: cf.br276// INLINE-LOC: ^bb{{[0-9]+}}(%{{.*}}: i32 loc(callsite("foo" at "bar"))277func.func @func_with_block_args_location_callee1(%arg0 : i32) {278  call @func_with_block_args_location(%arg0) : (i32) -> () loc("bar")279  return280}281 282// CHECK-LABEL: func @func_with_block_args_location_callee2283func.func @func_with_block_args_location_callee2(%arg0 : i32) {284  call @func_with_block_args_location(%arg0) : (i32) -> ()285  return286}287 288func.func @func_with_multiple_blocks(%arg0 : i32) {289  cf.br ^bb1(%arg0 : i32)290^bb1(%x : i32):291  "test.foo" (%x) : (i32) -> () loc("bar")292  return293}294 295// CHECK-LABEL: func @func_with_multiple_blocks_callee1296func.func @func_with_multiple_blocks_callee1(%arg0 : i32) {297  "test.dummy_op"() ({298    // Call cannot be inlined because "test.dummy" may not support unstructured299    // control flow in its body.300    // CHECK: call @func_with_multiple_blocks301    call @func_with_multiple_blocks(%arg0) : (i32) -> ()302    "test.terminator"() : () -> ()303  }) : () -> ()304  return305}306 307// CHECK-LABEL: func @func_with_multiple_blocks_callee2308func.func @func_with_multiple_blocks_callee2(%arg0 : i32, %c : i1) {309  %0 = scf.while (%arg1 = %arg0) : (i32) -> (i32) {310    // Call cannot be inlined because scf.while does not support unstructured311    // control flow in its body.312    // CHECK: call @func_with_multiple_blocks313    func.call @func_with_multiple_blocks(%arg0) : (i32) -> ()314    scf.condition(%c) %arg1 : i32315  } do {316  ^bb0(%arg1: i32):317    scf.yield %arg1 : i32318  }319  return320}321 322// Check that we can handle argument and result attributes.323test.conversion_func_op @handle_attr_callee_fn_multi_arg(%arg0 : i16, %arg1 : i16 {"test.handle_argument"}) -> (i16 {"test.handle_result"}, i16) {324  %0 = arith.addi %arg0, %arg1 : i16325  %1 = arith.subi %arg0, %arg1 : i16326  "test.return"(%0, %1) : (i16, i16) -> ()327}328test.conversion_func_op @handle_attr_callee_fn(%arg0 : i32 {"test.handle_argument"}) -> (i32 {"test.handle_result"}) {329  "test.return"(%arg0) : (i32) -> ()330}331 332// CHECK-LABEL: func @inline_handle_attr_call333// CHECK-SAME: %[[ARG0:[a-zA-Z0-9]+]]334// CHECK-SAME: %[[ARG1:[a-zA-Z0-9]+]]335func.func @inline_handle_attr_call(%arg0 : i16, %arg1 : i16) -> (i16, i16) {336 337  // CHECK: %[[CHANGE_INPUT:.*]] = "test.type_changer"(%[[ARG1]]) : (i16) -> i16338  // CHECK: %[[SUM:.*]] = arith.addi %[[ARG0]], %[[CHANGE_INPUT]]339  // CHECK: %[[DIFF:.*]] = arith.subi %[[ARG0]], %[[CHANGE_INPUT]]340  // CHECK: %[[CHANGE_RESULT:.*]] = "test.type_changer"(%[[SUM]]) : (i16) -> i16341  // CHECK-NEXT: return %[[CHANGE_RESULT]], %[[DIFF]]342  %res0, %res1 = "test.conversion_call_op"(%arg0, %arg1) { callee=@handle_attr_callee_fn_multi_arg } : (i16, i16) -> (i16, i16)343  return %res0, %res1 : i16, i16344}345 346// CHECK-LABEL: func @inline_convert_and_handle_attr_call347// CHECK-SAME: %[[ARG0:[a-zA-Z0-9]+]]348func.func @inline_convert_and_handle_attr_call(%arg0 : i16) -> (i16) {349 350  // CHECK: %[[CAST_INPUT:.*]] = "test.cast"(%[[ARG0]]) : (i16) -> i32351  // CHECK: %[[CHANGE_INPUT:.*]] = "test.type_changer"(%[[CAST_INPUT]]) : (i32) -> i32352  // CHECK: %[[CHANGE_RESULT:.*]] = "test.type_changer"(%[[CHANGE_INPUT]]) : (i32) -> i32353  // CHECK: %[[CAST_RESULT:.*]] = "test.cast"(%[[CHANGE_RESULT]]) : (i32) -> i16354  // CHECK: return %[[CAST_RESULT]]355  %res = "test.conversion_call_op"(%arg0) { callee=@handle_attr_callee_fn } : (i16) -> (i16)356  return %res : i16357}358 359// Check a function with complex ops is inlined.360func.func @double_square_complex(%cplx: complex<f32>) -> complex<f32> {361  %double = complex.add %cplx, %cplx : complex<f32>362  %square = complex.mul %double, %double : complex<f32>363  return %square : complex<f32>364}365 366// CHECK-LABEL: func @inline_with_complex_ops367func.func @inline_with_complex_ops() -> complex<f32> {368  %c1 = arith.constant 1.0 : f32369  %c2 = arith.constant 2.0 : f32370  %c = complex.create %c1, %c2 : complex<f32>371 372  // CHECK: complex.add373  // CHECK: complex.mul374  // CHECK-NOT: call375  %r = call @double_square_complex(%c) : (complex<f32>) -> (complex<f32>)376  return %r : complex<f32>377}378