[llvm] r337961 - [GlobalMerge] Allow merging globals with arbitrary alignment.
Eli Friedman via llvm-commits
llvm-commits at lists.llvm.org
Wed Jul 25 13:58:01 PDT 2018
Author: efriedma
Date: Wed Jul 25 13:58:01 2018
New Revision: 337961
URL: http://llvm.org/viewvc/llvm-project?rev=337961&view=rev
Log:
[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
Added:
llvm/trunk/test/Transforms/GlobalMerge/alignment-2.ll
llvm/trunk/test/Transforms/GlobalMerge/alignment.ll
Modified:
llvm/trunk/lib/CodeGen/GlobalMerge.cpp
llvm/trunk/test/Transforms/GlobalMerge/basic.ll
llvm/trunk/test/Transforms/GlobalMerge/debug-info.ll
Modified: llvm/trunk/lib/CodeGen/GlobalMerge.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/GlobalMerge.cpp?rev=337961&r1=337960&r2=337961&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/GlobalMerge.cpp (original)
+++ llvm/trunk/lib/CodeGen/GlobalMerge.cpp Wed Jul 25 13:58:01 2018
@@ -440,6 +440,7 @@ bool GlobalMerge::doMerge(const SmallVec
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 SmallVec
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 SmallVec
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 SmallVec
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 SmallVec
// 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 SmallVec
// 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(Modul
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(Modul
if (isMustKeepGlobalVariable(&GV))
continue;
+ Type *Ty = GV.getValueType();
if (DL.getTypeAllocSize(Ty) < MaxOffset) {
if (TM &&
TargetLoweringObjectFile::getKindForGlobal(&GV, *TM).isBSSLocal())
Added: llvm/trunk/test/Transforms/GlobalMerge/alignment-2.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalMerge/alignment-2.ll?rev=337961&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalMerge/alignment-2.ll (added)
+++ llvm/trunk/test/Transforms/GlobalMerge/alignment-2.ll Wed Jul 25 13:58:01 2018
@@ -0,0 +1,22 @@
+; RUN: opt -global-merge -global-merge-max-offset=100 -S -o - %s | FileCheck %s
+
+target datalayout = "e-p:64:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+; This produces align 4, not the obvious align 1, to be consistent with what
+; the AsmPrinter would do.
+; CHECK: @_MergedGlobals = private global <{ [2 x i32], [2 x i32] }> <{ [2 x i32] [i32 1, i32 1], [2 x i32] [i32 2, i32 2] }>, align 4
+
+; CHECK: @a = internal alias [2 x i32], getelementptr inbounds (<{ [2 x i32], [2 x i32] }>, <{ [2 x i32], [2 x i32] }>* @_MergedGlobals, i32 0, i32 0)
+ at a = internal global [2 x i32] [i32 1, i32 1], align 1
+
+; CHECK: @b = internal alias [2 x i32], getelementptr inbounds (<{ [2 x i32], [2 x i32] }>, <{ [2 x i32], [2 x i32] }>* @_MergedGlobals, i32 0, i32 1)
+ at b = internal global [2 x i32] [i32 2, i32 2], align 1
+
+define void @use() {
+ ; CHECK: load i32, i32* getelementptr inbounds (<{ [2 x i32], [2 x i32] }>, <{ [2 x i32], [2 x i32] }>* @_MergedGlobals, i32 0, i32 0, i32 0)
+ %x = load i32, i32* bitcast ([2 x i32]* @a to i32*)
+ ; CHECK: load i32, i32* getelementptr inbounds (<{ [2 x i32], [2 x i32] }>, <{ [2 x i32], [2 x i32] }>* @_MergedGlobals, i32 0, i32 1, i32 0)
+ %y = load i32, i32* bitcast ([2 x i32]* @b to i32*)
+ ret void
+}
Added: llvm/trunk/test/Transforms/GlobalMerge/alignment.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalMerge/alignment.ll?rev=337961&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalMerge/alignment.ll (added)
+++ llvm/trunk/test/Transforms/GlobalMerge/alignment.ll Wed Jul 25 13:58:01 2018
@@ -0,0 +1,20 @@
+; RUN: opt -global-merge -global-merge-max-offset=100 -S -o - %s | FileCheck %s
+
+target datalayout = "e-p:64:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+; CHECK: @_MergedGlobals = private global <{ [5 x i8], [3 x i8], [2 x i32] }> <{ [5 x i8] c"\01\01\01\01\01", [3 x i8] zeroinitializer, [2 x i32] [i32 2, i32 2] }>, align 4
+
+; CHECK: @a = internal alias [5 x i8], getelementptr inbounds (<{ [5 x i8], [3 x i8], [2 x i32] }>, <{ [5 x i8], [3 x i8], [2 x i32] }>* @_MergedGlobals, i32 0, i32 0)
+ at a = internal global [5 x i8] [i8 1, i8 1, i8 1, i8 1, i8 1], align 4
+
+; CHECK: @b = internal alias [2 x i32], getelementptr inbounds (<{ [5 x i8], [3 x i8], [2 x i32] }>, <{ [5 x i8], [3 x i8], [2 x i32] }>* @_MergedGlobals, i32 0, i32 2)
+ at b = internal global [2 x i32] [i32 2, i32 2]
+
+define void @use() {
+ ; CHECK: load i32, i32* bitcast (<{ [5 x i8], [3 x i8], [2 x i32] }>* @_MergedGlobals to i32*)
+ %x = load i32, i32* bitcast ([5 x i8]* @a to i32*)
+ ; CHECK: load i32, i32* getelementptr inbounds (<{ [5 x i8], [3 x i8], [2 x i32] }>, <{ [5 x i8], [3 x i8], [2 x i32] }>* @_MergedGlobals, i32 0, i32 2, i32 0)
+ %y = load i32, i32* bitcast ([2 x i32]* @b to i32*)
+ ret void
+}
Modified: llvm/trunk/test/Transforms/GlobalMerge/basic.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalMerge/basic.ll?rev=337961&r1=337960&r2=337961&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/GlobalMerge/basic.ll (original)
+++ llvm/trunk/test/Transforms/GlobalMerge/basic.ll Wed Jul 25 13:58:01 2018
@@ -3,18 +3,18 @@
target datalayout = "e-p:64:64"
target triple = "x86_64-unknown-linux-gnu"
-; CHECK: @_MergedGlobals = private global { i32, i32 } { i32 1, i32 2 }
+; CHECK: @_MergedGlobals = private global <{ i32, i32 }> <{ i32 1, i32 2 }>, align 4
-; CHECK: @a = internal alias i32, getelementptr inbounds ({ i32, i32 }, { i32, i32 }* @_MergedGlobals, i32 0, i32 0)
+; CHECK: @a = internal alias i32, getelementptr inbounds (<{ i32, i32 }>, <{ i32, i32 }>* @_MergedGlobals, i32 0, i32 0)
@a = internal global i32 1
-; CHECK: @b = internal alias i32, getelementptr inbounds ({ i32, i32 }, { i32, i32 }* @_MergedGlobals, i32 0, i32 1)
+; CHECK: @b = internal alias i32, getelementptr inbounds (<{ i32, i32 }>, <{ i32, i32 }>* @_MergedGlobals, i32 0, i32 1)
@b = internal global i32 2
define void @use() {
- ; CHECK: load i32, i32* getelementptr inbounds ({ i32, i32 }, { i32, i32 }* @_MergedGlobals, i32 0, i32 0)
+ ; CHECK: load i32, i32* getelementptr inbounds (<{ i32, i32 }>, <{ i32, i32 }>* @_MergedGlobals, i32 0, i32 0)
%x = load i32, i32* @a
- ; CHECK: load i32, i32* getelementptr inbounds ({ i32, i32 }, { i32, i32 }* @_MergedGlobals, i32 0, i32 1)
+ ; CHECK: load i32, i32* getelementptr inbounds (<{ i32, i32 }>, <{ i32, i32 }>* @_MergedGlobals, i32 0, i32 1)
%y = load i32, i32* @b
ret void
}
Modified: llvm/trunk/test/Transforms/GlobalMerge/debug-info.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalMerge/debug-info.ll?rev=337961&r1=337960&r2=337961&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/GlobalMerge/debug-info.ll (original)
+++ llvm/trunk/test/Transforms/GlobalMerge/debug-info.ll Wed Jul 25 13:58:01 2018
@@ -3,7 +3,7 @@
source_filename = "test/Transforms/GlobalMerge/debug-info.ll"
target datalayout = "e-p:64:64"
target triple = "x86_64-unknown-linux-gnu"
-; CHECK: @_MergedGlobals = private global { i32, i32 } { i32 1, i32 2 }, align 4, !dbg [[A:![0-9]+]], !dbg [[B:![0-9]+]]
+; CHECK: @_MergedGlobals = private global <{ i32, i32 }> <{ i32 1, i32 2 }>, align 4, !dbg [[A:![0-9]+]], !dbg [[B:![0-9]+]]
@a = internal global i32 1, !dbg !0
@b = internal global i32 2, !dbg !2
More information about the llvm-commits
mailing list