diff options
author | Alexander Potapenko <glider@google.com> | 2019-03-01 09:00:41 +0000 |
---|---|---|
committer | Alexander Potapenko <glider@google.com> | 2019-03-01 09:00:41 +0000 |
commit | fa61dddf5dc8cc35de6f814a04012b73a1afcb0e (patch) | |
tree | 06491add841101cc66bfce8fc13b53b82c86a9f2 /clang/lib/CodeGen/CGDecl.cpp | |
parent | 90641b5581b20bee4b689733d0008d3fbba4973c (diff) | |
download | bcm5719-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.cpp | 30 |
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()), |