[PATCH] D46241: [CodeGen] Recognize more cases of zero initialization

Serge Pavlov via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Sun Apr 29 22:56:02 PDT 2018


sepavloff created this revision.
sepavloff added reviewers: rjmccall, rsmith.

If a variable has initializer, codegen tries to build its value. It
causes strange behavior from user viewpoint: compilation of huge zero
initialized arrays like:

  int char data_1[2147483648u] = { 0 };

consumes enormous amount of time and memory.

With this change compiler recognizes more patterns when variable is
initialized with zeros and elementwise treatment can be avoided.


Repository:
  rC Clang

https://reviews.llvm.org/D46241

Files:
  lib/CodeGen/CGExprConstant.cpp
  test/CodeGenCXX/cxx11-initializer-aggregate.cpp


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() };
+}
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<CXXConstructExpr>(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<InitListExpr>(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<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();
 


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D46241.144500.patch
Type: text/x-patch
Size: 2643 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20180430/d74e8417/attachment.bin>


More information about the cfe-commits mailing list