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,6 +2,8 @@ // CHECK: @a = internal thread_local global // CHECK: @_tlv_atexit({{.*}}@_ZN1AD1Ev +// CHECK: call {{.*}} @_ZTW3ext() +// CHECK: declare hidden {{.*}} @_ZTW3ext() // CHECK: define weak hidden {{.*}} @_ZTW1a struct A { @@ -9,3 +11,8 @@ }; thread_local A a; + +extern thread_local A ext; +A &get_ext() { + return ext; +}