Merged in r291912. Thanks, Hans
On Thu, Jan 12, 2017 at 5:50 PM, Richard Smith <rich...@metafoo.co.uk> wrote: > This should go onto the 4.0 branch. > > ---------- Forwarded message ---------- > From: Richard Smith via cfe-commits <cfe-commits@lists.llvm.org> > Date: 12 January 2017 at 16:43 > Subject: r291865 - Improve handling of instantiated thread_local variables > in Itanium C++ ABI. > To: cfe-commits@lists.llvm.org > > > Author: rsmith > Date: Thu Jan 12 18:43:31 2017 > New Revision: 291865 > > URL: http://llvm.org/viewvc/llvm-project?rev=291865&view=rev > Log: > Improve handling of instantiated thread_local variables in Itanium C++ ABI. > > * Do not initialize these variables when initializing the rest of the > thread_locals in the TU; they have unordered initialization so they can > be > initialized by themselves. > > This fixes a rejects-valid bug: we would make the per-variable > initializer > function internal, but put it in a comdat keyed off the variable, > resulting > in link errors when the comdat is selected from a different TU (as the > per > TU TLS init function tries to call an init function that does not exist). > > * On Darwin, when we decide that we're not going to emit a thread wrapper > function at all, demote its linkage to External. Fixes a verifier failure > on explicit instantiation of a thread_local variable on Darwin. > > Modified: > cfe/trunk/lib/CodeGen/CGDeclCXX.cpp > cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp > cfe/trunk/test/CodeGenCXX/cxx11-thread-local.cpp > cfe/trunk/test/OpenMP/threadprivate_codegen.cpp > > Modified: cfe/trunk/lib/CodeGen/CGDeclCXX.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDeclCXX.cpp?rev=291865&r1=291864&r2=291865&view=diff > ============================================================================== > --- cfe/trunk/lib/CodeGen/CGDeclCXX.cpp (original) > +++ cfe/trunk/lib/CodeGen/CGDeclCXX.cpp Thu Jan 12 18:43:31 2017 > @@ -353,9 +353,6 @@ CodeGenModule::EmitCXXGlobalVarDeclInitF > > if (D->getTLSKind()) { > // FIXME: Should we support init_priority for thread_local? > - // FIXME: Ideally, initialization of instantiated thread_local static > data > - // members of class templates should not trigger initialization of > other > - // entities in the TU. > // FIXME: We only need to register one __cxa_thread_atexit function for > the > // entire TU. > CXXThreadLocalInits.push_back(Fn); > > Modified: cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp?rev=291865&r1=291864&r2=291865&view=diff > ============================================================================== > --- cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp (original) > +++ cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp Thu Jan 12 18:43:31 2017 > @@ -2272,7 +2272,21 @@ void ItaniumCXXABI::EmitThreadLocalInitF > ArrayRef<llvm::Function *> CXXThreadLocalInits, > ArrayRef<const VarDecl *> CXXThreadLocalInitVars) { > llvm::Function *InitFunc = nullptr; > - if (!CXXThreadLocalInits.empty()) { > + > + // Separate initializers into those with ordered (or partially-ordered) > + // initialization and those with unordered initialization. > + llvm::SmallVector<llvm::Function *, 8> OrderedInits; > + llvm::SmallDenseMap<const VarDecl *, llvm::Function *> UnorderedInits; > + for (unsigned I = 0; I != CXXThreadLocalInits.size(); ++I) { > + if (isTemplateInstantiation( > + CXXThreadLocalInitVars[I]->getTemplateSpecializationKind())) > + UnorderedInits[CXXThreadLocalInitVars[I]->getCanonicalDecl()] = > + CXXThreadLocalInits[I]; > + else > + OrderedInits.push_back(CXXThreadLocalInits[I]); > + } > + > + if (!OrderedInits.empty()) { > // Generate a guarded initialization function. > llvm::FunctionType *FTy = > llvm::FunctionType::get(CGM.VoidTy, /*isVarArg=*/false); > @@ -2289,24 +2303,28 @@ void ItaniumCXXABI::EmitThreadLocalInitF > CharUnits GuardAlign = CharUnits::One(); > Guard->setAlignment(GuardAlign.getQuantity()); > > - CodeGenFunction(CGM) > - .GenerateCXXGlobalInitFunc(InitFunc, CXXThreadLocalInits, > - Address(Guard, GuardAlign)); > + CodeGenFunction(CGM).GenerateCXXGlobalInitFunc(InitFunc, OrderedInits, > + Address(Guard, > GuardAlign)); > // On Darwin platforms, use CXX_FAST_TLS calling convention. > if (CGM.getTarget().getTriple().isOSDarwin()) { > InitFunc->setCallingConv(llvm::CallingConv::CXX_FAST_TLS); > InitFunc->addFnAttr(llvm::Attribute::NoUnwind); > } > } > + > + // Emit thread wrappers. > for (const VarDecl *VD : CXXThreadLocals) { > llvm::GlobalVariable *Var = > > cast<llvm::GlobalVariable>(CGM.GetGlobalValue(CGM.getMangledName(VD))); > + llvm::Function *Wrapper = getOrCreateThreadLocalWrapper(VD, Var); > > // 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 (isThreadWrapperReplaceable(VD, CGM) && !VD->hasDefinition()) > + if (isThreadWrapperReplaceable(VD, CGM) && !VD->hasDefinition()) { > + Wrapper->setLinkage(llvm::Function::ExternalLinkage); > continue; > + } > > // Mangle the name for the thread_local initialization function. > SmallString<256> InitFnName; > @@ -2322,18 +2340,21 @@ void ItaniumCXXABI::EmitThreadLocalInitF > bool InitIsInitFunc = false; > if (VD->hasDefinition()) { > InitIsInitFunc = true; > - if (InitFunc) > + llvm::Function *InitFuncToUse = InitFunc; > + if (isTemplateInstantiation(VD->getTemplateSpecializationKind())) > + InitFuncToUse = UnorderedInits.lookup(VD->getCanonicalDecl()); > + if (InitFuncToUse) > Init = llvm::GlobalAlias::create(Var->getLinkage(), > InitFnName.str(), > - InitFunc); > + InitFuncToUse); > } else { > // Emit a weak global function referring to the initialization > function. > // This function will not exist if the TU defining the thread_local > // variable in question does not need any dynamic initialization for > // its thread_local variables. > llvm::FunctionType *FnTy = llvm::FunctionType::get(CGM.VoidTy, > false); > - Init = llvm::Function::Create( > - FnTy, llvm::GlobalVariable::ExternalWeakLinkage, > InitFnName.str(), > - &CGM.getModule()); > + Init = llvm::Function::Create(FnTy, > + > llvm::GlobalVariable::ExternalWeakLinkage, > + InitFnName.str(), &CGM.getModule()); > const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction(); > CGM.SetLLVMFunctionAttributes(nullptr, FI, > cast<llvm::Function>(Init)); > } > @@ -2341,7 +2362,6 @@ void ItaniumCXXABI::EmitThreadLocalInitF > if (Init) > Init->setVisibility(Var->getVisibility()); > > - llvm::Function *Wrapper = getOrCreateThreadLocalWrapper(VD, Var); > llvm::LLVMContext &Context = CGM.getModule().getContext(); > llvm::BasicBlock *Entry = llvm::BasicBlock::Create(Context, "", > Wrapper); > CGBuilderTy Builder(CGM, Entry); > > Modified: cfe/trunk/test/CodeGenCXX/cxx11-thread-local.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/cxx11-thread-local.cpp?rev=291865&r1=291864&r2=291865&view=diff > ============================================================================== > --- cfe/trunk/test/CodeGenCXX/cxx11-thread-local.cpp (original) > +++ cfe/trunk/test/CodeGenCXX/cxx11-thread-local.cpp Thu Jan 12 18:43:31 > 2017 > @@ -6,18 +6,18 @@ > int f(); > int g(); > > -// LINUX: @a = thread_local global i32 0 > -// DARWIN: @a = internal thread_local global i32 0 > +// LINUX-DAG: @a = thread_local global i32 0 > +// DARWIN-DAG: @a = internal thread_local global i32 0 > thread_local int a = f(); > extern thread_local int b; > -// CHECK: @c = global i32 0 > +// CHECK-DAG: @c = global i32 0 > int c = b; > -// CHECK: @_ZL1d = internal thread_local global i32 0 > +// CHECK-DAG: @_ZL1d = internal thread_local global i32 0 > static thread_local int d = g(); > > struct U { static thread_local int m; }; > -// LINUX: @_ZN1U1mE = thread_local global i32 0 > -// DARWIN: @_ZN1U1mE = internal thread_local global i32 0 > +// LINUX-DAG: @_ZN1U1mE = thread_local global i32 0 > +// DARWIN-DAG: @_ZN1U1mE = internal thread_local global i32 0 > thread_local int U::m = f(); > > namespace MismatchedInitType { > @@ -35,37 +35,64 @@ namespace MismatchedInitType { > template<typename T> struct V { static thread_local int m; }; > template<typename T> thread_local int V<T>::m = g(); > > -// CHECK: @e = global i32 0 > -int e = V<int>::m; > +template<typename T> struct W { static thread_local int m; }; > +template<typename T> thread_local int W<T>::m = 123; > > -// CHECK: @_ZN1VIiE1mE = linkonce_odr thread_local global i32 0 > +struct Dtor { ~Dtor(); }; > +template<typename T> struct X { static thread_local Dtor m; }; > +template<typename T> thread_local Dtor X<T>::m; > > -// CHECK: @_ZZ1fvE1n = internal thread_local global i32 0 > +// CHECK-DAG: @e = global > +void *e = V<int>::m + W<int>::m + &X<int>::m; > > -// CHECK: @_ZGVZ1fvE1n = internal thread_local global i8 0 > +template thread_local int V<float>::m; > +template thread_local int W<float>::m; > +template thread_local Dtor X<float>::m; > > -// CHECK: @_ZZ8tls_dtorvE1s = internal thread_local global > -// CHECK: @_ZGVZ8tls_dtorvE1s = internal thread_local global i8 0 > +extern template thread_local int V<char>::m; > +extern template thread_local int W<char>::m; > +extern template thread_local Dtor X<char>::m; > > -// CHECK: @_ZZ8tls_dtorvE1t = internal thread_local global > -// CHECK: @_ZGVZ8tls_dtorvE1t = internal thread_local global i8 0 > +void *e2 = V<char>::m + W<char>::m + &X<char>::m; > > -// CHECK: @_ZZ8tls_dtorvE1u = internal thread_local global > -// CHECK: @_ZGVZ8tls_dtorvE1u = internal thread_local global i8 0 > -// CHECK: @_ZGRZ8tls_dtorvE1u_ = internal thread_local global > +// CHECK-DAG: @_ZN1VIiE1mE = linkonce_odr thread_local global i32 0 > +// CHECK-DAG: @_ZN1WIiE1mE = linkonce_odr thread_local global i32 123 > +// CHECK-DAG: @_ZN1XIiE1mE = linkonce_odr thread_local global {{.*}} > +// CHECK-DAG: @_ZN1VIfE1mE = weak_odr thread_local global i32 0 > +// CHECK-DAG: @_ZN1WIfE1mE = weak_odr thread_local global i32 123 > +// CHECK-DAG: @_ZN1XIfE1mE = weak_odr thread_local global {{.*}} > > -// CHECK: @_ZGVN1VIiE1mE = linkonce_odr thread_local global i64 0 > +// CHECK-DAG: @_ZZ1fvE1n = internal thread_local global i32 0 > > -// CHECK: @__tls_guard = internal thread_local global i8 0 > +// CHECK-DAG: @_ZGVZ1fvE1n = internal thread_local global i8 0 > > -// CHECK: @llvm.global_ctors = appending global {{.*}} @[[GLOBAL_INIT:[^ > ]*]] > +// CHECK-DAG: @_ZZ8tls_dtorvE1s = internal thread_local global > +// CHECK-DAG: @_ZGVZ8tls_dtorvE1s = internal thread_local global i8 0 > > -// LINUX: @_ZTH1a = alias void (), void ()* @__tls_init > -// DARWIN: @_ZTH1a = internal alias void (), void ()* @__tls_init > -// CHECK: @_ZTHL1d = internal alias void (), void ()* @__tls_init > -// LINUX: @_ZTHN1U1mE = alias void (), void ()* @__tls_init > -// DARWIN: @_ZTHN1U1mE = internal alias void (), void ()* @__tls_init > -// CHECK: @_ZTHN1VIiE1mE = linkonce_odr alias void (), void ()* @__tls_init > +// CHECK-DAG: @_ZZ8tls_dtorvE1t = internal thread_local global > +// CHECK-DAG: @_ZGVZ8tls_dtorvE1t = internal thread_local global i8 0 > + > +// CHECK-DAG: @_ZZ8tls_dtorvE1u = internal thread_local global > +// CHECK-DAG: @_ZGVZ8tls_dtorvE1u = internal thread_local global i8 0 > +// CHECK-DAG: @_ZGRZ8tls_dtorvE1u_ = internal thread_local global > + > +// CHECK-DAG: @_ZGVN1VIiE1mE = linkonce_odr thread_local global i64 0 > + > +// CHECK-DAG: @__tls_guard = internal thread_local global i8 0 > + > +// CHECK-DAG: @llvm.global_ctors = appending global {{.*}} > @[[GLOBAL_INIT:[^ ]*]] > + > +// LINUX-DAG: @_ZTH1a = alias void (), void ()* @__tls_init > +// DARWIN-DAG: @_ZTH1a = internal alias void (), void ()* @__tls_init > +// CHECK-DAG: @_ZTHL1d = internal alias void (), void ()* @__tls_init > +// LINUX-DAG: @_ZTHN1U1mE = alias void (), void ()* @__tls_init > +// DARWIN-DAG: @_ZTHN1U1mE = internal alias void (), void ()* @__tls_init > +// CHECK-DAG: @_ZTHN1VIiE1mE = linkonce_odr alias void (), void ()* > @[[V_M_INIT:[^, ]*]] > +// CHECK-NOT: @_ZTHN1WIiE1mE = > +// CHECK-DAG: @_ZTHN1XIiE1mE = linkonce_odr alias void (), void ()* > @[[X_M_INIT:[^, ]*]] > +// CHECK-DAG: @_ZTHN1VIfE1mE = weak_odr alias void (), void ()* > @[[VF_M_INIT:[^, ]*]] > +// CHECK-NOT: @_ZTHN1WIfE1mE = > +// CHECK-DAG: @_ZTHN1XIfE1mE = weak_odr alias void (), void ()* > @[[XF_M_INIT:[^, ]*]] > > > // Individual variable initialization functions: > @@ -118,7 +145,9 @@ int f() { > // LINUX: call i32* @_ZTWN1VIiE1mE() > // DARWIN: call cxx_fast_tlscc i32* @_ZTWN1VIiE1mE() > // CHECK-NEXT: load i32, i32* %{{.*}}, align 4 > -// CHECK-NEXT: store i32 %{{.*}}, i32* @e, align 4 > +// LINUX: call {{.*}}* @_ZTWN1XIiE1mE() > +// DARWIN: call cxx_fast_tlscc {{.*}}* @_ZTWN1XIiE1mE() > +// CHECK: store {{.*}} @e > > // LINUX-LABEL: define weak_odr hidden i32* @_ZTWN1VIiE1mE() > // DARWIN-LABEL: define weak_odr hidden cxx_fast_tlscc i32* > @_ZTWN1VIiE1mE() > @@ -126,6 +155,64 @@ int f() { > // DARWIN: call cxx_fast_tlscc void @_ZTHN1VIiE1mE() > // CHECK: ret i32* @_ZN1VIiE1mE > > +// LINUX-LABEL: define weak_odr hidden i32* @_ZTWN1WIiE1mE() > +// DARWIN-LABEL: define weak_odr hidden cxx_fast_tlscc i32* > @_ZTWN1WIiE1mE() > +// CHECK-NOT: call > +// CHECK: ret i32* @_ZN1WIiE1mE > + > +// LINUX-LABEL: define weak_odr hidden {{.*}}* @_ZTWN1XIiE1mE() > +// DARWIN-LABEL: define weak_odr hidden cxx_fast_tlscc {{.*}}* > @_ZTWN1XIiE1mE() > +// LINUX: call void @_ZTHN1XIiE1mE() > +// DARWIN: call cxx_fast_tlscc void @_ZTHN1XIiE1mE() > +// CHECK: ret {{.*}}* @_ZN1XIiE1mE > + > +// CHECK: define internal {{.*}} @[[VF_M_INIT]]() > +// LINUX-SAME: comdat($_ZN1VIfE1mE) > +// DARWIN-NOT: comdat > +// CHECK: load i8, i8* bitcast (i64* @_ZGVN1VIfE1mE to i8*) > +// CHECK: %[[VF_M_INITIALIZED:.*]] = icmp eq i8 %{{.*}}, 0 > +// CHECK: br i1 %[[VF_M_INITIALIZED]], > +// need init: > +// CHECK: call i32 @_Z1gv() > +// CHECK: store i32 %{{.*}}, i32* @_ZN1VIfE1mE, align 4 > +// CHECK: store i64 1, i64* @_ZGVN1VIfE1mE > +// CHECK: br label > + > +// CHECK: define internal {{.*}} @[[XF_M_INIT]]() > +// LINUX-SAME: comdat($_ZN1XIfE1mE) > +// DARWIN-NOT: comdat > +// CHECK: load i8, i8* bitcast (i64* @_ZGVN1XIfE1mE to i8*) > +// CHECK: %[[XF_M_INITIALIZED:.*]] = icmp eq i8 %{{.*}}, 0 > +// CHECK: br i1 %[[XF_M_INITIALIZED]], > +// need init: > +// LINUX: call {{.*}}__cxa_thread_atexit > +// DARWIN: call {{.*}}_tlv_atexit > +// CHECK: store i64 1, i64* @_ZGVN1XIfE1mE > +// CHECK: br label > + > +// LINUX: declare i32 @__cxa_thread_atexit(void (i8*)*, i8*, i8*) > +// DARWIN: declare i32 @_tlv_atexit(void (i8*)*, i8*, i8*) > + > +// DARWIN: declare cxx_fast_tlscc i32* @_ZTWN1VIcE1mE() > +// LINUX: define weak_odr hidden i32* @_ZTWN1VIcE1mE() > +// LINUX-NOT: comdat > +// LINUX: br i1 icmp ne (void ()* @_ZTHN1VIcE1mE, > +// LINUX: call void @_ZTHN1VIcE1mE() > +// LINUX: ret i32* @_ZN1VIcE1mE > + > +// DARWIN: declare cxx_fast_tlscc i32* @_ZTWN1WIcE1mE() > +// LINUX: define weak_odr hidden i32* @_ZTWN1WIcE1mE() > +// LINUX-NOT: comdat > +// LINUX: br i1 icmp ne (void ()* @_ZTHN1WIcE1mE, > +// LINUX: call void @_ZTHN1WIcE1mE() > +// LINUX: ret i32* @_ZN1WIcE1mE > + > +// DARWIN: declare cxx_fast_tlscc {{.*}}* @_ZTWN1XIcE1mE() > +// LINUX: define weak_odr hidden {{.*}}* @_ZTWN1XIcE1mE() > +// LINUX-NOT: comdat > +// LINUX: br i1 icmp ne (void ()* @_ZTHN1XIcE1mE, > +// LINUX: call void @_ZTHN1XIcE1mE() > +// LINUX: ret {{.*}}* @_ZN1XIcE1mE > > struct S { S(); ~S(); }; > struct T { ~T(); }; > @@ -154,9 +241,6 @@ void tls_dtor() { > static thread_local const S &u = S(); > } > > -// LINUX: declare i32 @__cxa_thread_atexit(void (i8*)*, i8*, i8*) > -// DARWIN: declare i32 @_tlv_atexit(void (i8*)*, i8*, i8*) > - > // CHECK: define {{.*}} @_Z7PR15991v( > int PR15991() { > thread_local int n; > @@ -184,7 +268,9 @@ void set_anon_i() { > // LINUX-LABEL: define internal i32* @_ZTWN12_GLOBAL__N_16anon_iE() > // DARWIN-LABEL: define internal cxx_fast_tlscc i32* > @_ZTWN12_GLOBAL__N_16anon_iE() > > -// CHECK: define {{.*}} @[[V_M_INIT:.*]]() > +// CHECK: define internal {{.*}} @[[V_M_INIT]]() > +// LINUX-SAME: comdat($_ZN1VIiE1mE) > +// DARWIN-NOT: comdat > // CHECK: load i8, i8* bitcast (i64* @_ZGVN1VIiE1mE to i8*) > // CHECK: %[[V_M_INITIALIZED:.*]] = icmp eq i8 %{{.*}}, 0 > // CHECK: br i1 %[[V_M_INITIALIZED]], > @@ -194,6 +280,18 @@ void set_anon_i() { > // CHECK: store i64 1, i64* @_ZGVN1VIiE1mE > // CHECK: br label > > +// CHECK: define internal {{.*}} @[[X_M_INIT]]() > +// LINUX-SAME: comdat($_ZN1XIiE1mE) > +// DARWIN-NOT: comdat > +// CHECK: load i8, i8* bitcast (i64* @_ZGVN1XIiE1mE to i8*) > +// CHECK: %[[X_M_INITIALIZED:.*]] = icmp eq i8 %{{.*}}, 0 > +// CHECK: br i1 %[[X_M_INITIALIZED]], > +// need init: > +// LINUX: call {{.*}}__cxa_thread_atexit > +// DARWIN: call {{.*}}_tlv_atexit > +// CHECK: store i64 1, i64* @_ZGVN1XIiE1mE > +// CHECK: br label > + > // CHECK: define {{.*}}@[[GLOBAL_INIT:.*]]() > // CHECK: call void @[[C_INIT]]() > // CHECK: call void @[[E_INIT]]() > @@ -205,10 +303,13 @@ void set_anon_i() { > // CHECK: br i1 %[[NEED_TLS_INIT]], > // init: > // CHECK: store i8 1, i8* @__tls_guard > +// CHECK-NOT: call void @[[V_M_INIT]]() > // CHECK: call void @[[A_INIT]]() > +// CHECK-NOT: call void @[[V_M_INIT]]() > // CHECK: call void @[[D_INIT]]() > +// CHECK-NOT: call void @[[V_M_INIT]]() > // CHECK: call void @[[U_M_INIT]]() > -// CHECK: call void @[[V_M_INIT]]() > +// CHECK-NOT: call void @[[V_M_INIT]]() > > > // LIUNX: define weak_odr hidden i32* @_ZTW1a() { > > Modified: cfe/trunk/test/OpenMP/threadprivate_codegen.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/threadprivate_codegen.cpp?rev=291865&r1=291864&r2=291865&view=diff > ============================================================================== > --- cfe/trunk/test/OpenMP/threadprivate_codegen.cpp (original) > +++ cfe/trunk/test/OpenMP/threadprivate_codegen.cpp Thu Jan 12 18:43:31 2017 > @@ -179,9 +179,9 @@ struct S5 { > // CHECK-TLS-DAG: @__dso_handle = external global i8 > // CHECK-TLS-DAG: [[GS1_TLS_INIT:@_ZTHL3gs1]] = internal alias void (), > void ()* @__tls_init > // CHECK-TLS-DAG: [[ARR_X_TLS_INIT:@_ZTH5arr_x]] = alias void (), void ()* > @__tls_init > -// CHECK-TLS-DAG: [[ST_INT_ST_TLS_INIT:@_ZTHN2STIiE2stE]] = linkonce_odr > alias void (), void ()* @__tls_init > -// CHECK-TLS-DAG: [[ST_FLOAT_ST_TLS_INIT:@_ZTHN2STIfE2stE]] = linkonce_odr > alias void (), void ()* @__tls_init > -// CHECK-TLS-DAG: [[ST_S4_ST_TLS_INIT:@_ZTHN2STI2S4E2stE]] = linkonce_odr > alias void (), void ()* @__tls_init > + > + > +// CHECK-TLS-DAG: [[ST_S4_ST_TLS_INIT:@_ZTHN2STI2S4E2stE]] = linkonce_odr > alias void (), void ()* [[ST_S4_ST_CXX_INIT:@[^, ]*]] > > struct Static { > static S3 s; > @@ -640,11 +640,11 @@ int main() { > // CHECK-TLS: ret [2 x [3 x [[S1]]]]* [[ARR_X]] > // CHECK-TLS: } > // CHECK-TLS: define {{.*}} i32* [[ST_INT_ST_TLS_INITD]] {{#[0-9]+}} { > -// CHECK-TLS: call void [[ST_INT_ST_TLS_INIT]] > +// CHECK-TLS-NOT: call > // CHECK-TLS: ret i32* [[ST_INT_ST]] > // CHECK-TLS: } > // CHECK-TLS: define {{.*}} float* [[ST_FLOAT_ST_TLS_INITD]] {{#[0-9]+}} { > -// CHECK-TLS: call void [[ST_FLOAT_ST_TLS_INIT]] > +// CHECK-TLS-NOT: call > // CHECK-TLS: ret float* [[ST_FLOAT_ST]] > // CHECK-TLS: } > // CHECK-TLS: define {{.*}} [[S4]]* [[ST_S4_ST_TLS_INITD]] {{#[0-9]+}} { > @@ -923,7 +923,7 @@ int foobar() { > // CHECK-TLS: define {{.*}}void [[SM_CTOR2]]([[SMAIN]]* {{.*}}, i32 {{.*}}) > // CHECK-TLS: define {{.*}}void [[SM_DTOR2]]([[SMAIN]]* {{.*}}) > > -// CHECK-TLS: define internal void [[ST_S4_ST_CXX_INIT:@.*]]() > +// CHECK-TLS: define internal void [[ST_S4_ST_CXX_INIT]]() > // CHECK-TLS: call void [[ST_S4_ST_CTOR1:@.*]]([[S4]]* [[ST_S4_ST]], i32 > 23) > // CHECK-TLS: call i32 @__cxa_thread_atexit(void (i8*)* bitcast (void > ([[S4]]*)* [[ST_S4_ST_DTOR1:.*]] to void (i8*)*), i8* bitcast ([[S4]]* > [[ST_S4_ST]] to i8*) > // CHECK-TLS: } > @@ -945,7 +945,7 @@ int foobar() { > // CHECK-TLS: call void [[GS1_CXX_INIT]] > // CHECK-TLS-NOT: call void [[GS2_CXX_INIT]] > // CHECK-TLS: call void [[ARR_X_CXX_INIT]] > -// CHECK-TLS: call void [[ST_S4_ST_CXX_INIT]] > +// CHECK-TLS-NOT: call void [[ST_S4_ST_CXX_INIT]] > // CHECK-TLS: [[DONE_LABEL]] > > // CHECK-TLS-DAG: declare {{.*}} void [[GS3_TLS_INIT]] > > > _______________________________________________ > cfe-commits mailing list > cfe-commits@lists.llvm.org > http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits > _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits