[llvm] r238487 - Disable x86 tail call optimizations that jump through GOT

Reid Kleckner reid at kleckner.net
Thu May 28 13:44:28 PDT 2015


Author: rnk
Date: Thu May 28 15:44:28 2015
New Revision: 238487

URL: http://llvm.org/viewvc/llvm-project?rev=238487&view=rev
Log:
Disable x86 tail call optimizations that jump through GOT

For x86 targets, do not do sibling call optimization when materializing
the callee's address would require a GOT relocation. We can still do
tail calls to internal functions, hidden functions, and protected
functions, because they do not require this kind of relocation. It is
still possible to get GOT relocations when the user explicitly asks for
it with musttail or -tailcallopt, both of which are supposed to
guarantee TCO.

Based on a patch by Chih-hung Hsieh.

Reviewers: srhines, timmurray, danalbert, enh, void, nadav, rnk

Subscribers: joerg, davidxl, llvm-commits

Differential Revision: http://reviews.llvm.org/D9799

Added:
    llvm/trunk/test/CodeGen/X86/tailcallpic3.ll
Modified:
    llvm/trunk/lib/Target/X86/X86ISelLowering.cpp
    llvm/trunk/test/CodeGen/X86/pic.ll
    llvm/trunk/test/CodeGen/X86/tail-call-got.ll
    llvm/trunk/test/CodeGen/X86/tailcallpic1.ll

Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelLowering.cpp?rev=238487&r1=238486&r2=238487&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86ISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/X86/X86ISelLowering.cpp Thu May 28 15:44:28 2015
@@ -2780,6 +2780,24 @@ X86TargetLowering::LowerCall(TargetLower
   if (MF.getTarget().Options.DisableTailCalls)
     isTailCall = false;
 
+  if (Subtarget->isPICStyleGOT() &&
+      !MF.getTarget().Options.GuaranteedTailCallOpt) {
+    // If we are using a GOT, disable tail calls to external symbols with
+    // default visibility. Tail calling such a symbol requires using a GOT
+    // relocation, which forces early binding of the symbol. This breaks code
+    // that require lazy function symbol resolution. Using musttail or
+    // GuaranteedTailCallOpt will override this.
+    GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee);
+    if (!G || (!G->getGlobal()->hasLocalLinkage() &&
+               G->getGlobal()->hasDefaultVisibility())) {
+      isTailCall = false;
+      if (G) {
+        llvm::errs() << "disabling tail call for default visibility symbol\n";
+        G->getGlobal()->dump();
+      }
+    }
+  }
+
   bool IsMustTail = CLI.CS && CLI.CS->isMustTailCall();
   if (IsMustTail) {
     // Force this to be a tail call.  The verifier rules are enough to ensure
@@ -2964,8 +2982,8 @@ X86TargetLowering::LowerCall(TargetLower
 
       // Note: The actual moving to ECX is done further down.
       GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee);
-      if (G && !G->getGlobal()->hasHiddenVisibility() &&
-          !G->getGlobal()->hasProtectedVisibility())
+      if (G && !G->getGlobal()->hasLocalLinkage() &&
+          G->getGlobal()->hasDefaultVisibility())
         Callee = LowerGlobalAddress(Callee, DAG);
       else if (isa<ExternalSymbolSDNode>(Callee))
         Callee = LowerExternalSymbol(Callee, DAG);

Modified: llvm/trunk/test/CodeGen/X86/pic.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/pic.ll?rev=238487&r1=238486&r2=238487&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/pic.ll (original)
+++ llvm/trunk/test/CodeGen/X86/pic.ll Thu May 28 15:44:28 2015
@@ -196,9 +196,11 @@ bb12:
 ; LINUX-NEXT: .LJTI7_0:
 ; LINUX:   .long	 .LBB7_2 at GOTOFF
 ; LINUX:   .long	 .LBB7_8 at GOTOFF
-; LINUX:   .long	 .LBB7_14 at GOTOFF
-; LINUX:   .long	 .LBB7_9 at GOTOFF
-; LINUX:   .long	 .LBB7_10 at GOTOFF
+; LINUX:   .long	 .LBB7_4 at GOTOFF
+; LINUX:   .long	 .LBB7_6 at GOTOFF
+; LINUX:   .long	 .LBB7_5 at GOTOFF
+; LINUX:   .long	 .LBB7_8 at GOTOFF
+; LINUX:   .long	 .LBB7_7 at GOTOFF
 }
 
 declare void @foo1(...)

Modified: llvm/trunk/test/CodeGen/X86/tail-call-got.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/tail-call-got.ll?rev=238487&r1=238486&r2=238487&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/tail-call-got.ll (original)
+++ llvm/trunk/test/CodeGen/X86/tail-call-got.ll Thu May 28 15:44:28 2015
@@ -1,12 +1,14 @@
 ; RUN: llc < %s -relocation-model=pic -mattr=+sse2 | FileCheck %s
 
+; We used to do tail calls through the GOT for these symbols, but it was
+; disabled due to PR15086.
+
 target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32"
 target triple = "i386-unknown-freebsd9.0"
 
 define double @test1(double %x) nounwind readnone {
 ; CHECK-LABEL: test1:
-; CHECK: movl foo at GOT
-; CHECK-NEXT: jmpl
+; CHECK:  calll foo at PLT
   %1 = tail call double @foo(double %x) nounwind readnone
   ret double %1
 }
@@ -15,10 +17,18 @@ declare double @foo(double) readnone
 
 define double @test2(double %x) nounwind readnone {
 ; CHECK-LABEL: test2:
-; CHECK: movl sin at GOT
-; CHECK-NEXT: jmpl
+; CHECK:  calll sin at PLT
   %1 = tail call double @sin(double %x) nounwind readnone
   ret double %1
 }
 
 declare double @sin(double) readnone
+
+define double @test3(double %x) nounwind readnone {
+; CHECK-LABEL: test3:
+; CHECK:  calll sin2 at PLT
+  %1 = tail call double @sin2(double %x) nounwind readnone
+  ret double %1
+}
+
+declare double @sin2(double) readnone

Modified: llvm/trunk/test/CodeGen/X86/tailcallpic1.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/tailcallpic1.ll?rev=238487&r1=238486&r2=238487&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/tailcallpic1.ll (original)
+++ llvm/trunk/test/CodeGen/X86/tailcallpic1.ll Thu May 28 15:44:28 2015
@@ -1,5 +1,8 @@
 ; RUN: llc < %s  -tailcallopt -mtriple=i686-pc-linux-gnu -relocation-model=pic | FileCheck %s
 
+; This test uses guaranteed TCO so these will be tail calls, despite the early
+; binding issues.
+
 define protected fastcc i32 @tailcallee(i32 %a1, i32 %a2, i32 %a3, i32 %a4) {
 entry:
 	ret i32 %a3

Added: llvm/trunk/test/CodeGen/X86/tailcallpic3.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/tailcallpic3.ll?rev=238487&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/X86/tailcallpic3.ll (added)
+++ llvm/trunk/test/CodeGen/X86/tailcallpic3.ll Thu May 28 15:44:28 2015
@@ -0,0 +1,73 @@
+; RUN: llc < %s -mtriple=i686-pc-linux-gnu -relocation-model=pic | FileCheck %s
+
+; While many of these could be tail called, we don't do it because it forces
+; early binding.
+
+declare void @external()
+
+define hidden void @tailcallee_hidden() {
+entry:
+  ret void
+}
+
+define void @tailcall_hidden() {
+entry:
+  tail call void @tailcallee_hidden()
+  ret void
+}
+; CHECK: tailcall_hidden:
+; CHECK: jmp tailcallee_hidden
+
+define internal void @tailcallee_internal() {
+entry:
+  ret void
+}
+
+define void @tailcall_internal() {
+entry:
+  tail call void @tailcallee_internal()
+  ret void
+}
+; CHECK: tailcall_internal:
+; CHECK: jmp tailcallee_internal
+
+define default void @tailcallee_default() {
+entry:
+  ret void
+}
+
+define void @tailcall_default() {
+entry:
+  tail call void @tailcallee_default()
+  ret void
+}
+; CHECK: tailcall_default:
+; CHECK: calll tailcallee_default at PLT
+
+define void @tailcallee_default_implicit() {
+entry:
+  ret void
+}
+
+define void @tailcall_default_implicit() {
+entry:
+  tail call void @tailcallee_default_implicit()
+  ret void
+}
+; CHECK: tailcall_default_implicit:
+; CHECK: calll tailcallee_default_implicit at PLT
+
+define void @tailcall_external() {
+  tail call void @external()
+  ret void
+}
+; CHECK: tailcall_external:
+; CHECK: calll external at PLT
+
+define void @musttail_external() {
+  musttail call void @external()
+  ret void
+}
+; CHECK: musttail_external:
+; CHECK: movl external at GOT
+; CHECK: jmpl





More information about the llvm-commits mailing list