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@XZ" // CHECK: call i32 @atexit(void ()* [[FOO_DTOR:@"__dtor_.*foo@.*]]) // 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 _______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
