Index: lib/Target/X86/X86ISelLowering.cpp =================================================================== --- lib/Target/X86/X86ISelLowering.cpp +++ lib/Target/X86/X86ISelLowering.cpp @@ -4182,10 +4182,10 @@ if (RegInfo->needsStackRealignment(MF)) return false; - // Also avoid sibcall optimization if either caller or callee uses struct - // return semantics. - if (isCalleeStructRet || isCallerStructRet) - return false; + // Struct-return functions need to return its argument in RAX, so they can not + // sibcall non-struct-return functions. + if (!isCalleeStructRet && isCallerStructRet) + return false; // Do not sibcall optimize vararg calls unless all arguments are passed via // registers. Index: test/CodeGen/X86/sibcall.ll =================================================================== --- test/CodeGen/X86/sibcall.ll +++ test/CodeGen/X86/sibcall.ll @@ -448,21 +448,11 @@ ; ; X64-LABEL: t15: ; X64: # %bb.0: -; X64-NEXT: pushq %rbx -; X64-NEXT: movq %rdi, %rbx -; X64-NEXT: callq f -; X64-NEXT: movq %rbx, %rax -; X64-NEXT: popq %rbx -; X64-NEXT: retq +; X64-NEXT: jmp f # TAILCALL ; ; X32-LABEL: t15: ; X32: # %bb.0: -; X32-NEXT: pushq %rbx -; X32-NEXT: movl %edi, %ebx -; X32-NEXT: callq f -; X32-NEXT: movl %ebx, %eax -; X32-NEXT: popq %rbx -; X32-NEXT: retq +; X32-NEXT: jmp f # TAILCALL tail call fastcc void @f(%struct.foo* noalias sret %agg.result) nounwind ret void } @@ -611,32 +601,15 @@ define fastcc void @t21_sret_to_sret(%struct.foo* noalias sret %agg.result) nounwind { ; X86-LABEL: t21_sret_to_sret: ; X86: # %bb.0: -; X86-NEXT: pushl %esi -; X86-NEXT: subl $8, %esp -; X86-NEXT: movl %ecx, %esi -; X86-NEXT: calll t21_f_sret -; X86-NEXT: movl %esi, %eax -; X86-NEXT: addl $8, %esp -; X86-NEXT: popl %esi -; X86-NEXT: retl +; X86-NEXT: jmp t21_f_sret # TAILCALL ; ; X64-LABEL: t21_sret_to_sret: ; X64: # %bb.0: -; X64-NEXT: pushq %rbx -; X64-NEXT: movq %rdi, %rbx -; X64-NEXT: callq t21_f_sret -; X64-NEXT: movq %rbx, %rax -; X64-NEXT: popq %rbx -; X64-NEXT: retq +; X64-NEXT: jmp t21_f_sret # TAILCALL ; ; X32-LABEL: t21_sret_to_sret: ; X32: # %bb.0: -; X32-NEXT: pushq %rbx -; X32-NEXT: movl %edi, %ebx -; X32-NEXT: callq t21_f_sret -; X32-NEXT: movl %ebx, %eax -; X32-NEXT: popq %rbx -; X32-NEXT: retq +; X32-NEXT: jmp t21_f_sret # TAILCALL tail call fastcc void @t21_f_sret(%struct.foo* noalias sret %agg.result) nounwind ret void } @@ -677,24 +650,15 @@ define fastcc void @t21_non_sret_to_sret(%struct.foo* %agg.result) nounwind { ; X86-LABEL: t21_non_sret_to_sret: ; X86: # %bb.0: -; X86-NEXT: subl $12, %esp -; X86-NEXT: calll t21_f_sret -; X86-NEXT: addl $12, %esp -; X86-NEXT: retl +; X86-NEXT: jmp t21_f_sret # TAILCALL ; ; X64-LABEL: t21_non_sret_to_sret: ; X64: # %bb.0: -; X64-NEXT: pushq %rax -; X64-NEXT: callq t21_f_sret -; X64-NEXT: popq %rax -; X64-NEXT: retq +; X64-NEXT: jmp t21_f_sret # TAILCALL ; ; X32-LABEL: t21_non_sret_to_sret: ; X32: # %bb.0: -; X32-NEXT: pushq %rax -; X32-NEXT: callq t21_f_sret -; X32-NEXT: popq %rax -; X32-NEXT: retq +; X32-NEXT: jmp t21_f_sret # TAILCALL tail call fastcc void @t21_f_sret(%struct.foo* noalias sret %agg.result) nounwind ret void } @@ -705,26 +669,15 @@ define ccc void @t22_non_sret_to_sret(%struct.foo* %agg.result) nounwind { ; X86-LABEL: t22_non_sret_to_sret: ; X86: # %bb.0: -; X86-NEXT: subl $12, %esp -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: movl %eax, (%esp) -; X86-NEXT: calll t22_f_sret -; X86-NEXT: addl $8, %esp -; X86-NEXT: retl +; X86-NEXT: jmp t22_f_sret # TAILCALL ; ; X64-LABEL: t22_non_sret_to_sret: ; X64: # %bb.0: -; X64-NEXT: pushq %rax -; X64-NEXT: callq t22_f_sret -; X64-NEXT: popq %rax -; X64-NEXT: retq +; X64-NEXT: jmp t22_f_sret # TAILCALL ; ; X32-LABEL: t22_non_sret_to_sret: ; X32: # %bb.0: -; X32-NEXT: pushq %rax -; X32-NEXT: callq t22_f_sret -; X32-NEXT: popq %rax -; X32-NEXT: retq +; X32-NEXT: jmp t22_f_sret # TAILCALL tail call ccc void @t22_f_sret(%struct.foo* noalias sret %agg.result) nounwind ret void }