|
| 1 | +; RUN: llc -o - %s | FileCheck --check-prefix=SELDAG --check-prefix=CHECK %s |
| 2 | +; RUN: llc -global-isel -o - %s | FileCheck --check-prefix=GISEL --check-prefix=CHECK %s |
| 3 | + |
| 4 | +; TODO: support marker generation with GlobalISel |
| 5 | +target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" |
| 6 | +target triple = "arm64-apple-iphoneos" |
| 7 | + |
| 8 | +declare i8* @foo0(i32) |
| 9 | +declare i8* @foo1() |
| 10 | + |
| 11 | +declare void @llvm.objc.release(i8*) |
| 12 | +declare void @objc_object(i8*) |
| 13 | + |
| 14 | +declare void @foo2(i8*) |
| 15 | + |
| 16 | +declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture) |
| 17 | + |
| 18 | +declare %struct.S* @_ZN1SD1Ev(%struct.S* nonnull dereferenceable(1)) |
| 19 | + |
| 20 | +declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture) |
| 21 | + |
| 22 | + |
| 23 | +%struct.S = type { i8 } |
| 24 | + |
| 25 | +@g = global i8* null, align 8 |
| 26 | +@fptr = global i8* ()* null, align 8 |
| 27 | + |
| 28 | +define i8* @rv_marker_1() { |
| 29 | +; CHECK-LABEL: rv_marker_1: |
| 30 | +; CHECK: .cfi_offset w30, -16 |
| 31 | +; CHECK-NEXT: bl foo1 |
| 32 | +; SELDAG-NEXT: mov x29, x29 |
| 33 | +; GISEL-NOT: mov x29, x29 |
| 34 | +; |
| 35 | +entry: |
| 36 | + %call = call "rv_marker" i8* @foo1() |
| 37 | + ret i8* %call |
| 38 | +} |
| 39 | + |
| 40 | +define void @rv_marker_2_select(i32 %c) { |
| 41 | +; CHECK-LABEL: rv_marker_2_select: |
| 42 | +; SELDAG: cinc w0, w8, eq |
| 43 | +; GISEL: csinc w0, w8, wzr, eq |
| 44 | +; CHECK-NEXT: bl foo0 |
| 45 | +; SELDAG-NEXT: mov x29, x29 |
| 46 | +; CHECK-NEXT: ldr x30, [sp], #16 |
| 47 | +; CHECK-NEXT: b foo2 |
| 48 | +; |
| 49 | +entry: |
| 50 | + %tobool.not = icmp eq i32 %c, 0 |
| 51 | + %.sink = select i1 %tobool.not, i32 2, i32 1 |
| 52 | + %call1 = call "rv_marker" i8* @foo0(i32 %.sink) |
| 53 | + tail call void @foo2(i8* %call1) |
| 54 | + ret void |
| 55 | +} |
| 56 | + |
| 57 | +define void @rv_marker_3() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) { |
| 58 | +; CHECK-LABEL: rv_marker_3 |
| 59 | +; CHECK: .cfi_offset w30, -32 |
| 60 | +; CHECK-NEXT: bl foo1 |
| 61 | +; SELDAG-NEXT: mov x29, x29 |
| 62 | +; |
| 63 | +entry: |
| 64 | + %call = call "rv_marker" i8* @foo1() |
| 65 | + invoke void @objc_object(i8* %call) #5 |
| 66 | + to label %invoke.cont unwind label %lpad |
| 67 | + |
| 68 | +invoke.cont: ; preds = %entry |
| 69 | + tail call void @llvm.objc.release(i8* %call) |
| 70 | + ret void |
| 71 | + |
| 72 | +lpad: ; preds = %entry |
| 73 | + %0 = landingpad { i8*, i32 } |
| 74 | + cleanup |
| 75 | + tail call void @llvm.objc.release(i8* %call) |
| 76 | + resume { i8*, i32 } %0 |
| 77 | +} |
| 78 | + |
| 79 | +define void @rv_marker_4() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) { |
| 80 | +; CHECK-LABEL: rv_marker_4 |
| 81 | +; CHECK: .Ltmp3: |
| 82 | +; CHECK-NEXT: bl foo1 |
| 83 | +; SELDAG-NEXT: mov x29, x29 |
| 84 | +; CHECK-NEXT: .Ltmp4: |
| 85 | +; |
| 86 | +entry: |
| 87 | + %s = alloca %struct.S, align 1 |
| 88 | + %0 = getelementptr inbounds %struct.S, %struct.S* %s, i64 0, i32 0 |
| 89 | + call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull %0) #2 |
| 90 | + %call = invoke "rv_marker" i8* @foo1() |
| 91 | + to label %invoke.cont unwind label %lpad |
| 92 | + |
| 93 | +invoke.cont: ; preds = %entry |
| 94 | + invoke void @objc_object(i8* %call) #5 |
| 95 | + to label %invoke.cont2 unwind label %lpad1 |
| 96 | + |
| 97 | +invoke.cont2: ; preds = %invoke.cont |
| 98 | + tail call void @llvm.objc.release(i8* %call) |
| 99 | + %call3 = call %struct.S* @_ZN1SD1Ev(%struct.S* nonnull dereferenceable(1) %s) |
| 100 | + call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull %0) |
| 101 | + ret void |
| 102 | + |
| 103 | +lpad: ; preds = %entry |
| 104 | + %1 = landingpad { i8*, i32 } |
| 105 | + cleanup |
| 106 | + br label %ehcleanup |
| 107 | + |
| 108 | +lpad1: ; preds = %invoke.cont |
| 109 | + %2 = landingpad { i8*, i32 } |
| 110 | + cleanup |
| 111 | + tail call void @llvm.objc.release(i8* %call) |
| 112 | + br label %ehcleanup |
| 113 | + |
| 114 | +ehcleanup: ; preds = %lpad1, %lpad |
| 115 | + %.pn = phi { i8*, i32 } [ %2, %lpad1 ], [ %1, %lpad ] |
| 116 | + %call4 = call %struct.S* @_ZN1SD1Ev(%struct.S* nonnull dereferenceable(1) %s) |
| 117 | + call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull %0) |
| 118 | + resume { i8*, i32 } %.pn |
| 119 | +} |
| 120 | + |
| 121 | +define i8* @rv_marker_5_indirect_call() { |
| 122 | +; CHECK-LABEL: rv_marker_5_indirect_call |
| 123 | +; CHECK: ldr [[ADDR:x[0-9]+]], [ |
| 124 | +; CHECK-NEXT: blr [[ADDR]] |
| 125 | +; SLEDAG-NEXT: mov x29, x29 |
| 126 | +; GISEL-NOT: mov x29, x29 |
| 127 | +; |
| 128 | +entry: |
| 129 | + %0 = load i8* ()*, i8* ()** @fptr, align 8 |
| 130 | + %call = call "rv_marker" i8* %0() |
| 131 | + tail call void @foo2(i8* %call) |
| 132 | + ret i8* %call |
| 133 | +} |
| 134 | + |
| 135 | +declare void @foo(i64, i64, i64) |
| 136 | + |
| 137 | +define void @rv_marker_multiarg(i64 %a, i64 %b, i64 %c) { |
| 138 | +; CHECK-LABEL: rv_marker_multiarg |
| 139 | +; CHECK: mov [[TMP:x[0-9]+]], x0 |
| 140 | +; CHECK-NEXT: mov x0, x2 |
| 141 | +; CHECK-NEXT: mov x2, [[TMP]] |
| 142 | +; CHECK-NEXT: bl foo |
| 143 | +; SELDAG-NEXT: mov x29, x29 |
| 144 | +; GISEL-NOT: mov x29, x29 |
| 145 | + call "rv_marker" void @foo(i64 %c, i64 %b, i64 %a) |
| 146 | + ret void |
| 147 | +} |
| 148 | + |
| 149 | +declare i32 @__gxx_personality_v0(...) |
0 commit comments