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;