diff options
author | Serge Pavlov <sepavloff@gmail.com> | 2018-05-21 16:09:54 +0000 |
---|---|---|
committer | Serge Pavlov <sepavloff@gmail.com> | 2018-05-21 16:09:54 +0000 |
commit | 9f8068420a7b18180a7c8da2224508e93f99587f (patch) | |
tree | f12032b5586f2b39029f20a2fdee57ca8c30c437 /clang/lib/CodeGen/CGExprConstant.cpp | |
parent | 1a7aaf3cd50422797a45910e76aa197975a1e1ed (diff) | |
download | bcm5719-llvm-9f8068420a7b18180a7c8da2224508e93f99587f.tar.gz bcm5719-llvm-9f8068420a7b18180a7c8da2224508e93f99587f.zip |
[CodeGen] Recognize more cases of zero initialization
If a variable has an initializer, codegen tries to build its value. If
the variable is large in size, building its value requires substantial
resources. It causes strange behavior from user viewpoint: compilation
of huge zero initialized arrays like:
char data_1[2147483648u] = { 0 };
consumes enormous amount of time and memory.
With this change codegen tries to determine if variable initializer is
equivalent to zero initializer. In this case variable value is not
constructed.
This change fixes PR18978.
Differential Revision: https://reviews.llvm.org/D46241
llvm-svn: 332847
Diffstat (limited to 'clang/lib/CodeGen/CGExprConstant.cpp')
-rw-r--r-- | clang/lib/CodeGen/CGExprConstant.cpp | 40 |
1 files changed, 30 insertions, 10 deletions
diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp index 7b076ea3e65..ae05df1be58 100644 --- a/clang/lib/CodeGen/CGExprConstant.cpp +++ b/clang/lib/CodeGen/CGExprConstant.cpp @@ -1392,20 +1392,40 @@ static QualType getNonMemoryType(CodeGenModule &CGM, QualType type) { return type; } +/// Checks if the specified initializer is equivalent to zero initialization. +static bool isZeroInitializer(ConstantEmitter &CE, const Expr *Init) { + if (auto *E = dyn_cast_or_null<CXXConstructExpr>(Init)) { + CXXConstructorDecl *CD = E->getConstructor(); + return CD->isDefaultConstructor() && CD->isTrivial(); + } + + if (auto *IL = dyn_cast_or_null<InitListExpr>(Init)) { + for (auto I : IL->inits()) + if (!isZeroInitializer(CE, I)) + return false; + if (const Expr *Filler = IL->getArrayFiller()) + return isZeroInitializer(CE, Filler); + return true; + } + + QualType InitTy = Init->getType(); + if (InitTy->isIntegralOrEnumerationType() || InitTy->isPointerType()) { + Expr::EvalResult Result; + if (Init->EvaluateAsRValue(Result, CE.CGM.getContext()) && + !Result.hasUnacceptableSideEffect(Expr::SE_NoSideEffects)) + return (Result.Val.isInt() && Result.Val.getInt().isNullValue()) || + (Result.Val.isLValue() && Result.Val.isNullPointer()); + } + + 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<CXXConstructExpr>(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(); |