summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r--clang/lib/CodeGen/CGExpr.cpp24
1 files changed, 22 insertions, 2 deletions
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 78e80a15836..a1cbef26457 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -301,6 +301,25 @@ 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());
+ // Put the new global in the same COMDAT the function containing the
+ // temporary is in.
+ GV->setComdat(CGF.CurFn->getComdat());
+ return GV;
+ }
return CGF.CreateMemTemp(Inner->getType(), "ref.tmp");
case SD_Thread:
@@ -370,8 +389,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