From 3e407efb8bfd5211e939822f15509aacb7b26ac6 Mon Sep 17 00:00:00 2001 From: Charles Davis Date: Thu, 4 Jun 2015 22:50:05 +0000 Subject: [PATCH] [Target/X86] Don't use callee-saved registers in a Win64 tail call on non-Windows. Summary: A small bit that I missed when I updated the X86 backend to account for the Win64 calling convention on non-Windows. Now we don't use dead non-volatile registers when emitting a Win64 indirect tail call on non-Windows. Should fix PR23710. Test Plan: Added test for the correct behavior based on the case I posted to PR23710. Reviewers: rnk Subscribers: llvm-commits Differential Revision: http://reviews.llvm.org/D10258 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@239111 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/X86/X86RegisterInfo.cpp | 4 ++-- test/CodeGen/X86/sibcall-win64.ll | 24 ++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/lib/Target/X86/X86RegisterInfo.cpp b/lib/Target/X86/X86RegisterInfo.cpp index 1f361631a0b..e9b6bfc3273 100644 --- a/lib/Target/X86/X86RegisterInfo.cpp +++ b/lib/Target/X86/X86RegisterInfo.cpp @@ -175,12 +175,12 @@ X86RegisterInfo::getPointerRegClass(const MachineFunction &MF, return &X86::GR64_NOSPRegClass; return &X86::GR32_NOSPRegClass; case 2: // Available for tailcall (not callee-saved GPRs). - if (IsWin64) + const Function *F = MF.getFunction(); + if (IsWin64 || (F && F->getCallingConv() == CallingConv::X86_64_Win64)) return &X86::GR64_TCW64RegClass; else if (Is64Bit) return &X86::GR64_TCRegClass; - const Function *F = MF.getFunction(); bool hasHipeCC = (F ? F->getCallingConv() == CallingConv::HiPE : false); if (hasHipeCC) return &X86::GR32RegClass; diff --git a/test/CodeGen/X86/sibcall-win64.ll b/test/CodeGen/X86/sibcall-win64.ll index f7038726f9c..204e1f8b050 100644 --- a/test/CodeGen/X86/sibcall-win64.ll +++ b/test/CodeGen/X86/sibcall-win64.ll @@ -1,7 +1,11 @@ ; RUN: llc < %s -mtriple=x86_64-pc-linux | FileCheck %s declare x86_64_win64cc void @win64_callee(i32) +declare x86_64_win64cc void (i32)* @win64_indirect() +declare x86_64_win64cc void @win64_other(i32) declare void @sysv_callee(i32) +declare void (i32)* @sysv_indirect() +declare void @sysv_other(i32) define void @sysv_caller(i32 %p1) { entry: @@ -40,3 +44,23 @@ define x86_64_win64cc void @win64_matched(i32 %p1) { ; CHECK-LABEL: win64_matched: ; CHECK: jmp win64_callee # TAILCALL + +define x86_64_win64cc void @win64_indirect_caller(i32 %p1) { + %1 = call x86_64_win64cc void (i32)* @win64_indirect() + call x86_64_win64cc void @win64_other(i32 0) + tail call x86_64_win64cc void %1(i32 %p1) + ret void +} + +; CHECK-LABEL: win64_indirect_caller: +; CHECK: jmpq *%{{rax|rcx|rdx|r8|r9|r11}} # TAILCALL + +define void @sysv_indirect_caller(i32 %p1) { + %1 = call void (i32)* @sysv_indirect() + call void @sysv_other(i32 0) + tail call void %1(i32 %p1) + ret void +} + +; CHECK-LABEL: sysv_indirect_caller: +; CHECK: jmpq *%{{rax|rcx|rdx|rsi|rdi|r8|r9|r11}} # TAILCALL