Index: llvm/lib/CodeGen/Analysis.cpp =================================================================== --- llvm/lib/CodeGen/Analysis.cpp +++ llvm/lib/CodeGen/Analysis.cpp @@ -533,6 +533,7 @@ // longjmp on x86), it can end up causing miscompilation that has not // been fully understood. if (!Ret && ((!TM.Options.GuaranteedTailCallOpt && + !Call.isMustTailCall() && Call.getCallingConv() != CallingConv::Tail && Call.getCallingConv() != CallingConv::SwiftTail) || !isa(Term))) Index: llvm/lib/IR/Verifier.cpp =================================================================== --- llvm/lib/IR/Verifier.cpp +++ llvm/lib/IR/Verifier.cpp @@ -3505,11 +3505,13 @@ } // Check the return. - ReturnInst *Ret = dyn_cast_or_null(Next); - Check(Ret, "musttail call must precede a ret with an optional bitcast", &CI); - Check(!Ret->getReturnValue() || Ret->getReturnValue() == RetVal || + if (ReturnInst *Ret = dyn_cast_or_null(Next)) { + Check(!Ret->getReturnValue() || Ret->getReturnValue() == RetVal || isa(Ret->getReturnValue()), "musttail call result must be returned", Ret); + } else if (!Next || !isa(Next)) + CheckFailed("musttail call must precede a ret or unreachable with an " + "optional bitcast"); AttributeList CallerAttrs = F->getAttributes(); AttributeList CalleeAttrs = CI.getAttributes(); Index: llvm/test/CodeGen/AArch64/musttail-noreturn.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/AArch64/musttail-noreturn.ll @@ -0,0 +1,10 @@ +; RUN: llc -mtriple=aarch64-linux-gnu %s -o - | FileCheck %s + +define void @caller() { +; CHECK: caller: +; CHECK: b callee + musttail call void @callee() noreturn + unreachable +} + +declare void @callee() noreturn Index: llvm/test/CodeGen/ARM/musttail-noreturn.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/ARM/musttail-noreturn.ll @@ -0,0 +1,10 @@ +; RUN: llc -mtriple=thumbv7k-apple-watchos4 %s -o - | FileCheck %s + +define void @caller() { +; CHECK: caller: +; CHECK: b.w _callee + musttail call void @callee() noreturn + unreachable +} + +declare void @callee() noreturn Index: llvm/test/CodeGen/X86/musttail-noreturn.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/X86/musttail-noreturn.ll @@ -0,0 +1,10 @@ +; RUN: llc -mtriple=x86_64-linux-gnu %s -o - | FileCheck %s + +define void @caller() { +; CHECK: caller: +; CHECK: jmp callee + musttail call void @callee() noreturn + unreachable +} + +declare void @callee() noreturn Index: llvm/test/Verifier/musttail-invalid.ll =================================================================== --- llvm/test/Verifier/musttail-invalid.ll +++ llvm/test/Verifier/musttail-invalid.ll @@ -70,7 +70,7 @@ declare i32 @not_tail_pos_callee() define i32 @not_tail_pos() { -; CHECK: musttail call must precede a ret with an optional bitcast +; CHECK: musttail call must precede a ret or unreachable with an optional bitcast %v = musttail call i32 @not_tail_pos_callee() %w = add i32 %v, 1 ret i32 %w Index: llvm/test/Verifier/musttail-valid.ll =================================================================== --- llvm/test/Verifier/musttail-valid.ll +++ llvm/test/Verifier/musttail-valid.ll @@ -37,3 +37,9 @@ bb1: ret void } + +define void @noreturn_caller() { + musttail call void @noreturn_callee() noreturn + unreachable +} +declare void @noreturn_callee() noreturn