From 8db87291efb97d12fd4e229803a2ad790672023d Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Wed, 31 Aug 2016 13:42:08 +0000 Subject: [PATCH] Internalize common variables. Before this lld was always creating common symbols itself. It worked, but prevented them from being internalized when possible. Now it preserves common symbols is the bitcode and they are internalized. Fixes pr30184. llvm-svn: 280242 --- lld/ELF/LTO.cpp | 9 ++++++--- lld/ELF/SymbolTable.cpp | 7 ++++--- lld/test/ELF/lto/Inputs/common3.ll | 3 +++ lld/test/ELF/lto/common2.ll | 13 ++++++++----- lld/test/ELF/lto/common3.ll | 14 ++++++++++++++ 5 files changed, 35 insertions(+), 11 deletions(-) create mode 100644 lld/test/ELF/lto/Inputs/common3.ll create mode 100644 lld/test/ELF/lto/common3.ll diff --git a/lld/ELF/LTO.cpp b/lld/ELF/LTO.cpp index f24327a139a2..228dc95d78fa 100644 --- a/lld/ELF/LTO.cpp +++ b/lld/ELF/LTO.cpp @@ -202,8 +202,6 @@ void BitcodeCompiler::add(BitcodeFile &F) { continue; } SymbolBody *B = S->body(); - if (B->kind() != SymbolBody::DefinedRegularKind) - continue; if (B->File != &F) continue; @@ -221,7 +219,12 @@ void BitcodeCompiler::add(BitcodeFile &F) { // needs to be able to replace the original definition without conflicting. // In the latter case, we need to allow the combined LTO object to provide a // definition with the same name, for example when doing parallel codegen. - undefine(S); + if (auto *C = dyn_cast(B)) { + if (auto *GO = dyn_cast(GV)) + GO->setAlignment(C->Alignment); + } else { + undefine(S); + } if (!GV) // Module asm symbol. diff --git a/lld/ELF/SymbolTable.cpp b/lld/ELF/SymbolTable.cpp index e99e5077d7ed..caae09787660 100644 --- a/lld/ELF/SymbolTable.cpp +++ b/lld/ELF/SymbolTable.cpp @@ -351,7 +351,7 @@ Symbol *SymbolTable::addCommon(StringRef N, uint64_t Size, bool WasInserted; std::tie(S, WasInserted) = insert(N, Type, StOther & 3, /*CanOmitFromDynSym*/ false, HasUnnamedAddr, - /*IsUsedInRegularObj*/ true, File); + !isa(File), File); int Cmp = compareDefined(S, WasInserted, Binding); if (Cmp > 0) { S->Binding = Binding; @@ -368,8 +368,9 @@ Symbol *SymbolTable::addCommon(StringRef N, uint64_t Size, if (Config->WarnCommon) warning("multiple common of " + S->body()->getName()); - C->Size = std::max(C->Size, Size); - C->Alignment = std::max(C->Alignment, Alignment); + Alignment = C->Alignment = std::max(C->Alignment, Alignment); + if (Size > C->Size) + replaceBody(S, N, Size, Alignment, StOther, Type, File); } return S; } diff --git a/lld/test/ELF/lto/Inputs/common3.ll b/lld/test/ELF/lto/Inputs/common3.ll new file mode 100644 index 000000000000..a4efc6591570 --- /dev/null +++ b/lld/test/ELF/lto/Inputs/common3.ll @@ -0,0 +1,3 @@ +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" +@a = common hidden global i64 0, align 4 diff --git a/lld/test/ELF/lto/common2.ll b/lld/test/ELF/lto/common2.ll index 59a2676e4fc9..6b740c4be701 100644 --- a/lld/test/ELF/lto/common2.ll +++ b/lld/test/ELF/lto/common2.ll @@ -7,15 +7,18 @@ target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" @a = common global i8 0, align 8 +; CHECK-DAG: @a = common global i8 0, align 8 -; Shared library case, we ensure that the bitcode generated file -; has not the a symbol but is appears in the final shared library -; produced. -; CHECK-NOT: @a = common global i8 0, align 8 +@b = common hidden global i32 0, align 4 +define i32 @f() { + %t = load i32, i32* @b, align 4 + ret i32 %t +} +; CHECK-DAG: @b = internal global i32 0, align 4 ; SHARED: Symbol { ; SHARED: Name: a -; SHARED-NEXT: Value: 0x2000 +; SHARED-NEXT: Value: ; SHARED-NEXT: Size: 1 ; SHARED-NEXT: Binding: Global ; SHARED-NEXT: Type: Object diff --git a/lld/test/ELF/lto/common3.ll b/lld/test/ELF/lto/common3.ll new file mode 100644 index 000000000000..a6020ca8c927 --- /dev/null +++ b/lld/test/ELF/lto/common3.ll @@ -0,0 +1,14 @@ +; RUN: llvm-as %s -o %t1.o +; RUN: llvm-as %S/Inputs/common3.ll -o %t2.o +; RUN: ld.lld -m elf_x86_64 %t1.o %t2.o -o %t -shared -save-temps +; RUN: llvm-dis < %t.lto.bc | FileCheck %s + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" +@a = common hidden global i32 0, align 8 +define i32 @f() { + %t = load i32, i32* @a, align 4 + ret i32 %t +} + +; CHECK: @a = internal global i64 0, align 8