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