diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -4257,16 +4257,19 @@ isTailCall = false; } - if (isTailCall && !IsMustTail) { + if (isTailCall) { + // It seems this function actually checks for sib call. // Check if it's really possible to do a tail call. - isTailCall = IsEligibleForTailCallOptimization( + IsSibcall = IsEligibleForTailCallOptimization( Callee, CallConv, IsCalleePopSRet, isVarArg, CLI.RetTy, Outs, OutVals, Ins, DAG); - // Sibcalls are automatically detected tailcalls which do not require - // ABI changes. - if (!IsGuaranteeTCO && isTailCall) - IsSibcall = true; + if (!IsMustTail) { + isTailCall = IsSibcall; + // Sibcalls are automatically detected tailcalls which do not require ABI + // changes. + IsSibcall = IsSibcall && !IsGuaranteeTCO; + } if (isTailCall) ++NumTailCalls; @@ -4305,7 +4308,8 @@ NumBytes = GetAlignedArgumentStackSize(NumBytes, DAG); int FPDiff = 0; - if (isTailCall && + // Sibcall should not adjust stack pointer. + if (isTailCall && !IsSibcall && shouldGuaranteeTCO(CallConv, MF.getTarget().Options.GuaranteedTailCallOpt)) { // Lower arguments at fp - stackoffset + fpdiff. diff --git a/llvm/test/CodeGen/X86/musttail-struct.ll b/llvm/test/CodeGen/X86/musttail-struct.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/X86/musttail-struct.ll @@ -0,0 +1,57 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: llc < %s -mtriple=x86_64-unknown-unknown | FileCheck %s +; RUN: llc < %s -mtriple=i686-unknown-unknown | FileCheck %s + +; Test correct handling of musttail call with struct. + +%struct.1xi32 = type { [1 x i32] } +%struct.3xi32 = type { [3 x i32] } +%struct.5xi32 = type { [5 x i32] } + +declare dso_local i32 @Func1(ptr byval(%struct.1xi32) %0) +declare dso_local i32 @Func3(ptr byval(%struct.3xi32) %0) +declare dso_local i32 @Func5(ptr byval(%struct.5xi32) %0) +declare dso_local i32 @FuncManyArgs(i32 %0, i32 %1, i32 %2, i32 %3, i32 %4, i32 %5, i8 %6, ptr byval(%struct.5xi32) %7) + +define dso_local i32 @test1(ptr byval(%struct.1xi32) %0) { +; CHECK-LABEL: test1: +; CHECK: # %bb.0: +; CHECK-NEXT: jmp Func1 # TAILCALL + %r = musttail call i32 @Func1(ptr byval(%struct.1xi32) %0) + ret i32 %r +} + +define dso_local i32 @test3(ptr byval(%struct.3xi32) %0) { +; CHECK-LABEL: test3: +; CHECK: # %bb.0: +; CHECK-NEXT: jmp Func3 # TAILCALL + %r = musttail call i32 @Func3(ptr byval(%struct.3xi32) %0) + ret i32 %r +} + +; sizeof(%struct.5xi32) > 16, in x64 this is passed on stack. +define dso_local i32 @test5(ptr byval(%struct.5xi32) %0) { +; CHECK-LABEL: test5: +; CHECK: # %bb.0: +; CHECK-NEXT: jmp Func5 # TAILCALL + %r = musttail call i32 @Func5(ptr byval(%struct.5xi32) %0) + ret i32 %r +} + +; Test passing multiple arguments with different sizes on stack. In x64 Linux +; the first 6 are passed by register. +define dso_local i32 @testManyArgs(i32 %0, i32 %1, i32 %2, i32 %3, i32 %4, i32 %5, i8 %6, ptr byval(%struct.5xi32) %7) { +; CHECK-LABEL: testManyArgs: +; CHECK: # %bb.0: +; CHECK-NEXT: jmp FuncManyArgs # TAILCALL + %r = musttail call i32 @FuncManyArgs(i32 %0, i32 %1, i32 %2, i32 %3, i32 %4, i32 %5, i8 %6, ptr byval(%struct.5xi32) %7) + ret i32 %r +} + +define dso_local i32 @testRecursion(i32 %0, i32 %1, i32 %2, i32 %3, i32 %4, i32 %5, i8 %6, ptr byval(%struct.5xi32) %7) { +; CHECK-LABEL: testRecursion: +; CHECK: # %bb.0: +; CHECK-NEXT: jmp testRecursion # TAILCALL + %r = musttail call i32 @testRecursion(i32 %0, i32 %1, i32 %2, i32 %3, i32 %4, i32 %5, i8 %6, ptr byval(%struct.5xi32) %7) + ret i32 %r +} diff --git a/llvm/test/CodeGen/X86/musttail-tailcc.ll b/llvm/test/CodeGen/X86/musttail-tailcc.ll --- a/llvm/test/CodeGen/X86/musttail-tailcc.ll +++ b/llvm/test/CodeGen/X86/musttail-tailcc.ll @@ -54,15 +54,6 @@ ; ; X32-LABEL: void_test: ; X32: # %bb.0: # %entry -; X32-NEXT: pushl %esi -; X32-NEXT: .cfi_def_cfa_offset 8 -; X32-NEXT: .cfi_offset %esi, -8 -; X32-NEXT: movl {{[0-9]+}}(%esp), %eax -; X32-NEXT: movl {{[0-9]+}}(%esp), %esi -; X32-NEXT: movl %esi, {{[0-9]+}}(%esp) -; X32-NEXT: movl %eax, {{[0-9]+}}(%esp) -; X32-NEXT: popl %esi -; X32-NEXT: .cfi_def_cfa_offset 4 ; X32-NEXT: jmp void_test # TAILCALL entry: musttail call tailcc void @void_test( i32 %0, i32 %1, i32 %2, i32 %3) @@ -76,15 +67,6 @@ ; ; X32-LABEL: i1test: ; X32: # %bb.0: # %entry -; X32-NEXT: pushl %esi -; X32-NEXT: .cfi_def_cfa_offset 8 -; X32-NEXT: .cfi_offset %esi, -8 -; X32-NEXT: movl {{[0-9]+}}(%esp), %eax -; X32-NEXT: movl {{[0-9]+}}(%esp), %esi -; X32-NEXT: movl %esi, {{[0-9]+}}(%esp) -; X32-NEXT: movl %eax, {{[0-9]+}}(%esp) -; X32-NEXT: popl %esi -; X32-NEXT: .cfi_def_cfa_offset 4 ; X32-NEXT: jmp i1test # TAILCALL entry: %4 = musttail call tailcc i1 @i1test( i32 %0, i32 %1, i32 %2, i32 %3)