mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-12-13 14:35:54 +00:00
[LTO] Fix commons handling
Previously the prevailing information was not honored, and commons symbols could override a strong definition. This patch fixes it and propose the following semantic for commons: the client should mark as prevailing the commons that it expects the LTO implementation to merge (i.e. take the maximum size and alignment). It implies that commons are allowed to have multiple prevailing definitions. Differential Revision: https://reviews.llvm.org/D24545 llvm-svn: 281538
This commit is contained in:
parent
1c71f902d0
commit
5f7f123920
@ -315,6 +315,8 @@ private:
|
||||
struct CommonResolution {
|
||||
uint64_t Size = 0;
|
||||
unsigned Align = 0;
|
||||
/// Record if at least one instance of the common was marked as prevailing
|
||||
bool Prevailing = false;
|
||||
};
|
||||
std::map<std::string, CommonResolution> Commons;
|
||||
|
||||
|
@ -352,13 +352,14 @@ Error LTO::addRegularLTO(std::unique_ptr<InputFile> Input,
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Common resolution: collect the maximum size/alignment.
|
||||
// FIXME: right now we ignore the prevailing information, it is not clear
|
||||
// what is the "right" behavior here.
|
||||
// Common resolution: collect the maximum size/alignment over all commons.
|
||||
// We also record if we see an instance of a common as prevailing, so that
|
||||
// if none is prevailing we can ignore it later.
|
||||
if (Sym.getFlags() & object::BasicSymbolRef::SF_Common) {
|
||||
auto &CommonRes = RegularLTO.Commons[Sym.getIRName()];
|
||||
CommonRes.Size = std::max(CommonRes.Size, Sym.getCommonSize());
|
||||
CommonRes.Align = std::max(CommonRes.Align, Sym.getCommonAlignment());
|
||||
CommonRes.Prevailing |= Res.Prevailing;
|
||||
}
|
||||
|
||||
// FIXME: use proposed local attribute for FinalDefinitionInLinkageUnit.
|
||||
@ -421,6 +422,9 @@ Error LTO::runRegularLTO(AddOutputFn AddOutput) {
|
||||
// all the prevailing when adding the inputs, and we apply it here.
|
||||
const DataLayout &DL = RegularLTO.CombinedModule->getDataLayout();
|
||||
for (auto &I : RegularLTO.Commons) {
|
||||
if (!I.second.Prevailing)
|
||||
// Don't do anything if no instance of this common was prevailing.
|
||||
continue;
|
||||
GlobalVariable *OldGV = RegularLTO.CombinedModule->getNamedGlobal(I.first);
|
||||
if (OldGV && DL.getTypeAllocSize(OldGV->getValueType()) == I.second.Size) {
|
||||
// Don't create a new global if the type is already correct, just make
|
||||
|
4
test/LTO/Resolution/X86/Inputs/commons.ll
Normal file
4
test/LTO/Resolution/X86/Inputs/commons.ll
Normal file
@ -0,0 +1,4 @@
|
||||
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
|
||||
target triple = "x86_64-unknown-linux-gnu"
|
||||
|
||||
@x = global i32 42, align 4
|
12
test/LTO/Resolution/X86/commons.ll
Normal file
12
test/LTO/Resolution/X86/commons.ll
Normal file
@ -0,0 +1,12 @@
|
||||
; RUN: llvm-as -o %t1.bc %s
|
||||
; RUN: llvm-as -o %t2.bc %p/Inputs/commons.ll
|
||||
; RUN: llvm-lto2 %t1.bc -r=%t1.bc,x,l %t2.bc -r=%t2.bc,x,pl -o %t.out -save-temps
|
||||
; RUN: llvm-dis -o - %t.out.0.0.preopt.bc | FileCheck %s
|
||||
|
||||
; A strong definition should override the common
|
||||
; CHECK: @x = global i32 42, align 4
|
||||
|
||||
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
|
||||
target triple = "x86_64-unknown-linux-gnu"
|
||||
|
||||
@x = common global i16 0, align 2
|
@ -19,7 +19,6 @@
|
||||
; RUN: -r %t2.bc,bar,px
|
||||
; RUN: llvm-dis < %t.o.0.0.preopt.bc | FileCheck %s --check-prefix=LARGE-PREVAILED
|
||||
|
||||
|
||||
; Client marked the "small with large alignment" one as prevailing
|
||||
; RUN: llvm-lto2 %t1.bc %t2.bc -o %t.o -save-temps \
|
||||
; RUN: -r %t1.bc,v,px \
|
||||
@ -53,16 +52,37 @@
|
||||
; RUN: -r %t2.bc,bar,px
|
||||
; RUN: llvm-dis < %t.o.0.0.preopt.bc | FileCheck %s --check-prefix=NONE-PREVAILED2
|
||||
|
||||
|
||||
|
||||
; Client marked both as prevailing
|
||||
; RUN: llvm-lto2 %t1.bc %t2.bc -o %t.o -save-temps \
|
||||
; RUN: -r %t1.bc,v,px \
|
||||
; RUN: -r %t2.bc,v,px \
|
||||
; RUN: -r %t1.bc,foo,px \
|
||||
; RUN: -r %t2.bc,bar,px
|
||||
; RUN: llvm-dis < %t.o.0.0.preopt.bc | FileCheck %s --check-prefix=BOTH-PREVAILED1
|
||||
|
||||
; Same as before, but reversing the order of the inputs
|
||||
; RUN: llvm-lto2 %t2.bc %t1.bc -o %t.o -save-temps \
|
||||
; RUN: -r %t1.bc,v,px \
|
||||
; RUN: -r %t2.bc,v,px \
|
||||
; RUN: -r %t1.bc,foo,px \
|
||||
; RUN: -r %t2.bc,bar,px
|
||||
; RUN: llvm-dis < %t.o.0.0.preopt.bc | FileCheck %s --check-prefix=BOTH-PREVAILED2
|
||||
|
||||
|
||||
|
||||
target triple = "x86_64-apple-macosx10.11.0"
|
||||
|
||||
@v = common global i8 0, align 8
|
||||
|
||||
; LARGE-PREVAILED: @v = common global i16 0, align 8
|
||||
; SMALL-PREVAILED: @v = common global [2 x i8] zeroinitializer, align 8
|
||||
; In this case the first was kept as external, but we created a new merged
|
||||
; common due to the second requiring a larger size:
|
||||
; NONE-PREVAILED1: @v = common global [2 x i8] zeroinitializer, align 8
|
||||
; NONE-PREVAILED2: @v = external global i16, align 8
|
||||
; BOTH-PREVAILED1: @v = common global i16 0, align 8
|
||||
; BOTH-PREVAILED2: common global [2 x i8] zeroinitializer, align 8
|
||||
; In this case the first is kept as external
|
||||
; NONE-PREVAILED1: @v = external global i8, align 8
|
||||
; NONE-PREVAILED2: @v = external global i16, align 4
|
||||
|
||||
define i8 *@foo() {
|
||||
ret i8 *@v
|
||||
|
Loading…
Reference in New Issue
Block a user