r219806 - Don't use a global_ctors comdat for globals that aren't externally visible

Reid Kleckner reid at kleckner.net
Wed Oct 15 09:38:01 PDT 2014


Author: rnk
Date: Wed Oct 15 11:38:00 2014
New Revision: 219806

URL: http://llvm.org/viewvc/llvm-project?rev=219806&view=rev
Log:
Don't use a global_ctors comdat for globals that aren't externally visible

In particular, if you have two identical templates in different TUs in
anonymous namespaces, we would use the same global_ctors comdat key for
both. As a result, only one would be run.

Modified:
    cfe/trunk/lib/CodeGen/CGDeclCXX.cpp
    cfe/trunk/test/CodeGenCXX/static-member-variable-explicit-specialization.cpp

Modified: cfe/trunk/lib/CodeGen/CGDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDeclCXX.cpp?rev=219806&r1=219805&r2=219806&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGDeclCXX.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGDeclCXX.cpp Wed Oct 15 11:38:00 2014
@@ -292,7 +292,8 @@ CodeGenModule::EmitCXXGlobalVarDeclInitF
   CodeGenFunction(*this).GenerateCXXGlobalVarDeclInitFunc(Fn, D, Addr,
                                                           PerformInit);
 
-  llvm::GlobalVariable *Key = supportsCOMDAT() ? Addr : nullptr;
+  llvm::GlobalVariable *COMDATKey =
+      supportsCOMDAT() && D->isExternallyVisible() ? Addr : nullptr;
 
   if (D->getTLSKind()) {
     // FIXME: Should we support init_priority for thread_local?
@@ -310,8 +311,7 @@ CodeGenModule::EmitCXXGlobalVarDeclInitF
     OrderGlobalInits Key(IPA->getPriority(), PrioritizedCXXGlobalInits.size());
     PrioritizedCXXGlobalInits.push_back(std::make_pair(Key, Fn));
     DelayedCXXInitPosition.erase(D);
-  } else if (D->getTemplateSpecializationKind() != TSK_ExplicitSpecialization &&
-             D->getTemplateSpecializationKind() != TSK_Undeclared) {
+  } else if (isTemplateInstantiation(D->getTemplateSpecializationKind())) {
     // C++ [basic.start.init]p2:
     //   Definitions of explicitly specialized class template static data
     //   members have ordered initialization. Other class template static data
@@ -320,16 +320,16 @@ CodeGenModule::EmitCXXGlobalVarDeclInitF
     //
     // As a consequence, we can put them into their own llvm.global_ctors entry.
     //
-    // In addition, put the initializer into a COMDAT group with the global
-    // being initialized.  On most platforms, this is a minor startup time
-    // optimization.  In the MS C++ ABI, there are no guard variables, so this
-    // COMDAT key is required for correctness.
-    AddGlobalCtor(Fn, 65535, Key);
+    // If the global is externally visible, put the initializer into a COMDAT
+    // group with the global being initialized.  On most platforms, this is a
+    // minor startup time optimization.  In the MS C++ ABI, there are no guard
+    // variables, so this COMDAT key is required for correctness.
+    AddGlobalCtor(Fn, 65535, COMDATKey);
     DelayedCXXInitPosition.erase(D);
   } else if (D->hasAttr<SelectAnyAttr>()) {
     // SelectAny globals will be comdat-folded. Put the initializer into a COMDAT
     // group associated with the global, so the initializers get folded too.
-    AddGlobalCtor(Fn, 65535, Key);
+    AddGlobalCtor(Fn, 65535, COMDATKey);
     DelayedCXXInitPosition.erase(D);
   } else {
     llvm::DenseMap<const Decl *, unsigned>::iterator I =

Modified: cfe/trunk/test/CodeGenCXX/static-member-variable-explicit-specialization.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/static-member-variable-explicit-specialization.cpp?rev=219806&r1=219805&r2=219806&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/static-member-variable-explicit-specialization.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/static-member-variable-explicit-specialization.cpp Wed Oct 15 11:38:00 2014
@@ -14,7 +14,7 @@ template<> int A<char>::a;
 // ALL: @_ZN1AIbE1aE = global i32 10
 template<> int A<bool>::a = 10;
 
-// ALL: @llvm.global_ctors = appending global [7 x { i32, void ()*, i8* }]
+// ALL: @llvm.global_ctors = appending global [8 x { i32, void ()*, i8* }]
 
 // ELF: [{ i32, void ()*, i8* } { i32 65535, void ()* @[[unordered1:[^,]*]], i8* bitcast (i32* @_ZN1AIsE1aE to i8*) },
 // MACHO: [{ i32, void ()*, i8* } { i32 65535, void ()* @[[unordered1:[^,]*]], i8* null },
@@ -34,6 +34,8 @@ template<> int A<bool>::a = 10;
 // ELF:  { i32, void ()*, i8* } { i32 65535, void ()* @[[unordered6:[^,]*]], i8* @_Z1xIcE },
 // MACHO:  { i32, void ()*, i8* } { i32 65535, void ()* @[[unordered6:[^,]*]], i8* null },
 
+// ALL:  { i32, void ()*, i8* } { i32 65535, void ()* @[[unordered7:[^,]*]], i8* null },
+
 // ALL:  { i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__sub_I_static_member_variable_explicit_specialization.cpp, i8* null }]
 
 template int A<short>::a;  // Unordered
@@ -67,6 +69,13 @@ struct b {
 template<typename T> T b::i = foo();
 template int b::i<int>;
 }
+
+namespace {
+template<typename T> struct Internal { static int a; };
+template<typename T> int Internal<T>::a = foo();
+}
+int *use_internal_a = &Internal<int>::a;
+
 // ALL: define internal void @[[unordered1]]
 // ALL: call i32 @foo()
 // ALL: store {{.*}} @_ZN1AIsE1aE
@@ -97,6 +106,11 @@ template int b::i<int>;
 // ALL: store {{.*}} @_Z1xIcE
 // ALL: ret
 
+// ALL: define internal void @[[unordered7]]
+// ALL: call i32 @foo()
+// ALL: store {{.*}} @_ZN12_GLOBAL__N_18InternalIiE1aE
+// ALL: ret
+
 // ALL: define internal void @_GLOBAL__sub_I_static_member_variable_explicit_specialization.cpp()
 //   We call unique stubs for every ordered dynamic initializer in the TU.
 // ALL: call





More information about the cfe-commits mailing list