1; RUN: llc -mtriple=arm64-apple-darwin -debug-entry-values -enable-misched=0 -mcpu=cyclone < %s | FileCheck %s 2; RUN: llc -mtriple=arm64-apple-darwin -debug-entry-values -enable-misched=0 -mcpu=cyclone -fast-isel -fast-isel-abort=1 < %s | FileCheck %s 3 4; Trivial patchpoint codegen 5; 6define i64 @trivial_patchpoint_codegen(i64 %p1, i64 %p2, i64 %p3, i64 %p4) { 7entry: 8; CHECK-LABEL: trivial_patchpoint_codegen: 9; CHECK: mov x16, #244834610708480 10; CHECK-NEXT: movk x16, #48879, lsl #16 11; CHECK-NEXT: movk x16, #51966 12; CHECK-NEXT: blr x16 13; CHECK: mov x16, #244834610708480 14; CHECK-NEXT: movk x16, #48879, lsl #16 15; CHECK-NEXT: movk x16, #51967 16; CHECK-NEXT: blr x16 17; CHECK: ret 18 %resolveCall2 = inttoptr i64 244837814094590 to ptr 19 %result = tail call i64 (i64, i32, ptr, i32, ...) @llvm.experimental.patchpoint.i64(i64 2, i32 20, ptr %resolveCall2, i32 4, i64 %p1, i64 %p2, i64 %p3, i64 %p4) 20 %resolveCall3 = inttoptr i64 244837814094591 to ptr 21 tail call void (i64, i32, ptr, i32, ...) @llvm.experimental.patchpoint.void(i64 3, i32 20, ptr %resolveCall3, i32 2, i64 %p1, i64 %result) 22 ret i64 %result 23} 24 25; Caller frame metadata with stackmaps. This should not be optimized 26; as a leaf function. 27; 28; CHECK-LABEL: caller_meta_leaf 29; CHECK: sub sp, sp, #48 30; CHECK-NEXT: stp x29, x30, [sp, #32] 31; CHECK-NEXT: add x29, sp, #32 32; CHECK: Ltmp 33; CHECK: add sp, sp, #48 34; CHECK: ret 35 36define void @caller_meta_leaf() { 37entry: 38 %metadata = alloca i64, i32 3, align 8 39 store i64 11, ptr %metadata 40 store i64 12, ptr %metadata 41 store i64 13, ptr %metadata 42 call void (i64, i32, ...) @llvm.experimental.stackmap(i64 4, i32 0, ptr %metadata) 43 ret void 44} 45 46; Test patchpoints reusing the same TargetConstant. 47; <rdar:15390785> Assertion failed: (CI.getNumArgOperands() >= NumArgs + 4) 48; There is no way to verify this, since it depends on memory allocation. 49; But I think it's useful to include as a working example. 50define i64 @testLowerConstant(i64 %arg, i64 %tmp2, i64 %tmp10, ptr %tmp33, i64 %tmp79) { 51entry: 52 %tmp80 = add i64 %tmp79, -16 53 %tmp81 = inttoptr i64 %tmp80 to ptr 54 %tmp82 = load i64, ptr %tmp81, align 8 55 tail call void (i64, i32, ...) @llvm.experimental.stackmap(i64 14, i32 8, i64 %arg, i64 %tmp2, i64 %tmp10, i64 %tmp82) 56 tail call void (i64, i32, ptr, i32, ...) @llvm.experimental.patchpoint.void(i64 15, i32 32, ptr null, i32 3, i64 %arg, i64 %tmp10, i64 %tmp82) 57 %tmp83 = load i64, ptr %tmp33, align 8 58 %tmp84 = add i64 %tmp83, -24 59 %tmp85 = inttoptr i64 %tmp84 to ptr 60 %tmp86 = load i64, ptr %tmp85, align 8 61 tail call void (i64, i32, ...) @llvm.experimental.stackmap(i64 17, i32 8, i64 %arg, i64 %tmp10, i64 %tmp86) 62 tail call void (i64, i32, ptr, i32, ...) @llvm.experimental.patchpoint.void(i64 18, i32 32, ptr null, i32 3, i64 %arg, i64 %tmp10, i64 %tmp86) 63 ret i64 10 64} 65 66; Test small patchpoints that don't emit calls. 67define void @small_patchpoint_codegen(i64 %p1, i64 %p2, i64 %p3, i64 %p4) { 68entry: 69; CHECK-LABEL: small_patchpoint_codegen: 70; CHECK: Ltmp 71; CHECK: nop 72; CHECK-NEXT: nop 73; CHECK-NEXT: nop 74; CHECK-NEXT: nop 75; CHECK-NEXT: nop 76; CHECK-NEXT: ldp 77; CHECK-NEXT: ret 78 %result = tail call i64 (i64, i32, ptr, i32, ...) @llvm.experimental.patchpoint.i64(i64 5, i32 20, ptr null, i32 2, i64 %p1, i64 %p2) 79 ret void 80} 81 82; Test register allocation for an i32 result value of patchpoint. 83define i32 @generic_patchpoint_i32() { 84entry: 85; CHECK-LABEL: generic_patchpoint_i32: 86; CHECK: Ltmp 87; CHECK-NEXT: nop 88; The return value is already in w0. 89; CHECK-NEXT: ldp 90; CHECK-NEXT: ret 91 %result = tail call i32 (i64, i32, ptr, i32, ...) @llvm.experimental.patchpoint.i32(i64 5, i32 4, ptr null, i32 0) 92 ret i32 %result 93} 94 95; Test register allocation for an i64 result value of patchpoint. 96define i64 @generic_patchpoint_i64() { 97entry: 98; CHECK-LABEL: generic_patchpoint_i64: 99; CHECK: Ltmp 100; CHECK-NEXT: nop 101; The return value is already in x0. 102; CHECK-NEXT: ldp 103; CHECK-NEXT: ret 104 %result = tail call i64 (i64, i32, ptr, i32, ...) @llvm.experimental.patchpoint.i64(i64 5, i32 4, ptr null, i32 0) 105 ret i64 %result 106} 107 108; Test register allocation for a ptr result value of patchpoint. 109define ptr @generic_patchpoint_p0() { 110entry: 111; CHECK-LABEL: generic_patchpoint_p0: 112; CHECK: Ltmp 113; CHECK-NEXT: nop 114; The return value is already in x0. 115; CHECK-NEXT: ldp 116; CHECK-NEXT: ret 117 %result = tail call ptr (i64, i32, ptr, i32, ...) @llvm.experimental.patchpoint.p0(i64 5, i32 4, ptr null, i32 0) 118 ret ptr %result 119} 120 121; Test register allocation for a half result value of patchpoint. 122define half @generic_patchpoint_f16() { 123entry: 124; CHECK-LABEL: generic_patchpoint_f16: 125; CHECK: Ltmp 126; CHECK-NEXT: nop 127; The return value is already in h0. 128; CHECK-NEXT: ldp 129; CHECK-NEXT: ret 130 %result = tail call half (i64, i32, ptr, i32, ...) @llvm.experimental.patchpoint.f16(i64 5, i32 4, ptr null, i32 0) 131 ret half %result 132} 133 134; Test register allocation for a float result value of patchpoint. 135define float @generic_patchpoint_f32() { 136entry: 137; CHECK-LABEL: generic_patchpoint_f32: 138; CHECK: Ltmp 139; CHECK-NEXT: nop 140; The return value is already in s0. 141; CHECK-NEXT: ldp 142; CHECK-NEXT: ret 143 %result = tail call float (i64, i32, ptr, i32, ...) @llvm.experimental.patchpoint.f32(i64 5, i32 4, ptr null, i32 0) 144 ret float %result 145} 146 147; Test register allocation for a double result value of patchpoint. 148define double @generic_patchpoint_f64() { 149entry: 150; CHECK-LABEL: generic_patchpoint_f64: 151; CHECK: Ltmp 152; CHECK-NEXT: nop 153; The return value is already in d0. 154; CHECK-NEXT: ldp 155; CHECK-NEXT: ret 156 %result = tail call double (i64, i32, ptr, i32, ...) @llvm.experimental.patchpoint.f64(i64 5, i32 4, ptr null, i32 0) 157 ret double %result 158} 159 160; Test register allocation for a <16 x i8> result value of patchpoint. 161define <16 x i8> @generic_patchpoint_v16i8() { 162entry: 163; CHECK-LABEL: generic_patchpoint_v16i8: 164; CHECK: Ltmp 165; CHECK-NEXT: nop 166; The return value is already in v0.16b. 167; CHECK-NEXT: ldp 168; CHECK-NEXT: ret 169 %result = tail call <16 x i8> (i64, i32, ptr, i32, ...) @llvm.experimental.patchpoint.v16i8(i64 5, i32 4, ptr null, i32 0) 170 ret <16 x i8> %result 171} 172 173; Test register allocation for a <4 x i32> result value of patchpoint. 174define <4 x i32> @generic_patchpoint_v4i32() { 175entry: 176; CHECK-LABEL: generic_patchpoint_v4i32: 177; CHECK: Ltmp 178; CHECK-NEXT: nop 179; The return value is already in v0.4s. 180; CHECK-NEXT: ldp 181; CHECK-NEXT: ret 182 %result = tail call <4 x i32> (i64, i32, ptr, i32, ...) @llvm.experimental.patchpoint.v4i32(i64 5, i32 4, ptr null, i32 0) 183 ret <4 x i32> %result 184} 185 186; Test register allocation for a <4 x float> result value of patchpoint. 187define <4 x float> @generic_patchpoint_v4f32() { 188entry: 189; CHECK-LABEL: generic_patchpoint_v4f32: 190; CHECK: Ltmp 191; CHECK-NEXT: nop 192; The return value is already in v0.4s. 193; CHECK-NEXT: ldp 194; CHECK-NEXT: ret 195 %result = tail call <4 x float> (i64, i32, ptr, i32, ...) @llvm.experimental.patchpoint.v4f32(i64 5, i32 4, ptr null, i32 0) 196 ret <4 x float> %result 197} 198 199; Test register allocation for a <2 x double> result value of patchpoint. 200define <2 x double> @generic_patchpoint_v2f64() { 201entry: 202; CHECK-LABEL: generic_patchpoint_v2f64: 203; CHECK: Ltmp 204; CHECK-NEXT: nop 205; The return value is already in v0.2d. 206; CHECK-NEXT: ldp 207; CHECK-NEXT: ret 208 %result = tail call <2 x double> (i64, i32, ptr, i32, ...) @llvm.experimental.patchpoint.v2f64(i64 5, i32 4, ptr null, i32 0) 209 ret <2 x double> %result 210} 211 212declare void @llvm.experimental.stackmap(i64, i32, ...) 213declare void @llvm.experimental.patchpoint.void(i64, i32, ptr, i32, ...) 214declare i32 @llvm.experimental.patchpoint.i32(i64, i32, ptr, i32, ...) 215declare i64 @llvm.experimental.patchpoint.i64(i64, i32, ptr, i32, ...) 216declare ptr @llvm.experimental.patchpoint.p0(i64, i32, ptr, i32, ...) 217declare half @llvm.experimental.patchpoint.f16(i64, i32, ptr, i32, ...) 218declare float @llvm.experimental.patchpoint.f32(i64, i32, ptr, i32, ...) 219declare double @llvm.experimental.patchpoint.f64(i64, i32, ptr, i32, ...) 220declare <16 x i8> @llvm.experimental.patchpoint.v16i8(i64, i32, ptr, i32, ...) 221declare <4 x i32> @llvm.experimental.patchpoint.v4i32(i64, i32, ptr, i32, ...) 222declare <4 x float> @llvm.experimental.patchpoint.v4f32(i64, i32, ptr, i32, ...) 223declare <2 x double> @llvm.experimental.patchpoint.v2f64(i64, i32, ptr, i32, ...) 224