]> granicus.if.org Git - clang/commitdiff
[CodeGen] Use the zero initializer instead of storing an all zero representation.
authorMatt Davis <Matthew.Davis@sony.com>
Fri, 9 Feb 2018 22:10:09 +0000 (22:10 +0000)
committerMatt Davis <Matthew.Davis@sony.com>
Fri, 9 Feb 2018 22:10:09 +0000 (22:10 +0000)
Summary:
This change avoids the overhead of storing, and later crawling,
an initializer list of all zeros for arrays. When LLVM
visits this (llvm/IR/Constants.cpp) ConstantArray::getImpl()
it will scan the list looking for an array of all zero.

We can avoid the store, and short-cut the scan, by detecting
all zeros when clang builds-up the initialization representation.

This was brought to my attention when investigating PR36030

Reviewers: majnemer, rjmccall

Reviewed By: rjmccall

Subscribers: cfe-commits

Differential Revision: https://reviews.llvm.org/D42549

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

lib/CodeGen/CGExprConstant.cpp
test/CodeGen/array-init.c [new file with mode: 0644]

index d1b9e13a6f9377f4296f2ca943d8e4429d3fa382..7b076ea3e65eaac074686507cbe10d4f6cc59b26 100644 (file)
@@ -859,9 +859,10 @@ public:
 
     // Copy initializer elements.
     SmallVector<llvm::Constant*, 16> Elts;
-    Elts.reserve(NumInitableElts + NumElements);
+    Elts.reserve(std::max(NumInitableElts, NumElements));
 
     bool RewriteType = false;
+    bool AllNullValues = true;
     for (unsigned i = 0; i < NumInitableElts; ++i) {
       Expr *Init = ILE->getInit(i);
       llvm::Constant *C = Emitter.tryEmitPrivateForMemory(Init, EltType);
@@ -869,15 +870,22 @@ public:
         return nullptr;
       RewriteType |= (C->getType() != ElemTy);
       Elts.push_back(C);
+      if (AllNullValues && !C->isNullValue())
+        AllNullValues = false;
     }
 
+    // If all initializer elements are "zero," then avoid storing NumElements
+    // instances of the zero representation.
+    if (AllNullValues)
+      return llvm::ConstantAggregateZero::get(AType);
+
     RewriteType |= (fillC->getType() != ElemTy);
     Elts.resize(NumElements, fillC);
 
     if (RewriteType) {
       // FIXME: Try to avoid packing the array
       std::vector<llvm::Type*> Types;
-      Types.reserve(NumInitableElts + NumElements);
+      Types.reserve(Elts.size());
       for (unsigned i = 0, e = Elts.size(); i < e; ++i)
         Types.push_back(Elts[i]->getType());
       llvm::StructType *SType = llvm::StructType::get(AType->getContext(),
diff --git a/test/CodeGen/array-init.c b/test/CodeGen/array-init.c
new file mode 100644 (file)
index 0000000..fa54994
--- /dev/null
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 %s -O0 -triple x86_64-unknown-linux-gnu -emit-llvm -o - | FileCheck %s
+
+// CHECK: @{{.*}}.a1 = internal constant [5 x i32] [i32 0, i32 1, i32 2, i32 0, i32 0]
+// CHECK: @{{.*}}.a2 = internal constant [5 x i32] zeroinitializer
+// CHECK: @{{.*}}.a3 = internal constant [5 x i32] zeroinitializer
+
+void testConstArrayInits(void)
+{
+  const int a1[5] = {0,1,2};
+  const int a2[5] = {0,0,0};
+  const int a3[5] = {0};
+}