Author: rsmith
Date: Sat Jun  1 19:09:52 2013
New Revision: 183082

URL: http://llvm.org/viewvc/llvm-project?rev=183082&view=rev
Log:
PR12848: When emitting a local variable declared 'constexpr', always initialize 
it with a store or a memcpy, not by emitting the initializer expression. This 
is not required for correctness, but more closely aligns with people's 
expectations, and is cheap (since we've already evaluated the initializer).

Modified:
    cfe/trunk/lib/CodeGen/CGDecl.cpp
    cfe/trunk/test/CodeGenCXX/blocks-cxx11.cpp
    cfe/trunk/test/CodeGenCXX/const-init-cxx11.cpp

Modified: cfe/trunk/lib/CodeGen/CGDecl.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDecl.cpp?rev=183082&r1=183081&r2=183082&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGDecl.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGDecl.cpp Sat Jun  1 19:09:52 2013
@@ -840,19 +840,19 @@ CodeGenFunction::EmitAutoVarAlloca(const
     bool NRVO = getLangOpts().ElideConstructors &&
       D.isNRVOVariable();
 
-    // If this value is a POD array or struct with a statically
-    // determinable constant initializer, there are optimizations we can do.
+    // If this value is an array or struct with a statically determinable
+    // constant initializer, there are optimizations we can do.
     //
     // TODO: We should constant-evaluate the initializer of any variable,
     // as long as it is initialized by a constant expression. Currently,
     // isConstantInitializer produces wrong answers for structs with
     // reference or bitfield members, and a few other cases, and checking
     // for POD-ness protects us from some of these.
-    if (D.getInit() &&
-        (Ty->isArrayType() || Ty->isRecordType()) &&
-        (Ty.isPODType(getContext()) ||
-         getContext().getBaseElementType(Ty)->isObjCObjectPointerType()) &&
-        D.getInit()->isConstantInitializer(getContext(), false)) {
+    if (D.getInit() && (Ty->isArrayType() || Ty->isRecordType()) &&
+        (D.isConstexpr() ||
+         ((Ty.isPODType(getContext()) ||
+           getContext().getBaseElementType(Ty)->isObjCObjectPointerType()) &&
+          D.getInit()->isConstantInitializer(getContext(), false)))) {
 
       // If the variable's a const type, and it's neither an NRVO
       // candidate nor a __block variable and has no mutable members,
@@ -1080,7 +1080,7 @@ void CodeGenFunction::EmitAutoVarInit(co
     capturedByInit ? emission.Address : emission.getObjectAddress(*this);
 
   llvm::Constant *constant = 0;
-  if (emission.IsConstantAggregate) {
+  if (emission.IsConstantAggregate || D.isConstexpr()) {
     assert(!capturedByInit && "constant init contains a capturing block?");
     constant = CGM.EmitConstantInit(D, this);
   }
@@ -1091,6 +1091,13 @@ void CodeGenFunction::EmitAutoVarInit(co
     return EmitExprAsInit(Init, &D, lv, capturedByInit);
   }
 
+  if (!emission.IsConstantAggregate) {
+    // For simple scalar/complex initialization, store the value directly.
+    LValue lv = MakeAddrLValue(Loc, type, alignment);
+    lv.setNonGC(true);
+    return EmitStoreThroughLValue(RValue::get(constant), lv, true);
+  }
+
   // If this is a simple aggregate initialization, we can optimize it
   // in various ways.
   bool isVolatile = type.isVolatileQualified();

Modified: cfe/trunk/test/CodeGenCXX/blocks-cxx11.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/blocks-cxx11.cpp?rev=183082&r1=183081&r2=183082&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/blocks-cxx11.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/blocks-cxx11.cpp Sat Jun  1 19:09:52 2013
@@ -46,7 +46,7 @@ namespace test_complex_int {
   void test() {
     constexpr _Complex int x = 500;
     takeABlock(^{ takeItByValue(x); });
-    // CHECK:      store i32 500,
+    // CHECK:      store { i32, i32 } { i32 500, i32 0 },
 
     // CHECK:      store i32 500,
     // CHECK-NEXT: store i32 0,

Modified: cfe/trunk/test/CodeGenCXX/const-init-cxx11.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/const-init-cxx11.cpp?rev=183082&r1=183081&r2=183082&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/const-init-cxx11.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/const-init-cxx11.cpp Sat Jun  1 19:09:52 2013
@@ -330,6 +330,10 @@ namespace PR13273 {
   extern const S s {};
 }
 
+// CHECK: @_ZZN12LocalVarInit3aggEvE1a = internal constant {{.*}} i32 101
+// CHECK: @_ZZN12LocalVarInit4ctorEvE1a = internal constant {{.*}} i32 102
+// CHECK: @_ZZN12LocalVarInit8mutable_EvE1a = private unnamed_addr constant 
{{.*}} i32 103
+
 // Constant initialization tests go before this point,
 // dynamic initialization tests go after.
 
@@ -356,6 +360,40 @@ namespace PR13273 {
 // CHECK-NOT: }
 // CHECK: call {{.*}}cxa_atexit{{.*}}@_ZN19NonLiteralConstexpr4BothD1Ev
 
+// PR12848: Don't emit dynamic initializers for local constexpr variables.
+namespace LocalVarInit {
+  constexpr int f(int n) { return n; }
+  struct Agg { int k; };
+  struct Ctor { constexpr Ctor(int n) : k(n) {} int k; };
+  struct Mutable { constexpr Mutable(int n) : k(n) {} mutable int k; };
+
+  // CHECK: define {{.*}} @_ZN12LocalVarInit6scalarEv
+  // CHECK-NOT: call
+  // CHECK: store i32 100,
+  // CHECK-NOT: call
+  // CHECK: ret i32 100
+  int scalar() { constexpr int a = { f(100) }; return a; }
+
+  // CHECK: define {{.*}} @_ZN12LocalVarInit3aggEv
+  // CHECK-NOT: call
+  // CHECK: ret i32 101
+  int agg() { constexpr Agg a = { f(101) }; return a.k; }
+
+  // CHECK: define {{.*}} @_ZN12LocalVarInit4ctorEv
+  // CHECK-NOT: call
+  // CHECK: ret i32 102
+  int ctor() { constexpr Ctor a = { f(102) }; return a.k; }
+
+  // CHECK: define {{.*}} @_ZN12LocalVarInit8mutable_Ev
+  // CHECK-NOT: call
+  // CHECK: call {{.*}}memcpy{{.*}} @_ZZN12LocalVarInit8mutable_EvE1a
+  // CHECK-NOT: call
+  // Can't fold return value due to 'mutable'.
+  // CHECK-NOT: ret i32 103
+  // CHECK: }
+  int mutable_() { constexpr Mutable a = { f(103) }; return a.k; }
+}
+
 namespace CrossFuncLabelDiff {
   // Make sure we refuse to constant-fold the variable b.
   constexpr long a(bool x) { return x ? 0 : (long)&&lbl + (0 && ({lbl: 0;})); }


_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to