1; RUN: llc -verify-machineinstrs -mtriple=aarch64-apple-ios -o - %s | FileCheck --check-prefix=CHECK --check-prefix=OPT --check-prefix=OPTAARCH64 %s 2; RUN: llc -O0 -fast-isel -verify-machineinstrs -mtriple=aarch64-apple-ios -o - %s | FileCheck %s 3; RUN: llc -verify-machineinstrs -mtriple=aarch64-unknown-linux-gnu -o - %s | FileCheck --check-prefix=CHECK --check-prefix=OPT --check-prefix=OPTAARCH64 %s 4; RUN: llc -verify-machineinstrs -mtriple=arm64_32-apple-ios -o - %s | FileCheck --check-prefix=CHECK --check-prefix=OPT --check-prefix=OPTARM64_32 %s 5 6; Parameter with swiftself should be allocated to x20. 7; CHECK-LABEL: swiftself_param: 8; CHECK: mov x0, x20 9; CHECK-NEXT: ret 10define ptr @swiftself_param(ptr swiftself %addr0) { 11 ret ptr %addr0 12} 13 14; Check that x20 is used to pass a swiftself argument. 15; CHECK-LABEL: call_swiftself: 16; CHECK: mov x20, x0 17; CHECK: bl {{_?}}swiftself_param 18; CHECK: ret 19define ptr @call_swiftself(ptr %arg) { 20 %res = call ptr @swiftself_param(ptr swiftself %arg) 21 ret ptr %res 22} 23 24; x20 should be saved by the callee even if used for swiftself 25; CHECK-LABEL: swiftself_clobber: 26; CHECK: {{stp|str}} {{.*}}x20{{.*}}sp 27; ... 28; CHECK: {{ldp|ldr}} {{.*}}x20{{.*}}sp 29; CHECK: ret 30define ptr @swiftself_clobber(ptr swiftself %addr0) { 31 call void asm sideeffect "", "~{x20}"() 32 ret ptr %addr0 33} 34 35; Demonstrate that we do not need any movs when calling multiple functions 36; with swiftself argument. 37; CHECK-LABEL: swiftself_passthrough: 38; OPT-NOT: mov{{.*}}x20 39; OPT: bl {{_?}}swiftself_param 40; OPT-NOT: mov{{.*}}x20 41; OPT-NEXT: bl {{_?}}swiftself_param 42; OPT: ret 43define void @swiftself_passthrough(ptr swiftself %addr0) { 44 call ptr @swiftself_param(ptr swiftself %addr0) 45 call ptr @swiftself_param(ptr swiftself %addr0) 46 ret void 47} 48 49; We can use a tail call if the callee swiftself is the same as the caller one. 50; This should also work with fast-isel. 51; CHECK-LABEL: swiftself_tail: 52; OPTAARCH64: b {{_?}}swiftself_param 53; OPTAARCH64-NOT: ret 54; OPTARM64_32: b {{_?}}swiftself_param 55define ptr @swiftself_tail(ptr swiftself %addr0) { 56 call void asm sideeffect "", "~{x20}"() 57 %res = musttail call ptr @swiftself_param(ptr swiftself %addr0) 58 ret ptr %res 59} 60 61; We can not use a tail call if the callee swiftself is not the same as the 62; caller one. 63; CHECK-LABEL: swiftself_notail: 64; CHECK: mov x20, x0 65; CHECK: bl {{_?}}swiftself_param 66; CHECK: ret 67define ptr @swiftself_notail(ptr swiftself %addr0, ptr %addr1) nounwind { 68 %res = tail call ptr @swiftself_param(ptr swiftself %addr1) 69 ret ptr %res 70} 71 72; We cannot pretend that 'x0' is alive across the thisreturn_attribute call as 73; we normally would. We marked the first parameter with swiftself which means it 74; will no longer be passed in x0. 75declare swiftcc ptr @thisreturn_attribute(ptr returned swiftself) 76; OPTAARCH64-LABEL: swiftself_nothisreturn: 77; OPTAARCH64-DAG: ldr x20, [x20] 78; OPTAARCH64-DAG: mov [[CSREG:x[1-9].*]], x8 79; OPTAARCH64: bl {{_?}}thisreturn_attribute 80; OPTAARCH64: str x0, [[[CSREG]] 81; OPTAARCH64: ret 82 83; OPTARM64_32-LABEL: swiftself_nothisreturn: 84; OPTARM64_32-DAG: ldr w20, [x20] 85; OPTARM64_32-DAG: mov [[CSREG:x[1-9].*]], x8 86; OPTARM64_32: bl {{_?}}thisreturn_attribute 87; OPTARM64_32: str w0, [[[CSREG]] 88; OPTARM64_32: ret 89define hidden swiftcc void @swiftself_nothisreturn(ptr noalias nocapture sret(ptr), ptr noalias nocapture readonly swiftself) { 90entry: 91 %2 = load ptr, ptr %1, align 8 92 %3 = tail call swiftcc ptr @thisreturn_attribute(ptr swiftself %2) 93 store ptr %3, ptr %0, align 8 94 ret void 95} 96