gollvm: fast path for creating zero valued composite constant

Detect if we're creating a zero value, and if so take a fast
path. This makes "[1<<30]byte{}" not take forever.

Nonzero value like "[1<<30]byte{1<<29: 42}" is still very slow.
gccgo just sets the element inlined without creating a gigantic
literal in static data. Maybe we can do this as well. This will
rely on a fast creation of zero value. So this CL sets up the
base.

Change-Id: I15a9cf828e528a99c3cd72be1fb03344156687c8
Reviewed-on: https://go-review.googlesource.com/63271
Reviewed-by: Than McIntosh <thanm@google.com>
diff --git a/llvm-gofrontend/go-llvm-materialize.cpp b/llvm-gofrontend/go-llvm-materialize.cpp
index 2596b4a..f99ec9c 100644
--- a/llvm-gofrontend/go-llvm-materialize.cpp
+++ b/llvm-gofrontend/go-llvm-materialize.cpp
@@ -873,48 +873,63 @@
                                      const std::vector<Bexpression *> &vals,
                                      Location location)
 {
-  llvm::SmallVector<llvm::Constant *, 64> llvals(numElements);
-  unsigned long nvals = vals.size();
+  llvm::Value *scon;
 
-  if (indexes) {
-    std::set<unsigned long> touched;
-    unsigned long nindxs = indexes->size();
-    for (unsigned ii = 0; ii < nindxs; ++ii) {
-      auto idx = (*indexes)[ii];
-      if (numElements != nvals)
-        touched.insert(idx);
-      Bexpression *bex = vals[ii];
-      llvm::Constant *con = llvm::cast<llvm::Constant>(bex->value());
-      llvm::Type *elt = llct->getTypeAtIndex(ii);
-      if (elt != con->getType())
-        con = llvm::ConstantExpr::getBitCast(con, elt);
-      llvals[idx] = con;
+  // If all elements are zero, just create a zero value for the
+  // aggregate type. No need to create LLVM Value for each element.
+  bool allZero = true;
+  for (auto v : vals) {
+    llvm::Constant *con = llvm::cast<llvm::Constant>(v->value());
+    if (!con->isNullValue()) {
+      allZero = false;
+      break;
     }
-    if (numElements != nvals) {
-      for (unsigned long ii = 0; ii < numElements; ++ii) {
-        if (touched.find(ii) == touched.end()) {
-          llvm::Type *elt = llct->getTypeAtIndex(ii);
-          llvals[ii] = llvm::Constant::getNullValue(elt);
+  }
+  if (allZero)
+    scon = llvm::ConstantAggregateZero::get(llct);
+  else {
+    llvm::SmallVector<llvm::Constant *, 64> llvals(numElements);
+    unsigned long nvals = vals.size();
+
+    if (indexes) {
+      std::set<unsigned long> touched;
+      unsigned long nindxs = indexes->size();
+      for (unsigned ii = 0; ii < nindxs; ++ii) {
+        auto idx = (*indexes)[ii];
+        if (numElements != nvals)
+          touched.insert(idx);
+        Bexpression *bex = vals[ii];
+        llvm::Constant *con = llvm::cast<llvm::Constant>(bex->value());
+        llvm::Type *elt = llct->getTypeAtIndex(ii);
+        if (elt != con->getType())
+          con = llvm::ConstantExpr::getBitCast(con, elt);
+        llvals[idx] = con;
+      }
+      if (numElements != nvals) {
+        for (unsigned long ii = 0; ii < numElements; ++ii) {
+          if (touched.find(ii) == touched.end()) {
+            llvm::Type *elt = llct->getTypeAtIndex(ii);
+            llvals[ii] = llvm::Constant::getNullValue(elt);
+          }
         }
       }
+    } else {
+      for (unsigned long ii = 0; ii < numElements; ++ii) {
+        llvm::Constant *con = llvm::cast<llvm::Constant>(vals[ii]->value());
+        llvm::Type *elt = llct->getTypeAtIndex(ii);
+        if (elt != con->getType())
+          con = llvm::ConstantExpr::getBitCast(con, elt);
+        llvals[ii] = con;
+      }
     }
-  } else {
-    for (unsigned long ii = 0; ii < numElements; ++ii) {
-      llvm::Constant *con = llvm::cast<llvm::Constant>(vals[ii]->value());
-      llvm::Type *elt = llct->getTypeAtIndex(ii);
-      if (elt != con->getType())
-        con = llvm::ConstantExpr::getBitCast(con, elt);
-      llvals[ii] = con;
-    }
-   }
 
-  llvm::Value *scon;
-  if (llct->isStructTy()) {
-    llvm::StructType *llst = llvm::cast<llvm::StructType>(llct);
-    scon = llvm::ConstantStruct::get(llst, llvals);
-  } else {
-    llvm::ArrayType *llat = llvm::cast<llvm::ArrayType>(llct);
-    scon = llvm::ConstantArray::get(llat, llvals);
+    if (llct->isStructTy()) {
+      llvm::StructType *llst = llvm::cast<llvm::StructType>(llct);
+      scon = llvm::ConstantStruct::get(llst, llvals);
+    } else {
+      llvm::ArrayType *llat = llvm::cast<llvm::ArrayType>(llct);
+      scon = llvm::ConstantArray::get(llat, llvals);
+    }
   }
 
   Binstructions noInstructions;