From 2930d7662e9c7a90976d41be9086298c5305d7a6 Mon Sep 17 00:00:00 2001 From: Matt Davis Date: Fri, 9 Feb 2018 22:10:09 +0000 Subject: [PATCH] [CodeGen] Use the zero initializer instead of storing an all zero representation. 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 llvm-svn: 324776 --- clang/lib/CodeGen/CGExprConstant.cpp | 12 ++++++++++-- clang/test/CodeGen/array-init.c | 12 ++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) create mode 100644 clang/test/CodeGen/array-init.c diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp index d1b9e13..7b076ea 100644 --- a/clang/lib/CodeGen/CGExprConstant.cpp +++ b/clang/lib/CodeGen/CGExprConstant.cpp @@ -859,9 +859,10 @@ public: // Copy initializer elements. SmallVector 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 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/clang/test/CodeGen/array-init.c b/clang/test/CodeGen/array-init.c new file mode 100644 index 0000000..fa54994 --- /dev/null +++ b/clang/test/CodeGen/array-init.c @@ -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}; +} -- 2.7.4