r183967 - Emit initializers for static-storage-duration temporaries as constants where

Richard Smith richard-llvm at metafoo.co.uk
Thu Jun 13 20:07:01 PDT 2013


Author: rsmith
Date: Thu Jun 13 22:07:01 2013
New Revision: 183967

URL: http://llvm.org/viewvc/llvm-project?rev=183967&view=rev
Log:
Emit initializers for static-storage-duration temporaries as constants where
possible.

Modified:
    cfe/trunk/lib/AST/ExprConstant.cpp
    cfe/trunk/lib/CodeGen/CGExpr.cpp
    cfe/trunk/lib/CodeGen/CodeGenModule.cpp
    cfe/trunk/test/CodeGenCXX/const-init-cxx1y.cpp
    cfe/trunk/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist-pr12086.cpp
    cfe/trunk/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp

Modified: cfe/trunk/lib/AST/ExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=183967&r1=183966&r2=183967&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprConstant.cpp (original)
+++ cfe/trunk/lib/AST/ExprConstant.cpp Thu Jun 13 22:07:01 2013
@@ -4093,6 +4093,7 @@ bool LValueExprEvaluator::VisitMateriali
   APValue *Value;
   if (E->getStorageDuration() == SD_Static) {
     Value = Info.Ctx.getMaterializedTemporaryValue(E, true);
+    *Value = APValue();
     Result.set(E);
   } else {
     Value = &Info.CurrentCall->Temporaries[E];

Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=183967&r1=183966&r2=183967&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExpr.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExpr.cpp Thu Jun 13 22:07:01 2013
@@ -321,6 +321,13 @@ LValue CodeGenFunction::EmitMaterializeT
     llvm::Value *Object = createReferenceTemporary(*this, M, E);
     LValue RefTempDst = MakeAddrLValue(Object, M->getType());
 
+    if (llvm::GlobalVariable *Var = dyn_cast<llvm::GlobalVariable>(Object)) {
+      // We should not have emitted the initializer for this temporary as a
+      // constant.
+      assert(!Var->hasInitializer());
+      Var->setInitializer(CGM.EmitNullConstant(E->getType()));
+    }
+
     EmitScalarInit(E, M->getExtendingDecl(), RefTempDst, false);
 
     pushTemporaryCleanup(*this, M, E, Object);
@@ -343,7 +350,16 @@ LValue CodeGenFunction::EmitMaterializeT
 
   // Create and initialize the reference temporary.
   llvm::Value *Object = createReferenceTemporary(*this, M, E);
-  EmitAnyExprToMem(E, Object, Qualifiers(), /*IsInit*/true);
+  if (llvm::GlobalVariable *Var = dyn_cast<llvm::GlobalVariable>(Object)) {
+    // If the temporary is a global and has a constant initializer, we may
+    // have already initialized it.
+    if (!Var->hasInitializer()) {
+      Var->setInitializer(CGM.EmitNullConstant(E->getType()));
+      EmitAnyExprToMem(E, Object, Qualifiers(), /*IsInit*/true);
+    }
+  } else {
+    EmitAnyExprToMem(E, Object, Qualifiers(), /*IsInit*/true);
+  }
   pushTemporaryCleanup(*this, M, E, Object);
 
   // Perform derived-to-base casts and/or field accesses, to get from the

Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=183967&r1=183966&r2=183967&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Thu Jun 13 22:07:01 2013
@@ -2615,15 +2615,16 @@ llvm::Constant *CodeGenModule::GetAddrOf
 }
 
 llvm::Constant *CodeGenModule::GetAddrOfGlobalTemporary(
-    const MaterializeTemporaryExpr *E, const Expr *Inner) {
+    const MaterializeTemporaryExpr *E, const Expr *Init) {
   assert((E->getStorageDuration() == SD_Static ||
           E->getStorageDuration() == SD_Thread) && "not a global temporary");
   const VarDecl *VD = cast<VarDecl>(E->getExtendingDecl());
 
   // If we're not materializing a subobject of the temporary, keep the
   // cv-qualifiers from the type of the MaterializeTemporaryExpr.
-  if (Inner == E->GetTemporaryExpr())
-    Inner = E;
+  QualType MaterializedType = Init->getType();
+  if (Init == E->GetTemporaryExpr())
+    MaterializedType = E->getType();
 
   llvm::Constant *&Slot = MaterializedGlobalTemporaryMap[E];
   if (Slot)
@@ -2637,34 +2638,44 @@ llvm::Constant *CodeGenModule::GetAddrOf
   getCXXABI().getMangleContext().mangleReferenceTemporary(VD, Out);
   Out.flush();
 
-  llvm::Constant *InitialValue = 0;
   APValue *Value = 0;
   if (E->getStorageDuration() == SD_Static) {
-    // We might have a constant initializer for this temporary.
+    // We might have a cached constant initializer for this temporary. Note
+    // that this might have a different value from the value computed by
+    // evaluating the initializer if the surrounding constant expression
+    // modifies the temporary.
     Value = getContext().getMaterializedTemporaryValue(E, false);
     if (Value && Value->isUninit())
       Value = 0;
   }
 
-  bool Constant;
+  // Try evaluating it now, it might have a constant initializer.
+  Expr::EvalResult EvalResult;
+  if (!Value && Init->EvaluateAsRValue(EvalResult, getContext()) &&
+      !EvalResult.hasSideEffects())
+    Value = &EvalResult.Val;
+
+  llvm::Constant *InitialValue = 0;
+  bool Constant = false;
+  llvm::Type *Type;
   if (Value) {
     // The temporary has a constant initializer, use it.
-    InitialValue = EmitConstantValue(*Value, Inner->getType(), 0);
-    Constant = isTypeConstant(Inner->getType(), /*ExcludeCtor*/Value);
+    InitialValue = EmitConstantValue(*Value, MaterializedType, 0);
+    Constant = isTypeConstant(MaterializedType, /*ExcludeCtor*/Value);
+    Type = InitialValue->getType();
   } else {
-    // No constant initializer, the initialization will be provided when we
+    // No initializer, the initialization will be provided when we
     // initialize the declaration which performed lifetime extension.
-    InitialValue = EmitNullConstant(Inner->getType());
-    Constant = false;
+    Type = getTypes().ConvertTypeForMem(MaterializedType);
   }
 
   // Create a global variable for this lifetime-extended temporary.
   llvm::GlobalVariable *GV =
-    new llvm::GlobalVariable(getModule(), InitialValue->getType(), Constant,
-                             llvm::GlobalValue::PrivateLinkage, InitialValue,
-                             Name.c_str());
+    new llvm::GlobalVariable(getModule(), Type, Constant,
+                             llvm::GlobalValue::PrivateLinkage,
+                             InitialValue, Name.c_str());
   GV->setAlignment(
-      getContext().getTypeAlignInChars(Inner->getType()).getQuantity());
+      getContext().getTypeAlignInChars(MaterializedType).getQuantity());
   if (VD->getTLSKind())
     setTLSMode(GV, *VD);
   Slot = GV;

Modified: cfe/trunk/test/CodeGenCXX/const-init-cxx1y.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/const-init-cxx1y.cpp?rev=183967&r1=183966&r2=183967&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/const-init-cxx1y.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/const-init-cxx1y.cpp Thu Jun 13 22:07:01 2013
@@ -24,6 +24,25 @@ namespace ModifyStaticTemporary {
   A a = { 6, f(a.temporary) };
   // CHECK: @_ZGRN21ModifyStaticTemporary1aE = private global i32 54
   // CHECK: @_ZN21ModifyStaticTemporary1aE = global {{.*}} i32* @_ZGRN21ModifyStaticTemporary1aE, i32 42
+
+  A b = { 7, ++b.temporary };
+  // CHECK: @_ZGRN21ModifyStaticTemporary1bE = private global i32 8
+  // CHECK: @_ZN21ModifyStaticTemporary1bE = global {{.*}} i32* @_ZGRN21ModifyStaticTemporary1bE, i32 8
+
+  // Can't emit all of 'c' as a constant here, so emit the initial value of
+  // 'c.temporary', not the value as modified by the partial evaluation within
+  // the initialization of 'c.x'.
+  A c = { 10, (++c.temporary, b.x) };
+  // CHECK: @_ZGRN21ModifyStaticTemporary1cE = private global i32 10
+  // CHECK: @_ZN21ModifyStaticTemporary1cE = global {{.*}} zeroinitializer
 }
 
 // CHECK: __cxa_atexit({{.*}} @_ZN1BD1Ev {{.*}} @b
+
+// CHECK: define
+// CHECK-NOT: @_ZGRN21ModifyStaticTemporary1cE
+// CHECK: store {{.*}} @_ZGRN21ModifyStaticTemporary1cE, {{.*}} @_ZN21ModifyStaticTemporary1cE
+// CHECK: add
+// CHECK: store
+// CHECK: load {{.*}} @_ZN21ModifyStaticTemporary1bE
+// CHECK: store {{.*}} @_ZN21ModifyStaticTemporary1cE

Modified: cfe/trunk/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist-pr12086.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist-pr12086.cpp?rev=183967&r1=183966&r2=183967&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist-pr12086.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist-pr12086.cpp Thu Jun 13 22:07:01 2013
@@ -50,8 +50,9 @@ namespace std {
   };
 }
 
+constexpr int a = 2, b = 4, c = 6;
 std::initializer_list<std::initializer_list<int>> nested = {
-  {1, 2}, {3, 4}, {5, 6}
+  {1, a}, {3, b}, {5, c}
 };
 
 // CHECK-STATIC-BL: @_ZGR6nested = private constant [2 x i32] [i32 1, i32 2], align 4
@@ -70,17 +71,17 @@ std::initializer_list<std::initializer_l
 // CHECK-DYNAMIC-BL: @_ZGR6nested2 = private global [2 x i32] zeroinitializer
 // CHECK-DYNAMIC-BL: @_ZGR6nested3 = private global [2 x i32] zeroinitializer
 // CHECK-DYNAMIC-BL: store i32 1, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested1, i64 0, i64 0)
-// CHECK-DYNAMIC-BL: store i32 2, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested1, i64 0, i64 1)
+// CHECK-DYNAMIC-BL: store i32 {{.*}}, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested1, i64 0, i64 1)
 // CHECK-DYNAMIC-BL: store i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested1, i64 0, i64 0),
 // CHECK-DYMAMIC-BL:       i32** getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i64 0, i64 0, i32 0), align 8
 // CHECK-DYNAMIC-BL: store i64 2, i64* getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i64 0, i64 0, i32 1), align 8
 // CHECK-DYNAMIC-BL: store i32 3, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested2, i64 0, i64 0)
-// CHECK-DYNAMIC-BL: store i32 4, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested2, i64 0, i64 1)
+// CHECK-DYNAMIC-BL: store i32 {{.*}}, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested2, i64 0, i64 1)
 // CHECK-DYNAMIC-BL: store i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested2, i64 0, i64 0),
 // CHECK-DYNAMIC-BL:       i32** getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i64 0, i64 1, i32 0), align 8
 // CHECK-DYNAMIC-BL: store i64 2, i64* getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i64 0, i64 1, i32 1), align 8
 // CHECK-DYNAMIC-BL: store i32 5, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested3, i64 0, i64 0)
-// CHECK-DYNAMIC-BL: store i32 6, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested3, i64 0, i64 1)
+// CHECK-DYNAMIC-BL: store i32 {{.*}}, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested3, i64 0, i64 1)
 // CHECK-DYNAMIC-BL: store i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested3, i64 0, i64 0),
 // CHECK-DYNAMIC-BL:       i32** getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i64 0, i64 2, i32 0), align 8
 // CHECK-DYNAMIC-BL: store i64 2, i64* getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i64 0, i64 2, i32 1), align 8
@@ -108,19 +109,19 @@ std::initializer_list<std::initializer_l
 // CHECK-DYNAMIC-BE: @_ZGR6nested2 = private global [2 x i32] zeroinitializer
 // CHECK-DYNAMIC-BE: @_ZGR6nested3 = private global [2 x i32] zeroinitializer
 // CHECK-DYNAMIC-BE: store i32 1, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested1, i64 0, i64 0)
-// CHECK-DYNAMIC-BE: store i32 2, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested1, i64 0, i64 1)
+// CHECK-DYNAMIC-BE: store i32 {{.*}}, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested1, i64 0, i64 1)
 // CHECK-DYNAMIC-BE: store i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested1, i64 0, i64 0),
 // CHECK-DYMAMIC-BE:       i32** getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i64 0, i64 0, i32 0), align 8
 // CHECK-DYNAMIC-BE: store i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested1, i64 1, i64 0),
 // CHECK-DYMAMIC-BE:       i32** getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i64 0, i64 0, i32 1), align 8
 // CHECK-DYNAMIC-BE: store i32 3, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested2, i64 0, i64 0)
-// CHECK-DYNAMIC-BE: store i32 4, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested2, i64 0, i64 1)
+// CHECK-DYNAMIC-BE: store i32 {{.*}}, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested2, i64 0, i64 1)
 // CHECK-DYNAMIC-BE: store i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested2, i64 0, i64 0),
 // CHECK-DYNAMIC-BE:       i32** getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i64 0, i64 1, i32 0), align 8
 // CHECK-DYNAMIC-BE: store i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested2, i64 1, i64 0),
 // CHECK-DYNAMIC-BE:       i32** getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i64 0, i64 1, i32 1), align 8
 // CHECK-DYNAMIC-BE: store i32 5, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested3, i64 0, i64 0)
-// CHECK-DYNAMIC-BE: store i32 6, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested3, i64 0, i64 1)
+// CHECK-DYNAMIC-BE: store i32 {{.*}}, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested3, i64 0, i64 1)
 // CHECK-DYNAMIC-BE: store i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested3, i64 0, i64 0),
 // CHECK-DYNAMIC-BE:       i32** getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i64 0, i64 2, i32 0), align 8
 // CHECK-DYNAMIC-BE: store i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested3, i64 1, i64 0),

Modified: cfe/trunk/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp?rev=183967&r1=183966&r2=183967&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp Thu Jun 13 22:07:01 2013
@@ -57,21 +57,26 @@ namespace thread_local_global_array {
   // objects aren't really a problem).
   //
   // CHECK: @_ZN25thread_local_global_array1xE = thread_local global
-  // CHECK: @_ZGRN25thread_local_global_array1xE = private thread_local global [4 x i32]
+  // CHECK: @_ZGRN25thread_local_global_array1xE = private thread_local constant [4 x i32] [i32 1, i32 2, i32 3, i32 4]
   std::initializer_list<int> thread_local x = { 1, 2, 3, 4 };
 }
 
 // CHECK: @globalInitList2 = global %{{[^ ]+}} zeroinitializer
 // CHECK: @_ZGR15globalInitList2 = private global [2 x %[[WITHARG:[^ ]*]]] zeroinitializer
+
+// CHECK: @_ZN15partly_constant1kE = global i32 0, align 4
+// CHECK: @_ZN15partly_constant2ilE = global {{.*}} null, align 8
+// CHECK: @[[PARTLY_CONSTANT_OUTER:_ZGRN15partly_constant2ilE.*]] = private global {{.*}} zeroinitializer, align 8
+// CHECK: @[[PARTLY_CONSTANT_INNER:_ZGRN15partly_constant2ilE.*]] = private global [3 x {{.*}}] zeroinitializer, align 8
+// CHECK: @[[PARTLY_CONSTANT_FIRST:_ZGRN15partly_constant2ilE.*]] = private constant [3 x i32] [i32 1, i32 2, i32 3], align 4
+// CHECK: @[[PARTLY_CONSTANT_SECOND:_ZGRN15partly_constant2ilE.*]] = private global [2 x i32] zeroinitializer, align 4
+// CHECK: @[[PARTLY_CONSTANT_THIRD:_ZGRN15partly_constant2ilE.*]] = private constant [4 x i32] [i32 5, i32 6, i32 7, i32 8], align 4
+
 // CHECK: appending global
 
 
 // thread_local initializer:
 // CHECK: define internal void
-// CHECK: store i32 1, i32* getelementptr inbounds ([4 x i32]* @_ZGRN25thread_local_global_array1xE, i64 0, i64 0)
-// CHECK: store i32 2, i32* getelementptr inbounds ([4 x i32]* @_ZGRN25thread_local_global_array1xE, i64 0, i64 1)
-// CHECK: store i32 3, i32* getelementptr inbounds ([4 x i32]* @_ZGRN25thread_local_global_array1xE, i64 0, i64 2)
-// CHECK: store i32 4, i32* getelementptr inbounds ([4 x i32]* @_ZGRN25thread_local_global_array1xE, i64 0, i64 3)
 // CHECK: store i32* getelementptr inbounds ([4 x i32]* @_ZGRN25thread_local_global_array1xE, i64 0, i64 0),
 // CHECK:       i32** getelementptr inbounds ({{.*}}* @_ZN25thread_local_global_array1xE, i32 0, i32 0), align 8
 // CHECK: store i64 4, i64* getelementptr inbounds ({{.*}}* @_ZN25thread_local_global_array1xE, i32 0, i32 1), align 8
@@ -354,3 +359,39 @@ namespace dtors {
     // CHECK: br i1
   }
 }
+
+namespace partly_constant {
+  int k;
+  std::initializer_list<std::initializer_list<int>> &&il = { { 1, 2, 3 }, { 4, k }, { 5, 6, 7, 8 } };
+  // First init list.
+  // CHECK-NOT: @[[PARTLY_CONSTANT_FIRST]],
+  // CHECK: store i32* getelementptr inbounds ({{.*}}* @[[PARTLY_CONSTANT_FIRST]], i64 0, i64 0),
+  // CHECK:       i32** getelementptr inbounds ({{.*}}* @[[PARTLY_CONSTANT_INNER]], i64 0, i64 0, i32 0)
+  // CHECK: store i64 3, i64* getelementptr inbounds ({{.*}}* @[[PARTLY_CONSTANT_INNER]], i64 0, i64 0, i32 1)
+  // CHECK-NOT: @[[PARTLY_CONSTANT_FIRST]],
+  //
+  // Second init list array (non-constant).
+  // CHECK: store i32 4, i32* getelementptr inbounds ({{.*}}* @[[PARTLY_CONSTANT_SECOND]], i64 0, i64 0)
+  // CHECK: load i32* @_ZN15partly_constant1kE
+  // CHECK: store i32 {{.*}}, i32* getelementptr inbounds ({{.*}}* @[[PARTLY_CONSTANT_SECOND]], i64 0, i64 1)
+  //
+  // Second init list.
+  // CHECK: store i32* getelementptr inbounds ({{.*}}* @[[PARTLY_CONSTANT_SECOND]], i64 0, i64 0),
+  // CHECK:       i32** getelementptr inbounds ({{.*}}* @[[PARTLY_CONSTANT_INNER]], i64 0, i64 1, i32 0)
+  // CHECK: store i64 2, i64* getelementptr inbounds ({{.*}}* @[[PARTLY_CONSTANT_INNER]], i64 0, i64 1, i32 1)
+  //
+  // Third init list.
+  // CHECK-NOT: @[[PARTLY_CONSTANT_THIRD]],
+  // CHECK: store i32* getelementptr inbounds ({{.*}}* @[[PARTLY_CONSTANT_THIRD]], i64 0, i64 0),
+  // CHECK:       i32** getelementptr inbounds ({{.*}}* @[[PARTLY_CONSTANT_INNER]], i64 0, i64 2, i32 0)
+  // CHECK: store i64 4, i64* getelementptr inbounds ({{.*}}* @_ZGRN15partly_constant2ilE4, i64 0, i64 2, i32 1)
+  // CHECK-NOT: @[[PARTLY_CONSTANT_THIRD]],
+  //
+  // Outer init list.
+  // CHECK: store {{.*}}* getelementptr inbounds ({{.*}}* @[[PARTLY_CONSTANT_INNER]], i64 0, i64 0),
+  // CHECK:       {{.*}}** getelementptr inbounds ({{.*}}* @[[PARTLY_CONSTANT_OUTER]], i32 0, i32 0)
+  // CHECK: store i64 3, i64* getelementptr inbounds ({{.*}}* @[[PARTLY_CONSTANT_OUTER]], i32 0, i32 1)
+  //
+  // 'il' reference.
+  // CHECK: store {{.*}}* @[[PARTLY_CONSTANT_OUTER]], {{.*}}** @_ZN15partly_constant2ilE, align 8
+}





More information about the cfe-commits mailing list