mirror of
https://github.com/RPCS3/llvm.git
synced 2025-05-13 17:06:15 +00:00
[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
This commit is contained in:
parent
11df0bc741
commit
a5e10524ac
@ -509,8 +509,10 @@ bool AArch64CallLowering::areCalleeOutgoingArgsTailCallable(
|
||||
// supported.
|
||||
auto TRI = MF.getSubtarget<AArch64Subtarget>().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;
|
||||
|
@ -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
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user