From 99507c0d65cbd3ab2bc138a69608a4de3fd89b3b Mon Sep 17 00:00:00 2001 From: Jessica Paquette Date: Wed, 18 Sep 2019 22:42:25 +0000 Subject: [PATCH] [AArch64][GlobalISel] Support lowering musttail calls Since we now lower most tail calls, it makes sense to support musttail. Instead of always falling back to SelectionDAG, only fall back when a musttail call was not able to be emitted as a tail call. Once we can handle most incoming and outgoing arguments, we can change this to a `report_fatal_error` like in ISelLowering. Remove the assert that we don't have varargs and a musttail, and replace it with a return false. Implementing this requires that we implement `saveVarArgRegisters` from AArch64ISelLowering, which is an entirely different patch. Add GlobalISel lines to vararg-tallcall.ll to make sure that we produce correct code. Right now we only fall back, but eventually this will be relevant. Differential Revision: https://reviews.llvm.org/D67681 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@372273 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/AArch64/AArch64CallLowering.cpp | 34 +++++++++++++------ .../GlobalISel/call-translator-musttail.ll | 15 ++++---- .../GlobalISel/call-translator-tail-call.ll | 15 ++++++++ test/CodeGen/AArch64/vararg-tallcall.ll | 2 ++ 4 files changed, 50 insertions(+), 16 deletions(-) diff --git a/lib/Target/AArch64/AArch64CallLowering.cpp b/lib/Target/AArch64/AArch64CallLowering.cpp index f331c170e85..a4f2bac8d60 100644 --- a/lib/Target/AArch64/AArch64CallLowering.cpp +++ b/lib/Target/AArch64/AArch64CallLowering.cpp @@ -596,6 +596,11 @@ bool AArch64CallLowering::isEligibleForTailCallOptimization( MachineIRBuilder &MIRBuilder, CallLoweringInfo &Info, SmallVectorImpl &InArgs, SmallVectorImpl &OutArgs) const { + + // Must pass all target-independent checks in order to tail call optimize. + if (!Info.IsTailCall) + return false; + CallingConv::ID CalleeCC = Info.CallConv; MachineFunction &MF = MIRBuilder.getMF(); const Function &CallerF = MF.getFunction(); @@ -675,8 +680,12 @@ bool AArch64CallLowering::isEligibleForTailCallOptimization( // 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!"); + if (Info.IsVarArg && Info.IsMustTailCall) { + LLVM_DEBUG( + dbgs() + << "... Cannot handle vararg musttail functions yet.\n"); + return false; + } // Verify that the incoming and outgoing arguments from the callee are // safe to tail call. @@ -841,12 +850,6 @@ bool AArch64CallLowering::lowerCall(MachineIRBuilder &MIRBuilder, auto &DL = F.getParent()->getDataLayout(); const AArch64TargetLowering &TLI = *getTLI(); - if (Info.IsMustTailCall) { - // TODO: Until we lower all tail calls, we should fall back on this. - LLVM_DEBUG(dbgs() << "Cannot lower musttail calls yet.\n"); - return false; - } - SmallVector OutArgs; for (auto &OrigArg : Info.OrigArgs) { splitToValueTypes(OrigArg, OutArgs, DL, MRI, Info.CallConv); @@ -860,8 +863,19 @@ bool AArch64CallLowering::lowerCall(MachineIRBuilder &MIRBuilder, splitToValueTypes(Info.OrigRet, InArgs, DL, MRI, F.getCallingConv()); // If we can lower as a tail call, do that instead. - if (Info.IsTailCall && - isEligibleForTailCallOptimization(MIRBuilder, Info, InArgs, OutArgs)) + bool CanTailCallOpt = + isEligibleForTailCallOptimization(MIRBuilder, Info, InArgs, OutArgs); + + // We must emit a tail call if we have musttail. + if (Info.IsMustTailCall && !CanTailCallOpt) { + // There are types of incoming/outgoing arguments we can't handle yet, so + // it doesn't make sense to actually die here like in ISelLowering. Instead, + // fall back to SelectionDAG and let it try to handle this. + LLVM_DEBUG(dbgs() << "Failed to lower musttail call as tail call\n"); + return false; + } + + if (CanTailCallOpt) return lowerTailCall(MIRBuilder, Info, OutArgs); // Find out which ABI gets to decide where things go. diff --git a/test/CodeGen/AArch64/GlobalISel/call-translator-musttail.ll b/test/CodeGen/AArch64/GlobalISel/call-translator-musttail.ll index 7d6ba8489b7..72af098a894 100644 --- a/test/CodeGen/AArch64/GlobalISel/call-translator-musttail.ll +++ b/test/CodeGen/AArch64/GlobalISel/call-translator-musttail.ll @@ -1,10 +1,13 @@ -; RUN: not llc %s -mtriple aarch64-unknown-unknown -debug-only=aarch64-call-lowering -global-isel -o - 2>&1 | FileCheck %s +; RUN: not llc %s -mtriple aarch64-apple-darwin -debug-only=aarch64-call-lowering -global-isel -global-isel-abort=2 -o - 2>&1 | FileCheck %s ; REQUIRES: asserts -; CHECK: Cannot lower musttail calls yet. -; CHECK-NEXT: LLVM ERROR: unable to translate instruction: call (in function: foo) -declare void @must_callee(i8*) -define void @foo(i32*) { - musttail call void @must_callee(i8* null) +; Verify that we fall back to SelectionDAG, and error out when we can't tail call musttail functions +; CHECK: ... Cannot tail call externally-defined function with weak linkage for this OS. +; CHECK-NEXT: Failed to lower musttail call as tail call +; CHECK-NEXT: warning: Instruction selection used fallback path for caller_weak +; CHECK-NEXT: LLVM ERROR: failed to perform tail call elimination on a call site marked musttail +declare extern_weak void @callee_weak() +define void @caller_weak() { + musttail call void @callee_weak() ret void } diff --git a/test/CodeGen/AArch64/GlobalISel/call-translator-tail-call.ll b/test/CodeGen/AArch64/GlobalISel/call-translator-tail-call.ll index 5be29e04512..78ab27e1039 100644 --- a/test/CodeGen/AArch64/GlobalISel/call-translator-tail-call.ll +++ b/test/CodeGen/AArch64/GlobalISel/call-translator-tail-call.ll @@ -224,3 +224,18 @@ define hidden swiftcc i64 @swiftself_indirect_tail(i64* swiftself %arg) { %tmp2 = tail call swiftcc i64 %tmp1(i64* swiftself %arg) ret i64 %tmp2 } + +; Verify that we can tail call musttail callees. +declare void @must_callee(i8*) +define void @foo(i32*) { + ; COMMON-LABEL: name: foo + ; COMMON: bb.1 (%ir-block.1): + ; COMMON: liveins: $x0 + ; COMMON: [[COPY:%[0-9]+]]:_(p0) = COPY $x0 + ; COMMON: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 0 + ; COMMON: [[INTTOPTR:%[0-9]+]]:_(p0) = G_INTTOPTR [[C]](s64) + ; COMMON: $x0 = COPY [[INTTOPTR]](p0) + ; COMMON: TCRETURNdi @must_callee, 0, csr_aarch64_aapcs, implicit $sp, implicit $x0 + musttail call void @must_callee(i8* null) + ret void +} diff --git a/test/CodeGen/AArch64/vararg-tallcall.ll b/test/CodeGen/AArch64/vararg-tallcall.ll index 56c56213af3..aa239a8d57e 100644 --- a/test/CodeGen/AArch64/vararg-tallcall.ll +++ b/test/CodeGen/AArch64/vararg-tallcall.ll @@ -1,5 +1,7 @@ ; RUN: llc -mtriple=aarch64-windows-msvc %s -o - | FileCheck %s ; RUN: llc -mtriple=aarch64-linux-gnu %s -o - | FileCheck %s +; RUN: llc -global-isel -global-isel-abort=2 -verify-machineinstrs -mtriple=aarch64-windows-msvc %s -o - | FileCheck %s +; RUN: llc -global-isel -global-isel-abort=2 -verify-machineinstrs -mtriple=aarch64-linux-gnu %s -o - | FileCheck %s target datalayout = "e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128" -- 2.40.0