diff options
-rw-r--r-- | llvm/include/llvm/LTO/LTO.h | 2 | ||||
-rw-r--r-- | llvm/lib/LTO/LTO.cpp | 10 | ||||
-rw-r--r-- | llvm/test/LTO/Resolution/X86/Inputs/commons.ll | 4 | ||||
-rw-r--r-- | llvm/test/LTO/Resolution/X86/commons.ll | 12 | ||||
-rw-r--r-- | llvm/test/tools/llvm-lto2/X86/common.ll | 30 |
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 |