<div dir="ltr">I suspect this caused PR23165, can you investigate? Looks like the global constant we emit for the temporary in that case has the wrong vptr!</div><div class="gmail_extra"><br><div class="gmail_quote">On Sat, Mar 7, 2015 at 5:37 AM, Benjamin Kramer <span dir="ltr"><<a href="mailto:benny.kra@googlemail.com" target="_blank">benny.kra@googlemail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: d0k<br>
Date: Sat Mar  7 07:37:13 2015<br>
New Revision: 231564<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=231564&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=231564&view=rev</a><br>
Log:<br>
Reapply r231508 "CodeGen: Emit constant temporaries into read-only globals."<br>
<br>
I disabled putting the new global into the same COMDAT as the function for now.<br>
There's a fundamental problem when we inline references to the global but still<br>
have the global in a COMDAT linked to the inlined function. Since this is only<br>
an optimization there may be other versions of the COMDAT around that are<br>
missing the new global and hell breaks loose at link time.<br>
<br>
I hope the chromium build doesn't break this time :)<br>
<br>
Modified:<br>
    cfe/trunk/lib/CodeGen/CGExpr.cpp<br>
    cfe/trunk/test/CodeGenCXX/compound-literals.cpp<br>
    cfe/trunk/test/CodeGenCXX/cxx0x-initializer-array.cpp<br>
    cfe/trunk/test/CodeGenCXX/cxx0x-initializer-references.cpp<br>
    cfe/trunk/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp<br>
<br>
Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=231564&r1=231563&r2=231564&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=231564&r1=231563&r2=231564&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/CodeGen/CGExpr.cpp (original)<br>
+++ cfe/trunk/lib/CodeGen/CGExpr.cpp Sat Mar  7 07:37:13 2015<br>
@@ -301,6 +301,23 @@ createReferenceTemporary(CodeGenFunction<br>
   switch (M->getStorageDuration()) {<br>
   case SD_FullExpression:<br>
   case SD_Automatic:<br>
+    // If we have a constant temporary array or record try to promote it into a<br>
+    // constant global under the same rules a normal constant would've been<br>
+    // promoted. This is easier on the optimizer and generally emits fewer<br>
+    // instructions.<br>
+    if (CGF.CGM.getCodeGenOpts().MergeAllConstants &&<br>
+        (M->getType()->isArrayType() || M->getType()->isRecordType()) &&<br>
+        CGF.CGM.isTypeConstant(M->getType(), true))<br>
+      if (llvm::Constant *Init =<br>
+              CGF.CGM.EmitConstantExpr(Inner, M->getType(), &CGF)) {<br>
+        auto *GV = new llvm::GlobalVariable(<br>
+            CGF.CGM.getModule(), Init->getType(), /*isConstant=*/true,<br>
+            llvm::GlobalValue::PrivateLinkage, Init, ".ref.tmp");<br>
+        GV->setAlignment(<br>
+            CGF.getContext().getTypeAlignInChars(M->getType()).getQuantity());<br>
+        // FIXME: Should we put the new global into a COMDAT?<br>
+        return GV;<br>
+      }<br>
     return CGF.CreateMemTemp(Inner->getType(), "ref.tmp");<br>
<br>
   case SD_Thread:<br>
@@ -370,8 +387,9 @@ EmitMaterializeTemporaryExpr(const Mater<br>
   // Create and initialize the reference temporary.<br>
   llvm::Value *Object = createReferenceTemporary(*this, M, E);<br>
   if (auto *Var = dyn_cast<llvm::GlobalVariable>(Object)) {<br>
-    // If the temporary is a global and has a constant initializer, we may<br>
-    // have already initialized it.<br>
+    // If the temporary is a global and has a constant initializer or is a<br>
+    // constant temporary that we promoted to a global, we may have already<br>
+    // initialized it.<br>
     if (!Var->hasInitializer()) {<br>
       Var->setInitializer(CGM.EmitNullConstant(E->getType()));<br>
       EmitAnyExprToMem(E, Object, Qualifiers(), /*IsInit*/true);<br>
<br>
Modified: cfe/trunk/test/CodeGenCXX/compound-literals.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/compound-literals.cpp?rev=231564&r1=231563&r2=231564&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/compound-literals.cpp?rev=231564&r1=231563&r2=231564&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/CodeGenCXX/compound-literals.cpp (original)<br>
+++ cfe/trunk/test/CodeGenCXX/compound-literals.cpp Sat Mar  7 07:37:13 2015<br>
@@ -28,7 +28,7 @@ int f() {<br>
<br>
 // CHECK-LABEL: define i32 @_Z1gv()<br>
 int g() {<br>
-  // CHECK: store [2 x i32]* %{{[a-z0-9.]+}}, [2 x i32]** [[V:%[a-z0-9.]+]]<br>
+  // CHECK: store [2 x i32]* @{{.*}}, [2 x i32]** [[V:%[a-z0-9.]+]]<br>
   const int (&v)[2] = (int [2]) {1,2};<br>
<br>
   // CHECK: [[A:%[a-z0-9.]+]] = load [2 x i32]*, [2 x i32]** [[V]]<br>
<br>
Modified: cfe/trunk/test/CodeGenCXX/cxx0x-initializer-array.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/cxx0x-initializer-array.cpp?rev=231564&r1=231563&r2=231564&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/cxx0x-initializer-array.cpp?rev=231564&r1=231563&r2=231564&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/CodeGenCXX/cxx0x-initializer-array.cpp (original)<br>
+++ cfe/trunk/test/CodeGenCXX/cxx0x-initializer-array.cpp Sat Mar  7 07:37:13 2015<br>
@@ -42,10 +42,11 @@ namespace ValueInitArrayOfMemPtr {<br>
     // CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* %{{.*}}, i8* bitcast ([3 x i32]* @[[THREE_NULL_MEMPTRS]] to i8*), i32 12, i32 4, i1 false)<br>
   }<br>
<br>
-  // CHECK-LABEL: define void @_ZN22ValueInitArrayOfMemPtr1gEv<br>
-  void g() {<br>
+  // Test dynamic initialization.<br>
+  // CHECK-LABEL: define void @_ZN22ValueInitArrayOfMemPtr1gEMNS_1SEi<br>
+  void g(p ptr) {<br>
     // CHECK: store i32 -1,<br>
-    f(a{});<br>
+    f(a{ptr});<br>
   }<br>
 }<br>
<br>
<br>
Modified: cfe/trunk/test/CodeGenCXX/cxx0x-initializer-references.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/cxx0x-initializer-references.cpp?rev=231564&r1=231563&r2=231564&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/cxx0x-initializer-references.cpp?rev=231564&r1=231563&r2=231564&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/CodeGenCXX/cxx0x-initializer-references.cpp (original)<br>
+++ cfe/trunk/test/CodeGenCXX/cxx0x-initializer-references.cpp Sat Mar  7 07:37:13 2015<br>
@@ -35,22 +35,30 @@ namespace reference {<br>
     // CHECK-NEXT: ret<br>
   }<br>
<br>
-  void reference_to_aggregate() {<br>
+  void reference_to_aggregate(int i) {<br>
     // CHECK: getelementptr {{.*}}, i32 0, i32 0<br>
     // CHECK-NEXT: store i32 1<br>
     // CHECK-NEXT: getelementptr {{.*}}, i32 0, i32 1<br>
-    // CHECK-NEXT: store i32 2<br>
+    // CHECK-NEXT: %[[I1:.*]] = load i32, i32*<br>
+    // CHECK-NEXT: store i32 %[[I1]]<br>
     // CHECK-NEXT: store %{{.*}}* %{{.*}}, %{{.*}}** %{{.*}}, align<br>
-    const A &ra1{1, 2};<br>
+    const A &ra1{1, i};<br>
<br>
     // CHECK-NEXT: getelementptr inbounds [3 x i32], [3 x i32]* %{{.*}}, i{{32|64}} 0, i{{32|64}} 0<br>
     // CHECK-NEXT: store i32 1<br>
     // CHECK-NEXT: getelementptr inbounds i32, i32* %{{.*}}, i{{32|64}} 1<br>
     // CHECK-NEXT: store i32 2<br>
     // CHECK-NEXT: getelementptr inbounds i32, i32* %{{.*}}, i{{32|64}} 1<br>
-    // CHECK-NEXT: store i32 3<br>
+    // CHECK-NEXT: %[[I2:.*]] = load i32, i32*<br>
+    // CHECK-NEXT: store i32 %[[I2]]<br>
     // CHECK-NEXT: store [3 x i32]* %{{.*}}, [3 x i32]** %{{.*}}, align<br>
-    const int (&arrayRef)[] = {1, 2, 3};<br>
+    const int (&arrayRef)[] = {1, 2, i};<br>
+<br>
+    // CHECK: store %{{.*}}* @{{.*}}, %{{.*}}** %{{.*}}, align<br>
+    const A &constra1{1, 2};<br>
+<br>
+    // CHECK-NEXT: store [3 x i32]* @{{.*}}, [3 x i32]** %{{.*}}, align<br>
+    const int (&constarrayRef)[] = {1, 2, 3};<br>
<br>
     // CHECK-NEXT: ret<br>
   }<br>
<br>
Modified: cfe/trunk/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp?rev=231564&r1=231563&r2=231564&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp?rev=231564&r1=231563&r2=231564&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp (original)<br>
+++ cfe/trunk/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp Sat Mar  7 07:37:13 2015<br>
@@ -72,6 +72,9 @@ namespace thread_local_global_array {<br>
 // CHECK: @[[PARTLY_CONSTANT_SECOND:_ZGRN15partly_constant2ilE.*]] = internal global [2 x i32] zeroinitializer, align 4<br>
 // CHECK: @[[PARTLY_CONSTANT_THIRD:_ZGRN15partly_constant2ilE.*]] = internal constant [4 x i32] [i32 5, i32 6, i32 7, i32 8], align 4<br>
<br>
+// CHECK: @[[REFTMP1:.*]] = private constant [2 x i32] [i32 42, i32 43], align 4<br>
+// CHECK: @[[REFTMP2:.*]] = private constant [3 x %{{.*}}] [%{{.*}} { i32 1 }, %{{.*}} { i32 2 }, %{{.*}} { i32 3 }], align 4<br>
+<br>
 // CHECK: appending global<br>
<br>
<br>
@@ -215,17 +218,16 @@ void fn9() {<br>
<br>
 struct haslist1 {<br>
   std::initializer_list<int> il;<br>
-  haslist1();<br>
+  haslist1(int i);<br>
 };<br>
<br>
-// CHECK-LABEL: define void @_ZN8haslist1C2Ev<br>
-haslist1::haslist1()<br>
+// CHECK-LABEL: define void @_ZN8haslist1C2Ei<br>
+haslist1::haslist1(int i)<br>
 // CHECK: alloca [3 x i32]<br>
-// CHECK: store i32 1<br>
+// CHECK: store i32 %<br>
 // CHECK: store i32 2<br>
 // CHECK: store i32 3<br>
-// CHECK: store i{{32|64}} 3<br>
-  : il{1, 2, 3}<br>
+  : il{i, 2, 3}<br>
 {<br>
   destroyme2 dm2;<br>
 }<br>
@@ -244,16 +246,15 @@ haslist2::haslist2()<br>
   // CHECK: call void @_ZN10destroyme1D1Ev<br>
 }<br>
<br>
-void fn10() {<br>
-  // CHECK-LABEL: define void @_Z4fn10v<br>
+void fn10(int i) {<br>
+  // CHECK-LABEL: define void @_Z4fn10i<br>
   // CHECK: alloca [3 x i32]<br>
   // CHECK: call noalias i8* @_Znw{{[jm]}}<br>
-  // CHECK: store i32 1<br>
+  // CHECK: store i32 %<br>
   // CHECK: store i32 2<br>
   // CHECK: store i32 3<br>
   // CHECK: store i32*<br>
-  // CHECK: store i{{32|64}} 3<br>
-  (void) new std::initializer_list<int> {1, 2, 3};<br>
+  (void) new std::initializer_list<int> {i, 2, 3};<br>
 }<br>
<br>
 void fn11() {<br>
@@ -462,6 +463,22 @@ namespace PR20445 {<br>
   template<int x> void f() { new MyClass({42, 43}); }<br>
   template void f<0>();<br>
   // CHECK-LABEL: define {{.*}} @_ZN7PR204451fILi0EEEvv(<br>
+  // CHECK: store i32* getelementptr inbounds ([2 x i32]* @[[REFTMP1]], i64 0, i64 0)<br>
   // CHECK: call void @_ZN7PR204456vectorC1ESt16initializer_listIiE(<br>
   // CHECK: call void @_ZN7PR204457MyClassC1ERKNS_6vectorE(<br>
 }<br>
+<br>
+namespace ConstExpr {<br>
+  class C {<br>
+    int x;<br>
+  public:<br>
+    constexpr C(int x) : x(x) {}<br>
+  };<br>
+  void f(std::initializer_list<C>);<br>
+  void g() {<br>
+// CHECK-LABEL: _ZN9ConstExpr1gEv<br>
+// CHECK: store %"class.ConstExpr::C"* getelementptr inbounds ([3 x %"class.ConstExpr::C"]* @[[REFTMP2]], i64 0, i64 0)<br>
+// CHECK: call void @_ZN9ConstExpr1fESt16initializer_listINS_1CEE<br>
+    f({C(1), C(2), C(3)});<br>
+  }<br>
+}<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>