Skip to content

Commit

Permalink
[LTO] Fix commons handling
Browse files Browse the repository at this point in the history
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

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@281538 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
joker-eph committed Sep 14, 2016
1 parent e038466 commit bdf517a
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 8 deletions.
2 changes: 2 additions & 0 deletions include/llvm/LTO/LTO.h
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,8 @@ class LTO {
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;

Expand Down
10 changes: 7 additions & 3 deletions lib/LTO/LTO.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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
Expand Down
4 changes: 4 additions & 0 deletions test/LTO/Resolution/X86/Inputs/commons.ll
Original file line number Diff line number Diff line change
@@ -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 changes: 12 additions & 0 deletions test/LTO/Resolution/X86/commons.ll
Original file line number Diff line number Diff line change
@@ -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
30 changes: 25 additions & 5 deletions test/tools/llvm-lto2/X86/common.ll
Original file line number Diff line number Diff line change
Expand Up @@ -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 \
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit bdf517a

Please sign in to comment.