[AArch64][GlobalISel] Add support for sibcalling callees with varargs

This adds support for tail calling callees with varargs, equivalent to how it
is done in AArch64ISelLowering.

This only works for sibling calls, and does not add the necessary support for
musttail with varargs. (See r345641 for equivalent ISelLowering support.) This
should be implemented when we stop falling back on musttail.

Update call-translator-tail-call.ll to show that we can now tail call varargs.

Differential Revision: https://reviews.llvm.org/D67518

llvm-svn: 371868
This commit is contained in:
Jessica Paquette 2019-09-13 16:10:19 +00:00
parent 2a573784f3
commit 14bfb56b1a
2 changed files with 44 additions and 20 deletions

View File

@ -514,8 +514,20 @@ bool AArch64CallLowering::areCalleeOutgoingArgsTailCallable(
for (unsigned i = 0; i < OutLocs.size(); ++i) {
auto &ArgLoc = OutLocs[i];
// If it's not a register, it's fine.
if (!ArgLoc.isRegLoc())
if (!ArgLoc.isRegLoc()) {
if (Info.IsVarArg) {
// Be conservative and disallow variadic memory operands to match SDAG's
// behaviour.
// FIXME: If the caller's calling convention is C, then we can
// potentially use its argument area. However, for cases like fastcc,
// we can't do anything.
LLVM_DEBUG(
dbgs()
<< "... Cannot tail call vararg function with stack arguments\n");
return false;
}
continue;
}
Register Reg = ArgLoc.getLocReg();
@ -583,11 +595,6 @@ bool AArch64CallLowering::isEligibleForTailCallOptimization(
return false;
}
if (Info.IsVarArg) {
LLVM_DEBUG(dbgs() << "... Tail calling varargs not supported yet.\n");
return false;
}
// Byval parameters hand the function a pointer directly into the stack area
// we want to reuse during a tail call. Working around this *is* possible (see
// X86).
@ -641,6 +648,12 @@ bool AArch64CallLowering::isEligibleForTailCallOptimization(
assert((!Info.IsVarArg || CalleeCC == CallingConv::C) &&
"Unexpected variadic calling convention");
// Before we can musttail varargs, we need to forward parameters like in
// r345641. Make sure that we don't enable musttail with varargs without
// addressing that!
assert(!(Info.IsVarArg && Info.IsMustTailCall) &&
"musttail support for varargs not implemented yet!");
// Verify that the incoming and outgoing arguments from the callee are
// safe to tail call.
if (!doCallerAndCalleePassArgsTheSameWay(Info, MF, InArgs)) {

View File

@ -75,22 +75,33 @@ define i32 @test_nonvoid_ret() {
ret i32 %call
}
; Right now, this should not be tail called.
; TODO: Support this.
declare void @varargs(i32, double, i64, ...)
define void @test_varargs() {
; COMMON-LABEL: name: test_varargs
; COMMON: bb.1 (%ir-block.0):
; COMMON: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 42
; COMMON: [[C1:%[0-9]+]]:_(s64) = G_FCONSTANT double 1.000000e+00
; COMMON: [[C2:%[0-9]+]]:_(s64) = G_CONSTANT i64 12
; COMMON: ADJCALLSTACKDOWN 0, 0, implicit-def $sp, implicit $sp
; COMMON: $w0 = COPY [[C]](s32)
; COMMON: $d0 = COPY [[C1]](s64)
; COMMON: $x1 = COPY [[C2]](s64)
; COMMON: BL @varargs, csr_aarch64_aapcs, implicit-def $lr, implicit $sp, implicit $w0, implicit $d0, implicit $x1
; COMMON: ADJCALLSTACKUP 0, 0, implicit-def $sp, implicit $sp
; COMMON: RET_ReallyLR
; On Darwin, everything is passed on the stack. Since the caller has no stack,
; we don't tail call.
; DARWIN-LABEL: name: test_varargs
; DARWIN: bb.1 (%ir-block.0):
; DARWIN: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 42
; DARWIN: [[C1:%[0-9]+]]:_(s64) = G_FCONSTANT double 1.000000e+00
; DARWIN: [[C2:%[0-9]+]]:_(s64) = G_CONSTANT i64 12
; DARWIN: ADJCALLSTACKDOWN 0, 0, implicit-def $sp, implicit $sp
; DARWIN: $w0 = COPY [[C]](s32)
; DARWIN: $d0 = COPY [[C1]](s64)
; DARWIN: $x1 = COPY [[C2]](s64)
; DARWIN: BL @varargs, csr_aarch64_aapcs, implicit-def $lr, implicit $sp, implicit $w0, implicit $d0, implicit $x1
; DARWIN: ADJCALLSTACKUP 0, 0, implicit-def $sp, implicit $sp
; DARWIN: RET_ReallyLR
; Windows uses registers, so we don't need to worry about using the stack.
; WINDOWS-LABEL: name: test_varargs
; WINDOWS: bb.1 (%ir-block.0):
; WINDOWS: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 42
; WINDOWS: [[C1:%[0-9]+]]:_(s64) = G_FCONSTANT double 1.000000e+00
; WINDOWS: [[C2:%[0-9]+]]:_(s64) = G_CONSTANT i64 12
; WINDOWS: $w0 = COPY [[C]](s32)
; WINDOWS: $d0 = COPY [[C1]](s64)
; WINDOWS: $x1 = COPY [[C2]](s64)
; WINDOWS: TCRETURNdi @varargs, 0, csr_aarch64_aapcs, implicit $sp, implicit $w0, implicit $d0, implicit $x1
tail call void(i32, double, i64, ...) @varargs(i32 42, double 1.0, i64 12)
ret void
}