diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 4df300b3ea8d..b558f342a112 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -4663,13 +4663,15 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, Address Buf = EmitPointerWithAlignment(E->getArg(0)); // Store the frame pointer to the setjmp buffer. - Value *FrameAddr = Builder.CreateCall( + CallInst *FrameAddr = Builder.CreateCall( CGM.getIntrinsic(Intrinsic::frameaddress, AllocaInt8PtrTy), ConstantInt::get(Int32Ty, 0)); + FrameAddr->setTailCallKind(CallInst::TCK_NoTail); Builder.CreateStore(FrameAddr, Buf); // Store the stack pointer to the setjmp buffer. - Value *StackAddr = Builder.CreateStackSave(); + CallInst *StackAddr = Builder.CreateStackSave(); + StackAddr->setTailCallKind(CallInst::TCK_NoTail); assert(Buf.emitRawPointer(*this)->getType() == StackAddr->getType()); Address StackSaveSlot = Builder.CreateConstInBoundsGEP(Buf, 2); @@ -4677,7 +4679,10 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, // Call LLVM's EH setjmp, which is lightweight. Function *F = CGM.getIntrinsic(Intrinsic::eh_sjlj_setjmp); - return RValue::get(Builder.CreateCall(F, Buf.emitRawPointer(*this))); + CallInst *C = Builder.CreateCall(F, Buf.emitRawPointer(*this)); + C->setTailCallKind(CallInst::TCK_NoTail); + C->addFnAttr(Attribute::ReturnsTwice); + return RValue::get(C); } case Builtin::BI__builtin_longjmp: { Value *Buf = EmitScalarExpr(E->getArg(0)); diff --git a/clang/test/Cilk/notail.c b/clang/test/Cilk/notail.c new file mode 100644 index 000000000000..d35841730f77 --- /dev/null +++ b/clang/test/Cilk/notail.c @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 %s -O -triple x86_64-unknown-linux-gnu -verify -emit-llvm -o - | FileCheck %s +// expected-no-diagnostics + +// This tests that a call in tail position is not subject to tail +// call optimization in a function that calls __builtin_setjmp. + +extern void f(void **); + +// CHECK-LABEL: caller +void caller(void **data) +{ + // CHECK: call i32 @llvm.eh.sjlj.setjmp + if (__builtin_setjmp(data) == 0) + // CHECK-NOT: tail + f(data); +}