Index: ELF/LTO.h =================================================================== --- ELF/LTO.h +++ 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 @@ llvm::IRMover Mover{Combined}; SmallString<0> OwningData; std::unique_ptr MB; + llvm::StringSet<> InternalizedSyms; }; } } Index: ELF/LTO.cpp =================================================================== --- ELF/LTO.cpp +++ ELF/LTO.cpp @@ -15,6 +15,7 @@ #include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/Analysis/TargetTransformInfo.h" #include "llvm/Bitcode/ReaderWriter.h" +#include "llvm/IR/AutoUpgrade.h" #include "llvm/IR/LegacyPassManager.h" #include "llvm/Linker/IRMover.h" #include "llvm/Support/StringSaver.h" @@ -22,6 +23,7 @@ #include "llvm/Target/TargetMachine.h" #include "llvm/Transforms/IPO.h" #include "llvm/Transforms/IPO/PassManagerBuilder.h" +#include "llvm/Transforms/Utils/ModuleUtils.h" using namespace llvm; using namespace llvm::object; @@ -75,6 +77,10 @@ unsigned BodyIndex = 0; ArrayRef Bodies = F.getSymbols(); + SmallPtrSet Used; + Module &M = Obj->getModule(); + collectUsedGlobalVariables(M, Used, /* CompilerUsed */ false); + for (const BasicSymbolRef &Sym : Obj->symbols()) { GlobalValue *GV = Obj->getSymbolGV(Sym.getRawDataRefImpl()); assert(GV); @@ -95,6 +101,18 @@ 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 && !Used.count(GV) && !B->isUsedInRegularObj()) + InternalizedSyms.insert(GV->getName()); + Keep.push_back(GV); } } @@ -104,10 +122,21 @@ [](GlobalValue &, IRMover::ValueAdder) {}); } +static void internalize(GlobalValue &GV) { + if (!GV.hasLocalLinkage()) + 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()); + if (GV) + internalize(*GV); + } + if (Config->SaveTemps) saveBCFile(Combined, ".lto.bc"); Index: ELF/SymbolTable.cpp =================================================================== --- ELF/SymbolTable.cpp +++ ELF/SymbolTable.cpp @@ -214,6 +214,16 @@ SymbolBody *Existing = Sym->Body; + // We want to internalize symbols for LTO to be effective, + // but we can internalize only those that are not referenced + // from regular objects. + if (auto *BC = dyn_cast(Existing)) + if (auto *U = dyn_cast(New)) + BC->setUsedInRegularObj(); + if (auto *U = dyn_cast(Existing)) + if (auto *BC = dyn_cast(New)) + BC->setUsedInRegularObj(); + if (Lazy *L = dyn_cast(Existing)) { if (auto *Undef = dyn_cast(New)) { addMemberFile(Undef, L); Index: ELF/Symbols.h =================================================================== --- ELF/Symbols.h +++ ELF/Symbols.h @@ -92,6 +92,8 @@ template typename ELFT::uint getVA(typename ELFT::uint Addend = 0) const; + void setUsedInRegularObj() { IsUsedInRegularObj = true; } + template typename ELFT::uint getGotVA() const; template typename ELFT::uint getGotPltVA() const; template typename ELFT::uint getPltVA() const; @@ -120,7 +122,8 @@ 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; @@ -318,7 +321,6 @@ std::unique_ptr getMember(); void setWeak() { IsWeak = true; } - void setUsedInRegularObj() { IsUsedInRegularObj = true; } private: ArchiveFile *File;