Skip to content

Commit

Permalink
[CodeGen] Use the zero initializer instead of storing an all zero rep…
Browse files Browse the repository at this point in the history
…resentation.

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
  • Loading branch information
Matt Davis authored and Matt Davis committed Feb 9, 2018
1 parent 95a0f39 commit 2930d76
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 2 deletions.
12 changes: 10 additions & 2 deletions clang/lib/CodeGen/CGExprConstant.cpp
Expand Up @@ -859,25 +859,33 @@ class ConstExprEmitter :

// 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);
if (!C)
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(),
Expand Down
12 changes: 12 additions & 0 deletions 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};
}

0 comments on commit 2930d76

Please sign in to comment.