summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen/CGDecl.cpp
diff options
context:
space:
mode:
authorAlexander Potapenko <glider@google.com>2019-03-01 09:00:41 +0000
committerAlexander Potapenko <glider@google.com>2019-03-01 09:00:41 +0000
commitfa61dddf5dc8cc35de6f814a04012b73a1afcb0e (patch)
tree06491add841101cc66bfce8fc13b53b82c86a9f2 /clang/lib/CodeGen/CGDecl.cpp
parent90641b5581b20bee4b689733d0008d3fbba4973c (diff)
downloadbcm5719-llvm-fa61dddf5dc8cc35de6f814a04012b73a1afcb0e.tar.gz
bcm5719-llvm-fa61dddf5dc8cc35de6f814a04012b73a1afcb0e.zip
CodeGen: Fix PR40605 by splitting constant struct initializers
When emitting initializers for local structures for code built with -ftrivial-auto-var-init, replace constant structures with sequences of stores. This appears to greatly help removing dead initialization stores to those locals that are later overwritten by other data. This also removes a lot of .rodata constants (see PR40605), replacing most of them with immediate values (for Linux kernel the .rodata size is reduced by ~1.9%) llvm-svn: 355181
Diffstat (limited to 'clang/lib/CodeGen/CGDecl.cpp')
-rw-r--r--clang/lib/CodeGen/CGDecl.cpp30
1 files changed, 30 insertions, 0 deletions
diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp
index 91b0c970625..a008ad022bd 100644
--- a/clang/lib/CodeGen/CGDecl.cpp
+++ b/clang/lib/CodeGen/CGDecl.cpp
@@ -969,6 +969,20 @@ static llvm::Value *shouldUseMemSetToInitialize(llvm::Constant *Init,
return llvm::isBytewiseValue(Init);
}
+/// Decide whether we want to split a constant structure store into a sequence
+/// of its fields' stores. This may cost us code size and compilation speed,
+/// but plays better with store optimizations.
+static bool shouldSplitStructStore(CodeGenModule &CGM,
+ uint64_t GlobalByteSize) {
+ // Don't break structures that occupy more than one cacheline.
+ uint64_t ByteSizeLimit = 64;
+ if (CGM.getCodeGenOpts().OptimizationLevel == 0)
+ return false;
+ if (GlobalByteSize <= ByteSizeLimit)
+ return true;
+ return false;
+}
+
static llvm::Constant *patternFor(CodeGenModule &CGM, llvm::Type *Ty) {
// The following value is a guaranteed unmappable pointer value and has a
// repeated byte-pattern which makes it easier to synthesize. We use it for
@@ -1201,6 +1215,8 @@ static void emitStoresForConstant(CodeGenModule &CGM, const VarDecl &D,
// If the initializer is all or mostly the same, codegen with bzero / memset
// then do a few stores afterward.
uint64_t ConstantSize = CGM.getDataLayout().getTypeAllocSize(Ty);
+ if (!ConstantSize)
+ return;
auto *SizeVal = llvm::ConstantInt::get(IntPtrTy, ConstantSize);
if (shouldUseBZeroPlusStoresToInitialize(constant, ConstantSize)) {
Builder.CreateMemSet(Loc, llvm::ConstantInt::get(Int8Ty, 0), SizeVal,
@@ -1228,6 +1244,20 @@ static void emitStoresForConstant(CodeGenModule &CGM, const VarDecl &D,
return;
}
+ llvm::StructType *STy = dyn_cast<llvm::StructType>(Ty);
+ // FIXME: handle the case when STy != Loc.getElementType().
+ // FIXME: handle non-struct aggregate types.
+ if (STy && (STy == Loc.getElementType()) &&
+ shouldSplitStructStore(CGM, ConstantSize)) {
+ for (unsigned i = 0; i != constant->getNumOperands(); i++) {
+ Address EltPtr = Builder.CreateStructGEP(Loc, i);
+ emitStoresForConstant(
+ CGM, D, EltPtr, isVolatile, Builder,
+ cast<llvm::Constant>(Builder.CreateExtractValue(constant, i)));
+ }
+ return;
+ }
+
Builder.CreateMemCpy(
Loc,
createUnnamedGlobalFrom(CGM, D, Builder, constant, Loc.getAlignment()),
OpenPOWER on IntegriCloud