diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 8320fc1b882..1a15bea0d92 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -3092,9 +3092,13 @@ X86TargetLowering::IsEligibleForTailCallOptimization(SDValue Callee, if (isCalleeStructRet || isCallerStructRet) return false; - // An stdcall caller is expected to clean up its arguments; the callee - // isn't going to do that. - if (!CCMatch && CallerCC == CallingConv::X86_StdCall) + // An stdcall/thiscall caller is expected to clean up its arguments; the + // callee isn't going to do that. + // FIXME: this is more restrictive than needed. We could produce a tailcall + // when the stack adjustment matches. For example, with a thiscall that takes + // only one argument. + if (!CCMatch && (CallerCC == CallingConv::X86_StdCall || + CallerCC == CallingConv::X86_ThisCall)) return false; // Do not sibcall optimize vararg calls unless all arguments are passed via diff --git a/test/CodeGen/X86/stdcall-notailcall.ll b/test/CodeGen/X86/stdcall-notailcall.ll index 8f522cda284..c847ec7b6c0 100644 --- a/test/CodeGen/X86/stdcall-notailcall.ll +++ b/test/CodeGen/X86/stdcall-notailcall.ll @@ -10,4 +10,12 @@ entry: ret void } +define x86_thiscallcc void @test2(%struct.I* %this, i32 %a) { +; CHECK-LABEL: test2: +; CHECK: calll _foo +; CHECK: ret $4 + tail call void @foo() + ret void +} + declare void @foo()