]> granicus.if.org Git - clang/commitdiff
When we choose to use zeroinitializer for a trailing portion of an array
authorRichard Smith <richard-llvm@metafoo.co.uk>
Thu, 19 Jul 2018 21:38:56 +0000 (21:38 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Thu, 19 Jul 2018 21:38:56 +0000 (21:38 +0000)
constant, don't convert the rest into a packed struct.

If an array constant has a large non-zero portion and a large zero
portion, we want to emit the first part as an array and the rest as a
zeroinitializer if possible. This fixes a memory usage regression from
r333141 when compiling PHP.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337498 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGExprConstant.cpp
test/CodeGen/init.c

index b26ff3d20e49ebaf678afae86c4d6d8e0a9e158b..afe2bfe8e9b2357b67bf31f932728842d2573f04 100644 (file)
@@ -659,7 +659,19 @@ EmitArrayConstant(CodeGenModule &CGM, const ConstantArrayType *DestType,
   if (TrailingZeroes >= 8) {
     assert(Elements.size() >= NonzeroLength &&
            "missing initializer for non-zero element");
-    Elements.resize(NonzeroLength + 1);
+
+    // If all the elements had the same type up to the trailing zeroes, emit a
+    // struct of two arrays (the nonzero data and the zeroinitializer).
+    if (CommonElementType && NonzeroLength >= 8) {
+      llvm::Constant *Initial = llvm::ConstantArray::get(
+          llvm::ArrayType::get(CommonElementType, ArrayBound),
+          makeArrayRef(Elements).take_front(NonzeroLength));
+      Elements.resize(2);
+      Elements[0] = Initial;
+    } else {
+      Elements.resize(NonzeroLength + 1);
+    }
+
     auto *FillerType =
         CommonElementType
             ? CommonElementType
index b53968101032e78240d5c3dcaf6c98ba9f299388..770995f93f3853d7cb4c23f73f57af3c8f40975b 100644 (file)
@@ -81,6 +81,10 @@ struct Huge {
   int arr[1000 * 1000 * 1000];
 } huge_struct = {1, {2, 0, 0, 0}};
 
+// CHECK-DAG: @large_array_with_zeroes = constant <{ [21 x i8], [979 x i8] }> <{ [21 x i8] c"abc\01\02\03xyzzy\00\00\00\00\00\00\00\00\00q", [979 x i8] zeroinitializer }>
+const char large_array_with_zeroes[1000] = {
+  'a', 'b', 'c', 1, 2, 3, 'x', 'y', 'z', 'z', 'y', [20] = 'q'
+};
 
 // PR279 comment #3
 char test8(int X) {