brintos

brintos / llvm-project-archived public Read only

0
0
Text · 22.4 KiB · 9a77c5e Raw
712 lines · plain
1// RUN: mlir-opt %s -inline -split-input-file | FileCheck %s2 3#file = #llvm.di_file<"foo.mlir" in "/foo/">4#variable = #llvm.di_local_variable<scope = #file>5#variableAddr = #llvm.di_local_variable<scope = #file>6#label = #llvm.di_label<scope = #file>7 8func.func @inner_func_inlinable(%ptr : !llvm.ptr) -> i32 {9  %0 = llvm.mlir.constant(42 : i32) : i3210  %stack = llvm.intr.stacksave : !llvm.ptr11  llvm.store %0, %ptr { alignment = 8 } : i32, !llvm.ptr12  %1 = llvm.load %ptr { alignment = 8 } : !llvm.ptr -> i3213  llvm.intr.dbg.value #variable = %0 : i3214  llvm.intr.dbg.declare #variableAddr = %ptr : !llvm.ptr15  llvm.intr.dbg.label #label16  %byte = llvm.mlir.constant(43 : i8) : i817  %true = llvm.mlir.constant(1 : i1) : i118  "llvm.intr.memset"(%ptr, %byte, %0) <{isVolatile = true}> : (!llvm.ptr, i8, i32) -> ()19  "llvm.intr.memmove"(%ptr, %ptr, %0) <{isVolatile = true}> : (!llvm.ptr, !llvm.ptr, i32) -> ()20  "llvm.intr.memcpy"(%ptr, %ptr, %0) <{isVolatile = true}> : (!llvm.ptr, !llvm.ptr, i32) -> ()21  llvm.intr.assume %true : i122  llvm.fence release23  %2 = llvm.atomicrmw add %ptr, %0 monotonic : !llvm.ptr, i3224  %3 = llvm.cmpxchg %ptr, %0, %1 acq_rel monotonic : !llvm.ptr, i3225  llvm.inline_asm has_side_effects "foo", "bar" : () -> ()26  llvm.cond_br %true, ^bb1, ^bb227^bb1:28  llvm.unreachable29^bb2:30  llvm.intr.stackrestore %stack : !llvm.ptr31  llvm.call_intrinsic "llvm.x86.sse41.round.ss"() : () -> (vector<8xf32>)32  return %1 : i3233}34 35// CHECK-LABEL: func.func @test_inline(36// CHECK-SAME: %[[PTR:[a-zA-Z0-9_]+]]37// CHECK: %[[CST:.*]] = llvm.mlir.constant(4238// CHECK: %[[STACK:.+]] = llvm.intr.stacksave39// CHECK: llvm.store %[[CST]], %[[PTR]]40// CHECK: %[[RES:.+]] = llvm.load %[[PTR]]41// CHECK: llvm.intr.dbg.value #{{.+}} = %[[CST]]42// CHECK: llvm.intr.dbg.declare #{{.+}} = %[[PTR]]43// CHECK: llvm.intr.dbg.label #{{.+}}44// CHECK: "llvm.intr.memset"(%[[PTR]]45// CHECK: "llvm.intr.memmove"(%[[PTR]], %[[PTR]]46// CHECK: "llvm.intr.memcpy"(%[[PTR]], %[[PTR]]47// CHECK: llvm.intr.assume48// CHECK: llvm.fence release49// CHECK: llvm.atomicrmw add %[[PTR]], %[[CST]] monotonic50// CHECK: llvm.cmpxchg %[[PTR]], %[[CST]], %[[RES]] acq_rel monotonic51// CHECK: llvm.inline_asm has_side_effects "foo", "bar"52// CHECK: llvm.unreachable53// CHECK: llvm.intr.stackrestore %[[STACK]]54// CHECK: llvm.call_intrinsic "llvm.x86.sse41.round.ss"(55func.func @test_inline(%ptr : !llvm.ptr) -> i32 {56  %0 = call @inner_func_inlinable(%ptr) : (!llvm.ptr) -> i3257  return %0 : i3258}59 60// -----61// Check that llvm.return is correctly handled62 63func.func @func(%arg0 : i32) -> i32  {64  llvm.return %arg0 : i3265}66// CHECK-LABEL: @llvm_ret67// CHECK-NOT: call68// CHECK:  return %arg069func.func @llvm_ret(%arg0 : i32) -> i32 {70  %res = call @func(%arg0) : (i32) -> (i32)71  return %res : i3272}73 74// -----75 76// Include all function attributes that don't prevent inlining77llvm.func internal fastcc @callee() -> (i32) attributes { function_entry_count = 42 : i64, dso_local } {78  %0 = llvm.mlir.constant(42 : i32) : i3279  llvm.return %0 : i3280}81 82// CHECK-LABEL: llvm.func @caller83// CHECK-NEXT: %[[CST:.+]] = llvm.mlir.constant84// CHECK-NEXT: llvm.return %[[CST]]85llvm.func @caller() -> (i32) {86  // Include all call attributes that don't prevent inlining.87  %0 = llvm.call fastcc @callee() { fastmathFlags = #llvm.fastmath<nnan, ninf>, branch_weights = dense<42> : vector<1xi32> } : () -> (i32)88  llvm.return %0 : i3289}90 91// -----92 93llvm.func @foo() -> (i32) attributes { no_inline } {94  %0 = llvm.mlir.constant(0 : i32) : i3295  llvm.return %0 : i3296}97 98llvm.func @bar() -> (i32) {99  %0 = llvm.mlir.constant(1 : i32) : i32100  llvm.return %0 : i32101}102 103llvm.func @callee_with_multiple_blocks(%cond: i1) -> (i32) {104  llvm.cond_br %cond, ^bb1, ^bb2105^bb1:106  %0 = llvm.call @foo() : () -> (i32)107  llvm.br ^bb3(%0: i32)108^bb2:109  %1 = llvm.call @bar() { no_inline } : () -> (i32)110  llvm.br ^bb3(%1: i32)111^bb3(%arg: i32):112  llvm.return %arg : i32113}114 115// CHECK-LABEL: llvm.func @caller116// CHECK-NEXT: llvm.cond_br {{.+}}, ^[[BB1:.+]], ^[[BB2:.+]]117// CHECK-NEXT: ^[[BB1]]:118// CHECK-NEXT: llvm.call @foo119// CHECK-NEXT: llvm.br ^[[BB3:[a-zA-Z0-9_]+]]120// CHECK-NEXT: ^[[BB2]]:121// CHECK-NEXT: llvm.call @bar122// CHECK-NEXT: llvm.br ^[[BB3]]123// CHECK-NEXT: ^[[BB3]]124// CHECK-NEXT: llvm.br ^[[BB4:[a-zA-Z0-9_]+]]125// CHECK-NEXT: ^[[BB4]]126// CHECK-NEXT: llvm.return127llvm.func @caller(%cond: i1) -> (i32) {128  %0 = llvm.call @callee_with_multiple_blocks(%cond) : (i1) -> (i32)129  llvm.return %0 : i32130}131 132// -----133 134llvm.func @personality() -> i32135 136llvm.func @callee() -> (i32) attributes { personality = @personality } {137  %0 = llvm.mlir.constant(42 : i32) : i32138  llvm.return %0 : i32139}140 141// CHECK-LABEL: llvm.func @caller142// CHECK-NEXT: llvm.call @callee143// CHECK-NEXT: return144llvm.func @caller() -> (i32) {145  %0 = llvm.call @callee() : () -> (i32)146  llvm.return %0 : i32147}148 149// -----150 151llvm.func @callee() attributes { passthrough = ["foo", "bar"] } {152  llvm.return153}154 155// CHECK-LABEL: llvm.func @caller156// CHECK-NEXT: llvm.return157llvm.func @caller() {158  llvm.call @callee() : () -> ()159  llvm.return160}161 162// -----163 164llvm.func @callee_noinline() attributes { no_inline } {165  llvm.return166}167 168llvm.func @callee_noduplicate() attributes { passthrough = ["noduplicate"] } {169  llvm.return170}171 172llvm.func @callee_presplitcoroutine() attributes { passthrough = ["presplitcoroutine"] } {173  llvm.return174}175 176llvm.func @callee_returns_twice() attributes { passthrough = ["returns_twice"] } {177  llvm.return178}179 180llvm.func @callee_strictfp() attributes { passthrough = ["strictfp"] } {181  llvm.return182}183 184// CHECK-LABEL: llvm.func @caller185// CHECK-NEXT: llvm.call @callee_noinline186// CHECK-NEXT: llvm.call @callee_noduplicate187// CHECK-NEXT: llvm.call @callee_presplitcoroutine188// CHECK-NEXT: llvm.call @callee_returns_twice189// CHECK-NEXT: llvm.call @callee_strictfp190// CHECK-NEXT: llvm.return191llvm.func @caller() {192  llvm.call @callee_noinline() : () -> ()193  llvm.call @callee_noduplicate() : () -> ()194  llvm.call @callee_presplitcoroutine() : () -> ()195  llvm.call @callee_returns_twice() : () -> ()196  llvm.call @callee_strictfp() : () -> ()197  llvm.return198}199 200// -----201 202llvm.func @static_alloca() -> f32 {203  %0 = llvm.mlir.constant(4 : i32) : i32204  %1 = llvm.alloca %0 x f32 : (i32) -> !llvm.ptr205  %2 = llvm.load %1 : !llvm.ptr -> f32206  llvm.return %2 : f32207}208 209llvm.func @dynamic_alloca(%size : i32) -> f32 {210  %0 = llvm.add %size, %size : i32211  %1 = llvm.alloca %0 x f32 : (i32) -> !llvm.ptr212  %2 = llvm.load %1 : !llvm.ptr -> f32213  llvm.return %2 : f32214}215 216// CHECK-LABEL: llvm.func @test_inline217llvm.func @test_inline(%cond : i1, %size : i32) -> f32 {218  // Check that the static alloca was moved to the entry block after inlining219  // with its size defined by a constant.220  // CHECK-NOT: ^{{.+}}:221  // CHECK-NEXT: llvm.mlir.constant222  // CHECK-NEXT: llvm.alloca223  // CHECK: llvm.cond_br224  llvm.cond_br %cond, ^bb1, ^bb2225  // CHECK: ^{{.+}}:226^bb1:227  // CHECK-NOT: llvm.call @static_alloca228  // CHECK: llvm.intr.lifetime.start229  %0 = llvm.call @static_alloca() : () -> f32230  // CHECK: llvm.intr.lifetime.end231  // CHECK: llvm.br ^[[BB3:[a-zA-Z0-9_]+]]232  llvm.br ^bb3(%0: f32)233  // CHECK: ^{{.+}}:234^bb2:235  // Check that the dynamic alloca was inlined, but that it was not moved to the236  // entry block.237  // CHECK: %[[STACK:[a-zA-Z0-9_]+]] = llvm.intr.stacksave238  // CHECK: llvm.add239  // CHECK: llvm.alloca240  // CHECK: llvm.intr.stackrestore %[[STACK]]241  // CHECK-NOT: llvm.call @dynamic_alloca242  %1 = llvm.call @dynamic_alloca(%size) : (i32) -> f32243  // CHECK: llvm.br ^[[BB3]]244  llvm.br ^bb3(%1: f32)245  // CHECK: ^[[BB3]]246^bb3(%arg : f32):247  // CHECK-NEXT: return248  llvm.return %arg : f32249}250 251// -----252 253llvm.func @static_alloca_not_in_entry(%cond : i1) -> f32 {254  llvm.cond_br %cond, ^bb1, ^bb2255^bb1:256  %0 = llvm.mlir.constant(4 : i32) : i32257  %1 = llvm.alloca %0 x f32 : (i32) -> !llvm.ptr258  llvm.br ^bb3(%1: !llvm.ptr)259^bb2:260  %2 = llvm.mlir.constant(8 : i32) : i32261  %3 = llvm.alloca %2 x f32 : (i32) -> !llvm.ptr262  llvm.br ^bb3(%3: !llvm.ptr)263^bb3(%ptr : !llvm.ptr):264  %4 = llvm.load %ptr : !llvm.ptr -> f32265  llvm.return %4 : f32266}267 268// CHECK-LABEL: llvm.func @test_inline269llvm.func @test_inline(%cond : i1) -> f32 {270  // Make sure the alloca was not moved to the entry block.271  // CHECK-NOT: llvm.alloca272  // CHECK: llvm.cond_br273  // CHECK: llvm.alloca274  %0 = llvm.call @static_alloca_not_in_entry(%cond) : (i1) -> f32275  llvm.return %0 : f32276}277 278// -----279 280llvm.func @static_alloca(%cond: i1) -> f32 {281  %0 = llvm.mlir.constant(4 : i32) : i32282  %1 = llvm.alloca %0 x f32 : (i32) -> !llvm.ptr283  llvm.cond_br %cond, ^bb1, ^bb2284^bb1:285  %2 = llvm.load %1 : !llvm.ptr -> f32286  llvm.return %2 : f32287^bb2:288  %3 = llvm.mlir.constant(3.14192 : f32) : f32289  llvm.return %3 : f32290}291 292// CHECK-LABEL: llvm.func @test_inline293llvm.func @test_inline(%cond0 : i1, %cond1 : i1, %funcArg : f32) -> f32 {294  // CHECK-NOT: llvm.cond_br295  // CHECK: %[[PTR:.+]] = llvm.alloca296  // CHECK: llvm.cond_br %{{.+}}, ^[[BB1:.+]], ^{{.+}}297  llvm.cond_br %cond0, ^bb1, ^bb2298  // CHECK: ^[[BB1]]299^bb1:300  // Make sure the lifetime begin intrinsic has been inserted where the call301  // used to be, even though the alloca has been moved to the entry block.302  // CHECK-NEXT: llvm.intr.lifetime.start %[[PTR]]303  %0 = llvm.call @static_alloca(%cond1) : (i1) -> f32304  // CHECK: llvm.cond_br %{{.+}}, ^[[BB2:.+]], ^[[BB3:.+]]305  llvm.br ^bb3(%0: f32)306  // Make sure the lifetime end intrinsic has been inserted at both former307  // return sites of the callee.308  // CHECK: ^[[BB2]]:309  // CHECK-NEXT: llvm.load310  // CHECK-NEXT: llvm.intr.lifetime.end %[[PTR]]311  // CHECK: ^[[BB3]]:312  // CHECK-NEXT: llvm.intr.lifetime.end %[[PTR]]313^bb2:314  llvm.br ^bb3(%funcArg: f32)315^bb3(%blockArg: f32):316  llvm.return %blockArg : f32317}318 319// -----320 321llvm.func @static_alloca() -> f32 {322  %0 = llvm.mlir.constant(4 : i32) : i32323  %1 = llvm.alloca %0 x f32 : (i32) -> !llvm.ptr324  %2 = llvm.load %1 : !llvm.ptr -> f32325  llvm.return %2 : f32326}327 328// CHECK-LABEL: llvm.func @test_inline329llvm.func @test_inline(%cond0 : i1) {330  // Verify the alloca is relocated to the entry block of the parent function331  // if the region operation is neither marked as isolated from above or332  // automatic allocation scope.333  // CHECK: %[[ALLOCA:.+]] = llvm.alloca334  // CHECK: "test.one_region_op"() ({335  "test.one_region_op"() ({336    %0 = llvm.call @static_alloca() : () -> f32337    // CHECK-NEXT: llvm.intr.lifetime.start %[[ALLOCA]]338    // CHECK-NEXT: %[[RES:.+]] = llvm.load %[[ALLOCA]]339    // CHECK-NEXT: llvm.intr.lifetime.end %[[ALLOCA]]340    // CHECK-NEXT: test.region_yield %[[RES]]341    test.region_yield %0 : f32342  }) : () -> ()343  // Verify the alloca is not relocated out of operations that are marked as344  // isolated from above.345  // CHECK-NOT: llvm.alloca346  // CHECK: test.isolated_regions347  test.isolated_regions {348    // CHECK: %[[ALLOCA:.+]] = llvm.alloca349    %0 = llvm.call @static_alloca() : () -> f32350    // CHECK: test.region_yield351    test.region_yield %0 : f32352  }353  // Verify the alloca is not relocated out of operations that are marked as354  // automatic allocation scope.355  // CHECK-NOT: llvm.alloca356  // CHECK: test.alloca_scope_region357  test.alloca_scope_region {358    // CHECK: %[[ALLOCA:.+]] = llvm.alloca359    %0 = llvm.call @static_alloca() : () -> f32360    // CHECK: test.region_yield361    test.region_yield %0 : f32362  }363  llvm.return364}365 366// -----367 368llvm.func @alloca_with_lifetime(%cond: i1) -> f32 {369  %0 = llvm.mlir.constant(4 : i32) : i32370  %1 = llvm.alloca %0 x f32 : (i32) -> !llvm.ptr371  llvm.intr.lifetime.start %1 : !llvm.ptr372  %2 = llvm.load %1 : !llvm.ptr -> f32373  llvm.intr.lifetime.end %1 : !llvm.ptr374  %3 = llvm.fadd %2, %2 : f32375  llvm.return %3 : f32376}377 378// CHECK-LABEL: llvm.func @test_inline379llvm.func @test_inline(%cond0 : i1, %cond1 : i1, %funcArg : f32) -> f32 {380  // CHECK-NOT: llvm.cond_br381  // CHECK: %[[PTR:.+]] = llvm.alloca382  // CHECK: llvm.cond_br %{{.+}}, ^[[BB1:.+]], ^{{.+}}383  llvm.cond_br %cond0, ^bb1, ^bb2384  // CHECK: ^[[BB1]]385^bb1:386  // Make sure the original lifetime intrinsic has been preserved, rather than387  // inserting a new one with a larger scope.388  // CHECK: llvm.intr.lifetime.start %[[PTR]]389  // CHECK-NEXT: llvm.load %[[PTR]]390  // CHECK-NEXT: llvm.intr.lifetime.end %[[PTR]]391  // CHECK: llvm.fadd392  // CHECK-NOT: llvm.intr.lifetime.end393  %0 = llvm.call @alloca_with_lifetime(%cond1) : (i1) -> f32394  llvm.br ^bb3(%0: f32)395^bb2:396  llvm.br ^bb3(%funcArg: f32)397^bb3(%blockArg: f32):398  llvm.return %blockArg : f32399}400 401// -----402 403llvm.func @with_byval_arg(%ptr : !llvm.ptr { llvm.byval = f64 }) {404  llvm.return405}406 407// CHECK-LABEL: llvm.func @test_byval408// CHECK-SAME: %[[PTR:[a-zA-Z0-9_]+]]: !llvm.ptr409llvm.func @test_byval(%ptr : !llvm.ptr) {410  // Make sure the new static alloca goes to the entry block.411  // CHECK: %[[ALLOCA:.+]] = llvm.alloca %{{.+}} x f64412  // CHECK: llvm.br ^[[BB1:[a-zA-Z0-9_]+]]413  llvm.br ^bb1414  // CHECK: ^[[BB1]]415^bb1:416  // CHECK: "llvm.intr.memcpy"(%[[ALLOCA]], %[[PTR]]417  llvm.call @with_byval_arg(%ptr) : (!llvm.ptr) -> ()418  llvm.br ^bb2419^bb2:420  llvm.return421}422 423// -----424 425llvm.func @with_byval_arg(%ptr : !llvm.ptr { llvm.byval = f64 }) attributes {memory_effects = #llvm.memory_effects<other = readwrite, argMem = read, inaccessibleMem = readwrite, errnoMem  = none, targetMem0 = none, targetMem1 = none>} {426  llvm.return427}428 429// CHECK-LABEL: llvm.func @test_byval_read_only430// CHECK-NOT: llvm.call431// CHECK-NEXT: llvm.return432llvm.func @test_byval_read_only(%ptr : !llvm.ptr) {433  llvm.call @with_byval_arg(%ptr) : (!llvm.ptr) -> ()434  llvm.return435}436 437// -----438 439llvm.func @with_byval_arg(%ptr : !llvm.ptr { llvm.byval = f64 }) attributes {memory_effects = #llvm.memory_effects<other = readwrite, argMem = write, inaccessibleMem = readwrite, errnoMem  = none, targetMem0 = none, targetMem1 = none>} {440  llvm.return441}442 443// CHECK-LABEL: llvm.func @test_byval_write_only444// CHECK-SAME: %[[PTR:[a-zA-Z0-9_]+]]: !llvm.ptr445// CHECK: %[[ALLOCA:.+]] = llvm.alloca %{{.+}} x f64446// CHECK: "llvm.intr.memcpy"(%[[ALLOCA]], %[[PTR]]447llvm.func @test_byval_write_only(%ptr : !llvm.ptr) {448  llvm.call @with_byval_arg(%ptr) : (!llvm.ptr) -> ()449  llvm.return450}451 452// -----453 454llvm.func @aligned_byval_arg(%ptr : !llvm.ptr { llvm.byval = i16, llvm.align = 16 }) attributes {memory_effects = #llvm.memory_effects<other = read, argMem = read, inaccessibleMem = read, errnoMem  = none, targetMem0 = none, targetMem1 = none>} {455  llvm.return456}457 458// CHECK-LABEL: llvm.func @test_byval_input_aligned459// CHECK-SAME: %[[UNALIGNED:[a-zA-Z0-9_]+]]: !llvm.ptr460// CHECK-SAME: %[[ALIGNED:[a-zA-Z0-9_]+]]: !llvm.ptr461llvm.func @test_byval_input_aligned(%unaligned : !llvm.ptr, %aligned : !llvm.ptr { llvm.align = 16 }) {462  // Make sure only the unaligned input triggers a memcpy.463  // CHECK: %[[ALLOCA:.+]] = llvm.alloca %{{.+}} x i16 {alignment = 16464  // CHECK: "llvm.intr.memcpy"(%[[ALLOCA]], %[[UNALIGNED]]465  llvm.call @aligned_byval_arg(%unaligned) : (!llvm.ptr) -> ()466  // CHECK-NOT: memcpy467  llvm.call @aligned_byval_arg(%aligned) : (!llvm.ptr) -> ()468  llvm.return469}470 471// -----472 473llvm.func @func_that_uses_ptr(%ptr : !llvm.ptr)474 475llvm.func @aligned_byval_arg(%ptr : !llvm.ptr { llvm.byval = i16, llvm.align = 16 }) attributes {memory_effects = #llvm.memory_effects<other = read, argMem = read, inaccessibleMem = read, errnoMem  = none, targetMem0 = none, targetMem1 = none>} {476  llvm.call @func_that_uses_ptr(%ptr) : (!llvm.ptr) -> ()477  llvm.return478}479 480// CHECK-LABEL: llvm.func @test_byval_realign_alloca481llvm.func @test_byval_realign_alloca() {482  %size = llvm.mlir.constant(4 : i64) : i64483  // CHECK-NOT: llvm.alloca{{.+}}alignment = 1484  // CHECK: llvm.alloca {{.+}}alignment = 16 : i64485  // CHECK-NOT: llvm.intr.memcpy486  %unaligned = llvm.alloca %size x i16 { alignment = 1 } : (i64) -> !llvm.ptr487  llvm.call @aligned_byval_arg(%unaligned) : (!llvm.ptr) -> ()488  llvm.return489}490 491// -----492 493module attributes {494  dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry<"dlti.stack_alignment", 32 : i32>>495} {496 497llvm.func @func_that_uses_ptr(%ptr : !llvm.ptr)498 499llvm.func @aligned_byval_arg(%ptr : !llvm.ptr { llvm.byval = i16, llvm.align = 16 }) attributes {memory_effects = #llvm.memory_effects<other = read, argMem = read, inaccessibleMem = read, errnoMem  = none, targetMem0 = none, targetMem1 = none>} {500  llvm.call @func_that_uses_ptr(%ptr) : (!llvm.ptr) -> ()501  llvm.return502}503 504// CHECK-LABEL: llvm.func @test_exceeds_natural_stack_alignment505llvm.func @test_exceeds_natural_stack_alignment() {506  %size = llvm.mlir.constant(4 : i64) : i64507  // Natural stack alignment is exceeded, so prefer a copy instead of508  // triggering a dynamic stack realignment.509  // CHECK-DAG: %[[SRC:[a-zA-Z0-9_]+]] = llvm.alloca{{.+}}alignment = 2510  // CHECK-DAG: %[[DST:[a-zA-Z0-9_]+]] = llvm.alloca{{.+}}alignment = 16511  // CHECK: "llvm.intr.memcpy"(%[[DST]], %[[SRC]]512  %unaligned = llvm.alloca %size x i16 { alignment = 2 } : (i64) -> !llvm.ptr513  llvm.call @aligned_byval_arg(%unaligned) : (!llvm.ptr) -> ()514  llvm.return515}516 517}518 519// -----520 521module attributes {522  dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry<"dlti.stack_alignment", 32 : i32>>523} {524 525llvm.func @func_that_uses_ptr(%ptr : !llvm.ptr)526 527llvm.func @aligned_byval_arg(%ptr : !llvm.ptr { llvm.byval = i16, llvm.align = 16 }) attributes {memory_effects = #llvm.memory_effects<other = read, argMem = read, inaccessibleMem = read, errnoMem  = none, targetMem0 = none, targetMem1 = none>} {528  llvm.call @func_that_uses_ptr(%ptr) : (!llvm.ptr) -> ()529  llvm.return530}531 532// CHECK-LABEL: llvm.func @test_alignment_exceeded_anyway533llvm.func @test_alignment_exceeded_anyway() {534  %size = llvm.mlir.constant(4 : i64) : i64535  // Natural stack alignment is lower than the target alignment, but the536  // alloca's existing alignment already exceeds it, so we might as well avoid537  // the copy.538  // CHECK-NOT: llvm.alloca{{.+}}alignment = 1539  // CHECK: llvm.alloca {{.+}}alignment = 16 : i64540  // CHECK-NOT: llvm.intr.memcpy541  %unaligned = llvm.alloca %size x i16 { alignment = 8 } : (i64) -> !llvm.ptr542  llvm.call @aligned_byval_arg(%unaligned) : (!llvm.ptr) -> ()543  llvm.return544}545 546}547 548// -----549 550llvm.mlir.global private @unaligned_global(42 : i64) : i64551llvm.mlir.global private @aligned_global(42 : i64) { alignment = 64 } : i64552 553llvm.func @aligned_byval_arg(%ptr : !llvm.ptr { llvm.byval = i16, llvm.align = 16 }) attributes {memory_effects = #llvm.memory_effects<other = read, argMem = read, inaccessibleMem = read, errnoMem  = none, targetMem0 = none, targetMem1 = none>} {554  llvm.return555}556 557// CHECK-LABEL: llvm.func @test_byval_global558llvm.func @test_byval_global() {559  // Make sure only the unaligned global triggers a memcpy.560  // CHECK-DAG: %[[UNALIGNED:.+]] = llvm.mlir.addressof @unaligned_global561  // CHECK-DAG: %[[ALLOCA:.+]] = llvm.alloca562  // CHECK: "llvm.intr.memcpy"(%[[ALLOCA]], %[[UNALIGNED]]563  // CHECK-NOT: llvm.alloca564  %unaligned = llvm.mlir.addressof @unaligned_global : !llvm.ptr565  llvm.call @aligned_byval_arg(%unaligned) : (!llvm.ptr) -> ()566  %aligned = llvm.mlir.addressof @aligned_global : !llvm.ptr567  llvm.call @aligned_byval_arg(%aligned) : (!llvm.ptr) -> ()568  llvm.return569}570 571// -----572 573llvm.func @ignored_attrs(%ptr : !llvm.ptr { llvm.inreg, llvm.nocapture, llvm.nofree, llvm.preallocated = i32, llvm.returned, llvm.alignstack = 32 : i64, llvm.writeonly, llvm.noundef, llvm.nonnull }, %x : i32 { llvm.zeroext }) -> (!llvm.ptr { llvm.noundef, llvm.inreg, llvm.nonnull }) {574  llvm.return %ptr : !llvm.ptr575}576 577// CHECK-LABEL: @test_ignored_attrs578// CHECK-NOT: llvm.call579// CHECK-NEXT: llvm.return580llvm.func @test_ignored_attrs(%ptr : !llvm.ptr, %x : i32) {581  llvm.call @ignored_attrs(%ptr, %x) : (!llvm.ptr, i32) -> (!llvm.ptr)582  llvm.return583}584 585// -----586 587llvm.func @disallowed_arg_attr(%ptr : !llvm.ptr { llvm.inalloca = i64 }) {588  llvm.return589}590 591// CHECK-LABEL: @test_disallow_arg_attr592// CHECK-NEXT: llvm.call593llvm.func @test_disallow_arg_attr(%ptr : !llvm.ptr) {594  llvm.call @disallowed_arg_attr(%ptr) : (!llvm.ptr) -> ()595  llvm.return596}597 598// -----599 600#callee = #llvm.access_group<id = distinct[0]<>>601#caller = #llvm.access_group<id = distinct[1]<>>602 603llvm.func @inlinee(%ptr : !llvm.ptr) -> i32 {604  %0 = llvm.load %ptr { access_groups = [#callee] } : !llvm.ptr -> i32605  llvm.return %0 : i32606}607 608// CHECK-DAG: #[[$CALLEE:.*]] = #llvm.access_group<id = {{.*}}>609// CHECK-DAG: #[[$CALLER:.*]] = #llvm.access_group<id = {{.*}}>610 611// CHECK-LABEL: func @caller612// CHECK: llvm.load613// CHECK-SAME: access_groups = [#[[$CALLEE]], #[[$CALLER]]]614llvm.func @caller(%ptr : !llvm.ptr) -> i32 {615  %0 = llvm.call @inlinee(%ptr) { access_groups = [#caller] } : (!llvm.ptr) -> (i32)616  llvm.return %0 : i32617}618 619// -----620 621#caller = #llvm.access_group<id = distinct[1]<>>622 623llvm.func @inlinee(%ptr : !llvm.ptr) -> i32 {624  %0 = llvm.load %ptr : !llvm.ptr -> i32625  llvm.return %0 : i32626}627 628// CHECK-DAG: #[[$CALLER:.*]] = #llvm.access_group<id = {{.*}}>629 630// CHECK-LABEL: func @caller631// CHECK: llvm.load632// CHECK-SAME: access_groups = [#[[$CALLER]]]633// CHECK: llvm.store634// CHECK-SAME: access_groups = [#[[$CALLER]]]635llvm.func @caller(%ptr : !llvm.ptr) -> i32 {636  %c5 = llvm.mlir.constant(5 : i32) : i32637  %0 = llvm.call @inlinee(%ptr) { access_groups = [#caller] } : (!llvm.ptr) -> (i32)638  llvm.store %c5, %ptr { access_groups = [#caller] } : i32, !llvm.ptr639  llvm.return %0 : i32640}641 642// -----643 644llvm.func @vararg_func(...) {645  llvm.return646}647 648llvm.func @vararg_intrinrics() {649  %0 = llvm.mlir.constant(1 : i32) : i32650  %list = llvm.alloca %0 x !llvm.struct<"struct.va_list_opaque", (ptr)> : (i32) -> !llvm.ptr651  // The vararg intinriscs should normally be part of a variadic function.652  // However, this test uses a non-variadic function to ensure the presence of653  // the intrinsic alone suffices to prevent inlining.654  llvm.intr.vastart %list : !llvm.ptr655  llvm.return656}657 658// CHECK-LABEL: func @caller659llvm.func @caller() {660  // CHECK-NEXT: llvm.call @vararg_func()661  llvm.call @vararg_func() vararg(!llvm.func<void (...)>) : () -> ()662  // CHECK-NEXT: llvm.call @vararg_intrinrics()663  llvm.call @vararg_intrinrics() : () -> ()664  llvm.return665}666 667// -----668 669llvm.func @private_func(%a : i32) -> i32 attributes {sym_visibility = "private"} {670  llvm.return %a : i32671}672 673// CHECK-LABEL: func @caller674llvm.func @caller(%x : i32) -> i32 {675  // CHECK-NOT: llvm.call @private_func676  %z = llvm.call @private_func(%x) : (i32) -> (i32)677  llvm.return %z : i32678}679 680// -----681 682llvm.func @unreachable_func(%a : i32) -> i32 {683  "llvm.intr.trap"() : () -> ()684  llvm.unreachable685}686 687// CHECK-LABEL: func @caller688llvm.func @caller(%x : i32) -> i32 {689  // CHECK-NOT: llvm.call @unreachable_func690  // CHECK: llvm.intr.trap691  // CHECK: llvm.unreachable692  %z = llvm.call @unreachable_func(%x) : (i32) -> (i32)693  llvm.return %z : i32694}695 696// -----697// Check that @func is not inlined because of llvm.blocktag698 699func.func @func(%arg0 : i32) -> i32  {700  llvm.blocktag <id = 1>701  llvm.return %arg0 : i32702}703 704// CHECK-LABEL: @llvm_ret705func.func @llvm_ret(%arg0 : i32) -> i32 {706  // CHECK-NOT: llvm.blocktag707  // CHECK: %[[R:.*]] = call708  %res = call @func(%arg0) : (i32) -> (i32)709  // CHECK: return %[[R]]710  return %res : i32711}712