Skip to content

Commit 4d480ed

Browse files
committed
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
1 parent c34a519 commit 4d480ed

File tree

5 files changed

+45
-5
lines changed

5 files changed

+45
-5
lines changed

lld/ELF/InputFiles.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "InputSection.h"
1313
#include "Symbols.h"
1414
#include "llvm/ADT/STLExtras.h"
15+
#include "llvm/CodeGen/Analysis.h"
1516
#include "llvm/IR/LLVMContext.h"
1617
#include "llvm/IR/Module.h"
1718
#include "llvm/Object/IRObjectFile.h"
@@ -498,8 +499,11 @@ BitcodeFile::createSymbolBody(const DenseSet<const Comdat *> &KeptComdats,
498499
Body = new (Alloc) DefinedBitcode(NameRef, IsWeak, Visibility);
499500
}
500501
// FIXME: Expose a thread-local flag for module asm symbols.
501-
if (GV && GV->isThreadLocal())
502-
Body->Type = STT_TLS;
502+
if (GV) {
503+
if (GV->isThreadLocal())
504+
Body->Type = STT_TLS;
505+
Body->CanOmitFromDynSym = canBeOmittedFromSymbolTable(GV);
506+
}
503507
return Body;
504508
}
505509

lld/ELF/Symbols.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ void SymbolBody::init() {
109109
K == DefinedSyntheticKind || K == UndefinedElfKind;
110110
CanKeepUndefined = false;
111111
MustBeInDynSym = false;
112+
CanOmitFromDynSym = false;
112113
NeedsCopyOrPltAddr = false;
113114
}
114115

@@ -241,6 +242,9 @@ int SymbolBody::compare(SymbolBody *Other) {
241242
if (IsUsedInRegularObj || Other->IsUsedInRegularObj)
242243
IsUsedInRegularObj = Other->IsUsedInRegularObj = true;
243244

245+
if (!CanOmitFromDynSym || !Other->CanOmitFromDynSym)
246+
CanOmitFromDynSym = Other->CanOmitFromDynSym = false;
247+
244248
if (L != R)
245249
return -1;
246250
if (!isDefined() || isShared() || isWeak())
@@ -360,7 +364,9 @@ bool SymbolBody::includeInDynsym() const {
360364
uint8_t V = getVisibility();
361365
if (V != STV_DEFAULT && V != STV_PROTECTED)
362366
return false;
363-
return Config->ExportDynamic || Config->Shared;
367+
if (!Config->ExportDynamic && !Config->Shared)
368+
return false;
369+
return !CanOmitFromDynSym;
364370
}
365371

366372
template uint32_t SymbolBody::template getVA<ELF32LE>(uint32_t) const;

lld/ELF/Symbols.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,12 @@ class SymbolBody {
147147
unsigned IsUsedInRegularObj : 1;
148148

149149
public:
150+
// True if this symbol can be omitted from the symbol table if nothing else
151+
// requires it to be there. Right now this is only used for linkonce_odr in
152+
// LTO, but we could add the feature to ELF. It would be similar to
153+
// MachO's .weak_def_can_be_hidden.
154+
unsigned CanOmitFromDynSym : 1;
155+
150156
// If true, the symbol is added to .dynsym symbol table.
151157
unsigned MustBeInDynSym : 1;
152158

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
target triple = "x86_64-unknown-linux-gnu"
2+
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
3+
4+
define weak_odr void @bah() {
5+
ret void
6+
}

lld/test/ELF/lto/internalize-exportdyn.ll

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
; REQUIRES: x86
22
; RUN: llvm-as %s -o %t.o
3-
; RUN: ld.lld -m elf_x86_64 %t.o -o %t2 --export-dynamic -save-temps
3+
; RUN: llvm-as %p/Inputs/internalize-exportdyn.ll -o %t2.o
4+
; RUN: ld.lld -m elf_x86_64 %t.o %t2.o -o %t2 --export-dynamic -save-temps
45
; RUN: llvm-dis < %t2.lto.bc | FileCheck %s
56

67
target triple = "x86_64-unknown-linux-gnu"
@@ -18,7 +19,24 @@ define hidden void @bar() {
1819
ret void
1920
}
2021

21-
; Check that _start and foo are not internalized, but bar is.
22+
define linkonce_odr void @zed() unnamed_addr {
23+
ret void
24+
}
25+
26+
define linkonce_odr void @bah() {
27+
ret void
28+
}
29+
30+
define linkonce_odr void @baz() {
31+
ret void
32+
}
33+
34+
@use_baz = global void ()* @baz
35+
36+
; Check what gets internalized.
2237
; CHECK: define void @_start()
2338
; CHECK: define void @foo()
2439
; CHECK: define internal void @bar()
40+
; CHECK: define internal void @zed()
41+
; CHECK: define weak_odr void @bah()
42+
; CHECK: define weak_odr void @baz()

0 commit comments

Comments
 (0)