r189051 - Add a separate llvm.global_ctors entry for linkonce_odr data initializers

Reid Kleckner reid at kleckner.net
Thu Aug 22 13:07:45 PDT 2013


Author: rnk
Date: Thu Aug 22 15:07:45 2013
New Revision: 189051

URL: http://llvm.org/viewvc/llvm-project?rev=189051&view=rev
Log:
Add a separate llvm.global_ctors entry for linkonce_odr data initializers

Summary:
These typically come from static data members of class template
specializations.  This accomplishes two things:

1. May expose GlobalOpt optimizations for Itanium C++ ABI code.
2. Works toward fixing double initialization in the Microsoft C++ ABI.

CC: cfe-commits

Differential Revision: http://llvm-reviews.chandlerc.com/D1475

Modified:
    cfe/trunk/lib/CodeGen/CGDeclCXX.cpp
    cfe/trunk/test/CodeGenCXX/microsoft-abi-static-initializers.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=189051&r1=189050&r2=189051&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGDeclCXX.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGDeclCXX.cpp Thu Aug 22 15:07:45 2013
@@ -278,6 +278,19 @@ CodeGenModule::EmitCXXGlobalVarDeclInitF
     OrderGlobalInits Key(order, PrioritizedCXXGlobalInits.size());
     PrioritizedCXXGlobalInits.push_back(std::make_pair(Key, Fn));
     DelayedCXXInitPosition.erase(D);
+  } else if (D->getInstantiatedFromStaticDataMember()) {
+    // C++ [basic.start.init]p2:
+    //   Defnitions of explicitly specialized class template static data members
+    //   have ordered initialization. Other class template static data members
+    //   (i.e., implicitly or explicitly instantiated specializations) have
+    //   unordered initialization.
+    //
+    // As a consequence, we can put them into their own llvm.global_ctors entry.
+    // This should allow GlobalOpt to fire more often, and allow us to implement
+    // the Microsoft C++ ABI, which uses COMDAT elimination to avoid double
+    // initializaiton.
+    AddGlobalCtor(Fn);
+    DelayedCXXInitPosition.erase(D);
   } else {
     llvm::DenseMap<const Decl *, unsigned>::iterator I =
       DelayedCXXInitPosition.find(D);

Modified: cfe/trunk/test/CodeGenCXX/microsoft-abi-static-initializers.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/microsoft-abi-static-initializers.cpp?rev=189051&r1=189050&r2=189051&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/microsoft-abi-static-initializers.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/microsoft-abi-static-initializers.cpp Thu Aug 22 15:07:45 2013
@@ -1,5 +1,9 @@
 // RUN: %clang_cc1 -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 | FileCheck %s
 
+// CHECK: @llvm.global_ctors = appending global [2 x { i32, void ()* }]
+// CHECK: [{ i32, void ()* } { i32 65535, void ()* [[INIT_foo:@.*global_var.*]] },
+// CHECK:  { i32, void ()* } { i32 65535, void ()* @_GLOBAL__I_a }]
+
 struct S {
   S() {}
   ~S() {}
@@ -33,7 +37,7 @@ void force_usage() {
   (void)B<int>::foo;  // (void) - force usage
 }
 
-// CHECK: define internal void [[INIT_foo:@.*global_var.*]] [[NUW]]
+// CHECK: define internal void [[INIT_foo]]() [[NUW]]
 // CHECK: %{{[.0-9A-Z_a-z]+}} = call x86_thiscallcc %class.A* @"\01??0A@@QAE at XZ"
 // CHECK: call i32 @atexit(void ()* [[FOO_DTOR:@"__dtor_.*foo at .*]])
 // CHECK: ret void
@@ -48,7 +52,6 @@ void force_usage() {
 
 // CHECK: define internal void @_GLOBAL__I_a() [[NUW]] {
 // CHECK: call void [[INIT_s]]
-// CHECK: call void [[INIT_foo]]
 // CHECK: ret void
 
 // CHECK: attributes [[NUW]] = { nounwind }

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=189051&r1=189050&r2=189051&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/static-member-variable-explicit-specialization.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/static-member-variable-explicit-specialization.cpp Thu Aug 22 15:07:45 2013
@@ -1,5 +1,6 @@
 // RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s
 // CHECK: ; ModuleID
+
 template<typename> struct A { static int a; };
 
 // CHECK-NOT: @_ZN1AIcE1aE
@@ -8,4 +9,28 @@ template<> int A<char>::a;
 // CHECK: @_ZN1AIbE1aE = global i32 10
 template<> int A<bool>::a = 10;
 
+// CHECK: @llvm.global_ctors = appending global [2 x { i32, void ()* }]
+// CHECK: [{ i32, void ()* } { i32 65535, void ()* @__cxx_global_var_init },
+// CHECK:  { i32, void ()* } { i32 65535, void ()* @_GLOBAL__I_a }]
+
+extern "C" int foo();
+template<> int A<short>::a = foo();  // Separate global_ctor entry
+int b = foo();  // Goes in _GLOBAL__I_a
+int c = foo();  // Goes in _GLOBAL__I_a
+
+// An explicit specialization is ordered, and goes in __GLOBAL_I_a.
+template<> struct A<int> { static int a; };
+int A<int>::a = foo();
+
+// CHECK: define internal void @__cxx_global_var_init()
+// CHECK: call i32 @foo()
+// CHECK: store {{.*}} @_ZN1AIsE1aE
+// CHECK: ret
 
+// CHECK: define internal void @_GLOBAL__I_a()
+//   We call unique stubs for every ordered dynamic initializer in the TU.
+// CHECK: call
+// CHECK: call
+// CHECK: call
+// CHECK-NOT: call
+// CHECK: ret





More information about the cfe-commits mailing list