Index: lib/CodeGen/CGExprConstant.cpp =================================================================== --- lib/CodeGen/CGExprConstant.cpp +++ lib/CodeGen/CGExprConstant.cpp @@ -1392,20 +1392,36 @@ return type; } +static bool isZeroInitializer(ConstantEmitter &CE, const Expr *Init) { + QualType InitTy = Init->getType().getCanonicalType(); + QualType BaseTy = CE.CGM.getContext().getBaseElementType(InitTy); + if (BaseTy->isRecordType()) { + if (auto *E = dyn_cast_or_null(Init)) { + CXXConstructorDecl *CD = E->getConstructor(); + if (CD->isDefaultConstructor() && CD->isTrivial()) + return true; + } + } else if (InitTy->isIntegerType()) { + llvm::APSInt Value; + if (Init->isIntegerConstantExpr(Value, CE.CGM.getContext())) + return Value.isNullValue(); + } else if (InitTy->isConstantArrayType()) { + if (auto *IL = dyn_cast_or_null(Init)) { + for (auto I : IL->inits()) + if (!isZeroInitializer(CE, I)) + return false; + return true; + } + } + return false; +} + llvm::Constant *ConstantEmitter::tryEmitPrivateForVarInit(const VarDecl &D) { // Make a quick check if variable can be default NULL initialized // and avoid going through rest of code which may do, for c++11, // initialization of memory to all NULLs. - if (!D.hasLocalStorage()) { - QualType Ty = CGM.getContext().getBaseElementType(D.getType()); - if (Ty->isRecordType()) - if (const CXXConstructExpr *E = - dyn_cast_or_null(D.getInit())) { - const CXXConstructorDecl *CD = E->getConstructor(); - if (CD->isTrivial() && CD->isDefaultConstructor()) - return CGM.EmitNullConstant(D.getType()); - } - } + if (!D.hasLocalStorage() && isZeroInitializer(*this, D.getInit())) + return CGM.EmitNullConstant(D.getType()); QualType destType = D.getType(); Index: test/CodeGenCXX/cxx11-initializer-aggregate.cpp =================================================================== --- test/CodeGenCXX/cxx11-initializer-aggregate.cpp +++ test/CodeGenCXX/cxx11-initializer-aggregate.cpp @@ -51,3 +51,15 @@ // meaningful. B b[30] = {}; } + +namespace ZeroInit { + enum { Zero, One }; + constexpr int zero() { return 0; } + + // These declarations, if implemented elementwise, require huge + // amout of memory and compiler time. + unsigned char data_1[1024 * 1024 * 1024 * 2u] = { 0 }; + unsigned char data_2[1024 * 1024 * 1024 * 2u] = { Zero }; + unsigned char data_3[1024][1024][1024] = {{{0}}}; + unsigned char data_4[1024 * 1024 * 1024 * 2u] = { zero() }; +}