summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/include/llvm/LTO/LTO.h2
-rw-r--r--llvm/lib/LTO/LTO.cpp10
-rw-r--r--llvm/test/LTO/Resolution/X86/Inputs/commons.ll4
-rw-r--r--llvm/test/LTO/Resolution/X86/commons.ll12
-rw-r--r--llvm/test/tools/llvm-lto2/X86/common.ll30
5 files changed, 50 insertions, 8 deletions
diff --git a/llvm/include/llvm/LTO/LTO.h b/llvm/include/llvm/LTO/LTO.h
index 3a5b5eca909..86b76135740 100644
--- a/llvm/include/llvm/LTO/LTO.h
+++ b/llvm/include/llvm/LTO/LTO.h
@@ -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;
diff --git a/llvm/lib/LTO/LTO.cpp b/llvm/lib/LTO/LTO.cpp
index 0323bb83858..a1c287a10ad 100644
--- a/llvm/lib/LTO/LTO.cpp
+++ b/llvm/lib/LTO/LTO.cpp
@@ -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
diff --git a/llvm/test/LTO/Resolution/X86/Inputs/commons.ll b/llvm/test/LTO/Resolution/X86/Inputs/commons.ll
new file mode 100644
index 00000000000..9372600d03d
--- /dev/null
+++ b/llvm/test/LTO/Resolution/X86/Inputs/commons.ll
@@ -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
diff --git a/llvm/test/LTO/Resolution/X86/commons.ll b/llvm/test/LTO/Resolution/X86/commons.ll
new file mode 100644
index 00000000000..b3e504835af
--- /dev/null
+++ b/llvm/test/LTO/Resolution/X86/commons.ll
@@ -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
diff --git a/llvm/test/tools/llvm-lto2/X86/common.ll b/llvm/test/tools/llvm-lto2/X86/common.ll
index 61806190cc4..81862b7286a 100644
--- a/llvm/test/tools/llvm-lto2/X86/common.ll
+++ b/llvm/test/tools/llvm-lto2/X86/common.ll
@@ -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
OpenPOWER on IntegriCloud