summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael Espindola <rafael.espindola@gmail.com>2016-04-21 21:44:25 +0000
committerRafael Espindola <rafael.espindola@gmail.com>2016-04-21 21:44:25 +0000
commit4d480ed5451e9af88e84bcf8be62f8befa915bed (patch)
tree7aa49ad62bd096bfab59a35543d92be0cce4c473
parentc34a519407392fd6fc7432719d1ea05bb9a31d0f (diff)
downloadbcm5719-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.cpp8
-rw-r--r--lld/ELF/Symbols.cpp8
-rw-r--r--lld/ELF/Symbols.h6
-rw-r--r--lld/test/ELF/lto/Inputs/internalize-exportdyn.ll6
-rw-r--r--lld/test/ELF/lto/internalize-exportdyn.ll22
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()
OpenPOWER on IntegriCloud