summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen
diff options
context:
space:
mode:
authorBenjamin Kramer <benny.kra@googlemail.com>2015-03-07 13:37:13 +0000
committerBenjamin Kramer <benny.kra@googlemail.com>2015-03-07 13:37:13 +0000
commitf8b86964caa57da955fdddcedaf5cd86f319fffa (patch)
tree1a11dc5b5fa3ac91984aa537650ebebcfcb1f6b8 /clang/lib/CodeGen
parentc9d79e810313a084fe9a699e9242de3a3b0f0444 (diff)
downloadbcm5719-llvm-f8b86964caa57da955fdddcedaf5cd86f319fffa.tar.gz
bcm5719-llvm-f8b86964caa57da955fdddcedaf5cd86f319fffa.zip
Reapply r231508 "CodeGen: Emit constant temporaries into read-only globals."
I disabled putting the new global into the same COMDAT as the function for now. There's a fundamental problem when we inline references to the global but still have the global in a COMDAT linked to the inlined function. Since this is only an optimization there may be other versions of the COMDAT around that are missing the new global and hell breaks loose at link time. I hope the chromium build doesn't break this time :) llvm-svn: 231564
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r--clang/lib/CodeGen/CGExpr.cpp22
1 files changed, 20 insertions, 2 deletions
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 78e80a15836..4a382007813 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -301,6 +301,23 @@ createReferenceTemporary(CodeGenFunction &CGF,
switch (M->getStorageDuration()) {
case SD_FullExpression:
case SD_Automatic:
+ // If we have a constant temporary array or record try to promote it into a
+ // constant global under the same rules a normal constant would've been
+ // promoted. This is easier on the optimizer and generally emits fewer
+ // instructions.
+ if (CGF.CGM.getCodeGenOpts().MergeAllConstants &&
+ (M->getType()->isArrayType() || M->getType()->isRecordType()) &&
+ CGF.CGM.isTypeConstant(M->getType(), true))
+ if (llvm::Constant *Init =
+ CGF.CGM.EmitConstantExpr(Inner, M->getType(), &CGF)) {
+ auto *GV = new llvm::GlobalVariable(
+ CGF.CGM.getModule(), Init->getType(), /*isConstant=*/true,
+ llvm::GlobalValue::PrivateLinkage, Init, ".ref.tmp");
+ GV->setAlignment(
+ CGF.getContext().getTypeAlignInChars(M->getType()).getQuantity());
+ // FIXME: Should we put the new global into a COMDAT?
+ return GV;
+ }
return CGF.CreateMemTemp(Inner->getType(), "ref.tmp");
case SD_Thread:
@@ -370,8 +387,9 @@ EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *M) {
// Create and initialize the reference temporary.
llvm::Value *Object = createReferenceTemporary(*this, M, E);
if (auto *Var = dyn_cast<llvm::GlobalVariable>(Object)) {
- // If the temporary is a global and has a constant initializer, we may
- // have already initialized it.
+ // If the temporary is a global and has a constant initializer or is a
+ // constant temporary that we promoted to a global, we may have already
+ // initialized it.
if (!Var->hasInitializer()) {
Var->setInitializer(CGM.EmitNullConstant(E->getType()));
EmitAnyExprToMem(E, Object, Qualifiers(), /*IsInit*/true);
OpenPOWER on IntegriCloud