96 lines · plain
1; RUN: llc -verify-machineinstrs -mtriple=aarch64-apple-ios -o - %s | FileCheck --check-prefix=CHECK --check-prefix=OPT --check-prefix=OPTAARCH64 %s2; RUN: llc -O0 -fast-isel -verify-machineinstrs -mtriple=aarch64-apple-ios -o - %s | FileCheck %s3; RUN: llc -verify-machineinstrs -mtriple=aarch64-unknown-linux-gnu -o - %s | FileCheck --check-prefix=CHECK --check-prefix=OPT --check-prefix=OPTAARCH64 %s4; RUN: llc -verify-machineinstrs -mtriple=arm64_32-apple-ios -o - %s | FileCheck --check-prefix=CHECK --check-prefix=OPT --check-prefix=OPTARM64_32 %s5 6; Parameter with swiftself should be allocated to x20.7; CHECK-LABEL: swiftself_param:8; CHECK: mov x0, x209; CHECK-NEXT: ret10define ptr @swiftself_param(ptr swiftself %addr0) {11 ret ptr %addr012}13 14; Check that x20 is used to pass a swiftself argument.15; CHECK-LABEL: call_swiftself:16; CHECK: mov x20, x017; CHECK: bl {{_?}}swiftself_param18; CHECK: ret19define ptr @call_swiftself(ptr %arg) {20 %res = call ptr @swiftself_param(ptr swiftself %arg)21 ret ptr %res22}23 24; x20 should be saved by the callee even if used for swiftself25; CHECK-LABEL: swiftself_clobber:26; CHECK: {{stp|str}} {{.*}}x20{{.*}}sp27; ...28; CHECK: {{ldp|ldr}} {{.*}}x20{{.*}}sp29; CHECK: ret30define ptr @swiftself_clobber(ptr swiftself %addr0) {31 call void asm sideeffect "", "~{x20}"()32 ret ptr %addr033}34 35; Demonstrate that we do not need any movs when calling multiple functions36; with swiftself argument.37; CHECK-LABEL: swiftself_passthrough:38; OPT-NOT: mov{{.*}}x2039; OPT: bl {{_?}}swiftself_param40; OPT-NOT: mov{{.*}}x2041; OPT-NEXT: bl {{_?}}swiftself_param42; OPT: ret43define void @swiftself_passthrough(ptr swiftself %addr0) {44 call ptr @swiftself_param(ptr swiftself %addr0)45 call ptr @swiftself_param(ptr swiftself %addr0)46 ret void47}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_param53; OPTAARCH64-NOT: ret54; OPTARM64_32: b {{_?}}swiftself_param55define 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 %res59}60 61; We can not use a tail call if the callee swiftself is not the same as the62; caller one.63; CHECK-LABEL: swiftself_notail:64; CHECK: mov x20, x065; CHECK: bl {{_?}}swiftself_param66; CHECK: ret67define ptr @swiftself_notail(ptr swiftself %addr0, ptr %addr1) nounwind {68 %res = tail call ptr @swiftself_param(ptr swiftself %addr1)69 ret ptr %res70}71 72; We cannot pretend that 'x0' is alive across the thisreturn_attribute call as73; we normally would. We marked the first parameter with swiftself which means it74; 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].*]], x879; OPTAARCH64: bl {{_?}}thisreturn_attribute80; OPTAARCH64: str x0, [[[CSREG]]81; OPTAARCH64: ret82 83; OPTARM64_32-LABEL: swiftself_nothisreturn:84; OPTARM64_32-DAG: ldr w20, [x20]85; OPTARM64_32-DAG: mov [[CSREG:x[1-9].*]], x886; OPTARM64_32: bl {{_?}}thisreturn_attribute87; OPTARM64_32: str w0, [[[CSREG]]88; OPTARM64_32: ret89define hidden swiftcc void @swiftself_nothisreturn(ptr noalias nocapture sret(ptr), ptr noalias nocapture readonly swiftself) {90entry:91 %2 = load ptr, ptr %1, align 892 %3 = tail call swiftcc ptr @thisreturn_attribute(ptr swiftself %2)93 store ptr %3, ptr %0, align 894 ret void95}96