From ad429db7e8762fc7c839c282d39e6995d737f6df Mon Sep 17 00:00:00 2001 From: Matt Pharr Date: Tue, 14 Feb 2012 13:51:23 -0800 Subject: [PATCH] Generate more efficient code for variable initializers. If the initializer is a compile-time constant (or at least a part of it is), then store the constant value in a module-local constant global value and then memcpy the value into the variable. This, in turn, turns into much better assembly in the end. Issue #176. --- expr.cpp | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/expr.cpp b/expr.cpp index fc268ff1..e7432fb4 100644 --- a/expr.cpp +++ b/expr.cpp @@ -559,6 +559,32 @@ InitSymbol(llvm::Value *ptr, const Type *symType, Expr *initExpr, // leave it uninitialized return; + // See if we have a constant initializer a this point + llvm::Constant *constValue = initExpr->GetConstant(symType); + if (constValue != NULL) { + // It'd be nice if we could just do a StoreInst(constValue, ptr) + // at this point, but unfortunately that doesn't generate great + // code (e.g. a bunch of scalar moves for a constant array.) So + // instead we'll make a constant static global that holds the + // constant value and emit a memcpy to put its value into the + // pointer we have. + LLVM_TYPE_CONST llvm::Type *llvmType = symType->LLVMType(g->ctx); + if (llvmType == NULL) { + Assert(m->errorCount > 0); + return; + } + + llvm::Value *constPtr = + new llvm::GlobalVariable(*m->module, llvmType, true /* const */, + llvm::GlobalValue::InternalLinkage, + constValue, "const_initializer"); + llvm::Value *size = g->target.SizeOf(llvmType, + ctx->GetCurrentBasicBlock()); + ctx->MemcpyInst(ptr, constPtr, size); + + return; + } + // If the initializer is a straight up expression that isn't an // ExprList, then we'll see if we can type convert it to the type of // the variable.