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

Richard Smith richard at metafoo.co.uk
Tue Sep 3 15:14:11 PDT 2013


On Thu, Aug 22, 2013 at 1:07 PM, Reid Kleckner <reid at kleckner.net> wrote:

> 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);
>

This is incorrect: explicit specializations of static data members of class
templates have ordered initialization. This is causing a regression on code
such as:

int f();
template<typename T> struct S { static T x; static T y; };
template<> int S<int>::x = f();
template<> int S<int>::y = S<int>::x;

Here, 'x' is guaranteed to be initialized before 'y', but with your patch,
this property is not maintained, and globalopt will remove 'y's initializer.


>    } 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
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20130903/235f7518/attachment.html>


More information about the cfe-commits mailing list