r291865 - Improve handling of instantiated thread_local variables in Itanium C++ ABI.

Hans Wennborg via cfe-commits cfe-commits at lists.llvm.org
Fri Jan 13 08:59:05 PST 2017


Merged in r291912.

Thanks,
Hans

On Thu, Jan 12, 2017 at 5:50 PM, Richard Smith <richard at metafoo.co.uk> wrote:
> This should go onto the 4.0 branch.
>
> ---------- Forwarded message ----------
> From: Richard Smith via cfe-commits <cfe-commits at 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 at 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 at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>


More information about the cfe-commits mailing list