<div dir="ltr">On Thu, Aug 22, 2013 at 1:07 PM, Reid Kleckner <span dir="ltr"><<a href="mailto:reid@kleckner.net" target="_blank">reid@kleckner.net</a>></span> wrote:<br><div class="gmail_extra"><div class="gmail_quote">
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">Author: rnk<br>
Date: Thu Aug 22 15:07:45 2013<br>
New Revision: 189051<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=189051&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=189051&view=rev</a><br>
Log:<br>
Add a separate llvm.global_ctors entry for linkonce_odr data initializers<br>
<br>
Summary:<br>
These typically come from static data members of class template<br>
specializations.  This accomplishes two things:<br>
<br>
1. May expose GlobalOpt optimizations for Itanium C++ ABI code.<br>
2. Works toward fixing double initialization in the Microsoft C++ ABI.<br>
<br>
CC: cfe-commits<br>
<br>
Differential Revision: <a href="http://llvm-reviews.chandlerc.com/D1475" target="_blank">http://llvm-reviews.chandlerc.com/D1475</a><br>
<br>
Modified:<br>
    cfe/trunk/lib/CodeGen/CGDeclCXX.cpp<br>
    cfe/trunk/test/CodeGenCXX/microsoft-abi-static-initializers.cpp<br>
    cfe/trunk/test/CodeGenCXX/static-member-variable-explicit-specialization.cpp<br>
<br>
Modified: cfe/trunk/lib/CodeGen/CGDeclCXX.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDeclCXX.cpp?rev=189051&r1=189050&r2=189051&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDeclCXX.cpp?rev=189051&r1=189050&r2=189051&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/CodeGen/CGDeclCXX.cpp (original)<br>
+++ cfe/trunk/lib/CodeGen/CGDeclCXX.cpp Thu Aug 22 15:07:45 2013<br>
@@ -278,6 +278,19 @@ CodeGenModule::EmitCXXGlobalVarDeclInitF<br>
     OrderGlobalInits Key(order, PrioritizedCXXGlobalInits.size());<br>
     PrioritizedCXXGlobalInits.push_back(std::make_pair(Key, Fn));<br>
     DelayedCXXInitPosition.erase(D);<br>
+  } else if (D->getInstantiatedFromStaticDataMember()) {<br>
+    // C++ [basic.start.init]p2:<br>
+    //   Defnitions of explicitly specialized class template static data members<br>
+    //   have ordered initialization. Other class template static data members<br>
+    //   (i.e., implicitly or explicitly instantiated specializations) have<br>
+    //   unordered initialization.<br>
+    //<br>
+    // As a consequence, we can put them into their own llvm.global_ctors entry.<br>
+    // This should allow GlobalOpt to fire more often, and allow us to implement<br>
+    // the Microsoft C++ ABI, which uses COMDAT elimination to avoid double<br>
+    // initializaiton.<br>
+    AddGlobalCtor(Fn);<br>
+    DelayedCXXInitPosition.erase(D);<br></blockquote><div><br></div><div>This is incorrect: explicit specializations of static data members of class templates have ordered initialization. This is causing a regression on code such as:</div>
<div><br></div><div>int f();</div><div>template<typename T> struct S { static T x; static T y; };</div><div>template<> int S<int>::x = f();</div><div>template<> int S<int>::y = S<int>::x;<br>
</div><div><br></div><div>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.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">

   } else {<br>
     llvm::DenseMap<const Decl *, unsigned>::iterator I =<br>
       DelayedCXXInitPosition.find(D);<br>
<br>
Modified: cfe/trunk/test/CodeGenCXX/microsoft-abi-static-initializers.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/microsoft-abi-static-initializers.cpp?rev=189051&r1=189050&r2=189051&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/microsoft-abi-static-initializers.cpp?rev=189051&r1=189050&r2=189051&view=diff</a><br>

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

==============================================================================<br>
--- cfe/trunk/test/CodeGenCXX/static-member-variable-explicit-specialization.cpp (original)<br>
+++ cfe/trunk/test/CodeGenCXX/static-member-variable-explicit-specialization.cpp Thu Aug 22 15:07:45 2013<br>
@@ -1,5 +1,6 @@<br>
 // RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s<br>
 // CHECK: ; ModuleID<br>
+<br>
 template<typename> struct A { static int a; };<br>
<br>
 // CHECK-NOT: @_ZN1AIcE1aE<br>
@@ -8,4 +9,28 @@ template<> int A<char>::a;<br>
 // CHECK: @_ZN1AIbE1aE = global i32 10<br>
 template<> int A<bool>::a = 10;<br>
<br>
+// CHECK: @llvm.global_ctors = appending global [2 x { i32, void ()* }]<br>
+// CHECK: [{ i32, void ()* } { i32 65535, void ()* @__cxx_global_var_init },<br>
+// CHECK:  { i32, void ()* } { i32 65535, void ()* @_GLOBAL__I_a }]<br>
+<br>
+extern "C" int foo();<br>
+template<> int A<short>::a = foo();  // Separate global_ctor entry<br>
+int b = foo();  // Goes in _GLOBAL__I_a<br>
+int c = foo();  // Goes in _GLOBAL__I_a<br>
+<br>
+// An explicit specialization is ordered, and goes in __GLOBAL_I_a.<br>
+template<> struct A<int> { static int a; };<br>
+int A<int>::a = foo();<br>
+<br>
+// CHECK: define internal void @__cxx_global_var_init()<br>
+// CHECK: call i32 @foo()<br>
+// CHECK: store {{.*}} @_ZN1AIsE1aE<br>
+// CHECK: ret<br>
<br>
+// CHECK: define internal void @_GLOBAL__I_a()<br>
+//   We call unique stubs for every ordered dynamic initializer in the TU.<br>
+// CHECK: call<br>
+// CHECK: call<br>
+// CHECK: call<br>
+// CHECK-NOT: call<br>
+// CHECK: ret<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br></div></div>