From 14bfb56b1aea586f489aaa71af13bf742873de46 Mon Sep 17 00:00:00 2001 From: Jessica Paquette Date: Fri, 13 Sep 2019 16:10:19 +0000 Subject: [PATCH] [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 --- .../Target/AArch64/AArch64CallLowering.cpp | 25 +++++++++--- .../GlobalISel/call-translator-tail-call.ll | 39 ++++++++++++------- 2 files changed, 44 insertions(+), 20 deletions(-) diff --git a/llvm/lib/Target/AArch64/AArch64CallLowering.cpp b/llvm/lib/Target/AArch64/AArch64CallLowering.cpp index a3a212c51285..1e3d6e5483f5 100644 --- a/llvm/lib/Target/AArch64/AArch64CallLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64CallLowering.cpp @@ -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)) { diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/call-translator-tail-call.ll b/llvm/test/CodeGen/AArch64/GlobalISel/call-translator-tail-call.ll index 97252825f793..5be29e04512f 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/call-translator-tail-call.ll +++ b/llvm/test/CodeGen/AArch64/GlobalISel/call-translator-tail-call.ll @@ -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 }