Index: docs/LangRef.rst =================================================================== --- docs/LangRef.rst +++ docs/LangRef.rst @@ -6161,7 +6161,7 @@ :: - = [tail] call [cconv] [ret attrs] [*] () [fn attrs] + = [tail | musttail] call [cconv] [ret attrs] [*] () [fn attrs] Overview: """"""""" @@ -6173,17 +6173,38 @@ This instruction requires several arguments: -#. The optional "tail" marker indicates that the callee function does - not access any allocas or varargs in the caller. Note that calls may - be marked "tail" even if they do not occur before a - :ref:`ret ` instruction. If the "tail" marker is present, the - function call is eligible for tail call optimization, but `might not - in fact be optimized into a jump `_. - The code generator may optimize calls marked "tail" with either 1) - automatic `sibling call - optimization `_ when the caller and - callee have matching signatures, or 2) forced tail call optimization - when the following extra requirements are met: +#. The optional ``tail`` and ``musttail`` markers indicate that the optimizers + should perform tail call optimization. The ``tail`` marker is a hint that + `can be ignored `_. The ``musttail`` marker + means that the call must be tail call optimized in order for the program to + be correct. The ``musttail`` marker provides these guarantees: + + #. The call will not cause unbounded stack growth. + #. The callee may access variadic arguments of the caller. + #. Arguments with the :ref:`inalloca ` attribute are + forwarded in place. + + In particular, the inliner is only allowed to inline a ``musttail`` call or + a function containing ``musttail`` call sites if it can preserve these + guarantees. + + Both markers imply that the callee does not access allocas or varargs from + the caller. Calls marked ``musttail`` must obey the following additional + rules: + + - The call must immediately precede a :ref:`ret ` instruction, + or a pointer bitcast followed by a ret instruction. + - The ret instruction must return the (possibly bitcasted) value + produced by the call or void. + - The caller and callee prototypes must match. Pointer types of + parameters or return types may differ in pointee type, but not + in address space. + - The calling conventions of the caller and callee must match. + - All ABI-impacting function attributes, such as sret, byval, inreg, + returned, and inalloca, must match. + + 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``. - The call is in tail position (ret immediately follows call and ret Index: include/llvm/Bitcode/LLVMBitCodes.h =================================================================== --- include/llvm/Bitcode/LLVMBitCodes.h +++ include/llvm/Bitcode/LLVMBitCodes.h @@ -311,7 +311,7 @@ // 32 is unused. FUNC_CODE_DEBUG_LOC_AGAIN = 33, // DEBUG_LOC_AGAIN - FUNC_CODE_INST_CALL = 34, // CALL: [attr, fnty, fnid, args...] + FUNC_CODE_INST_CALL = 34, // CALL: [attr, cc, fnty, fnid, args...] FUNC_CODE_DEBUG_LOC = 35, // DEBUG_LOC: [Line,Col,ScopeVal, IAVal] FUNC_CODE_INST_FENCE = 36, // FENCE: [ordering, synchscope] Index: include/llvm/IR/CallSite.h =================================================================== --- include/llvm/IR/CallSite.h +++ include/llvm/IR/CallSite.h @@ -160,6 +160,15 @@ /// FunTy *getCaller() const { return (*this)->getParent()->getParent(); } + /// \brief Tests if this is a tail call. Only a CallInst can be a tail call. + bool isTailCall() const { return isCall() && cast->isTailCall(); } + + /// \brief Tests if this call site must be tail call optimized. Only a + /// CallInst can be tail call optimized. + bool isMustTailCall() const { + return isCall() && cast(getInstruction())->isMustTailCall(); + } + #define CALLSITE_DELEGATE_GETTER(METHOD) \ InstrTy *II = getInstruction(); \ return isCall() \ Index: include/llvm/IR/Instructions.h =================================================================== --- include/llvm/IR/Instructions.h +++ include/llvm/IR/Instructions.h @@ -1220,14 +1220,19 @@ void init(Value *Func, ArrayRef Args, const Twine &NameStr); void init(Value *Func, const Twine &NameStr); +public: + // Note that 'musttail' implies 'tail'. + enum TailCallKind { TCK_None = 0, TCK_Tail = 1, TCK_MustTail = 2 }; +private: + /// Construct a CallInst given a range of arguments. /// \brief Construct a CallInst from a range of arguments - inline CallInst(Value *Func, ArrayRef Args, + inline CallInst(TailCallKind TCK, Value *Func, ArrayRef Args, const Twine &NameStr, Instruction *InsertBefore); /// Construct a CallInst given a range of arguments. /// \brief Construct a CallInst from a range of arguments - inline CallInst(Value *Func, ArrayRef Args, + inline CallInst(TailCallKind TCK, Value *Func, ArrayRef Args, const Twine &NameStr, BasicBlock *InsertAtEnd); explicit CallInst(Value *F, const Twine &NameStr, @@ -1240,14 +1245,26 @@ ArrayRef Args, const Twine &NameStr = "", Instruction *InsertBefore = nullptr) { - return new(unsigned(Args.size() + 1)) - CallInst(Func, Args, NameStr, InsertBefore); + return new (unsigned(Args.size() + 1)) + CallInst(TCK_None, Func, Args, NameStr, InsertBefore); } static CallInst *Create(Value *Func, ArrayRef Args, const Twine &NameStr, BasicBlock *InsertAtEnd) { - return new(unsigned(Args.size() + 1)) - CallInst(Func, Args, NameStr, InsertAtEnd); + return new (unsigned(Args.size() + 1)) + CallInst(TCK_None, Func, Args, NameStr, InsertAtEnd); + } + static CallInst *Create(TailCallKind TCK, Value *Func, ArrayRef Args, + const Twine &NameStr = "", + Instruction *InsertBefore = nullptr) { + return new (unsigned(Args.size() + 1)) + CallInst(TCK, Func, Args, NameStr, InsertBefore); + } + static CallInst *Create(TailCallKind TCK, Value *Func, ArrayRef Args, + const Twine &NameStr, + BasicBlock *InsertAtEnd) { + return new (unsigned(Args.size() + 1)) + CallInst(TCK, Func, Args, NameStr, InsertAtEnd); } static CallInst *Create(Value *F, const Twine &NameStr = "", Instruction *InsertBefore = nullptr) { @@ -1279,11 +1296,26 @@ ~CallInst(); - bool isTailCall() const { return getSubclassDataFromInstruction() & 1; } - void setTailCall(bool isTC = true) { - setInstructionSubclassData((getSubclassDataFromInstruction() & ~1) | - unsigned(isTC)); + TailCallKind getTailCallKind() const { + return TailCallKind(getSubclassDataFromInstruction() & 3); + } + bool isTailCall() const { + return (getSubclassDataFromInstruction() & 3) != TCK_None; + } + bool isMustTailCall() const { + return (getSubclassDataFromInstruction() & 3) == TCK_MustTail; + } + void setTailCall(bool IsTC = true) { + assert((IsTC || !isMustTailCall()) && "cannot remove musttail from a call"); + setInstructionSubclassData((getSubclassDataFromInstruction() & ~3) | + unsigned(IsTC ? TCK_Tail : TCK_None)); } +private: + void setTailCallKind(TailCallKind TCK) { + setInstructionSubclassData((getSubclassDataFromInstruction() & ~3) | + unsigned(TCK)); + } +public: /// Provide fast operand accessors DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); @@ -1316,11 +1348,11 @@ /// getCallingConv/setCallingConv - Get or set the calling convention of this /// function call. CallingConv::ID getCallingConv() const { - return static_cast(getSubclassDataFromInstruction() >> 1); + return static_cast(getSubclassDataFromInstruction() >> 2); } void setCallingConv(CallingConv::ID CC) { - setInstructionSubclassData((getSubclassDataFromInstruction() & 1) | - (static_cast(CC) << 1)); + setInstructionSubclassData((getSubclassDataFromInstruction() & 3) | + (static_cast(CC) << 2)); } /// getAttributes - Return the parameter attributes for this call. @@ -1463,7 +1495,7 @@ struct OperandTraits : public VariadicOperandTraits { }; -CallInst::CallInst(Value *Func, ArrayRef Args, +CallInst::CallInst(TailCallKind TCK, Value *Func, ArrayRef Args, const Twine &NameStr, BasicBlock *InsertAtEnd) : Instruction(cast(cast(Func->getType()) ->getElementType())->getReturnType(), @@ -1471,9 +1503,10 @@ OperandTraits::op_end(this) - (Args.size() + 1), unsigned(Args.size() + 1), InsertAtEnd) { init(Func, Args, NameStr); + setTailCallKind(TCK); } -CallInst::CallInst(Value *Func, ArrayRef Args, +CallInst::CallInst(TailCallKind TCK, Value *Func, ArrayRef Args, const Twine &NameStr, Instruction *InsertBefore) : Instruction(cast(cast(Func->getType()) ->getElementType())->getReturnType(), @@ -1481,6 +1514,7 @@ OperandTraits::op_end(this) - (Args.size() + 1), unsigned(Args.size() + 1), InsertBefore) { init(Func, Args, NameStr); + setTailCallKind(TCK); } Index: lib/AsmParser/LLLexer.cpp =================================================================== --- lib/AsmParser/LLLexer.cpp +++ lib/AsmParser/LLLexer.cpp @@ -512,6 +512,7 @@ KEYWORD(null); KEYWORD(to); KEYWORD(tail); + KEYWORD(musttail); KEYWORD(target); KEYWORD(triple); KEYWORD(unwind); Index: lib/AsmParser/LLParser.h =================================================================== --- lib/AsmParser/LLParser.h +++ lib/AsmParser/LLParser.h @@ -371,6 +371,8 @@ bool ParseFunctionBody(Function &Fn); bool ParseBasicBlock(PerFunctionState &PFS); + enum TailCallType { TCT_None, TCT_Tail, TCT_MustTail }; + // Instruction Parsing. Each instruction parsing routine can return with a // normal result, an error result, or return having eaten an extra comma. enum InstResult { InstNormal = 0, InstError = 1, InstExtraComma = 2 }; @@ -397,7 +399,8 @@ bool ParseShuffleVector(Instruction *&I, PerFunctionState &PFS); int ParsePHI(Instruction *&I, PerFunctionState &PFS); bool ParseLandingPad(Instruction *&I, PerFunctionState &PFS); - bool ParseCall(Instruction *&I, PerFunctionState &PFS, bool isTail); + bool ParseCall(Instruction *&I, PerFunctionState &PFS, + CallInst::TailCallKind IsTail); int ParseAlloc(Instruction *&I, PerFunctionState &PFS); int ParseLoad(Instruction *&I, PerFunctionState &PFS); int ParseStore(Instruction *&I, PerFunctionState &PFS); Index: lib/AsmParser/LLParser.cpp =================================================================== --- lib/AsmParser/LLParser.cpp +++ lib/AsmParser/LLParser.cpp @@ -3367,8 +3367,10 @@ case lltok::kw_shufflevector: return ParseShuffleVector(Inst, PFS); case lltok::kw_phi: return ParsePHI(Inst, PFS); case lltok::kw_landingpad: return ParseLandingPad(Inst, PFS); - case lltok::kw_call: return ParseCall(Inst, PFS, false); - case lltok::kw_tail: return ParseCall(Inst, PFS, true); + // Call. + case lltok::kw_call: return ParseCall(Inst, PFS, CallInst::TCK_None); + case lltok::kw_tail: return ParseCall(Inst, PFS, CallInst::TCK_Tail); + case lltok::kw_musttail: return ParseCall(Inst, PFS, CallInst::TCK_MustTail); // Memory. case lltok::kw_alloca: return ParseAlloc(Inst, PFS); case lltok::kw_load: return ParseLoad(Inst, PFS); @@ -3984,10 +3986,14 @@ } /// ParseCall -/// ::= 'tail'? 'call' OptionalCallingConv OptionalAttrs Type Value +/// ::= 'call' OptionalCallingConv OptionalAttrs Type Value +/// ParameterList OptionalAttrs +/// ::= 'tail' 'call' OptionalCallingConv OptionalAttrs Type Value +/// ParameterList OptionalAttrs +/// ::= 'musttail' 'call' OptionalCallingConv OptionalAttrs Type Value /// ParameterList OptionalAttrs bool LLParser::ParseCall(Instruction *&Inst, PerFunctionState &PFS, - bool isTail) { + CallInst::TailCallKind TCK) { AttrBuilder RetAttrs, FnAttrs; std::vector FwdRefAttrGrps; LocTy BuiltinLoc; @@ -3998,7 +4004,8 @@ SmallVector ArgList; LocTy CallLoc = Lex.getLoc(); - if ((isTail && ParseToken(lltok::kw_call, "expected 'tail call'")) || + if ((TCK != CallInst::TCK_None && + ParseToken(lltok::kw_call, "expected 'tail call'")) || ParseOptionalCallingConv(CC) || ParseOptionalReturnAttrs(RetAttrs) || ParseType(RetType, RetTypeLoc, true /*void allowed*/) || @@ -4073,8 +4080,7 @@ // Finish off the Attribute and check them AttributeSet PAL = AttributeSet::get(Context, Attrs); - CallInst *CI = CallInst::Create(Callee, Args); - CI->setTailCall(isTail); + CallInst *CI = CallInst::Create(TCK, Callee, Args); CI->setCallingConv(CC); CI->setAttributes(PAL); ForwardRefAttrGroups[CI] = FwdRefAttrGrps; Index: lib/AsmParser/LLToken.h =================================================================== --- lib/AsmParser/LLToken.h +++ lib/AsmParser/LLToken.h @@ -54,6 +54,7 @@ kw_undef, kw_null, kw_to, kw_tail, + kw_musttail, kw_target, kw_triple, kw_unwind, Index: lib/Bitcode/Reader/BitcodeReader.cpp =================================================================== --- lib/Bitcode/Reader/BitcodeReader.cpp +++ lib/Bitcode/Reader/BitcodeReader.cpp @@ -2991,11 +2991,15 @@ } } - I = CallInst::Create(Callee, Args); + CallInst::TailCallKind TCK = CallInst::TCK_None; + if (CCInfo & 1) + TCK = CallInst::TCK_Tail; + if (CCInfo & (1 << 14)) + TCK = CallInst::TCK_MustTail; + I = CallInst::Create(TCK, Callee, Args); InstructionList.push_back(I); cast(I)->setCallingConv( - static_cast(CCInfo>>1)); - cast(I)->setTailCall(CCInfo & 1); + static_cast((~(1U << 14) & CCInfo) >> 1)); cast(I)->setAttributes(PAL); break; } Index: lib/Bitcode/Writer/BitcodeWriter.cpp =================================================================== --- lib/Bitcode/Writer/BitcodeWriter.cpp +++ lib/Bitcode/Writer/BitcodeWriter.cpp @@ -1469,7 +1469,8 @@ Code = bitc::FUNC_CODE_INST_CALL; Vals.push_back(VE.getAttributeID(CI.getAttributes())); - Vals.push_back((CI.getCallingConv() << 1) | unsigned(CI.isTailCall())); + Vals.push_back((CI.getCallingConv() << 1) | unsigned(CI.isTailCall()) | + unsigned(CI.isMustTailCall()) << 14); PushValueAndType(CI.getCalledValue(), InstID, Vals, VE); // Callee // Emit value #'s for the fixed parameters. Index: lib/IR/AsmWriter.cpp =================================================================== --- lib/IR/AsmWriter.cpp +++ lib/IR/AsmWriter.cpp @@ -1768,8 +1768,12 @@ Out << '%' << SlotNum << " = "; } - if (isa(I) && cast(I).isTailCall()) - Out << "tail "; + if (const CallInst *CI = dyn_cast(&I)) { + if (CI->isMustTailCall()) + Out << "musttail "; + else if (CI->isTailCall()) + Out << "tail "; + } // Print out the opcode... Out << I.getOpcodeName(); Index: lib/IR/Instructions.cpp =================================================================== --- lib/IR/Instructions.cpp +++ lib/IR/Instructions.cpp @@ -324,7 +324,7 @@ OperandTraits::op_end(this) - CI.getNumOperands(), CI.getNumOperands()) { setAttributes(CI.getAttributes()); - setTailCall(CI.isTailCall()); + setTailCallKind(CI.getTailCallKind()); setCallingConv(CI.getCallingConv()); std::copy(CI.op_begin(), CI.op_end(), op_begin()); Index: lib/IR/Verifier.cpp =================================================================== --- lib/IR/Verifier.cpp +++ lib/IR/Verifier.cpp @@ -301,6 +301,7 @@ void visitLandingPadInst(LandingPadInst &LPI); void VerifyCallSite(CallSite CS); + void verifyMustTailCall(CallInst &CI); bool PerformTypeCheck(Intrinsic::ID ID, Function *F, Type *Ty, int VT, unsigned ArgNo, std::string &Suffix); bool VerifyIntrinsicType(Type *Ty, ArrayRef &Infos, @@ -1545,9 +1546,92 @@ visitInstruction(*I); } +static bool isTypeCongruent(Type *L, Type *R) { + if (L == R) + return true; + PointerType *PL = dyn_cast(L); + PointerType *PR = dyn_cast(R); + if (!PL || !PR) + return false; + return PL->getAddressSpace() == PR->getAddressSpace(); +} + +void Verifier::verifyMustTailCall(CallInst &CI) { + // - The caller and callee prototypes must match. Pointer types of + // parameters or return types may differ in pointee type, but not + // address space. + Function *F = CI.getParent()->getParent(); + auto GetFnTy = [](Value *V) { + return cast( + cast(V->getType())->getElementType()); + }; + FunctionType *CallerTy = GetFnTy(F); + FunctionType *CalleeTy = GetFnTy(CI.getCalledValue()); + Assert1(CallerTy->getNumParams() == CalleeTy->getNumParams(), + "cannot guarantee tail call due to mismatched parameter counts", &CI); + Assert1(CallerTy->isVarArg() == CalleeTy->isVarArg(), + "cannot guarantee tail call due to mismatched varargs", &CI); + Assert1(isTypeCongruent(CallerTy->getReturnType(), CalleeTy->getReturnType()), + "cannot guarantee tail call due to mismatched return types", &CI); + for (int I = 0, E = CallerTy->getNumParams(); I != E; ++I) { + Assert1( + isTypeCongruent(CallerTy->getParamType(I), CalleeTy->getParamType(I)), + "cannot guarantee tail call due to mismatched parameter types", &CI); + } + + // - The calling conventions of the caller and callee must match. + Assert1(F->getCallingConv() == CI.getCallingConv(), + "cannot guarantee tail call due to mismatched calling conv", &CI); + + // - All ABI-impacting function attributes, such as sret, byval, inreg, + // returned, and inalloca, must match. + static const Attribute::AttrKind ABIAttrs[] = { + Attribute::Alignment, Attribute::StructRet, Attribute::ByVal, + Attribute::InAlloca, Attribute::InReg, Attribute::Returned}; + AttributeSet CallerAttrs = F->getAttributes(); + AttributeSet CalleeAttrs = CI.getAttributes(); + for (int I = 0, E = CallerTy->getNumParams(); I != E; ++I) { + AttrBuilder CallerABIAttrs; + AttrBuilder CalleeABIAttrs; + for (auto AK : ABIAttrs) { + if (CallerAttrs.hasAttribute(I + 1, AK)) + CallerABIAttrs.addAttribute(AK); + if (CalleeAttrs.hasAttribute(I + 1, AK)) + CalleeABIAttrs.addAttribute(AK); + } + Assert1(CallerABIAttrs == CalleeABIAttrs, "cannot guarantee tail call due " + "to mismatched ABI impacting function attributes", &CI); + } + + // - The call must immediately precede a :ref:`ret ` instruction, + // or a pointer bitcast followed by a ret instruction. + // - The ret instruction must return the (possibly bitcasted) value + // produced by the call or void. + Value *RetVal = &CI; + Instruction *Next = CI.getNextNode(); + + // Handle the optional bitcast. + if (BitCastInst *BI = dyn_cast_or_null(Next)) { + Assert1(BI->getOperand(0) == RetVal, + "bitcast following musttail call must use the call", BI); + RetVal = BI; + Next = BI->getNextNode(); + } + + // Check the return. + ReturnInst *Ret = dyn_cast_or_null(Next); + Assert1(Ret, "musttail call must be precede a ret with an optional bitcast", + &CI); + Assert1(!Ret->getReturnValue() || Ret->getReturnValue() == RetVal, + "ret must return the result from a preceding musttail call", Ret); +} + void Verifier::visitCallInst(CallInst &CI) { VerifyCallSite(&CI); + if (CI.isMustTailCall()) + verifyMustTailCall(CI); + if (Function *F = CI.getCalledFunction()) if (Intrinsic::ID ID = (Intrinsic::ID)F->getIntrinsicID()) visitIntrinsicFunctionCall(ID, CI); Index: lib/Target/AArch64/AArch64ISelLowering.cpp =================================================================== --- lib/Target/AArch64/AArch64ISelLowering.cpp +++ lib/Target/AArch64/AArch64ISelLowering.cpp @@ -1521,6 +1521,10 @@ IsVarArg, IsStructRet, MF.getFunction()->hasStructRetAttr(), Outs, OutVals, Ins, DAG); + if (!IsTailCall && CLI.CS && CLI.CS->isMustTailCall()) + report_fatal_error("failed to perform tail call elimination on a call " + "site marked musttail"); + // A sibling call is one where we're under the usual C ABI and not planning // to change that but can still do a tail call: if (!TailCallOpt && IsTailCall) Index: lib/Target/ARM/ARMISelLowering.cpp =================================================================== --- lib/Target/ARM/ARMISelLowering.cpp +++ lib/Target/ARM/ARMISelLowering.cpp @@ -1398,6 +1398,9 @@ isTailCall = IsEligibleForTailCallOptimization(Callee, CallConv, isVarArg, isStructRet, MF.getFunction()->hasStructRetAttr(), Outs, OutVals, Ins, DAG); + if (!isTailCall && CLI.CS && CLI.CS->isMustTailCall()) + report_fatal_error("failed to perform tail call elimination on a call " + "site marked musttail"); // We don't support GuaranteedTailCallOpt for ARM, only automatically // detected sibcalls. if (isTailCall) { Index: lib/Target/ARM64/ARM64ISelLowering.cpp =================================================================== --- lib/Target/ARM64/ARM64ISelLowering.cpp +++ lib/Target/ARM64/ARM64ISelLowering.cpp @@ -2404,6 +2404,9 @@ IsTailCall = isEligibleForTailCallOptimization( Callee, CallConv, IsVarArg, IsStructRet, MF.getFunction()->hasStructRetAttr(), Outs, OutVals, Ins, DAG); + if (!IsTailCall && CLI.CS && CLI.CS->isMustTailCall()) + report_fatal_error("failed to perform tail call elimination on a call " + "site marked musttail"); // We don't support GuaranteedTailCallOpt, only automatically // detected sibcalls. // FIXME: Re-evaluate. Is this true? Should it be true? Index: lib/Target/Mips/MipsISelLowering.cpp =================================================================== --- lib/Target/Mips/MipsISelLowering.cpp +++ lib/Target/Mips/MipsISelLowering.cpp @@ -2324,6 +2324,10 @@ isEligibleForTailCallOptimization(MipsCCInfo, NextStackOffset, *MF.getInfo()); + if (!IsTailCall && CLI.CS && CLI.CS->isMustTailCall()) + report_fatal_error("failed to perform tail call elimination on a call " + "site marked musttail"); + if (IsTailCall) ++NumTailCalls; Index: lib/Target/PowerPC/PPCISelLowering.cpp =================================================================== --- lib/Target/PowerPC/PPCISelLowering.cpp +++ lib/Target/PowerPC/PPCISelLowering.cpp @@ -3720,6 +3720,10 @@ isTailCall = IsEligibleForTailCallOptimization(Callee, CallConv, isVarArg, Ins, DAG); + if (!isTailCall && CLI.CS && CLI.CS->isMustTailCall()) + report_fatal_error("failed to perform tail call elimination on a call " + "site marked musttail"); + if (PPCSubTarget.isSVR4ABI()) { if (PPCSubTarget.isPPC64()) return LowerCall_64SVR4(Chain, Callee, CallConv, isVarArg, Index: lib/Target/X86/X86ISelLowering.cpp =================================================================== --- lib/Target/X86/X86ISelLowering.cpp +++ lib/Target/X86/X86ISelLowering.cpp @@ -2541,6 +2541,10 @@ MF.getFunction()->hasStructRetAttr(), CLI.RetTy, Outs, OutVals, Ins, DAG); + if (!isTailCall && CLI.CS && CLI.CS->isMustTailCall()) + report_fatal_error("failed to perform tail call elimination on a call " + "site marked musttail"); + // Sibcalls are automatically detected tailcalls which do not require // ABI changes. if (!MF.getTarget().Options.GuaranteedTailCallOpt && isTailCall) Index: test/Bitcode/tailcall.ll =================================================================== --- /dev/null +++ test/Bitcode/tailcall.ll @@ -0,0 +1,17 @@ +; RUN: llvm-as < %s | llvm-dis | FileCheck %s + +; Check that musttail and tail roundtrip. + +declare cc8191 void @t1_callee() +define cc8191 void @t1() { +; CHECK: tail call cc8191 void @t1_callee() + tail call cc8191 void @t1_callee() + ret void +} + +declare cc8191 void @t2_callee() +define cc8191 void @t2() { +; CHECK: musttail call cc8191 void @t2_callee() + musttail call cc8191 void @t2_callee() + ret void +} Index: test/CodeGen/X86/musttail.ll =================================================================== --- /dev/null +++ test/CodeGen/X86/musttail.ll @@ -0,0 +1,23 @@ +; RUN: llc -march=x86 < %s | FileCheck %s + +; FIXME: Eliminate this tail call at -O0, since musttail is a correctness +; requirement. +; RUN: not llc -march=x86 -O0 < %s + +declare void @t1_callee(i8*) +define void @t1(i32* %a) { +; CHECK-LABEL: t1: +; CHECK: jmp {{_?}}t1_callee + %b = bitcast i32* %a to i8* + musttail call void @t1_callee(i8* %b) + ret void +} + +declare i8* @t2_callee() +define i32* @t2() { +; CHECK-LABEL: t2: +; CHECK: jmp {{_?}}t2_callee + %v = musttail call i8* @t2_callee() + %w = bitcast i8* %v to i32* + ret i32* %w +} Index: test/Verifier/musttail-invalid.ll =================================================================== --- /dev/null +++ test/Verifier/musttail-invalid.ll @@ -0,0 +1,69 @@ +; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s + +; Each musttail call should fail to validate. + +declare x86_stdcallcc void @cc_mismatch_callee() +define void @cc_mismatch() { +; CHECK: mismatched calling conv + musttail call x86_stdcallcc void @cc_mismatch_callee() + ret void +} + +declare void @more_parms_callee(i32) +define void @more_parms() { +; CHECK: mismatched parameter counts + musttail call void @more_parms_callee(i32 0) + ret void +} + +declare void @mismatched_intty_callee(i8) +define void @mismatched_intty(i32) { +; CHECK: mismatched parameter types + musttail call void @mismatched_intty_callee(i8 0) + ret void +} + +declare void @mismatched_vararg_callee(i8*, ...) +define void @mismatched_vararg(i8*) { +; CHECK: mismatched varargs + musttail call void (i8*, ...)* @mismatched_vararg_callee(i8* null) + ret void +} + +; We would make this an implicit sret parameter, which would disturb the +; tail call. +declare { i32, i32, i32 } @mismatched_retty_callee(i32) +define void @mismatched_retty(i32) { +; CHECK: mismatched return types + musttail call { i32, i32, i32 } @mismatched_retty_callee(i32 0) + ret void +} + +declare void @mismatched_byval_callee({ i32 }*) +define void @mismatched_byval({ i32 }* byval %a) { +; CHECK: mismatched ABI impacting function attributes + musttail call void @mismatched_byval_callee({ i32 }* %a) + ret void +} + +declare void @mismatched_inreg_callee(i32 inreg) +define void @mismatched_inreg(i32 %a) { +; CHECK: mismatched ABI impacting function attributes + musttail call void @mismatched_inreg_callee(i32 inreg %a) + ret void +} + +declare void @mismatched_sret_callee(i32* sret) +define void @mismatched_sret(i32* %a) { +; CHECK: mismatched ABI impacting function attributes + musttail call void @mismatched_sret_callee(i32* sret %a) + ret void +} + +declare i32 @not_tail_pos_callee() +define i32 @not_tail_pos() { +; CHECK: musttail call must be precede a ret with an optional bitcast + %v = musttail call i32 @not_tail_pos_callee() + %w = add i32 %v, 1 + ret i32 %w +} Index: test/Verifier/musttail-valid.ll =================================================================== --- /dev/null +++ test/Verifier/musttail-valid.ll @@ -0,0 +1,16 @@ +; RUN: llvm-as %s -o /dev/null + +; Should assemble without error. + +declare void @similar_param_ptrty_callee(i8*) +define void @similar_param_ptrty(i32*) { + musttail call void @similar_param_ptrty_callee(i8* null) + ret void +} + +declare i8* @similar_ret_ptrty_callee() +define i32* @similar_ret_ptrty() { + %v = musttail call i8* @similar_ret_ptrty_callee() + %w = bitcast i8* %v to i32* + ret i32* %w +}