X86: Allow conditional tail calls in Win64 "leaf" functions (PR26302)
authorHans Wennborg <hans@hanshq.net>
Fri, 30 Sep 2016 20:07:35 +0000 (20:07 +0000)
committerHans Wennborg <hans@hanshq.net>
Fri, 30 Sep 2016 20:07:35 +0000 (20:07 +0000)
We can't use Jcc to leave a Win64 function in general, because that
confuses the unwinder. However, for "leaf" functions, that is, functions
where the return address is always on top of the stack and which don't
have unwind info, it's OK.

Differential Revision: https://reviews.llvm.org/D24836

llvm-svn: 282920

llvm/lib/Target/X86/X86ExpandPseudo.cpp
llvm/lib/Target/X86/X86InstrInfo.cpp
llvm/test/CodeGen/X86/conditional-tailcall.ll

index 63e8f01..8ae2149 100644 (file)
@@ -122,8 +122,9 @@ bool X86ExpandPseudo::ExpandMI(MachineBasicBlock &MBB,
         Op = X86::TAILJMPd_CC;
         break;
       case X86::TCRETURNdi64cc:
-        assert(!IsWin64 && "Conditional tail calls confuse the Win64 unwinder.");
-        // TODO: We could do it for Win64 "leaf" functions though; PR30337.
+        assert(!MBB.getParent()->hasWinCFI() &&
+               "Conditional tail calls confuse "
+               "the Win64 unwinder.");
         Op = X86::TAILJMPd64_CC;
         break;
       default:
index a71aac1..fd3849f 100644 (file)
@@ -4240,9 +4240,9 @@ bool X86InstrInfo::canMakeTailCallConditional(
     return false;
   }
 
-  if (Subtarget.isTargetWin64()) {
+  const MachineFunction *MF = TailCall.getParent()->getParent();
+  if (Subtarget.isTargetWin64() && MF->hasWinCFI()) {
     // Conditional tail calls confuse the Win64 unwinder.
-    // TODO: Allow them for "leaf" functions; PR30337.
     return false;
   }
 
@@ -4252,8 +4252,7 @@ bool X86InstrInfo::canMakeTailCallConditional(
     return false;
   }
 
-  const X86MachineFunctionInfo *X86FI =
-      TailCall.getParent()->getParent()->getInfo<X86MachineFunctionInfo>();
+  const X86MachineFunctionInfo *X86FI = MF->getInfo<X86MachineFunctionInfo>();
   if (X86FI->getTCReturnAddrDelta() != 0 ||
       TailCall.getOperand(1).getImm() != 0) {
     // A conditional tail call cannot do any stack adjustment.
index 502643d..331697c 100644 (file)
@@ -1,5 +1,6 @@
-; RUN: llc < %s -mtriple=i686-linux -show-mc-encoding | FileCheck %s
-; RUN: llc < %s -mtriple=x86_64-linux -show-mc-encoding | FileCheck %s
+; RUN: llc < %s -mtriple=i686-linux -show-mc-encoding | FileCheck -check-prefix=CHECK %s
+; RUN: llc < %s -mtriple=x86_64-linux -show-mc-encoding | FileCheck -check-prefix=CHECK %s
+; RUN: llc < %s -mtriple=x86_64-win32 -show-mc-encoding | FileCheck -check-prefix=CHECK -check-prefix=WIN64 %s
 
 declare void @foo()
 declare void @bar()
@@ -23,6 +24,28 @@ bb2:
 ; CHECK: jmp foo
 }
 
+define void @f_non_leaf(i32 %x, i32 %y) optsize {
+entry:
+  ; Force %ebx to be spilled on the stack, turning this into
+  ; not a "leaf" function for Win64.
+  tail call void asm sideeffect "", "~{ebx}"()
+
+       %p = icmp eq i32 %x, %y
+  br i1 %p, label %bb1, label %bb2
+bb1:
+  tail call void @foo()
+  ret void
+bb2:
+  tail call void @bar()
+  ret void
+
+; CHECK-LABEL: f_non_leaf:
+; WIN64-NOT: je foo
+; WIN64-NOT: jne bar
+; WIN64: jne
+; WIN64: jmp foo
+; WIN64: jmp bar
+}
 
 declare x86_thiscallcc zeroext i1 @baz(i8*, i32)
 define x86_thiscallcc zeroext i1 @BlockPlacementTest(i8* %this, i32 %x) optsize {