[llvm] r373976 - [X86] Add new calling convention that guarantees tail call optimization
Roman Lebedev via llvm-commits
llvm-commits at lists.llvm.org
Mon Oct 7 15:28:14 PDT 2019
On Tue, Oct 8, 2019 at 1:26 AM Reid Kleckner via llvm-commits
<llvm-commits at lists.llvm.org> wrote:
>
> Author: rnk
> Date: Mon Oct 7 15:28:58 2019
> New Revision: 373976
>
> URL: http://llvm.org/viewvc/llvm-project?rev=373976&view=rev
> Log:
> [X86] Add new calling convention that guarantees tail call optimization
>
> When the target option GuaranteedTailCallOpt is specified, calls with
> the fastcc calling convention will be transformed into tail calls if
> they are in tail position. This diff adds a new calling convention,
> tailcc, currently supported only on X86, which behaves the same way as
> fastcc, except that the GuaranteedTailCallOpt flag does not need to
> enabled in order to enable tail call optimization.
>
> Patch by Dwight Guth <dwight.guth at runtimeverification.com>!
>
> Reviewed By: lebedev.ri, paquette, rnk
Pretty sure i didn't review this.
> Differential Revision: https://reviews.llvm.org/D67855
>
> Added:
> llvm/trunk/test/CodeGen/X86/musttail-tailcc.ll
> llvm/trunk/test/CodeGen/X86/tailcall-tailcc.ll
> llvm/trunk/test/CodeGen/X86/tailcc-calleesave.ll
> llvm/trunk/test/CodeGen/X86/tailcc-disable-tail-calls.ll
> llvm/trunk/test/CodeGen/X86/tailcc-fastcc.ll
> llvm/trunk/test/CodeGen/X86/tailcc-fastisel.ll
> llvm/trunk/test/CodeGen/X86/tailcc-largecode.ll
> llvm/trunk/test/CodeGen/X86/tailcc-stackalign.ll
> llvm/trunk/test/CodeGen/X86/tailcc-structret.ll
> llvm/trunk/test/CodeGen/X86/tailccbyval.ll
> llvm/trunk/test/CodeGen/X86/tailccbyval64.ll
> llvm/trunk/test/CodeGen/X86/tailccfp.ll
> llvm/trunk/test/CodeGen/X86/tailccfp2.ll
> llvm/trunk/test/CodeGen/X86/tailccpic1.ll
> llvm/trunk/test/CodeGen/X86/tailccpic2.ll
> llvm/trunk/test/CodeGen/X86/tailccstack64.ll
> Modified:
> llvm/trunk/docs/BitCodeFormat.rst
> llvm/trunk/docs/CodeGenerator.rst
> llvm/trunk/docs/LangRef.rst
> llvm/trunk/include/llvm/IR/CallingConv.h
> llvm/trunk/lib/AsmParser/LLLexer.cpp
> llvm/trunk/lib/AsmParser/LLParser.cpp
> llvm/trunk/lib/AsmParser/LLToken.h
> llvm/trunk/lib/CodeGen/Analysis.cpp
> llvm/trunk/lib/IR/AsmWriter.cpp
> llvm/trunk/lib/Target/X86/X86CallingConv.td
> llvm/trunk/lib/Target/X86/X86FastISel.cpp
> llvm/trunk/lib/Target/X86/X86FrameLowering.cpp
> llvm/trunk/lib/Target/X86/X86ISelLowering.cpp
> llvm/trunk/lib/Target/X86/X86Subtarget.h
> llvm/trunk/utils/vim/syntax/llvm.vim
>
> Modified: llvm/trunk/docs/BitCodeFormat.rst
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/BitCodeFormat.rst?rev=373976&r1=373975&r2=373976&view=diff
> ==============================================================================
> --- llvm/trunk/docs/BitCodeFormat.rst (original)
> +++ llvm/trunk/docs/BitCodeFormat.rst Mon Oct 7 15:28:58 2019
> @@ -794,6 +794,7 @@ function. The operand fields are:
> * ``preserve_allcc``: code 15
> * ``swiftcc`` : code 16
> * ``cxx_fast_tlscc``: code 17
> + * ``tailcc`` : code 18
> * ``x86_stdcallcc``: code 64
> * ``x86_fastcallcc``: code 65
> * ``arm_apcscc``: code 66
>
> Modified: llvm/trunk/docs/CodeGenerator.rst
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/CodeGenerator.rst?rev=373976&r1=373975&r2=373976&view=diff
> ==============================================================================
> --- llvm/trunk/docs/CodeGenerator.rst (original)
> +++ llvm/trunk/docs/CodeGenerator.rst Mon Oct 7 15:28:58 2019
> @@ -2068,12 +2068,12 @@ supported on x86/x86-64, PowerPC, and We
> and PowerPC if:
>
> * Caller and callee have the calling convention ``fastcc``, ``cc 10`` (GHC
> - calling convention) or ``cc 11`` (HiPE calling convention).
> + calling convention), ``cc 11`` (HiPE calling convention), or ``tailcc``.
>
> * The call is a tail call - in tail position (ret immediately follows call and
> ret uses value of call or is void).
>
> -* Option ``-tailcallopt`` is enabled.
> +* Option ``-tailcallopt`` is enabled or the calling convention is ``tailcc``.
>
> * Platform-specific constraints are met.
>
>
> Modified: llvm/trunk/docs/LangRef.rst
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/LangRef.rst?rev=373976&r1=373975&r2=373976&view=diff
> ==============================================================================
> --- llvm/trunk/docs/LangRef.rst (original)
> +++ llvm/trunk/docs/LangRef.rst Mon Oct 7 15:28:58 2019
> @@ -299,7 +299,7 @@ added in the future:
> allows the target to use whatever tricks it wants to produce fast
> code for the target, without having to conform to an externally
> specified ABI (Application Binary Interface). `Tail calls can only
> - be optimized when this, the GHC or the HiPE convention is
> + be optimized when this, the tailcc, the GHC or the HiPE convention is
> used. <CodeGenerator.html#id80>`_ This calling convention does not
> support varargs and requires the prototype of all callees to exactly
> match the prototype of the function definition.
> @@ -436,6 +436,14 @@ added in the future:
> - On X86-64 RCX and R8 are available for additional integer returns, and
> XMM2 and XMM3 are available for additional FP/vector returns.
> - On iOS platforms, we use AAPCS-VFP calling convention.
> +"``tailcc``" - Tail callable calling convention
> + This calling convention ensures that calls in tail position will always be
> + tail call optimized. This calling convention is equivalent to fastcc,
> + except for an additional guarantee that tail calls will be produced
> + whenever possible. `Tail calls can only be optimized when this, the fastcc,
> + the GHC or the HiPE convention is used. <CodeGenerator.html#id80>`_ This
> + calling convention does not support varargs and requires the prototype of
> + all callees to exactly match the prototype of the function definition.
> "``cc <n>``" - Numbered convention
> Any calling convention may be specified by number, allowing
> target-specific calling conventions to be used. Target specific
> @@ -10232,11 +10240,12 @@ This instruction requires several argume
> Tail call optimization for calls marked ``tail`` is guaranteed to occur if
> the following conditions are met:
>
> - - Caller and callee both have the calling convention ``fastcc``.
> + - Caller and callee both have the calling convention ``fastcc`` or ``tailcc``.
> - The call is in tail position (ret immediately follows call and ret
> uses value of call or is void).
> - - Option ``-tailcallopt`` is enabled, or
> - ``llvm::GuaranteedTailCallOpt`` is ``true``.
> + - Option ``-tailcallopt`` is enabled,
> + ``llvm::GuaranteedTailCallOpt`` is ``true``, or the calling convention
> + is ``tailcc``
> - `Platform-specific constraints are
> met. <CodeGenerator.html#tailcallopt>`_
>
>
> Modified: llvm/trunk/include/llvm/IR/CallingConv.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/CallingConv.h?rev=373976&r1=373975&r2=373976&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/IR/CallingConv.h (original)
> +++ llvm/trunk/include/llvm/IR/CallingConv.h Mon Oct 7 15:28:58 2019
> @@ -75,6 +75,11 @@ namespace CallingConv {
> // CXX_FAST_TLS - Calling convention for access functions.
> CXX_FAST_TLS = 17,
>
> + /// Tail - This calling convention attemps to make calls as fast as
> + /// possible while guaranteeing that tail call optimization can always
> + /// be performed.
> + Tail = 18,
> +
> // Target - This is the start of the target-specific calling conventions,
> // e.g. fastcall and thiscall on X86.
> FirstTargetCC = 64,
>
> Modified: llvm/trunk/lib/AsmParser/LLLexer.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/LLLexer.cpp?rev=373976&r1=373975&r2=373976&view=diff
> ==============================================================================
> --- llvm/trunk/lib/AsmParser/LLLexer.cpp (original)
> +++ llvm/trunk/lib/AsmParser/LLLexer.cpp Mon Oct 7 15:28:58 2019
> @@ -622,6 +622,7 @@ lltok::Kind LLLexer::LexIdentifier() {
> KEYWORD(amdgpu_ps);
> KEYWORD(amdgpu_cs);
> KEYWORD(amdgpu_kernel);
> + KEYWORD(tailcc);
>
> KEYWORD(cc);
> KEYWORD(c);
>
> Modified: llvm/trunk/lib/AsmParser/LLParser.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/LLParser.cpp?rev=373976&r1=373975&r2=373976&view=diff
> ==============================================================================
> --- llvm/trunk/lib/AsmParser/LLParser.cpp (original)
> +++ llvm/trunk/lib/AsmParser/LLParser.cpp Mon Oct 7 15:28:58 2019
> @@ -1955,6 +1955,7 @@ void LLParser::ParseOptionalDLLStorageCl
> /// ::= 'amdgpu_ps'
> /// ::= 'amdgpu_cs'
> /// ::= 'amdgpu_kernel'
> +/// ::= 'tailcc'
> /// ::= 'cc' UINT
> ///
> bool LLParser::ParseOptionalCallingConv(unsigned &CC) {
> @@ -2000,6 +2001,7 @@ bool LLParser::ParseOptionalCallingConv(
> case lltok::kw_amdgpu_ps: CC = CallingConv::AMDGPU_PS; break;
> case lltok::kw_amdgpu_cs: CC = CallingConv::AMDGPU_CS; break;
> case lltok::kw_amdgpu_kernel: CC = CallingConv::AMDGPU_KERNEL; break;
> + case lltok::kw_tailcc: CC = CallingConv::Tail; break;
> case lltok::kw_cc: {
> Lex.Lex();
> return ParseUInt32(CC);
>
> Modified: llvm/trunk/lib/AsmParser/LLToken.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/LLToken.h?rev=373976&r1=373975&r2=373976&view=diff
> ==============================================================================
> --- llvm/trunk/lib/AsmParser/LLToken.h (original)
> +++ llvm/trunk/lib/AsmParser/LLToken.h Mon Oct 7 15:28:58 2019
> @@ -168,6 +168,7 @@ enum Kind {
> kw_amdgpu_ps,
> kw_amdgpu_cs,
> kw_amdgpu_kernel,
> + kw_tailcc,
>
> // Attributes:
> kw_attributes,
>
> Modified: llvm/trunk/lib/CodeGen/Analysis.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/Analysis.cpp?rev=373976&r1=373975&r2=373976&view=diff
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/Analysis.cpp (original)
> +++ llvm/trunk/lib/CodeGen/Analysis.cpp Mon Oct 7 15:28:58 2019
> @@ -523,7 +523,8 @@ bool llvm::isInTailCallPosition(Immutabl
> // longjmp on x86), it can end up causing miscompilation that has not
> // been fully understood.
> if (!Ret &&
> - (!TM.Options.GuaranteedTailCallOpt || !isa<UnreachableInst>(Term)))
> + ((!TM.Options.GuaranteedTailCallOpt &&
> + CS.getCallingConv() != CallingConv::Tail) || !isa<UnreachableInst>(Term)))
> return false;
>
> // If I will have a chain, make sure no other instruction that will have a
>
> Modified: llvm/trunk/lib/IR/AsmWriter.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/AsmWriter.cpp?rev=373976&r1=373975&r2=373976&view=diff
> ==============================================================================
> --- llvm/trunk/lib/IR/AsmWriter.cpp (original)
> +++ llvm/trunk/lib/IR/AsmWriter.cpp Mon Oct 7 15:28:58 2019
> @@ -352,6 +352,7 @@ static void PrintCallingConv(unsigned cc
> case CallingConv::PreserveAll: Out << "preserve_allcc"; break;
> case CallingConv::CXX_FAST_TLS: Out << "cxx_fast_tlscc"; break;
> case CallingConv::GHC: Out << "ghccc"; break;
> + case CallingConv::Tail: Out << "tailcc"; break;
> case CallingConv::X86_StdCall: Out << "x86_stdcallcc"; break;
> case CallingConv::X86_FastCall: Out << "x86_fastcallcc"; break;
> case CallingConv::X86_ThisCall: Out << "x86_thiscallcc"; break;
>
> Modified: llvm/trunk/lib/Target/X86/X86CallingConv.td
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86CallingConv.td?rev=373976&r1=373975&r2=373976&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Target/X86/X86CallingConv.td (original)
> +++ llvm/trunk/lib/Target/X86/X86CallingConv.td Mon Oct 7 15:28:58 2019
> @@ -433,6 +433,7 @@ defm X86_SysV64_RegCall :
> def RetCC_X86_32 : CallingConv<[
> // If FastCC, use RetCC_X86_32_Fast.
> CCIfCC<"CallingConv::Fast", CCDelegateTo<RetCC_X86_32_Fast>>,
> + CCIfCC<"CallingConv::Tail", CCDelegateTo<RetCC_X86_32_Fast>>,
> // If HiPE, use RetCC_X86_32_HiPE.
> CCIfCC<"CallingConv::HiPE", CCDelegateTo<RetCC_X86_32_HiPE>>,
> CCIfCC<"CallingConv::X86_VectorCall", CCDelegateTo<RetCC_X86_32_VectorCall>>,
> @@ -1000,6 +1001,7 @@ def CC_X86_32 : CallingConv<[
> CCIfCC<"CallingConv::X86_VectorCall", CCDelegateTo<CC_X86_Win32_VectorCall>>,
> CCIfCC<"CallingConv::X86_ThisCall", CCDelegateTo<CC_X86_32_ThisCall>>,
> CCIfCC<"CallingConv::Fast", CCDelegateTo<CC_X86_32_FastCC>>,
> + CCIfCC<"CallingConv::Tail", CCDelegateTo<CC_X86_32_FastCC>>,
> CCIfCC<"CallingConv::GHC", CCDelegateTo<CC_X86_32_GHC>>,
> CCIfCC<"CallingConv::HiPE", CCDelegateTo<CC_X86_32_HiPE>>,
> CCIfCC<"CallingConv::X86_RegCall", CCDelegateTo<CC_X86_32_RegCall>>,
>
> Modified: llvm/trunk/lib/Target/X86/X86FastISel.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86FastISel.cpp?rev=373976&r1=373975&r2=373976&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Target/X86/X86FastISel.cpp (original)
> +++ llvm/trunk/lib/Target/X86/X86FastISel.cpp Mon Oct 7 15:28:58 2019
> @@ -1160,6 +1160,7 @@ bool X86FastISel::X86SelectRet(const Ins
> CallingConv::ID CC = F.getCallingConv();
> if (CC != CallingConv::C &&
> CC != CallingConv::Fast &&
> + CC != CallingConv::Tail &&
> CC != CallingConv::X86_FastCall &&
> CC != CallingConv::X86_StdCall &&
> CC != CallingConv::X86_ThisCall &&
> @@ -1173,7 +1174,8 @@ bool X86FastISel::X86SelectRet(const Ins
>
> // fastcc with -tailcallopt is intended to provide a guaranteed
> // tail call optimization. Fastisel doesn't know how to do that.
> - if (CC == CallingConv::Fast && TM.Options.GuaranteedTailCallOpt)
> + if ((CC == CallingConv::Fast && TM.Options.GuaranteedTailCallOpt) ||
> + CC == CallingConv::Tail)
> return false;
>
> // Let SDISel handle vararg functions.
> @@ -3157,7 +3159,7 @@ static unsigned computeBytesPoppedByCall
> if (Subtarget->getTargetTriple().isOSMSVCRT())
> return 0;
> if (CC == CallingConv::Fast || CC == CallingConv::GHC ||
> - CC == CallingConv::HiPE)
> + CC == CallingConv::HiPE || CC == CallingConv::Tail)
> return 0;
>
> if (CS)
> @@ -3208,6 +3210,7 @@ bool X86FastISel::fastLowerCall(CallLowe
> default: return false;
> case CallingConv::C:
> case CallingConv::Fast:
> + case CallingConv::Tail:
> case CallingConv::WebKit_JS:
> case CallingConv::Swift:
> case CallingConv::X86_FastCall:
> @@ -3224,7 +3227,8 @@ bool X86FastISel::fastLowerCall(CallLowe
>
> // fastcc with -tailcallopt is intended to provide a guaranteed
> // tail call optimization. Fastisel doesn't know how to do that.
> - if (CC == CallingConv::Fast && TM.Options.GuaranteedTailCallOpt)
> + if ((CC == CallingConv::Fast && TM.Options.GuaranteedTailCallOpt) ||
> + CC == CallingConv::Tail)
> return false;
>
> // Don't know how to handle Win64 varargs yet. Nothing special needed for
>
> Modified: llvm/trunk/lib/Target/X86/X86FrameLowering.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86FrameLowering.cpp?rev=373976&r1=373975&r2=373976&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Target/X86/X86FrameLowering.cpp (original)
> +++ llvm/trunk/lib/Target/X86/X86FrameLowering.cpp Mon Oct 7 15:28:58 2019
> @@ -2269,7 +2269,8 @@ GetScratchRegister(bool Is64Bit, bool Is
> bool IsNested = HasNestArgument(&MF);
>
> if (CallingConvention == CallingConv::X86_FastCall ||
> - CallingConvention == CallingConv::Fast) {
> + CallingConvention == CallingConv::Fast ||
> + CallingConvention == CallingConv::Tail) {
> if (IsNested)
> report_fatal_error("Segmented stacks does not support fastcall with "
> "nested function.");
>
> Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelLowering.cpp?rev=373976&r1=373975&r2=373976&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Target/X86/X86ISelLowering.cpp (original)
> +++ llvm/trunk/lib/Target/X86/X86ISelLowering.cpp Mon Oct 7 15:28:58 2019
> @@ -2963,7 +2963,7 @@ static SDValue CreateCopyOfByValArgument
> static bool canGuaranteeTCO(CallingConv::ID CC) {
> return (CC == CallingConv::Fast || CC == CallingConv::GHC ||
> CC == CallingConv::X86_RegCall || CC == CallingConv::HiPE ||
> - CC == CallingConv::HHVM);
> + CC == CallingConv::HHVM || CC == CallingConv::Tail);
> }
>
> /// Return true if we might ever do TCO for calls with this calling convention.
> @@ -2989,7 +2989,7 @@ static bool mayTailCallThisCC(CallingCon
> /// Return true if the function is being made into a tailcall target by
> /// changing its ABI.
> static bool shouldGuaranteeTCO(CallingConv::ID CC, bool GuaranteedTailCallOpt) {
> - return GuaranteedTailCallOpt && canGuaranteeTCO(CC);
> + return (GuaranteedTailCallOpt && canGuaranteeTCO(CC)) || CC == CallingConv::Tail;
> }
>
> bool X86TargetLowering::mayBeEmittedAsTailCall(const CallInst *CI) const {
> @@ -3615,6 +3615,8 @@ X86TargetLowering::LowerCall(TargetLower
> bool IsWin64 = Subtarget.isCallingConvWin64(CallConv);
> StructReturnType SR = callIsStructReturn(Outs, Subtarget.isTargetMCU());
> bool IsSibcall = false;
> + bool IsGuaranteeTCO = MF.getTarget().Options.GuaranteedTailCallOpt ||
> + CallConv == CallingConv::Tail;
> X86MachineFunctionInfo *X86Info = MF.getInfo<X86MachineFunctionInfo>();
> auto Attr = MF.getFunction().getFnAttribute("disable-tail-calls");
> const auto *CI = dyn_cast_or_null<CallInst>(CLI.CS.getInstruction());
> @@ -3635,8 +3637,7 @@ X86TargetLowering::LowerCall(TargetLower
> if (Attr.getValueAsString() == "true")
> isTailCall = false;
>
> - if (Subtarget.isPICStyleGOT() &&
> - !MF.getTarget().Options.GuaranteedTailCallOpt) {
> + if (Subtarget.isPICStyleGOT() && !IsGuaranteeTCO) {
> // If we are using a GOT, disable tail calls to external symbols with
> // default visibility. Tail calling such a symbol requires using a GOT
> // relocation, which forces early binding of the symbol. This breaks code
> @@ -3663,7 +3664,7 @@ X86TargetLowering::LowerCall(TargetLower
>
> // Sibcalls are automatically detected tailcalls which do not require
> // ABI changes.
> - if (!MF.getTarget().Options.GuaranteedTailCallOpt && isTailCall)
> + if (!IsGuaranteeTCO && isTailCall)
> IsSibcall = true;
>
> if (isTailCall)
> @@ -3695,8 +3696,7 @@ X86TargetLowering::LowerCall(TargetLower
> // This is a sibcall. The memory operands are available in caller's
> // own caller's stack.
> NumBytes = 0;
> - else if (MF.getTarget().Options.GuaranteedTailCallOpt &&
> - canGuaranteeTCO(CallConv))
> + else if (IsGuaranteeTCO && canGuaranteeTCO(CallConv))
> NumBytes = GetAlignedArgumentStackSize(NumBytes, DAG);
>
> int FPDiff = 0;
> @@ -4321,6 +4321,8 @@ bool X86TargetLowering::IsEligibleForTai
> bool CCMatch = CallerCC == CalleeCC;
> bool IsCalleeWin64 = Subtarget.isCallingConvWin64(CalleeCC);
> bool IsCallerWin64 = Subtarget.isCallingConvWin64(CallerCC);
> + bool IsGuaranteeTCO = DAG.getTarget().Options.GuaranteedTailCallOpt ||
> + CalleeCC == CallingConv::Tail;
>
> // Win64 functions have extra shadow space for argument homing. Don't do the
> // sibcall if the caller and callee have mismatched expectations for this
> @@ -4328,7 +4330,7 @@ bool X86TargetLowering::IsEligibleForTai
> if (IsCalleeWin64 != IsCallerWin64)
> return false;
>
> - if (DAG.getTarget().Options.GuaranteedTailCallOpt) {
> + if (IsGuaranteeTCO) {
> if (canGuaranteeTCO(CalleeCC) && CCMatch)
> return true;
> return false;
> @@ -24421,6 +24423,7 @@ SDValue X86TargetLowering::LowerINIT_TRA
> case CallingConv::X86_FastCall:
> case CallingConv::X86_ThisCall:
> case CallingConv::Fast:
> + case CallingConv::Tail:
> // Pass 'nest' parameter in EAX.
> // Must be kept in sync with X86CallingConv.td
> NestReg = X86::EAX;
>
> Modified: llvm/trunk/lib/Target/X86/X86Subtarget.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86Subtarget.h?rev=373976&r1=373975&r2=373976&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Target/X86/X86Subtarget.h (original)
> +++ llvm/trunk/lib/Target/X86/X86Subtarget.h Mon Oct 7 15:28:58 2019
> @@ -815,6 +815,7 @@ public:
> // On Win64, all these conventions just use the default convention.
> case CallingConv::C:
> case CallingConv::Fast:
> + case CallingConv::Tail:
> case CallingConv::Swift:
> case CallingConv::X86_FastCall:
> case CallingConv::X86_StdCall:
>
> Added: llvm/trunk/test/CodeGen/X86/musttail-tailcc.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/musttail-tailcc.ll?rev=373976&view=auto
> ==============================================================================
> --- llvm/trunk/test/CodeGen/X86/musttail-tailcc.ll (added)
> +++ llvm/trunk/test/CodeGen/X86/musttail-tailcc.ll Mon Oct 7 15:28:58 2019
> @@ -0,0 +1,114 @@
> +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
> +; RUN: llc < %s -mtriple=x86_64-unknown-unknown | FileCheck %s -check-prefix=X64
> +; RUN: llc < %s -mtriple=i686-unknown-unknown | FileCheck %s -check-prefix=X32
> +
> +; tailcc will turn all of these musttail calls into tail calls.
> +
> +declare tailcc i32 @tailcallee(i32 %a1, i32 %a2)
> +
> +define tailcc i32 @tailcaller(i32 %in1, i32 %in2) nounwind {
> +; X64-LABEL: tailcaller:
> +; X64: # %bb.0: # %entry
> +; X64-NEXT: pushq %rax
> +; X64-NEXT: popq %rax
> +; X64-NEXT: jmp tailcallee # TAILCALL
> +;
> +; X32-LABEL: tailcaller:
> +; X32: # %bb.0: # %entry
> +; X32-NEXT: jmp tailcallee # TAILCALL
> +entry:
> + %tmp11 = musttail call tailcc i32 @tailcallee(i32 %in1, i32 %in2)
> + ret i32 %tmp11
> +}
> +
> +declare tailcc i8* @alias_callee()
> +
> +define tailcc noalias i8* @noalias_caller() nounwind {
> +; X64-LABEL: noalias_caller:
> +; X64: # %bb.0:
> +; X64-NEXT: pushq %rax
> +; X64-NEXT: popq %rax
> +; X64-NEXT: jmp alias_callee # TAILCALL
> +;
> +; X32-LABEL: noalias_caller:
> +; X32: # %bb.0:
> +; X32-NEXT: jmp alias_callee # TAILCALL
> + %p = musttail call tailcc i8* @alias_callee()
> + ret i8* %p
> +}
> +
> +declare tailcc noalias i8* @noalias_callee()
> +
> +define tailcc i8* @alias_caller() nounwind {
> +; X64-LABEL: alias_caller:
> +; X64: # %bb.0:
> +; X64-NEXT: pushq %rax
> +; X64-NEXT: popq %rax
> +; X64-NEXT: jmp noalias_callee # TAILCALL
> +;
> +; X32-LABEL: alias_caller:
> +; X32: # %bb.0:
> +; X32-NEXT: jmp noalias_callee # TAILCALL
> + %p = musttail call tailcc noalias i8* @noalias_callee()
> + ret i8* %p
> +}
> +
> +define tailcc void @void_test(i32, i32, i32, i32) {
> +; X64-LABEL: void_test:
> +; X64: # %bb.0: # %entry
> +; X64-NEXT: pushq %rax
> +; X64-NEXT: .cfi_def_cfa_offset 16
> +; X64-NEXT: popq %rax
> +; X64-NEXT: .cfi_def_cfa_offset 8
> +; X64-NEXT: jmp void_test # TAILCALL
> +;
> +; X32-LABEL: void_test:
> +; X32: # %bb.0: # %entry
> +; X32-NEXT: pushl %esi
> +; X32-NEXT: .cfi_def_cfa_offset 8
> +; X32-NEXT: subl $8, %esp
> +; X32-NEXT: .cfi_def_cfa_offset 16
> +; X32-NEXT: .cfi_offset %esi, -8
> +; X32-NEXT: movl {{[0-9]+}}(%esp), %eax
> +; X32-NEXT: movl {{[0-9]+}}(%esp), %esi
> +; X32-NEXT: movl %esi, {{[0-9]+}}(%esp)
> +; X32-NEXT: movl %eax, {{[0-9]+}}(%esp)
> +; X32-NEXT: addl $8, %esp
> +; X32-NEXT: .cfi_def_cfa_offset 8
> +; X32-NEXT: popl %esi
> +; X32-NEXT: .cfi_def_cfa_offset 4
> +; X32-NEXT: jmp void_test # TAILCALL
> + entry:
> + musttail call tailcc void @void_test( i32 %0, i32 %1, i32 %2, i32 %3)
> + ret void
> +}
> +
> +define tailcc i1 @i1test(i32, i32, i32, i32) {
> +; X64-LABEL: i1test:
> +; X64: # %bb.0: # %entry
> +; X64-NEXT: pushq %rax
> +; X64-NEXT: .cfi_def_cfa_offset 16
> +; X64-NEXT: popq %rax
> +; X64-NEXT: .cfi_def_cfa_offset 8
> +; X64-NEXT: jmp i1test # TAILCALL
> +;
> +; X32-LABEL: i1test:
> +; X32: # %bb.0: # %entry
> +; X32-NEXT: pushl %esi
> +; X32-NEXT: .cfi_def_cfa_offset 8
> +; X32-NEXT: subl $8, %esp
> +; X32-NEXT: .cfi_def_cfa_offset 16
> +; X32-NEXT: .cfi_offset %esi, -8
> +; X32-NEXT: movl {{[0-9]+}}(%esp), %eax
> +; X32-NEXT: movl {{[0-9]+}}(%esp), %esi
> +; X32-NEXT: movl %esi, {{[0-9]+}}(%esp)
> +; X32-NEXT: movl %eax, {{[0-9]+}}(%esp)
> +; X32-NEXT: addl $8, %esp
> +; X32-NEXT: .cfi_def_cfa_offset 8
> +; X32-NEXT: popl %esi
> +; X32-NEXT: .cfi_def_cfa_offset 4
> +; X32-NEXT: jmp i1test # TAILCALL
> + entry:
> + %4 = musttail call tailcc i1 @i1test( i32 %0, i32 %1, i32 %2, i32 %3)
> + ret i1 %4
> +}
>
> Added: llvm/trunk/test/CodeGen/X86/tailcall-tailcc.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/tailcall-tailcc.ll?rev=373976&view=auto
> ==============================================================================
> --- llvm/trunk/test/CodeGen/X86/tailcall-tailcc.ll (added)
> +++ llvm/trunk/test/CodeGen/X86/tailcall-tailcc.ll Mon Oct 7 15:28:58 2019
> @@ -0,0 +1,155 @@
> +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
> +; RUN: llc < %s -mtriple=x86_64-unknown-unknown | FileCheck %s -check-prefix=X64
> +; RUN: llc < %s -mtriple=i686-unknown-unknown | FileCheck %s -check-prefix=X32
> +
> +; With -tailcallopt, CodeGen guarantees a tail call optimization
> +; for all of these.
> +
> +declare tailcc i32 @tailcallee(i32 %a1, i32 %a2, i32 %a3, i32 %a4)
> +
> +define tailcc i32 @tailcaller(i32 %in1, i32 %in2) nounwind {
> +; X64-LABEL: tailcaller:
> +; X64: # %bb.0: # %entry
> +; X64-NEXT: pushq %rax
> +; X64-NEXT: movl %edi, %edx
> +; X64-NEXT: movl %esi, %ecx
> +; X64-NEXT: popq %rax
> +; X64-NEXT: jmp tailcallee # TAILCALL
> +;
> +; X32-LABEL: tailcaller:
> +; X32: # %bb.0: # %entry
> +; X32-NEXT: subl $16, %esp
> +; X32-NEXT: movl %ecx, {{[0-9]+}}(%esp)
> +; X32-NEXT: movl {{[0-9]+}}(%esp), %eax
> +; X32-NEXT: movl %edx, {{[0-9]+}}(%esp)
> +; X32-NEXT: movl %eax, {{[0-9]+}}(%esp)
> +; X32-NEXT: addl $8, %esp
> +; X32-NEXT: jmp tailcallee # TAILCALL
> +entry:
> + %tmp11 = tail call tailcc i32 @tailcallee(i32 %in1, i32 %in2, i32 %in1, i32 %in2)
> + ret i32 %tmp11
> +}
> +
> +declare tailcc i8* @alias_callee()
> +
> +define tailcc noalias i8* @noalias_caller() nounwind {
> +; X64-LABEL: noalias_caller:
> +; X64: # %bb.0:
> +; X64-NEXT: pushq %rax
> +; X64-NEXT: popq %rax
> +; X64-NEXT: jmp alias_callee # TAILCALL
> +;
> +; X32-LABEL: noalias_caller:
> +; X32: # %bb.0:
> +; X32-NEXT: jmp alias_callee # TAILCALL
> + %p = tail call tailcc i8* @alias_callee()
> + ret i8* %p
> +}
> +
> +declare tailcc noalias i8* @noalias_callee()
> +
> +define tailcc i8* @alias_caller() nounwind {
> +; X64-LABEL: alias_caller:
> +; X64: # %bb.0:
> +; X64-NEXT: pushq %rax
> +; X64-NEXT: popq %rax
> +; X64-NEXT: jmp noalias_callee # TAILCALL
> +;
> +; X32-LABEL: alias_caller:
> +; X32: # %bb.0:
> +; X32-NEXT: jmp noalias_callee # TAILCALL
> + %p = tail call tailcc noalias i8* @noalias_callee()
> + ret i8* %p
> +}
> +
> +declare tailcc i32 @i32_callee()
> +
> +define tailcc i32 @ret_undef() nounwind {
> +; X64-LABEL: ret_undef:
> +; X64: # %bb.0:
> +; X64-NEXT: pushq %rax
> +; X64-NEXT: popq %rax
> +; X64-NEXT: jmp i32_callee # TAILCALL
> +;
> +; X32-LABEL: ret_undef:
> +; X32: # %bb.0:
> +; X32-NEXT: jmp i32_callee # TAILCALL
> + %p = tail call tailcc i32 @i32_callee()
> + ret i32 undef
> +}
> +
> +declare tailcc void @does_not_return()
> +
> +define tailcc i32 @noret() nounwind {
> +; X64-LABEL: noret:
> +; X64: # %bb.0:
> +; X64-NEXT: pushq %rax
> +; X64-NEXT: popq %rax
> +; X64-NEXT: jmp does_not_return # TAILCALL
> +;
> +; X32-LABEL: noret:
> +; X32: # %bb.0:
> +; X32-NEXT: jmp does_not_return # TAILCALL
> + tail call tailcc void @does_not_return()
> + unreachable
> +}
> +
> +define tailcc void @void_test(i32, i32, i32, i32) {
> +; X64-LABEL: void_test:
> +; X64: # %bb.0: # %entry
> +; X64-NEXT: pushq %rax
> +; X64-NEXT: .cfi_def_cfa_offset 16
> +; X64-NEXT: popq %rax
> +; X64-NEXT: .cfi_def_cfa_offset 8
> +; X64-NEXT: jmp void_test # TAILCALL
> +;
> +; X32-LABEL: void_test:
> +; X32: # %bb.0: # %entry
> +; X32-NEXT: pushl %esi
> +; X32-NEXT: .cfi_def_cfa_offset 8
> +; X32-NEXT: subl $8, %esp
> +; X32-NEXT: .cfi_def_cfa_offset 16
> +; X32-NEXT: .cfi_offset %esi, -8
> +; X32-NEXT: movl {{[0-9]+}}(%esp), %eax
> +; X32-NEXT: movl {{[0-9]+}}(%esp), %esi
> +; X32-NEXT: movl %esi, {{[0-9]+}}(%esp)
> +; X32-NEXT: movl %eax, {{[0-9]+}}(%esp)
> +; X32-NEXT: addl $8, %esp
> +; X32-NEXT: .cfi_def_cfa_offset 8
> +; X32-NEXT: popl %esi
> +; X32-NEXT: .cfi_def_cfa_offset 4
> +; X32-NEXT: jmp void_test # TAILCALL
> + entry:
> + tail call tailcc void @void_test( i32 %0, i32 %1, i32 %2, i32 %3)
> + ret void
> +}
> +
> +define tailcc i1 @i1test(i32, i32, i32, i32) {
> +; X64-LABEL: i1test:
> +; X64: # %bb.0: # %entry
> +; X64-NEXT: pushq %rax
> +; X64-NEXT: .cfi_def_cfa_offset 16
> +; X64-NEXT: popq %rax
> +; X64-NEXT: .cfi_def_cfa_offset 8
> +; X64-NEXT: jmp i1test # TAILCALL
> +;
> +; X32-LABEL: i1test:
> +; X32: # %bb.0: # %entry
> +; X32-NEXT: pushl %esi
> +; X32-NEXT: .cfi_def_cfa_offset 8
> +; X32-NEXT: subl $8, %esp
> +; X32-NEXT: .cfi_def_cfa_offset 16
> +; X32-NEXT: .cfi_offset %esi, -8
> +; X32-NEXT: movl {{[0-9]+}}(%esp), %eax
> +; X32-NEXT: movl {{[0-9]+}}(%esp), %esi
> +; X32-NEXT: movl %esi, {{[0-9]+}}(%esp)
> +; X32-NEXT: movl %eax, {{[0-9]+}}(%esp)
> +; X32-NEXT: addl $8, %esp
> +; X32-NEXT: .cfi_def_cfa_offset 8
> +; X32-NEXT: popl %esi
> +; X32-NEXT: .cfi_def_cfa_offset 4
> +; X32-NEXT: jmp i1test # TAILCALL
> + entry:
> + %4 = tail call tailcc i1 @i1test( i32 %0, i32 %1, i32 %2, i32 %3)
> + ret i1 %4
> +}
>
> Added: llvm/trunk/test/CodeGen/X86/tailcc-calleesave.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/tailcc-calleesave.ll?rev=373976&view=auto
> ==============================================================================
> --- llvm/trunk/test/CodeGen/X86/tailcc-calleesave.ll (added)
> +++ llvm/trunk/test/CodeGen/X86/tailcc-calleesave.ll Mon Oct 7 15:28:58 2019
> @@ -0,0 +1,19 @@
> +; RUN: llc -mcpu=core < %s | FileCheck %s
> +
> +target triple = "i686-apple-darwin"
> +
> +declare tailcc void @foo(i32, i32, i32, i32, i32, i32)
> +declare i32* @bar(i32*)
> +
> +define tailcc void @hoge(i32 %b) nounwind {
> +; Do not overwrite pushed callee-save registers
> +; CHECK: pushl
> +; CHECK: subl $[[SIZE:[0-9]+]], %esp
> +; CHECK-NOT: [[SIZE]](%esp)
> + %a = alloca i32
> + store i32 0, i32* %a
> + %d = tail call i32* @bar(i32* %a) nounwind
> + store i32 %b, i32* %d
> + tail call tailcc void @foo(i32 1, i32 2, i32 3, i32 4, i32 5, i32 6) nounwind
> + ret void
> +}
>
> Added: llvm/trunk/test/CodeGen/X86/tailcc-disable-tail-calls.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/tailcc-disable-tail-calls.ll?rev=373976&view=auto
> ==============================================================================
> --- llvm/trunk/test/CodeGen/X86/tailcc-disable-tail-calls.ll (added)
> +++ llvm/trunk/test/CodeGen/X86/tailcc-disable-tail-calls.ll Mon Oct 7 15:28:58 2019
> @@ -0,0 +1,40 @@
> +; RUN: llc < %s -mtriple=x86_64-- | FileCheck %s --check-prefix=NO-OPTION
> +; RUN: llc < %s -mtriple=x86_64-- -disable-tail-calls | FileCheck %s --check-prefix=DISABLE-TRUE
> +; RUN: llc < %s -mtriple=x86_64-- -disable-tail-calls=false | FileCheck %s --check-prefix=DISABLE-FALSE
> +
> +; Check that command line option "-disable-tail-calls" overrides function
> +; attribute "disable-tail-calls".
> +
> +; NO-OPTION-LABEL: {{\_?}}func_attr
> +; NO-OPTION: callq {{\_?}}callee
> +
> +; DISABLE-FALSE-LABEL: {{\_?}}func_attr
> +; DISABLE-FALSE: jmp {{\_?}}callee
> +
> +; DISABLE-TRUE-LABEL: {{\_?}}func_attr
> +; DISABLE-TRUE: callq {{\_?}}callee
> +
> +define tailcc i32 @func_attr(i32 %a) #0 {
> +entry:
> + %call = tail call tailcc i32 @callee(i32 %a)
> + ret i32 %call
> +}
> +
> +; NO-OPTION-LABEL: {{\_?}}func_noattr
> +; NO-OPTION: jmp {{\_?}}callee
> +
> +; DISABLE-FALSE-LABEL: {{\_?}}func_noattr
> +; DISABLE-FALSE: jmp {{\_?}}callee
> +
> +; DISABLE-TRUE-LABEL: {{\_?}}func_noattr
> +; DISABLE-TRUE: callq {{\_?}}callee
> +
> +define tailcc i32 @func_noattr(i32 %a) {
> +entry:
> + %call = tail call tailcc i32 @callee(i32 %a)
> + ret i32 %call
> +}
> +
> +declare tailcc i32 @callee(i32)
> +
> +attributes #0 = { "disable-tail-calls"="true" }
>
> Added: llvm/trunk/test/CodeGen/X86/tailcc-fastcc.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/tailcc-fastcc.ll?rev=373976&view=auto
> ==============================================================================
> --- llvm/trunk/test/CodeGen/X86/tailcc-fastcc.ll (added)
> +++ llvm/trunk/test/CodeGen/X86/tailcc-fastcc.ll Mon Oct 7 15:28:58 2019
> @@ -0,0 +1,49 @@
> +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
> +; RUN: llc -tailcallopt < %s -mtriple=x86_64-unknown-unknown | FileCheck %s -check-prefix=X64
> +; RUN: llc -tailcallopt < %s -mtriple=i686-unknown-unknown | FileCheck %s -check-prefix=X32
> +
> +; llc -tailcallopt should not enable tail calls from fastcc to tailcc or vice versa
> +
> +declare tailcc i32 @tailcallee1(i32 %a1, i32 %a2, i32 %a3, i32 %a4)
> +
> +define fastcc i32 @tailcaller1(i32 %in1, i32 %in2) nounwind {
> +; X64-LABEL: tailcaller1:
> +; X64: # %bb.0: # %entry
> +; X64-NEXT: pushq %rax
> +; X64-NEXT: movl %edi, %edx
> +; X64-NEXT: movl %esi, %ecx
> +; X64-NEXT: callq tailcallee1
> +; X64-NEXT: retq $8
> +;
> +; X32-LABEL: tailcaller1:
> +; X32: # %bb.0: # %entry
> +; X32-NEXT: pushl %edx
> +; X32-NEXT: pushl %ecx
> +; X32-NEXT: calll tailcallee1
> +; X32-NEXT: retl
> +entry:
> + %tmp11 = tail call tailcc i32 @tailcallee1(i32 %in1, i32 %in2, i32 %in1, i32 %in2)
> + ret i32 %tmp11
> +}
> +
> +declare fastcc i32 @tailcallee2(i32 %a1, i32 %a2, i32 %a3, i32 %a4)
> +
> +define tailcc i32 @tailcaller2(i32 %in1, i32 %in2) nounwind {
> +; X64-LABEL: tailcaller2:
> +; X64: # %bb.0: # %entry
> +; X64-NEXT: pushq %rax
> +; X64-NEXT: movl %edi, %edx
> +; X64-NEXT: movl %esi, %ecx
> +; X64-NEXT: callq tailcallee2
> +; X64-NEXT: retq $8
> +;
> +; X32-LABEL: tailcaller2:
> +; X32: # %bb.0: # %entry
> +; X32-NEXT: pushl %edx
> +; X32-NEXT: pushl %ecx
> +; X32-NEXT: calll tailcallee2
> +; X32-NEXT: retl
> +entry:
> + %tmp11 = tail call fastcc i32 @tailcallee2(i32 %in1, i32 %in2, i32 %in1, i32 %in2)
> + ret i32 %tmp11
> +}
>
> Added: llvm/trunk/test/CodeGen/X86/tailcc-fastisel.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/tailcc-fastisel.ll?rev=373976&view=auto
> ==============================================================================
> --- llvm/trunk/test/CodeGen/X86/tailcc-fastisel.ll (added)
> +++ llvm/trunk/test/CodeGen/X86/tailcc-fastisel.ll Mon Oct 7 15:28:58 2019
> @@ -0,0 +1,18 @@
> +; RUN: llc < %s -mtriple=x86_64-apple-darwin -fast-isel -fast-isel-abort=1 | FileCheck %s
> +
> +%0 = type { i64, i32, i8* }
> +
> +define tailcc i8* @"visit_array_aux<`Reference>"(%0 %arg, i32 %arg1) nounwind {
> +fail: ; preds = %entry
> + %tmp20 = tail call tailcc i8* @"visit_array_aux<`Reference>"(%0 %arg, i32 undef) ; <i8*> [#uses=1]
> +; CHECK: jmp "_visit_array_aux<`Reference>" ## TAILCALL
> + ret i8* %tmp20
> +}
> +
> +define i32 @foo() nounwind {
> +entry:
> + %0 = tail call i32 (...) @bar() nounwind ; <i32> [#uses=1]
> + ret i32 %0
> +}
> +
> +declare i32 @bar(...) nounwind
>
> Added: llvm/trunk/test/CodeGen/X86/tailcc-largecode.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/tailcc-largecode.ll?rev=373976&view=auto
> ==============================================================================
> --- llvm/trunk/test/CodeGen/X86/tailcc-largecode.ll (added)
> +++ llvm/trunk/test/CodeGen/X86/tailcc-largecode.ll Mon Oct 7 15:28:58 2019
> @@ -0,0 +1,71 @@
> +; RUN: llc < %s -mtriple=x86_64-linux-gnu -code-model=large -enable-misched=false | FileCheck %s
> +
> +declare tailcc i32 @callee(i32 %arg)
> +define tailcc i32 @directcall(i32 %arg) {
> +entry:
> +; This is the large code model, so &callee may not fit into the jmp
> +; instruction. Instead, stick it into a register.
> +; CHECK: movabsq $callee, [[REGISTER:%r[a-z0-9]+]]
> +; CHECK: jmpq *[[REGISTER]] # TAILCALL
> + %res = tail call tailcc i32 @callee(i32 %arg)
> + ret i32 %res
> +}
> +
> +; Check that the register used for an indirect tail call doesn't
> +; clobber any of the arguments.
> +define tailcc i32 @indirect_manyargs(i32(i32,i32,i32,i32,i32,i32,i32)* %target) {
> +; Adjust the stack to enter the function. (The amount of the
> +; adjustment may change in the future, in which case the location of
> +; the stack argument and the return adjustment will change too.)
> +; CHECK: pushq
> +; Put the call target into R11, which won't be clobbered while restoring
> +; callee-saved registers and won't be used for passing arguments.
> +; CHECK: movq %rdi, %rax
> +; Pass the stack argument.
> +; CHECK: movl $7, 16(%rsp)
> +; Pass the register arguments, in the right registers.
> +; CHECK: movl $1, %edi
> +; CHECK: movl $2, %esi
> +; CHECK: movl $3, %edx
> +; CHECK: movl $4, %ecx
> +; CHECK: movl $5, %r8d
> +; CHECK: movl $6, %r9d
> +; Adjust the stack to "return".
> +; CHECK: popq
> +; And tail-call to the target.
> +; CHECK: jmpq *%rax # TAILCALL
> + %res = tail call tailcc i32 %target(i32 1, i32 2, i32 3, i32 4, i32 5,
> + i32 6, i32 7)
> + ret i32 %res
> +}
> +
> +; Check that the register used for a direct tail call doesn't clobber
> +; any of the arguments.
> +declare tailcc i32 @manyargs_callee(i32,i32,i32,i32,i32,i32,i32)
> +define tailcc i32 @direct_manyargs() {
> +; Adjust the stack to enter the function. (The amount of the
> +; adjustment may change in the future, in which case the location of
> +; the stack argument and the return adjustment will change too.)
> +; CHECK: pushq
> +; Pass the stack argument.
> +; CHECK: movl $7, 16(%rsp)
> +; This is the large code model, so &manyargs_callee may not fit into
> +; the jmp instruction. Put it into a register which won't be clobbered
> +; while restoring callee-saved registers and won't be used for passing
> +; arguments.
> +; CHECK: movabsq $manyargs_callee, %rax
> +; Pass the register arguments, in the right registers.
> +; CHECK: movl $1, %edi
> +; CHECK: movl $2, %esi
> +; CHECK: movl $3, %edx
> +; CHECK: movl $4, %ecx
> +; CHECK: movl $5, %r8d
> +; CHECK: movl $6, %r9d
> +; Adjust the stack to "return".
> +; CHECK: popq
> +; And tail-call to the target.
> +; CHECK: jmpq *%rax # TAILCALL
> + %res = tail call tailcc i32 @manyargs_callee(i32 1, i32 2, i32 3, i32 4,
> + i32 5, i32 6, i32 7)
> + ret i32 %res
> +}
>
> Added: llvm/trunk/test/CodeGen/X86/tailcc-stackalign.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/tailcc-stackalign.ll?rev=373976&view=auto
> ==============================================================================
> --- llvm/trunk/test/CodeGen/X86/tailcc-stackalign.ll (added)
> +++ llvm/trunk/test/CodeGen/X86/tailcc-stackalign.ll Mon Oct 7 15:28:58 2019
> @@ -0,0 +1,23 @@
> +; RUN: llc < %s -mtriple=i686-unknown-linux -no-x86-call-frame-opt | FileCheck %s
> +; Linux has 8 byte alignment so the params cause stack size 20,
> +; ensure that a normal tailcc call has matching stack size
> +
> +
> +define tailcc i32 @tailcallee(i32 %a1, i32 %a2, i32 %a3, i32 %a4) {
> + ret i32 %a3
> +}
> +
> +define tailcc i32 @tailcaller(i32 %in1, i32 %in2, i32 %in3, i32 %in4) {
> + %tmp11 = tail call tailcc i32 @tailcallee(i32 %in1, i32 %in2,
> + i32 %in1, i32 %in2)
> + ret i32 %tmp11
> +}
> +
> +define i32 @main(i32 %argc, i8** %argv) {
> + %tmp1 = call tailcc i32 @tailcaller( i32 1, i32 2, i32 3, i32 4 )
> + ; expect match subl [stacksize] here
> + ret i32 0
> +}
> +
> +; CHECK: calll tailcaller
> +; CHECK-NEXT: subl $12
>
> Added: llvm/trunk/test/CodeGen/X86/tailcc-structret.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/tailcc-structret.ll?rev=373976&view=auto
> ==============================================================================
> --- llvm/trunk/test/CodeGen/X86/tailcc-structret.ll (added)
> +++ llvm/trunk/test/CodeGen/X86/tailcc-structret.ll Mon Oct 7 15:28:58 2019
> @@ -0,0 +1,7 @@
> +; RUN: llc < %s -mtriple=i686-unknown-linux | FileCheck %s
> +define tailcc { { i8*, i8* }*, i8*} @init({ { i8*, i8* }*, i8*}, i32) {
> +entry:
> + %2 = tail call tailcc { { i8*, i8* }*, i8* } @init({ { i8*, i8*}*, i8*} %0, i32 %1)
> + ret { { i8*, i8* }*, i8*} %2
> +; CHECK: jmp init
> +}
>
> Added: llvm/trunk/test/CodeGen/X86/tailccbyval.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/tailccbyval.ll?rev=373976&view=auto
> ==============================================================================
> --- llvm/trunk/test/CodeGen/X86/tailccbyval.ll (added)
> +++ llvm/trunk/test/CodeGen/X86/tailccbyval.ll Mon Oct 7 15:28:58 2019
> @@ -0,0 +1,21 @@
> +; RUN: llc < %s -mtriple=i686-unknown-linux | FileCheck %s
> +%struct.s = type {i32, i32, i32, i32, i32, i32, i32, i32,
> + i32, i32, i32, i32, i32, i32, i32, i32,
> + i32, i32, i32, i32, i32, i32, i32, i32 }
> +
> +define tailcc i32 @tailcallee(%struct.s* byval %a) nounwind {
> +entry:
> + %tmp2 = getelementptr %struct.s, %struct.s* %a, i32 0, i32 0
> + %tmp3 = load i32, i32* %tmp2
> + ret i32 %tmp3
> +; CHECK: tailcallee
> +; CHECK: movl 4(%esp), %eax
> +}
> +
> +define tailcc i32 @tailcaller(%struct.s* byval %a) nounwind {
> +entry:
> + %tmp4 = tail call tailcc i32 @tailcallee(%struct.s* byval %a )
> + ret i32 %tmp4
> +; CHECK: tailcaller
> +; CHECK: jmp tailcallee
> +}
>
> Added: llvm/trunk/test/CodeGen/X86/tailccbyval64.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/tailccbyval64.ll?rev=373976&view=auto
> ==============================================================================
> --- llvm/trunk/test/CodeGen/X86/tailccbyval64.ll (added)
> +++ llvm/trunk/test/CodeGen/X86/tailccbyval64.ll Mon Oct 7 15:28:58 2019
> @@ -0,0 +1,42 @@
> +; RUN: llc < %s -mcpu=generic -mtriple=x86_64-linux | FileCheck %s
> +
> +; FIXME: Win64 does not support byval.
> +
> +; Expect the entry point.
> +; CHECK-LABEL: tailcaller:
> +
> +; Expect 2 rep;movs because of tail call byval lowering.
> +; CHECK: rep;
> +; CHECK: rep;
> +
> +; A sequence of copyto/copyfrom virtual registers is used to deal with byval
> +; lowering appearing after moving arguments to registers. The following two
> +; checks verify that the register allocator changes those sequences to direct
> +; moves to argument register where it can (for registers that are not used in
> +; byval lowering - not rsi, not rdi, not rcx).
> +; Expect argument 4 to be moved directly to register edx.
> +; CHECK: movl $7, %edx
> +
> +; Expect argument 6 to be moved directly to register r8.
> +; CHECK: movl $17, %r8d
> +
> +; Expect not call but jmp to @tailcallee.
> +; CHECK: jmp tailcallee
> +
> +; Expect the trailer.
> +; CHECK: .size tailcaller
> +
> +%struct.s = type { i64, i64, i64, i64, i64, i64, i64, i64,
> + i64, i64, i64, i64, i64, i64, i64, i64,
> + i64, i64, i64, i64, i64, i64, i64, i64 }
> +
> +declare tailcc i64 @tailcallee(%struct.s* byval %a, i64 %val, i64 %val2, i64 %val3, i64 %val4, i64 %val5)
> +
> +
> +define tailcc i64 @tailcaller(i64 %b, %struct.s* byval %a) {
> +entry:
> + %tmp2 = getelementptr %struct.s, %struct.s* %a, i32 0, i32 1
> + %tmp3 = load i64, i64* %tmp2, align 8
> + %tmp4 = tail call tailcc i64 @tailcallee(%struct.s* byval %a , i64 %tmp3, i64 %b, i64 7, i64 13, i64 17)
> + ret i64 %tmp4
> +}
>
> Added: llvm/trunk/test/CodeGen/X86/tailccfp.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/tailccfp.ll?rev=373976&view=auto
> ==============================================================================
> --- llvm/trunk/test/CodeGen/X86/tailccfp.ll (added)
> +++ llvm/trunk/test/CodeGen/X86/tailccfp.ll Mon Oct 7 15:28:58 2019
> @@ -0,0 +1,6 @@
> +; RUN: llc < %s -mtriple=i686-- | FileCheck %s
> +define tailcc i32 @bar(i32 %X, i32(double, i32) *%FP) {
> + %Y = tail call tailcc i32 %FP(double 0.0, i32 %X)
> + ret i32 %Y
> +; CHECK: jmpl
> +}
>
> Added: llvm/trunk/test/CodeGen/X86/tailccfp2.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/tailccfp2.ll?rev=373976&view=auto
> ==============================================================================
> --- llvm/trunk/test/CodeGen/X86/tailccfp2.ll (added)
> +++ llvm/trunk/test/CodeGen/X86/tailccfp2.ll Mon Oct 7 15:28:58 2019
> @@ -0,0 +1,27 @@
> +; RUN: llc < %s -mtriple=i686-- | FileCheck %s
> +
> +declare i32 @putchar(i32)
> +
> +define tailcc i32 @checktail(i32 %x, i32* %f, i32 %g) nounwind {
> +; CHECK-LABEL: checktail:
> + %tmp1 = icmp sgt i32 %x, 0
> + br i1 %tmp1, label %if-then, label %if-else
> +
> +if-then:
> + %fun_ptr = bitcast i32* %f to i32(i32, i32*, i32)*
> + %arg1 = add i32 %x, -1
> + call i32 @putchar(i32 90)
> +; CHECK: jmpl *%e{{.*}}
> + %res = tail call tailcc i32 %fun_ptr( i32 %arg1, i32 * %f, i32 %g)
> + ret i32 %res
> +
> +if-else:
> + ret i32 %x
> +}
> +
> +
> +define i32 @main() nounwind {
> + %f = bitcast i32 (i32, i32*, i32)* @checktail to i32*
> + %res = tail call tailcc i32 @checktail( i32 10, i32* %f,i32 10)
> + ret i32 %res
> +}
>
> Added: llvm/trunk/test/CodeGen/X86/tailccpic1.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/tailccpic1.ll?rev=373976&view=auto
> ==============================================================================
> --- llvm/trunk/test/CodeGen/X86/tailccpic1.ll (added)
> +++ llvm/trunk/test/CodeGen/X86/tailccpic1.ll Mon Oct 7 15:28:58 2019
> @@ -0,0 +1,16 @@
> +; RUN: llc < %s -mtriple=i686-pc-linux-gnu -relocation-model=pic | FileCheck %s
> +
> +; This test uses guaranteed TCO so these will be tail calls, despite the early
> +; binding issues.
> +
> +define protected tailcc i32 @tailcallee(i32 %a1, i32 %a2, i32 %a3, i32 %a4) {
> +entry:
> + ret i32 %a3
> +}
> +
> +define tailcc i32 @tailcaller(i32 %in1, i32 %in2) {
> +entry:
> + %tmp11 = tail call tailcc i32 @tailcallee( i32 %in1, i32 %in2, i32 %in1, i32 %in2 ) ; <i32> [#uses=1]
> + ret i32 %tmp11
> +; CHECK: jmp tailcallee
> +}
>
> Added: llvm/trunk/test/CodeGen/X86/tailccpic2.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/tailccpic2.ll?rev=373976&view=auto
> ==============================================================================
> --- llvm/trunk/test/CodeGen/X86/tailccpic2.ll (added)
> +++ llvm/trunk/test/CodeGen/X86/tailccpic2.ll Mon Oct 7 15:28:58 2019
> @@ -0,0 +1,15 @@
> +; RUN: llc < %s -mtriple=i686-pc-linux-gnu -relocation-model=pic | FileCheck %s
> +
> +define tailcc i32 @tailcallee(i32 %a1, i32 %a2, i32 %a3, i32 %a4) {
> +entry:
> + ret i32 %a3
> +}
> +
> +define tailcc i32 @tailcaller(i32 %in1, i32 %in2) {
> +entry:
> + %tmp11 = tail call tailcc i32 @tailcallee( i32 %in1, i32 %in2, i32 %in1, i32 %in2 ) ; <i32> [#uses=1]
> + ret i32 %tmp11
> +; CHECK: movl tailcallee at GOT
> +; CHECK: jmpl
> +}
> +
>
> Added: llvm/trunk/test/CodeGen/X86/tailccstack64.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/tailccstack64.ll?rev=373976&view=auto
> ==============================================================================
> --- llvm/trunk/test/CodeGen/X86/tailccstack64.ll (added)
> +++ llvm/trunk/test/CodeGen/X86/tailccstack64.ll Mon Oct 7 15:28:58 2019
> @@ -0,0 +1,28 @@
> +; RUN: llc < %s -mcpu=generic -mtriple=x86_64-linux -post-RA-scheduler=true | FileCheck %s
> +; RUN: llc < %s -mcpu=generic -mtriple=x86_64-win32 -post-RA-scheduler=true | FileCheck %s
> +
> +; FIXME: Redundant unused stack allocation could be eliminated.
> +; CHECK: subq ${{24|72|80}}, %rsp
> +
> +; Check that lowered arguments on the stack do not overwrite each other.
> +; Add %in1 %p1 to a different temporary register (%eax).
> +; CHECK: movl [[A1:32|144]](%rsp), [[R1:%e..]]
> +; Move param %in1 to temp register (%r10d).
> +; CHECK: movl [[A2:40|152]](%rsp), [[R2:%[a-z0-9]+]]
> +; Add %in1 %p1 to a different temporary register (%eax).
> +; CHECK: addl {{%edi|%ecx}}, [[R1]]
> +; Move param %in2 to stack.
> +; CHECK-DAG: movl [[R2]], [[A1]](%rsp)
> +; Move result of addition to stack.
> +; CHECK-DAG: movl [[R1]], [[A2]](%rsp)
> +; Eventually, do a TAILCALL
> +; CHECK: TAILCALL
> +
> +declare tailcc i32 @tailcallee(i32 %p1, i32 %p2, i32 %p3, i32 %p4, i32 %p5, i32 %p6, i32 %a, i32 %b) nounwind
> +
> +define tailcc i32 @tailcaller(i32 %p1, i32 %p2, i32 %p3, i32 %p4, i32 %p5, i32 %p6, i32 %in1, i32 %in2) nounwind {
> +entry:
> + %tmp = add i32 %in1, %p1
> + %retval = tail call tailcc i32 @tailcallee(i32 %p1, i32 %p2, i32 %p3, i32 %p4, i32 %p5, i32 %p6, i32 %in2,i32 %tmp)
> + ret i32 %retval
> +}
>
> Modified: llvm/trunk/utils/vim/syntax/llvm.vim
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/vim/syntax/llvm.vim?rev=373976&r1=373975&r2=373976&view=diff
> ==============================================================================
> --- llvm/trunk/utils/vim/syntax/llvm.vim (original)
> +++ llvm/trunk/utils/vim/syntax/llvm.vim Mon Oct 7 15:28:58 2019
> @@ -82,6 +82,7 @@ syn keyword llvmKeyword
> \ externally_initialized
> \ extern_weak
> \ fastcc
> + \ tailcc
> \ filter
> \ from
> \ gc
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
More information about the llvm-commits
mailing list