diff options
author | Rafael Espindola <rafael.espindola@gmail.com> | 2016-04-21 21:44:25 +0000 |
---|---|---|
committer | Rafael Espindola <rafael.espindola@gmail.com> | 2016-04-21 21:44:25 +0000 |
commit | 4d480ed5451e9af88e84bcf8be62f8befa915bed (patch) | |
tree | 7aa49ad62bd096bfab59a35543d92be0cce4c473 | |
parent | c34a519407392fd6fc7432719d1ea05bb9a31d0f (diff) | |
download | bcm5719-llvm-4d480ed5451e9af88e84bcf8be62f8befa915bed.tar.gz bcm5719-llvm-4d480ed5451e9af88e84bcf8be62f8befa915bed.zip |
Internalize linkonce_odr more often.
Since there is a copy in every translation unit that uses them, they can
be omitted from the symbol table if the address is not significant.
This still doesn't catch as many cases as the gold plugin. The
difference is that we check canBeOmittedFromSymbolTable in each file and
use lazy loading which limits what it can do. Gold checks it in the merged file.
I think the correct way of getting the same results as gold is just to
cache in the IR the result of canBeOmittedFromSymbolTable.
llvm-svn: 267063
-rw-r--r-- | lld/ELF/InputFiles.cpp | 8 | ||||
-rw-r--r-- | lld/ELF/Symbols.cpp | 8 | ||||
-rw-r--r-- | lld/ELF/Symbols.h | 6 | ||||
-rw-r--r-- | lld/test/ELF/lto/Inputs/internalize-exportdyn.ll | 6 | ||||
-rw-r--r-- | lld/test/ELF/lto/internalize-exportdyn.ll | 22 |
5 files changed, 45 insertions, 5 deletions
diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 71d7a585583..bccbddf5058 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -12,6 +12,7 @@ #include "InputSection.h" #include "Symbols.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/CodeGen/Analysis.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" #include "llvm/Object/IRObjectFile.h" @@ -498,8 +499,11 @@ BitcodeFile::createSymbolBody(const DenseSet<const Comdat *> &KeptComdats, Body = new (Alloc) DefinedBitcode(NameRef, IsWeak, Visibility); } // FIXME: Expose a thread-local flag for module asm symbols. - if (GV && GV->isThreadLocal()) - Body->Type = STT_TLS; + if (GV) { + if (GV->isThreadLocal()) + Body->Type = STT_TLS; + Body->CanOmitFromDynSym = canBeOmittedFromSymbolTable(GV); + } return Body; } diff --git a/lld/ELF/Symbols.cpp b/lld/ELF/Symbols.cpp index 747161efe8b..e6f8842b80d 100644 --- a/lld/ELF/Symbols.cpp +++ b/lld/ELF/Symbols.cpp @@ -109,6 +109,7 @@ void SymbolBody::init() { K == DefinedSyntheticKind || K == UndefinedElfKind; CanKeepUndefined = false; MustBeInDynSym = false; + CanOmitFromDynSym = false; NeedsCopyOrPltAddr = false; } @@ -241,6 +242,9 @@ int SymbolBody::compare(SymbolBody *Other) { if (IsUsedInRegularObj || Other->IsUsedInRegularObj) IsUsedInRegularObj = Other->IsUsedInRegularObj = true; + if (!CanOmitFromDynSym || !Other->CanOmitFromDynSym) + CanOmitFromDynSym = Other->CanOmitFromDynSym = false; + if (L != R) return -1; if (!isDefined() || isShared() || isWeak()) @@ -360,7 +364,9 @@ bool SymbolBody::includeInDynsym() const { uint8_t V = getVisibility(); if (V != STV_DEFAULT && V != STV_PROTECTED) return false; - return Config->ExportDynamic || Config->Shared; + if (!Config->ExportDynamic && !Config->Shared) + return false; + return !CanOmitFromDynSym; } template uint32_t SymbolBody::template getVA<ELF32LE>(uint32_t) const; diff --git a/lld/ELF/Symbols.h b/lld/ELF/Symbols.h index 11fcdcb5a45..da2ab59a72c 100644 --- a/lld/ELF/Symbols.h +++ b/lld/ELF/Symbols.h @@ -147,6 +147,12 @@ protected: unsigned IsUsedInRegularObj : 1; public: + // True if this symbol can be omitted from the symbol table if nothing else + // requires it to be there. Right now this is only used for linkonce_odr in + // LTO, but we could add the feature to ELF. It would be similar to + // MachO's .weak_def_can_be_hidden. + unsigned CanOmitFromDynSym : 1; + // If true, the symbol is added to .dynsym symbol table. unsigned MustBeInDynSym : 1; diff --git a/lld/test/ELF/lto/Inputs/internalize-exportdyn.ll b/lld/test/ELF/lto/Inputs/internalize-exportdyn.ll new file mode 100644 index 00000000000..21ac3580762 --- /dev/null +++ b/lld/test/ELF/lto/Inputs/internalize-exportdyn.ll @@ -0,0 +1,6 @@ +target triple = "x86_64-unknown-linux-gnu" +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" + +define weak_odr void @bah() { + ret void +} diff --git a/lld/test/ELF/lto/internalize-exportdyn.ll b/lld/test/ELF/lto/internalize-exportdyn.ll index fd70812fef7..4a71289c68f 100644 --- a/lld/test/ELF/lto/internalize-exportdyn.ll +++ b/lld/test/ELF/lto/internalize-exportdyn.ll @@ -1,6 +1,7 @@ ; REQUIRES: x86 ; RUN: llvm-as %s -o %t.o -; RUN: ld.lld -m elf_x86_64 %t.o -o %t2 --export-dynamic -save-temps +; RUN: llvm-as %p/Inputs/internalize-exportdyn.ll -o %t2.o +; RUN: ld.lld -m elf_x86_64 %t.o %t2.o -o %t2 --export-dynamic -save-temps ; RUN: llvm-dis < %t2.lto.bc | FileCheck %s target triple = "x86_64-unknown-linux-gnu" @@ -18,7 +19,24 @@ define hidden void @bar() { ret void } -; Check that _start and foo are not internalized, but bar is. +define linkonce_odr void @zed() unnamed_addr { + ret void +} + +define linkonce_odr void @bah() { + ret void +} + +define linkonce_odr void @baz() { + ret void +} + +@use_baz = global void ()* @baz + +; Check what gets internalized. ; CHECK: define void @_start() ; CHECK: define void @foo() ; CHECK: define internal void @bar() +; CHECK: define internal void @zed() +; CHECK: define weak_odr void @bah() +; CHECK: define weak_odr void @baz() |