From a5e10524acf16aad99a9ab0c4359de87fcb8d783 Mon Sep 17 00:00:00 2001 From: Jessica Paquette Date: Thu, 12 Sep 2019 23:00:59 +0000 Subject: [PATCH] [AArch64][GlobalISel] Support tail calling with swiftself parameters Swiftself uses a callee-saved register. We can tail call when the register used in the caller and callee is the same. This behaviour is equivalent to that in `TargetLowering::parametersInCSRMatch`. Update call-translator-tail-call.ll to verify that we can do this. When we support inline assembly, we can write a check similar to the one in the general swiftself.ll. For now, we need to verify that we get the correct COPY instruction after call lowering. Differential Revision: https://reviews.llvm.org/D67511 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@371788 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/AArch64/AArch64CallLowering.cpp | 37 ++++++++++++++++--- .../GlobalISel/call-translator-tail-call.ll | 21 +++++++++++ 2 files changed, 53 insertions(+), 5 deletions(-) diff --git a/lib/Target/AArch64/AArch64CallLowering.cpp b/lib/Target/AArch64/AArch64CallLowering.cpp index bad8fb3ab0d..a3a212c5128 100644 --- a/lib/Target/AArch64/AArch64CallLowering.cpp +++ b/lib/Target/AArch64/AArch64CallLowering.cpp @@ -509,8 +509,10 @@ bool AArch64CallLowering::areCalleeOutgoingArgsTailCallable( // supported. auto TRI = MF.getSubtarget().getRegisterInfo(); const uint32_t *CallerPreservedMask = TRI->getCallPreservedMask(MF, CallerCC); + MachineRegisterInfo &MRI = MF.getRegInfo(); - for (auto &ArgLoc : OutLocs) { + for (unsigned i = 0; i < OutLocs.size(); ++i) { + auto &ArgLoc = OutLocs[i]; // If it's not a register, it's fine. if (!ArgLoc.isRegLoc()) continue; @@ -521,12 +523,37 @@ bool AArch64CallLowering::areCalleeOutgoingArgsTailCallable( if (MachineOperand::clobbersPhysReg(CallerPreservedMask, Reg)) continue; - // TODO: Port the remainder of this check from TargetLowering to support - // tail calling swiftself. LLVM_DEBUG( dbgs() - << "... Cannot handle callee-saved registers in outgoing args yet.\n"); - return false; + << "... Call has an argument passed in a callee-saved register.\n"); + + // Check if it was copied from. + ArgInfo &OutInfo = OutArgs[i]; + + if (OutInfo.Regs.size() > 1) { + LLVM_DEBUG( + dbgs() << "... Cannot handle arguments in multiple registers.\n"); + return false; + } + + // Check if we copy the register, walking through copies from virtual + // registers. Note that getDefIgnoringCopies does not ignore copies from + // physical registers. + MachineInstr *RegDef = getDefIgnoringCopies(OutInfo.Regs[0], MRI); + if (!RegDef || RegDef->getOpcode() != TargetOpcode::COPY) { + LLVM_DEBUG( + dbgs() + << "... Parameter was not copied into a VReg, cannot tail call.\n"); + return false; + } + + // Got a copy. Verify that it's the same as the register we want. + Register CopyRHS = RegDef->getOperand(1).getReg(); + if (CopyRHS != Reg) { + LLVM_DEBUG(dbgs() << "... Callee-saved register was not copied into " + "VReg, cannot tail call.\n"); + return false; + } } return true; diff --git a/test/CodeGen/AArch64/GlobalISel/call-translator-tail-call.ll b/test/CodeGen/AArch64/GlobalISel/call-translator-tail-call.ll index 8a008896f76..97252825f79 100644 --- a/test/CodeGen/AArch64/GlobalISel/call-translator-tail-call.ll +++ b/test/CodeGen/AArch64/GlobalISel/call-translator-tail-call.ll @@ -192,3 +192,24 @@ entry: tail call void @llvm.lifetime.end.p0i8(i64 1, i8* %t) ret void } + +; We can tail call when the callee swiftself is the same as the caller one. +; It would be nice to move this to swiftself.ll, but it's important to verify +; that we get the COPY that makes this safe in the first place. +declare i8* @pluto() +define hidden swiftcc i64 @swiftself_indirect_tail(i64* swiftself %arg) { + ; COMMON-LABEL: name: swiftself_indirect_tail + ; COMMON: bb.1 (%ir-block.0): + ; COMMON: liveins: $x20 + ; COMMON: [[COPY:%[0-9]+]]:_(p0) = COPY $x20 + ; COMMON: ADJCALLSTACKDOWN 0, 0, implicit-def $sp, implicit $sp + ; COMMON: BL @pluto, csr_aarch64_aapcs, implicit-def $lr, implicit $sp, implicit-def $x0 + ; COMMON: [[COPY1:%[0-9]+]]:tcgpr64(p0) = COPY $x0 + ; COMMON: ADJCALLSTACKUP 0, 0, implicit-def $sp, implicit $sp + ; COMMON: $x20 = COPY [[COPY]](p0) + ; COMMON: TCRETURNri [[COPY1]](p0), 0, csr_aarch64_aapcs, implicit $sp, implicit $x20 + %tmp = call i8* @pluto() + %tmp1 = bitcast i8* %tmp to i64 (i64*)* + %tmp2 = tail call swiftcc i64 %tmp1(i64* swiftself %arg) + ret i64 %tmp2 +} -- 2.40.0