[PATCH] CodeGen: Don't emit a thread-wrapper if we can't touch the backing variable

David Majnemer david.majnemer at gmail.com
Thu Jun 12 02:17:04 PDT 2014


Hi rsmith, rjmccall,

OS X TLS has all accesses going through the thread-wrapper function and
gives the backing thread-local variable internal linkage.  This means
that thread-wrappers must have WeakAnyLinkage so that references to the
internal thread-local variables do not get propagated to other code.

It also means that translation units which do not provide a definition
for the thread-local variable cannot attempt to emit a thread-wrapper
because the thread wrapper will attempt to reference the backing
variable.

http://reviews.llvm.org/D4109

Files:
  lib/CodeGen/ItaniumCXXABI.cpp
  test/CodeGenCXX/tls-init-funcs.cpp

Index: lib/CodeGen/ItaniumCXXABI.cpp
===================================================================
--- lib/CodeGen/ItaniumCXXABI.cpp
+++ lib/CodeGen/ItaniumCXXABI.cpp
@@ -1572,6 +1572,15 @@
   CGF.registerGlobalDtorWithAtExit(D, dtor, addr);
 }
 
+static bool
+isThreadLocalBackingVariableAlwaysReferenceable(const VarDecl *VD,
+                                                CodeGen::CodeGenModule &CGM) {
+  // OS X prefers to have references to thread local variables to go through
+  // the thread wrapper instead of directly referencing the backing variable.
+  return VD->getTLSKind() != VarDecl::TLS_Dynamic ||
+         !CGM.getTarget().getTriple().isMacOSX();
+}
+
 /// Get the appropriate linkage for the wrapper function. This is essentially
 /// the weak form of the variable's linkage; every translation unit which wneeds
 /// the wrapper emits a copy, and we want the linker to merge them.
@@ -1584,12 +1593,11 @@
   if (llvm::GlobalValue::isLocalLinkage(VarLinkage))
     return VarLinkage;
 
-  // All accesses to the thread_local variable go through the thread wrapper.
-  // However, this means that we cannot allow the thread wrapper to get inlined
-  // into any functions.
-  if (VD->getTLSKind() == VarDecl::TLS_Dynamic &&
-      CGM.getTarget().getTriple().isMacOSX())
-    return llvm::GlobalValue::WeakAnyLinkage;
+  // The thread wrapper can't be inlined if the backing variable cannot always
+  // be referenced.
+  if (!isThreadLocalBackingVariableAlwaysReferenceable(VD, CGM))
+    return VD->hasDefinition() ? llvm::GlobalValue::WeakAnyLinkage
+                               : llvm::GlobalValue::ExternalLinkage;
   return llvm::GlobalValue::WeakODRLinkage;
 }
 
@@ -1628,6 +1636,13 @@
     const VarDecl *VD = Decls[I].first;
     llvm::GlobalVariable *Var = Decls[I].second;
 
+    // Some targets require that all access to thread local variables go through
+    // the thread wrapper.  This means that we cannot attempt to create a thread
+    // wrapper or a thread helper.
+    if (!isThreadLocalBackingVariableAlwaysReferenceable(VD, CGM) &&
+        !VD->hasDefinition())
+      continue;
+
     // Mangle the name for the thread_local initialization function.
     SmallString<256> InitFnName;
     {
Index: test/CodeGenCXX/tls-init-funcs.cpp
===================================================================
--- test/CodeGenCXX/tls-init-funcs.cpp
+++ test/CodeGenCXX/tls-init-funcs.cpp
@@ -2,10 +2,17 @@
 
 // CHECK: @a = internal thread_local global
 // CHECK: @_tlv_atexit({{.*}}@_ZN1AD1Ev
+// CHECK: call {{.*}} @_ZTW3ext()
+// CHECK: declare hidden {{.*}} @_ZTW3ext()
 // CHECK: define weak hidden {{.*}} @_ZTW1a
 
 struct A {
   ~A();
 };
 
 thread_local A a;
+
+extern thread_local A ext;
+A &get_ext() {
+  return ext;
+}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D4109.10343.patch
Type: text/x-patch
Size: 2779 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20140612/911f440b/attachment.bin>


More information about the cfe-commits mailing list