Skip to content

Commit b2f46d1

Browse files
committed
[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
1 parent 06a4780 commit b2f46d1

File tree

5 files changed

+50
-8
lines changed

5 files changed

+50
-8
lines changed

llvm/include/llvm/LTO/LTO.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,8 @@ class LTO {
315315
struct CommonResolution {
316316
uint64_t Size = 0;
317317
unsigned Align = 0;
318+
/// Record if at least one instance of the common was marked as prevailing
319+
bool Prevailing = false;
318320
};
319321
std::map<std::string, CommonResolution> Commons;
320322

llvm/lib/LTO/LTO.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -352,13 +352,14 @@ Error LTO::addRegularLTO(std::unique_ptr<InputFile> Input,
352352
break;
353353
}
354354
}
355-
// Common resolution: collect the maximum size/alignment.
356-
// FIXME: right now we ignore the prevailing information, it is not clear
357-
// what is the "right" behavior here.
355+
// Common resolution: collect the maximum size/alignment over all commons.
356+
// We also record if we see an instance of a common as prevailing, so that
357+
// if none is prevailing we can ignore it later.
358358
if (Sym.getFlags() & object::BasicSymbolRef::SF_Common) {
359359
auto &CommonRes = RegularLTO.Commons[Sym.getIRName()];
360360
CommonRes.Size = std::max(CommonRes.Size, Sym.getCommonSize());
361361
CommonRes.Align = std::max(CommonRes.Align, Sym.getCommonAlignment());
362+
CommonRes.Prevailing |= Res.Prevailing;
362363
}
363364

364365
// FIXME: use proposed local attribute for FinalDefinitionInLinkageUnit.
@@ -421,6 +422,9 @@ Error LTO::runRegularLTO(AddOutputFn AddOutput) {
421422
// all the prevailing when adding the inputs, and we apply it here.
422423
const DataLayout &DL = RegularLTO.CombinedModule->getDataLayout();
423424
for (auto &I : RegularLTO.Commons) {
425+
if (!I.second.Prevailing)
426+
// Don't do anything if no instance of this common was prevailing.
427+
continue;
424428
GlobalVariable *OldGV = RegularLTO.CombinedModule->getNamedGlobal(I.first);
425429
if (OldGV && DL.getTypeAllocSize(OldGV->getValueType()) == I.second.Size) {
426430
// Don't create a new global if the type is already correct, just make
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
2+
target triple = "x86_64-unknown-linux-gnu"
3+
4+
@x = global i32 42, align 4
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
; RUN: llvm-as -o %t1.bc %s
2+
; RUN: llvm-as -o %t2.bc %p/Inputs/commons.ll
3+
; RUN: llvm-lto2 %t1.bc -r=%t1.bc,x,l %t2.bc -r=%t2.bc,x,pl -o %t.out -save-temps
4+
; RUN: llvm-dis -o - %t.out.0.0.preopt.bc | FileCheck %s
5+
6+
; A strong definition should override the common
7+
; CHECK: @x = global i32 42, align 4
8+
9+
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
10+
target triple = "x86_64-unknown-linux-gnu"
11+
12+
@x = common global i16 0, align 2

llvm/test/tools/llvm-lto2/X86/common.ll

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
; RUN: -r %t2.bc,bar,px
2020
; RUN: llvm-dis < %t.o.0.0.preopt.bc | FileCheck %s --check-prefix=LARGE-PREVAILED
2121

22-
2322
; Client marked the "small with large alignment" one as prevailing
2423
; RUN: llvm-lto2 %t1.bc %t2.bc -o %t.o -save-temps \
2524
; RUN: -r %t1.bc,v,px \
@@ -53,16 +52,37 @@
5352
; RUN: -r %t2.bc,bar,px
5453
; RUN: llvm-dis < %t.o.0.0.preopt.bc | FileCheck %s --check-prefix=NONE-PREVAILED2
5554

55+
56+
57+
; Client marked both as prevailing
58+
; RUN: llvm-lto2 %t1.bc %t2.bc -o %t.o -save-temps \
59+
; RUN: -r %t1.bc,v,px \
60+
; RUN: -r %t2.bc,v,px \
61+
; RUN: -r %t1.bc,foo,px \
62+
; RUN: -r %t2.bc,bar,px
63+
; RUN: llvm-dis < %t.o.0.0.preopt.bc | FileCheck %s --check-prefix=BOTH-PREVAILED1
64+
65+
; Same as before, but reversing the order of the inputs
66+
; RUN: llvm-lto2 %t2.bc %t1.bc -o %t.o -save-temps \
67+
; RUN: -r %t1.bc,v,px \
68+
; RUN: -r %t2.bc,v,px \
69+
; RUN: -r %t1.bc,foo,px \
70+
; RUN: -r %t2.bc,bar,px
71+
; RUN: llvm-dis < %t.o.0.0.preopt.bc | FileCheck %s --check-prefix=BOTH-PREVAILED2
72+
73+
74+
5675
target triple = "x86_64-apple-macosx10.11.0"
5776

5877
@v = common global i8 0, align 8
5978

6079
; LARGE-PREVAILED: @v = common global i16 0, align 8
6180
; SMALL-PREVAILED: @v = common global [2 x i8] zeroinitializer, align 8
62-
; In this case the first was kept as external, but we created a new merged
63-
; common due to the second requiring a larger size:
64-
; NONE-PREVAILED1: @v = common global [2 x i8] zeroinitializer, align 8
65-
; NONE-PREVAILED2: @v = external global i16, align 8
81+
; BOTH-PREVAILED1: @v = common global i16 0, align 8
82+
; BOTH-PREVAILED2: common global [2 x i8] zeroinitializer, align 8
83+
; In this case the first is kept as external
84+
; NONE-PREVAILED1: @v = external global i8, align 8
85+
; NONE-PREVAILED2: @v = external global i16, align 4
6686

6787
define i8 *@foo() {
6888
ret i8 *@v

0 commit comments

Comments
 (0)