From 828ac541ef7620e7bccfded34866176d7186d2d1 Mon Sep 17 00:00:00 2001 From: Davide Italiano Date: Mon, 28 Mar 2016 15:44:21 +0000 Subject: [PATCH] [LTO] Internalize symbols. IPO doesn't work very well across symbols referenced by others TUs. The linker here tries to evaluate which symbols are safe to internalize and switches their linkage. Differential Revision: http://reviews.llvm.org/D18415 llvm-svn: 264585 --- lld/ELF/LTO.cpp | 24 ++++++++++++++++++++++++ lld/ELF/LTO.h | 2 ++ lld/ELF/Symbols.h | 3 ++- lld/test/ELF/lto/internalize-basic.ll | 21 +++++++++++++++++++++ 4 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 lld/test/ELF/lto/internalize-basic.ll diff --git a/lld/ELF/LTO.cpp b/lld/ELF/LTO.cpp index cbdd49a..528a914 100644 --- a/lld/ELF/LTO.cpp +++ b/lld/ELF/LTO.cpp @@ -97,6 +97,18 @@ void BitcodeCompiler::add(BitcodeFile &F) { GV->setLinkage(GlobalValue::WeakODRLinkage); break; } + + // We collect the set of symbols we want to internalize here + // and change the linkage after the IRMover executed, i.e. after + // we imported the symbols and satisfied undefined references + // to it. We can't just change linkage here because otherwise + // the IRMover will just rename the symbol. + // Shared libraries need to be handled slightly differently. + // For now, let's be conservative and just never internalize + // symbols when creating a shared library. + if (!Config->Shared && !B->isUsedInRegularObj()) + InternalizedSyms.insert(GV->getName()); + Keep.push_back(GV); } @@ -104,10 +116,22 @@ void BitcodeCompiler::add(BitcodeFile &F) { [](GlobalValue &, IRMover::ValueAdder) {}); } +static void internalize(GlobalValue &GV) { + assert(!GV.hasLocalLinkage() && + "Trying to internalize a symbol with local linkage!") ; + GV.setLinkage(GlobalValue::InternalLinkage); +} + // Merge all the bitcode files we have seen, codegen the result // and return the resulting ObjectFile. template std::unique_ptr> BitcodeCompiler::compile() { + for (const auto &Name : InternalizedSyms) { + GlobalValue *GV = Combined.getNamedValue(Name.first()); + assert(GV); + internalize(*GV); + } + if (Config->SaveTemps) saveBCFile(Combined, ".lto.bc"); diff --git a/lld/ELF/LTO.h b/lld/ELF/LTO.h index bc4d5b0..7a90e97 100644 --- a/lld/ELF/LTO.h +++ b/lld/ELF/LTO.h @@ -23,6 +23,7 @@ #include "lld/Core/LLVM.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringSet.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" #include "llvm/Linker/IRMover.h" @@ -46,6 +47,7 @@ private: llvm::IRMover Mover{Combined}; SmallString<0> OwningData; std::unique_ptr MB; + llvm::StringSet<> InternalizedSyms; }; } } diff --git a/lld/ELF/Symbols.h b/lld/ELF/Symbols.h index c314357..f316f83 100644 --- a/lld/ELF/Symbols.h +++ b/lld/ELF/Symbols.h @@ -120,7 +120,8 @@ protected: IsFunc = Type == llvm::ELF::STT_FUNC; IsTls = Type == llvm::ELF::STT_TLS; IsGnuIFunc = Type == llvm::ELF::STT_GNU_IFUNC; - IsUsedInRegularObj = K != SharedKind && K != LazyKind; + IsUsedInRegularObj = + K != SharedKind && K != LazyKind && K != DefinedBitcodeKind; } const unsigned SymbolKind : 8; diff --git a/lld/test/ELF/lto/internalize-basic.ll b/lld/test/ELF/lto/internalize-basic.ll new file mode 100644 index 0000000..396b9cb --- /dev/null +++ b/lld/test/ELF/lto/internalize-basic.ll @@ -0,0 +1,21 @@ +; REQUIRES: x86 +; RUN: llvm-as %s -o %t.o +; RUN: ld.lld -m elf_x86_64 %t.o -o %t2 -save-temps +; RUN: llvm-dis < %t2.lto.bc | FileCheck %s + +target triple = "x86_64-unknown-linux-gnu" +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" + +define void @_start() { + ret void +} + +define hidden void @foo() { + ret void +} + +; Check that _start is not internalized. +; CHECK: define void @_start() + +; Check that foo function is correctly internalized. +; CHECK: define internal void @foo() -- 2.7.4