diff options
author | Eli Friedman <efriedma@codeaurora.org> | 2018-07-25 20:58:01 +0000 |
---|---|---|
committer | Eli Friedman <efriedma@codeaurora.org> | 2018-07-25 20:58:01 +0000 |
commit | 0887cf9caba73b9800f6d46f51a098793fb00022 (patch) | |
tree | ce60bb6b68f08afb2a59eef3699260781a1ab654 /llvm/lib/CodeGen/GlobalMerge.cpp | |
parent | c55ac1055a419eeca16ec885ec2d18c3d4124726 (diff) | |
download | llvm-0887cf9caba73b9800f6d46f51a098793fb00022.zip llvm-0887cf9caba73b9800f6d46f51a098793fb00022.tar.gz llvm-0887cf9caba73b9800f6d46f51a098793fb00022.tar.bz2 |
[GlobalMerge] Allow merging globals with arbitrary alignment.
Instead of depending on implicit padding from the structure layout code,
use a packed struct and emit the padding explicitly.
Differential Revision: https://reviews.llvm.org/D49710
llvm-svn: 337961
Diffstat (limited to 'llvm/lib/CodeGen/GlobalMerge.cpp')
-rw-r--r-- | llvm/lib/CodeGen/GlobalMerge.cpp | 44 |
1 files changed, 26 insertions, 18 deletions
diff --git a/llvm/lib/CodeGen/GlobalMerge.cpp b/llvm/lib/CodeGen/GlobalMerge.cpp index bebf1d6..3343b33 100644 --- a/llvm/lib/CodeGen/GlobalMerge.cpp +++ b/llvm/lib/CodeGen/GlobalMerge.cpp @@ -440,6 +440,7 @@ bool GlobalMerge::doMerge(const SmallVectorImpl<GlobalVariable *> &Globals, assert(Globals.size() > 1); Type *Int32Ty = Type::getInt32Ty(M.getContext()); + Type *Int8Ty = Type::getInt8Ty(M.getContext()); auto &DL = M.getDataLayout(); LLVM_DEBUG(dbgs() << " Trying to merge set, starts with #" @@ -452,17 +453,31 @@ bool GlobalMerge::doMerge(const SmallVectorImpl<GlobalVariable *> &Globals, uint64_t MergedSize = 0; std::vector<Type*> Tys; std::vector<Constant*> Inits; + std::vector<unsigned> StructIdxs; bool HasExternal = false; StringRef FirstExternalName; + unsigned MaxAlign = 1; + unsigned CurIdx = 0; for (j = i; j != -1; j = GlobalSet.find_next(j)) { Type *Ty = Globals[j]->getValueType(); + unsigned Align = DL.getPreferredAlignment(Globals[j]); + unsigned Padding = alignTo(MergedSize, Align) - MergedSize; + MergedSize += Padding; MergedSize += DL.getTypeAllocSize(Ty); if (MergedSize > MaxOffset) { break; } + if (Padding) { + Tys.push_back(ArrayType::get(Int8Ty, Padding)); + Inits.push_back(ConstantAggregateZero::get(Tys.back())); + ++CurIdx; + } Tys.push_back(Ty); Inits.push_back(Globals[j]->getInitializer()); + StructIdxs.push_back(CurIdx++); + + MaxAlign = std::max(MaxAlign, Align); if (Globals[j]->hasExternalLinkage() && !HasExternal) { HasExternal = true; @@ -481,7 +496,8 @@ bool GlobalMerge::doMerge(const SmallVectorImpl<GlobalVariable *> &Globals, GlobalValue::LinkageTypes Linkage = HasExternal ? GlobalValue::ExternalLinkage : GlobalValue::InternalLinkage; - StructType *MergedTy = StructType::get(M.getContext(), Tys); + // Use a packed struct so we can control alignment. + StructType *MergedTy = StructType::get(M.getContext(), Tys, true); Constant *MergedInit = ConstantStruct::get(MergedTy, Inits); // On Darwin external linkage needs to be preserved, otherwise @@ -499,13 +515,9 @@ bool GlobalMerge::doMerge(const SmallVectorImpl<GlobalVariable *> &Globals, M, MergedTy, isConst, MergedLinkage, MergedInit, MergedName, nullptr, GlobalVariable::NotThreadLocal, AddrSpace); - const StructLayout *MergedLayout = DL.getStructLayout(MergedTy); - // Set the alignment of the merged struct as the maximum alignment of the - // globals to prevent over-alignment. We don't handle globals that are not - // default aligned, so the alignment of the MergedLayout struct is - // equivalent. - MergedGV->setAlignment(MergedLayout->getAlignment()); + MergedGV->setAlignment(MaxAlign); + const StructLayout *MergedLayout = DL.getStructLayout(MergedTy); for (ssize_t k = i, idx = 0; k != j; k = GlobalSet.find_next(k), ++idx) { GlobalValue::LinkageTypes Linkage = Globals[k]->getLinkage(); std::string Name = Globals[k]->getName(); @@ -514,11 +526,12 @@ bool GlobalMerge::doMerge(const SmallVectorImpl<GlobalVariable *> &Globals, // Copy metadata while adjusting any debug info metadata by the original // global's offset within the merged global. - MergedGV->copyMetadata(Globals[k], MergedLayout->getElementOffset(idx)); + MergedGV->copyMetadata(Globals[k], + MergedLayout->getElementOffset(StructIdxs[idx])); Constant *Idx[2] = { - ConstantInt::get(Int32Ty, 0), - ConstantInt::get(Int32Ty, idx), + ConstantInt::get(Int32Ty, 0), + ConstantInt::get(Int32Ty, StructIdxs[idx]), }; Constant *GEP = ConstantExpr::getInBoundsGetElementPtr(MergedTy, MergedGV, Idx); @@ -531,8 +544,8 @@ bool GlobalMerge::doMerge(const SmallVectorImpl<GlobalVariable *> &Globals, // It's not safe on Mach-O as the alias (and thus the portion of the // MergedGlobals variable) may be dead stripped at link time. if (Linkage != GlobalValue::InternalLinkage || !IsMachO) { - GlobalAlias *GA = - GlobalAlias::create(Tys[idx], AddrSpace, Linkage, Name, GEP, &M); + GlobalAlias *GA = GlobalAlias::create(Tys[StructIdxs[idx]], AddrSpace, + Linkage, Name, GEP, &M); GA->setDLLStorageClass(DLLStorage); } @@ -610,12 +623,6 @@ bool GlobalMerge::doInitialization(Module &M) { unsigned AddressSpace = PT->getAddressSpace(); - // Ignore fancy-aligned globals for now. - unsigned Alignment = DL.getPreferredAlignment(&GV); - Type *Ty = GV.getValueType(); - if (Alignment > DL.getABITypeAlignment(Ty)) - continue; - // Ignore all 'special' globals. if (GV.getName().startswith("llvm.") || GV.getName().startswith(".llvm.")) @@ -625,6 +632,7 @@ bool GlobalMerge::doInitialization(Module &M) { if (isMustKeepGlobalVariable(&GV)) continue; + Type *Ty = GV.getValueType(); if (DL.getTypeAllocSize(Ty) < MaxOffset) { if (TM && TargetLoweringObjectFile::getKindForGlobal(&GV, *TM).isBSSLocal()) |