aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/CodeGen/GlobalMerge.cpp
diff options
context:
space:
mode:
authorEli Friedman <efriedma@codeaurora.org>2018-07-25 20:58:01 +0000
committerEli Friedman <efriedma@codeaurora.org>2018-07-25 20:58:01 +0000
commit0887cf9caba73b9800f6d46f51a098793fb00022 (patch)
treece60bb6b68f08afb2a59eef3699260781a1ab654 /llvm/lib/CodeGen/GlobalMerge.cpp
parentc55ac1055a419eeca16ec885ec2d18c3d4124726 (diff)
downloadllvm-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.cpp44
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())