[PATCH] D24492: [LTO] Switch to the new resolution-based API.

Rafael EspĂ­ndola via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 15 07:56:54 PDT 2016


I rebased the patch to take a look.

Attached for convenience.



On 14 September 2016 at 15:05, Peter Collingbourne <peter at pcc.me.uk> wrote:
> pcc added inline comments.
>
> ================
> Comment at: ELF/SymbolTable.cpp:213
> @@ +212,3 @@
> +    Expected<std::unique_ptr<lto::InputFile>> ObjOrErr =
> +        lto::InputFile::create(F->getBuffer());
> +    if (!ObjOrErr)
> ----------------
> You should replace all uses of IRObjectFile elsewhere with lto::InputFile. Then you won't need to create a new InputFile here, you can just reuse the one in the BitcodeFile.
>
> ================
> Comment at: ELF/SymbolTable.cpp:225
> @@ +224,3 @@
> +    std::vector<lto::SymbolResolution> Resols(Syms.size());
> +    for (LLVM_ATTRIBUTE_UNUSED auto &ObjSym : Obj.symbols()) {
> +      Symbol *Sym = Syms[SymNum];
> ----------------
> You shouldn't need to do this, see r281437.
>
> ================
> Comment at: ELF/SymbolTable.cpp:234
> @@ +233,3 @@
> +        continue;
> +      R.Prevailing = Sym->body()->isDefined();
> +      R.VisibleToRegularObj = Sym->IsUsedInRegularObj || Sym->includeInDynsym();
> ----------------
> This isn't right, this should test whether the SymbolBody is a DefinedBitcode and is defined by this BitcodeFile.
>
> ================
> Comment at: ELF/SymbolTable.cpp:252
> @@ +251,3 @@
> +    auto &OutputName = Filenames[Task];
> +    getOutputFileName(Filename, OutputName, MaxTasks > 1 ? Task : -1);
> +    return llvm::make_unique<LTOOutput>(OutputName);
> ----------------
> There's no need to save objects to files, you can just use raw_string_ostream and operate on the object file directly in memory.
>
>
> https://reviews.llvm.org/D24492
>
>
>
-------------- next part --------------
diff --git a/ELF/CMakeLists.txt b/ELF/CMakeLists.txt
index b9e374a..24043e9 100644
--- a/ELF/CMakeLists.txt
+++ b/ELF/CMakeLists.txt
@@ -1,54 +1,53 @@
 set(LLVM_TARGET_DEFINITIONS Options.td)
 tablegen(LLVM Options.inc -gen-opt-parser-defs)
 add_public_tablegen_target(ELFOptionsTableGen)
 
 add_lld_library(lldELF
   Driver.cpp
   DriverUtils.cpp
   EhFrame.cpp
   ELFCreator.cpp
   Error.cpp
   ICF.cpp
   InputFiles.cpp
   InputSection.cpp
-  LTO.cpp
   LinkerScript.cpp
   MarkLive.cpp
   Mips.cpp
   OutputSections.cpp
   Relocations.cpp
   ScriptParser.cpp
   Strings.cpp
   SymbolListFile.cpp
   SymbolTable.cpp
   Symbols.cpp
   Target.cpp
   Thunks.cpp
   Writer.cpp
 
   LINK_COMPONENTS
   ${LLVM_TARGETS_TO_BUILD}
   Analysis
   BitReader
   BitWriter
   Codegen
   Core
   Demangle
   IPO
   Linker
   LTO
   Object
   Option
   Passes
   MC
   Support
   Target
   TransformUtils
 
   LINK_LIBS
   lldConfig
   lldCore
   ${PTHREAD_LIB}
   )
 
 add_dependencies(lldELF intrinsics_gen ELFOptionsTableGen)
diff --git a/ELF/Driver.h b/ELF/Driver.h
index cdb19f5..6819a6e 100644
--- a/ELF/Driver.h
+++ b/ELF/Driver.h
@@ -1,84 +1,85 @@
 //===- Driver.h -------------------------------------------------*- C++ -*-===//
 //
 //                             The LLVM Linker
 //
 // This file is distributed under the University of Illinois Open Source
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
 
 #ifndef LLD_ELF_DRIVER_H
 #define LLD_ELF_DRIVER_H
 
 #include "SymbolTable.h"
 #include "lld/Core/LLVM.h"
 #include "lld/Core/Reproduce.h"
 #include "llvm/ADT/Optional.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/StringSet.h"
+#include "llvm/IR/LLVMContext.h"
 #include "llvm/Option/ArgList.h"
 #include "llvm/Support/raw_ostream.h"
 
 namespace lld {
 namespace elf {
 
 extern class LinkerDriver *Driver;
 
 class LinkerDriver {
 public:
   void main(ArrayRef<const char *> Args);
   void addFile(StringRef Path, bool KnownScript = false);
   void addLibrary(StringRef Name);
   llvm::LLVMContext Context;      // to parse bitcode ifles
   std::unique_ptr<CpioFile> Cpio; // for reproduce
 
 private:
   std::vector<MemoryBufferRef> getArchiveMembers(MemoryBufferRef MB);
   llvm::Optional<MemoryBufferRef> readFile(StringRef Path);
   void readConfigs(llvm::opt::InputArgList &Args);
   void createFiles(llvm::opt::InputArgList &Args);
   template <class ELFT> void link(llvm::opt::InputArgList &Args);
 
   // True if we are in --whole-archive and --no-whole-archive.
   bool WholeArchive = false;
 
   // True if we are in --start-lib and --end-lib.
   bool InLib = false;
 
   llvm::BumpPtrAllocator Alloc;
   std::vector<InputFile *> Files;
   std::vector<std::unique_ptr<MemoryBuffer>> OwningMBs;
 };
 
 // Parses command line options.
 class ELFOptTable : public llvm::opt::OptTable {
 public:
   ELFOptTable();
   llvm::opt::InputArgList parse(ArrayRef<const char *> Argv);
 
 private:
   llvm::BumpPtrAllocator Alloc;
 };
 
 // Create enum with OPT_xxx values for each option in Options.td
 enum {
   OPT_INVALID = 0,
 #define OPTION(_1, _2, ID, _4, _5, _6, _7, _8, _9, _10, _11) OPT_##ID,
 #include "Options.inc"
 #undef OPTION
 };
 
 void printHelp(const char *Argv0);
 std::string getVersionString();
 std::vector<uint8_t> parseHexstring(StringRef S);
 
 std::string createResponseFile(const llvm::opt::InputArgList &Args);
 
 std::string findFromSearchPaths(StringRef Path);
 std::string searchLibrary(StringRef Path);
 std::string buildSysrootedPath(llvm::StringRef Dir, llvm::StringRef File);
 
 } // namespace elf
 } // namespace lld
 
 #endif
diff --git a/ELF/Error.h b/ELF/Error.h
index 552f504..5f3d059 100644
--- a/ELF/Error.h
+++ b/ELF/Error.h
@@ -1,61 +1,70 @@
 //===- Error.h --------------------------------------------------*- C++ -*-===//
 //
 //                             The LLVM Linker
 //
 // This file is distributed under the University of Illinois Open Source
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
 
 #ifndef LLD_COFF_ERROR_H
 #define LLD_COFF_ERROR_H
 
 #include "lld/Core/LLVM.h"
 
+#include "llvm/Support/Error.h"
+
 namespace lld {
 namespace elf {
 
 extern bool HasError;
 extern llvm::raw_ostream *ErrorOS;
 
 void log(const Twine &Msg);
 void warning(const Twine &Msg);
 
 void error(const Twine &Msg);
 void error(std::error_code EC, const Twine &Prefix);
 
 template <typename T> void error(const ErrorOr<T> &V, const Twine &Prefix) {
   error(V.getError(), Prefix);
 }
 
 LLVM_ATTRIBUTE_NORETURN void fatal(const Twine &Msg);
 LLVM_ATTRIBUTE_NORETURN void fatal(const Twine &Msg, const Twine &Prefix);
 
+inline void check(Error E, std::string Msg = "") {
+  handleAllErrors(std::move(E), [&](llvm::ErrorInfoBase &EIB) {
+    error(EIB.message().c_str());
+    return Error::success();
+  });
+}
+
 template <class T> T check(ErrorOr<T> E) {
   if (auto EC = E.getError())
     fatal(EC.message());
   return std::move(*E);
 }
 
 template <class T> T check(Expected<T> E) {
   if (!E)
     fatal(errorToErrorCode(E.takeError()).message());
   return std::move(*E);
 }
 
 template <class T> T check(ErrorOr<T> E, const Twine &Prefix) {
   if (auto EC = E.getError())
     fatal(EC.message(), Prefix);
   return std::move(*E);
 }
 
 template <class T> T check(Expected<T> E, const Twine &Prefix) {
   if (!E)
     fatal(errorToErrorCode(E.takeError()).message(), Prefix);
   return std::move(*E);
 }
 
 } // namespace elf
 } // namespace lld
 
 #endif
diff --git a/ELF/InputFiles.h b/ELF/InputFiles.h
index 4211574..ff4ac8c 100644
--- a/ELF/InputFiles.h
+++ b/ELF/InputFiles.h
@@ -1,329 +1,330 @@
 //===- InputFiles.h ---------------------------------------------*- C++ -*-===//
 //
 //                             The LLVM Linker
 //
 // This file is distributed under the University of Illinois Open Source
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
 
 #ifndef LLD_ELF_INPUT_FILES_H
 #define LLD_ELF_INPUT_FILES_H
 
 #include "Config.h"
 #include "InputSection.h"
 #include "Error.h"
 #include "Symbols.h"
 
 #include "lld/Core/LLVM.h"
 #include "lld/Core/Reproduce.h"
 #include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/IR/Comdat.h"
 #include "llvm/Object/Archive.h"
 #include "llvm/Object/ELF.h"
 #include "llvm/Object/IRObjectFile.h"
 #include "llvm/Support/StringSaver.h"
 
 #include <map>
 
 namespace lld {
 namespace elf {
 
 using llvm::object::Archive;
 
 class InputFile;
 class Lazy;
 class SymbolBody;
 
 // The root class of input files.
 class InputFile {
 public:
   virtual ~InputFile() = default;
 
   enum Kind {
     ObjectKind,
     SharedKind,
     LazyObjectKind,
     ArchiveKind,
     BitcodeKind,
     BinaryKind,
   };
 
   Kind kind() const { return FileKind; }
 
   StringRef getName() const { return MB.getBufferIdentifier(); }
   MemoryBufferRef MB;
 
   // Filename of .a which contained this file. If this file was
   // not in an archive file, it is the empty string. We use this
   // string for creating error messages.
   StringRef ArchiveName;
 
   // If this is an architecture-specific file, the following members
   // have ELF type (i.e. ELF{32,64}{LE,BE}) and target machine type.
   ELFKind EKind = ELFNoneKind;
   uint16_t EMachine = llvm::ELF::EM_NONE;
 
   static void freePool();
 
 protected:
   InputFile(Kind K, MemoryBufferRef M) : MB(M), FileKind(K) {
     Pool.push_back(this);
   }
 
 private:
   const Kind FileKind;
 
   // All InputFile instances are added to the pool
   // and freed all at once on exit by freePool().
   static std::vector<InputFile *> Pool;
 };
 
 // Returns "(internal)", "foo.a(bar.o)" or "baz.o".
 std::string getFilename(const InputFile *F);
 
 template <typename ELFT> class ELFFileBase : public InputFile {
 public:
   typedef typename ELFT::Shdr Elf_Shdr;
   typedef typename ELFT::Sym Elf_Sym;
   typedef typename ELFT::Word Elf_Word;
   typedef typename ELFT::SymRange Elf_Sym_Range;
 
   ELFFileBase(Kind K, MemoryBufferRef M);
   static bool classof(const InputFile *F) {
     Kind K = F->kind();
     return K == ObjectKind || K == SharedKind;
   }
 
   const llvm::object::ELFFile<ELFT> &getObj() const { return ELFObj; }
   llvm::object::ELFFile<ELFT> &getObj() { return ELFObj; }
 
   uint8_t getOSABI() const {
     return getObj().getHeader()->e_ident[llvm::ELF::EI_OSABI];
   }
 
   StringRef getStringTable() const { return StringTable; }
 
   uint32_t getSectionIndex(const Elf_Sym &Sym) const;
 
   Elf_Sym_Range getElfSymbols(bool OnlyGlobals);
 
 protected:
   llvm::object::ELFFile<ELFT> ELFObj;
   const Elf_Shdr *Symtab = nullptr;
   ArrayRef<Elf_Word> SymtabSHNDX;
   StringRef StringTable;
   void initStringTable();
 };
 
 // .o file.
 template <class ELFT> class ObjectFile : public ELFFileBase<ELFT> {
   typedef ELFFileBase<ELFT> Base;
   typedef typename ELFT::Sym Elf_Sym;
   typedef typename ELFT::Shdr Elf_Shdr;
   typedef typename ELFT::SymRange Elf_Sym_Range;
   typedef typename ELFT::Word Elf_Word;
   typedef typename ELFT::uint uintX_t;
 
   StringRef getShtGroupSignature(const Elf_Shdr &Sec);
   ArrayRef<Elf_Word> getShtGroupEntries(const Elf_Shdr &Sec);
 
 public:
   static bool classof(const InputFile *F) {
     return F->kind() == Base::ObjectKind;
   }
 
   ArrayRef<SymbolBody *> getSymbols();
   ArrayRef<SymbolBody *> getLocalSymbols();
   ArrayRef<SymbolBody *> getNonLocalSymbols();
 
   explicit ObjectFile(MemoryBufferRef M);
   void parse(llvm::DenseSet<StringRef> &ComdatGroups);
 
   ArrayRef<InputSectionBase<ELFT> *> getSections() const { return Sections; }
   InputSectionBase<ELFT> *getSection(const Elf_Sym &Sym) const;
 
   SymbolBody &getSymbolBody(uint32_t SymbolIndex) const {
     return *SymbolBodies[SymbolIndex];
   }
 
   template <typename RelT> SymbolBody &getRelocTargetSym(const RelT &Rel) const {
     uint32_t SymIndex = Rel.getSymbol(Config->Mips64EL);
     return getSymbolBody(SymIndex);
   }
 
   const Elf_Shdr *getSymbolTable() const { return this->Symtab; };
 
   // Get MIPS GP0 value defined by this file. This value represents the gp value
   // used to create the relocatable object and required to support
   // R_MIPS_GPREL16 / R_MIPS_GPREL32 relocations.
   uint32_t getMipsGp0() const;
 
   // The number is the offset in the string table. It will be used as the
   // st_name of the symbol.
   std::vector<std::pair<const DefinedRegular<ELFT> *, unsigned>> KeptLocalSyms;
 
   // SymbolBodies and Thunks for sections in this file are allocated
   // using this buffer.
   llvm::BumpPtrAllocator Alloc;
 
 private:
   void initializeSections(llvm::DenseSet<StringRef> &ComdatGroups);
   void initializeSymbols();
   InputSectionBase<ELFT> *getRelocTarget(const Elf_Shdr &Sec);
   InputSectionBase<ELFT> *createInputSection(const Elf_Shdr &Sec);
 
   bool shouldMerge(const Elf_Shdr &Sec);
   SymbolBody *createSymbolBody(const Elf_Sym *Sym);
 
   // List of all sections defined by this file.
   std::vector<InputSectionBase<ELFT> *> Sections;
 
   // List of all symbols referenced or defined by this file.
   std::vector<SymbolBody *> SymbolBodies;
 
   // MIPS .reginfo section defined by this file.
   std::unique_ptr<MipsReginfoInputSection<ELFT>> MipsReginfo;
   // MIPS .MIPS.options section defined by this file.
   std::unique_ptr<MipsOptionsInputSection<ELFT>> MipsOptions;
   // MIPS .MIPS.abiflags section defined by this file.
   std::unique_ptr<MipsAbiFlagsInputSection<ELFT>> MipsAbiFlags;
 
   llvm::SpecificBumpPtrAllocator<InputSection<ELFT>> IAlloc;
   llvm::SpecificBumpPtrAllocator<MergeInputSection<ELFT>> MAlloc;
   llvm::SpecificBumpPtrAllocator<EhInputSection<ELFT>> EHAlloc;
 };
 
 // LazyObjectFile is analogous to ArchiveFile in the sense that
 // the file contains lazy symbols. The difference is that
 // LazyObjectFile wraps a single file instead of multiple files.
 //
 // This class is used for --start-lib and --end-lib options which
 // instruct the linker to link object files between them with the
 // archive file semantics.
 class LazyObjectFile : public InputFile {
 public:
   explicit LazyObjectFile(MemoryBufferRef M) : InputFile(LazyObjectKind, M) {}
 
   static bool classof(const InputFile *F) {
     return F->kind() == LazyObjectKind;
   }
 
   template <class ELFT> void parse();
   MemoryBufferRef getBuffer();
 
 private:
   std::vector<StringRef> getSymbols();
   template <class ELFT> std::vector<StringRef> getElfSymbols();
   std::vector<StringRef> getBitcodeSymbols();
 
   llvm::BumpPtrAllocator Alloc;
   llvm::StringSaver Saver{Alloc};
   bool Seen = false;
 };
 
 // An ArchiveFile object represents a .a file.
 class ArchiveFile : public InputFile {
 public:
   explicit ArchiveFile(MemoryBufferRef M) : InputFile(ArchiveKind, M) {}
   static bool classof(const InputFile *F) { return F->kind() == ArchiveKind; }
   template <class ELFT> void parse();
 
   // Returns a memory buffer for a given symbol. An empty memory buffer
   // is returned if we have already returned the same memory buffer.
   // (So that we don't instantiate same members more than once.)
   MemoryBufferRef getMember(const Archive::Symbol *Sym);
 
 private:
   std::unique_ptr<Archive> File;
   llvm::DenseSet<uint64_t> Seen;
 };
 
 class BitcodeFile : public InputFile {
 public:
   explicit BitcodeFile(MemoryBufferRef M);
   static bool classof(const InputFile *F) { return F->kind() == BitcodeKind; }
   template <class ELFT>
   void parse(llvm::DenseSet<StringRef> &ComdatGroups);
   ArrayRef<Symbol *> getSymbols() { return Symbols; }
   static bool shouldSkip(uint32_t Flags);
   std::unique_ptr<llvm::object::IRObjectFile> Obj;
+  MemoryBufferRef getBuffer() { return MB; }
 
 private:
   std::vector<Symbol *> Symbols;
   llvm::BumpPtrAllocator Alloc;
   llvm::StringSaver Saver{Alloc};
   template <class ELFT>
   Symbol *createSymbol(const llvm::DenseSet<const llvm::Comdat *> &KeptComdats,
                        const llvm::object::IRObjectFile &Obj,
                        const llvm::object::BasicSymbolRef &Sym);
 };
 
 // .so file.
 template <class ELFT> class SharedFile : public ELFFileBase<ELFT> {
   typedef ELFFileBase<ELFT> Base;
   typedef typename ELFT::Shdr Elf_Shdr;
   typedef typename ELFT::Sym Elf_Sym;
   typedef typename ELFT::Word Elf_Word;
   typedef typename ELFT::SymRange Elf_Sym_Range;
   typedef typename ELFT::Versym Elf_Versym;
   typedef typename ELFT::Verdef Elf_Verdef;
 
   std::vector<StringRef> Undefs;
   StringRef SoName;
   const Elf_Shdr *VersymSec = nullptr;
   const Elf_Shdr *VerdefSec = nullptr;
 
 public:
   StringRef getSoName() const { return SoName; }
   const Elf_Shdr *getSection(const Elf_Sym &Sym) const;
   llvm::ArrayRef<StringRef> getUndefinedSymbols() { return Undefs; }
 
   static bool classof(const InputFile *F) {
     return F->kind() == Base::SharedKind;
   }
 
   explicit SharedFile(MemoryBufferRef M);
 
   void parseSoName();
   void parseRest();
   std::vector<const Elf_Verdef *> parseVerdefs(const Elf_Versym *&Versym);
 
   struct NeededVer {
     // The string table offset of the version name in the output file.
     size_t StrTab;
 
     // The version identifier for this version name.
     uint16_t Index;
   };
 
   // Mapping from Elf_Verdef data structures to information about Elf_Vernaux
   // data structures in the output file.
   std::map<const Elf_Verdef *, NeededVer> VerdefMap;
 
   // Used for --as-needed
   bool AsNeeded = false;
   bool IsUsed = false;
   bool isNeeded() const { return !AsNeeded || IsUsed; }
 };
 
 class BinaryFile : public InputFile {
 public:
   explicit BinaryFile(MemoryBufferRef M) : InputFile(BinaryKind, M) {}
 
   static bool classof(const InputFile *F) { return F->kind() == BinaryKind; }
 
   template <class ELFT> InputFile *createELF();
 
 private:
   std::vector<uint8_t> ELFData;
 };
 
 InputFile *createObjectFile(MemoryBufferRef MB, StringRef ArchiveName = "");
 InputFile *createSharedFile(MemoryBufferRef MB);
 
 } // namespace elf
 } // namespace lld
 
 #endif
diff --git a/ELF/LTO.cpp b/ELF/LTO.cpp
deleted file mode 100644
index 600a103..0000000
--- a/ELF/LTO.cpp
+++ /dev/null
@@ -1,333 +0,0 @@
-//===- LTO.cpp ------------------------------------------------------------===//
-//
-//                             The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "LTO.h"
-#include "Config.h"
-#include "Driver.h"
-#include "Error.h"
-#include "InputFiles.h"
-#include "Symbols.h"
-#include "llvm/Analysis/AliasAnalysis.h"
-#include "llvm/Analysis/CGSCCPassManager.h"
-#include "llvm/Analysis/LoopPassManager.h"
-#include "llvm/Analysis/TargetLibraryInfo.h"
-#include "llvm/Analysis/TargetTransformInfo.h"
-#include "llvm/Bitcode/ReaderWriter.h"
-#include "llvm/CodeGen/CommandFlags.h"
-#include "llvm/CodeGen/ParallelCG.h"
-#include "llvm/IR/AutoUpgrade.h"
-#include "llvm/IR/LegacyPassManager.h"
-#include "llvm/IR/PassManager.h"
-#include "llvm/IR/Verifier.h"
-#include "llvm/LTO/legacy/UpdateCompilerUsed.h"
-#include "llvm/Linker/IRMover.h"
-#include "llvm/Passes/PassBuilder.h"
-#include "llvm/Support/StringSaver.h"
-#include "llvm/Support/TargetRegistry.h"
-#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;
-using namespace llvm::ELF;
-
-using namespace lld;
-using namespace lld::elf;
-
-// This is for use when debugging LTO.
-static void saveBuffer(StringRef Buffer, const Twine &Path) {
-  std::error_code EC;
-  raw_fd_ostream OS(Path.str(), EC, sys::fs::OpenFlags::F_None);
-  if (EC)
-    error(EC, "cannot create " + Path);
-  OS << Buffer;
-}
-
-// This is for use when debugging LTO.
-static void saveBCFile(Module &M, const Twine &Path) {
-  std::error_code EC;
-  raw_fd_ostream OS(Path.str(), EC, sys::fs::OpenFlags::F_None);
-  if (EC)
-    error(EC, "cannot create " + Path);
-  WriteBitcodeToFile(&M, OS, /* ShouldPreserveUseListOrder */ true);
-}
-
-static void runNewCustomLtoPasses(Module &M, TargetMachine &TM) {
-  PassBuilder PB(&TM);
-
-  AAManager AA;
-
-  // Parse a custom AA pipeline if asked to.
-  if (!PB.parseAAPipeline(AA, Config->LtoAAPipeline)) {
-    error("Unable to parse AA pipeline description: " + Config->LtoAAPipeline);
-    return;
-  }
-
-  LoopAnalysisManager LAM;
-  FunctionAnalysisManager FAM;
-  CGSCCAnalysisManager CGAM;
-  ModuleAnalysisManager MAM;
-
-  // Register the AA manager first so that our version is the one used.
-  FAM.registerPass([&] { return std::move(AA); });
-
-  // Register all the basic analyses with the managers.
-  PB.registerModuleAnalyses(MAM);
-  PB.registerCGSCCAnalyses(CGAM);
-  PB.registerFunctionAnalyses(FAM);
-  PB.registerLoopAnalyses(LAM);
-  PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
-
-  ModulePassManager MPM;
-  if (!Config->DisableVerify)
-    MPM.addPass(VerifierPass());
-
-  // Now, add all the passes we've been requested to.
-  if (!PB.parsePassPipeline(MPM, Config->LtoNewPmPasses)) {
-    error("unable to parse pass pipeline description: " +
-          Config->LtoNewPmPasses);
-    return;
-  }
-
-  if (!Config->DisableVerify)
-    MPM.addPass(VerifierPass());
-  MPM.run(M, MAM);
-}
-
-static void runOldLtoPasses(Module &M, TargetMachine &TM) {
-  // Note that the gold plugin has a similar piece of code, so
-  // it is probably better to move this code to a common place.
-  legacy::PassManager LtoPasses;
-  LtoPasses.add(createTargetTransformInfoWrapperPass(TM.getTargetIRAnalysis()));
-  PassManagerBuilder PMB;
-  PMB.LibraryInfo = new TargetLibraryInfoImpl(Triple(TM.getTargetTriple()));
-  PMB.Inliner = createFunctionInliningPass();
-  PMB.VerifyInput = PMB.VerifyOutput = !Config->DisableVerify;
-  PMB.LoopVectorize = true;
-  PMB.SLPVectorize = true;
-  PMB.OptLevel = Config->LtoO;
-  PMB.populateLTOPassManager(LtoPasses);
-  LtoPasses.run(M);
-}
-
-static void runLTOPasses(Module &M, TargetMachine &TM) {
-  if (!Config->LtoNewPmPasses.empty()) {
-    // The user explicitly asked for a set of passes to be run.
-    // This needs the new PM to work as there's no clean way to
-    // pass a set of passes to run in the legacy PM.
-    runNewCustomLtoPasses(M, TM);
-    if (HasError)
-      return;
-  } else {
-    // Run the 'default' set of LTO passes. This code still uses
-    // the legacy PM as the new one is not the default.
-    runOldLtoPasses(M, TM);
-  }
-
-  if (Config->SaveTemps)
-    saveBCFile(M, Config->OutputFile + ".lto.opt.bc");
-}
-
-static bool shouldInternalize(const SmallPtrSet<GlobalValue *, 8> &Used,
-                              Symbol *S, GlobalValue *GV) {
-  if (S->IsUsedInRegularObj || Used.count(GV))
-    return false;
-  return !S->includeInDynsym();
-}
-
-BitcodeCompiler::BitcodeCompiler()
-    : Combined(new Module("ld-temp.o", Driver->Context)) {}
-
-static void undefine(Symbol *S) {
-  replaceBody<Undefined>(S, S->body()->getName(), STV_DEFAULT, S->body()->Type,
-                         nullptr);
-}
-
-static void handleUndefinedAsmRefs(const BasicSymbolRef &Sym, GlobalValue *GV,
-                                   StringSet<> &AsmUndefinedRefs) {
-  // GV associated => not an assembly symbol, bail out.
-  if (GV)
-    return;
-
-  // This is an undefined reference to a symbol in asm. We put that in
-  // compiler.used, so that we can preserve it from being dropped from
-  // the output, without necessarily preventing its internalization.
-  SmallString<64> Name;
-  raw_svector_ostream OS(Name);
-  Sym.printName(OS);
-  AsmUndefinedRefs.insert(Name.str());
-}
-
-void BitcodeCompiler::add(BitcodeFile &F) {
-  std::unique_ptr<IRObjectFile> Obj = std::move(F.Obj);
-  std::vector<GlobalValue *> Keep;
-  unsigned BodyIndex = 0;
-  ArrayRef<Symbol *> Syms = F.getSymbols();
-
-  Module &M = Obj->getModule();
-  if (M.getDataLayoutStr().empty())
-    fatal("invalid bitcode file: " + F.getName() + " has no datalayout");
-
-  // Discard non-compatible debug infos if necessary.
-  M.materializeMetadata();
-  UpgradeDebugInfo(M);
-
-  // If a symbol appears in @llvm.used, the linker is required
-  // to treat the symbol as there is a reference to the symbol
-  // that it cannot see. Therefore, we can't internalize.
-  SmallPtrSet<GlobalValue *, 8> Used;
-  collectUsedGlobalVariables(M, Used, /* CompilerUsed */ false);
-
-  for (const BasicSymbolRef &Sym : Obj->symbols()) {
-    uint32_t Flags = Sym.getFlags();
-    GlobalValue *GV = Obj->getSymbolGV(Sym.getRawDataRefImpl());
-    if (GV && GV->hasAppendingLinkage())
-      Keep.push_back(GV);
-    if (BitcodeFile::shouldSkip(Flags))
-      continue;
-    Symbol *S = Syms[BodyIndex++];
-    if (GV)
-      GV->setUnnamedAddr(S->HasUnnamedAddr ? GlobalValue::UnnamedAddr::Global
-                                           : GlobalValue::UnnamedAddr::None);
-    if (Flags & BasicSymbolRef::SF_Undefined) {
-      handleUndefinedAsmRefs(Sym, GV, AsmUndefinedRefs);
-      continue;
-    }
-    SymbolBody *B = S->body();
-    if (B->File != &F)
-      continue;
-
-    // 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.
-    if (GV && shouldInternalize(Used, S, GV))
-      InternalizedSyms.insert(GV->getName());
-
-    // At this point we know that either the combined LTO object will provide a
-    // definition of a symbol, or we will internalize it. In either case, we
-    // need to undefine the symbol. In the former case, the real definition
-    // needs to be able to replace the original definition without conflicting.
-    // In the latter case, we need to allow the combined LTO object to provide a
-    // definition with the same name, for example when doing parallel codegen.
-    if (auto *C = dyn_cast<DefinedCommon>(B)) {
-      if (auto *GO = dyn_cast<GlobalObject>(GV))
-        GO->setAlignment(C->Alignment);
-    } else {
-      undefine(S);
-    }
-
-    if (!GV)
-      // Module asm symbol.
-      continue;
-
-    switch (GV->getLinkage()) {
-    default:
-      break;
-    case GlobalValue::LinkOnceAnyLinkage:
-      GV->setLinkage(GlobalValue::WeakAnyLinkage);
-      break;
-    case GlobalValue::LinkOnceODRLinkage:
-      GV->setLinkage(GlobalValue::WeakODRLinkage);
-      break;
-    }
-
-    Keep.push_back(GV);
-  }
-
-  IRMover Mover(*Combined);
-  if (Error E = Mover.move(Obj->takeModule(), Keep,
-                           [](GlobalValue &, IRMover::ValueAdder) {})) {
-    handleAllErrors(std::move(E), [&](const ErrorInfoBase &EIB) {
-      fatal("failed to link module " + F.getName() + ": " + EIB.message());
-    });
-  }
-}
-
-static void internalize(GlobalValue &GV) {
-  assert(!GV.hasLocalLinkage() &&
-         "Trying to internalize a symbol with local linkage!");
-  GV.setLinkage(GlobalValue::InternalLinkage);
-}
-
-std::vector<InputFile *> BitcodeCompiler::runSplitCodegen(
-    const std::function<std::unique_ptr<TargetMachine>()> &TMFactory) {
-  unsigned NumThreads = Config->LtoJobs;
-  OwningData.resize(NumThreads);
-
-  std::list<raw_svector_ostream> OSs;
-  std::vector<raw_pwrite_stream *> OSPtrs;
-  for (SmallString<0> &Obj : OwningData) {
-    OSs.emplace_back(Obj);
-    OSPtrs.push_back(&OSs.back());
-  }
-
-  splitCodeGen(std::move(Combined), OSPtrs, {}, TMFactory);
-
-  std::vector<InputFile *> ObjFiles;
-  for (SmallString<0> &Obj : OwningData)
-    ObjFiles.push_back(createObjectFile(
-        MemoryBufferRef(Obj, "LLD-INTERNAL-combined-lto-object")));
-
-  // If -save-temps is given, we need to save temporary objects to files.
-  // This is for debugging.
-  if (Config->SaveTemps) {
-    if (NumThreads == 1) {
-      saveBuffer(OwningData[0], Config->OutputFile + ".lto.o");
-    } else {
-      for (unsigned I = 0; I < NumThreads; ++I)
-        saveBuffer(OwningData[I], Config->OutputFile + Twine(I) + ".lto.o");
-    }
-  }
-
-  return ObjFiles;
-}
-
-// Merge all the bitcode files we have seen, codegen the result
-// and return the resulting ObjectFile.
-std::vector<InputFile *> BitcodeCompiler::compile() {
-  for (const auto &Name : InternalizedSyms) {
-    GlobalValue *GV = Combined->getNamedValue(Name.first());
-    assert(GV);
-    internalize(*GV);
-  }
-
-  std::string TheTriple = Combined->getTargetTriple();
-  std::string Msg;
-  const Target *T = TargetRegistry::lookupTarget(TheTriple, Msg);
-  if (!T)
-    fatal("target not found: " + Msg);
-
-  // LLD supports the new relocations.
-  TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
-  Options.RelaxELFRelocations = true;
-
-  auto CreateTargetMachine = [&]() {
-    return std::unique_ptr<TargetMachine>(T->createTargetMachine(
-        TheTriple, "", "", Options, Config->Pic ? Reloc::PIC_ : Reloc::Static));
-  };
-
-  std::unique_ptr<TargetMachine> TM = CreateTargetMachine();
-
-  // Update llvm.compiler.used so that optimizations won't strip
-  // off AsmUndefinedReferences.
-  updateCompilerUsed(*Combined, *TM, AsmUndefinedRefs);
-
-  if (Config->SaveTemps)
-    saveBCFile(*Combined, Config->OutputFile + ".lto.bc");
-
-  runLTOPasses(*Combined, *TM);
-  if (HasError)
-    return {};
-
-  return runSplitCodegen(CreateTargetMachine);
-}
diff --git a/ELF/LTO.h b/ELF/LTO.h
deleted file mode 100644
index ec81fc8..0000000
--- a/ELF/LTO.h
+++ /dev/null
@@ -1,54 +0,0 @@
-//===- LTO.h ----------------------------------------------------*- C++ -*-===//
-//
-//                             The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file provides a way to combine bitcode files into one ELF
-// file by compiling them using LLVM.
-//
-// If LTO is in use, your input files are not in regular ELF files
-// but instead LLVM bitcode files. In that case, the linker has to
-// convert bitcode files into the native format so that we can create
-// an ELF file that contains native code. This file provides that
-// functionality.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_ELF_LTO_H
-#define LLD_ELF_LTO_H
-
-#include "lld/Core/LLVM.h"
-#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/StringSet.h"
-#include "llvm/IR/Module.h"
-#include "llvm/Linker/IRMover.h"
-
-namespace lld {
-namespace elf {
-
-class BitcodeFile;
-class InputFile;
-
-class BitcodeCompiler {
-public:
-  BitcodeCompiler();
-  void add(BitcodeFile &F);
-  std::vector<InputFile *> compile();
-
-private:
-  std::vector<InputFile *> runSplitCodegen(
-      const std::function<std::unique_ptr<llvm::TargetMachine>()> &TMFactory);
-
-  std::unique_ptr<llvm::Module> Combined;
-  std::vector<SmallString<0>> OwningData;
-  llvm::StringSet<> InternalizedSyms;
-  llvm::StringSet<> AsmUndefinedRefs;
-};
-}
-}
-
-#endif
diff --git a/ELF/SymbolTable.cpp b/ELF/SymbolTable.cpp
index e72f7ef..46f1e08 100644
--- a/ELF/SymbolTable.cpp
+++ b/ELF/SymbolTable.cpp
@@ -1,728 +1,885 @@
 //===- SymbolTable.cpp ----------------------------------------------------===//
 //
 //                             The LLVM Linker
 //
 // This file is distributed under the University of Illinois Open Source
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
 //
 // Symbol table is a bag of all known symbols. We put all symbols of
 // all input files to the symbol table. The symbol table is basically
 // a hash table with the logic to resolve symbol name conflicts using
 // the symbol types.
 //
 //===----------------------------------------------------------------------===//
 
 #include "SymbolTable.h"
 #include "Config.h"
+#include "Driver.h"
 #include "Error.h"
 #include "LinkerScript.h"
 #include "SymbolListFile.h"
 #include "Symbols.h"
 #include "llvm/Bitcode/ReaderWriter.h"
+#include "llvm/CodeGen/CommandFlags.h"
+#include "llvm/IR/DiagnosticPrinter.h"
+#include "llvm/LTO/LTO.h"
+#include "llvm/LTO/LTOBackend.h"
 #include "llvm/Support/StringSaver.h"
 
 using namespace llvm;
 using namespace llvm::object;
 using namespace llvm::ELF;
 
 using namespace lld;
 using namespace lld::elf;
 
 // All input object files must be for the same architecture
 // (e.g. it does not make sense to link x86 object files with
 // MIPS object files.) This function checks for that error.
 template <class ELFT> static bool isCompatible(InputFile *F) {
   if (!isa<ELFFileBase<ELFT>>(F) && !isa<BitcodeFile>(F))
     return true;
   if (F->EKind == Config->EKind && F->EMachine == Config->EMachine)
     return true;
   StringRef A = F->getName();
   StringRef B = Config->Emulation;
   if (B.empty())
     B = Config->FirstElf->getName();
   error(A + " is incompatible with " + B);
   return false;
 }
 
 // Add symbols in File to the symbol table.
 template <class ELFT> void SymbolTable<ELFT>::addFile(InputFile *File) {
   if (!isCompatible<ELFT>(File))
     return;
 
   // Binary file
   if (auto *F = dyn_cast<BinaryFile>(File)) {
     addFile(F->createELF<ELFT>());
     return;
   }
 
   // .a file
   if (auto *F = dyn_cast<ArchiveFile>(File)) {
     F->parse<ELFT>();
     return;
   }
 
   // Lazy object file
   if (auto *F = dyn_cast<LazyObjectFile>(File)) {
     F->parse<ELFT>();
     return;
   }
 
   if (Config->Trace)
     outs() << getFilename(File) << "\n";
 
   // .so file
   if (auto *F = dyn_cast<SharedFile<ELFT>>(File)) {
     // DSOs are uniquified not by filename but by soname.
     F->parseSoName();
     if (!SoNames.insert(F->getSoName()).second)
       return;
     SharedFiles.push_back(F);
     F->parseRest();
     return;
   }
 
   // LLVM bitcode file
   if (auto *F = dyn_cast<BitcodeFile>(File)) {
     BitcodeFiles.push_back(F);
     F->parse<ELFT>(ComdatGroups);
     return;
   }
 
   // Regular object file
   auto *F = cast<ObjectFile<ELFT>>(File);
   ObjectFiles.push_back(F);
   F->parse(ComdatGroups);
 }
 
+static void diagnosticHandler(const DiagnosticInfo &DI) {
+  if (const auto *BDI = dyn_cast<BitcodeDiagnosticInfo>(&DI)) {
+    std::error_code EC = BDI->getError();
+    if (EC == BitcodeError::InvalidBitcodeSignature)
+      return;
+  }
+
+  std::string ErrStorage;
+  {
+    raw_string_ostream OS(ErrStorage);
+    DiagnosticPrinterRawOStream DP(OS);
+    DI.print(DP);
+  }
+  warning(ErrStorage.c_str());
+}
+
+static std::unique_ptr<lto::LTO> createLTO() {
+  lto::Config Conf;
+  lto::ThinBackend Backend;
+  unsigned ParallelCodeGenParallelismLevel = Config->LtoJobs;
+
+  // LLD supports the new relocations.
+  Conf.Options = InitTargetOptionsFromCodeGenFlags();
+  Conf.Options.RelaxELFRelocations = true;
+
+  Conf.RelocModel = Config->Pic ? Reloc::PIC_ : Reloc::Static;
+  Conf.DisableVerify = Config->DisableVerify;
+  Conf.DiagHandler = diagnosticHandler;
+  Conf.OptLevel = Config->LtoO;
+
+  // Set up a custom pipeline if we've been asked to.
+  if (!Config->LtoNewPmPasses.empty())
+    Conf.OptPipeline = Config->LtoNewPmPasses;
+
+  if (Config->SaveTemps)
+    check(Conf.addSaveTemps(std::string(Config->OutputFile) + ".",
+                            /*UseInputModulePath*/ true));
+
+  return (HasError)
+             ? nullptr
+             : llvm::make_unique<lto::LTO>(std::move(Conf), Backend,
+                                           ParallelCodeGenParallelismLevel);
+}
+
+namespace {
+// Define the LTOOutput handling
+class LTOOutput : public lto::NativeObjectOutput {
+  StringRef Path;
+
+public:
+  LTOOutput(StringRef Path) : Path(Path) {}
+  // Open the filename \p Path and allocate a stream.
+  std::unique_ptr<raw_pwrite_stream> getStream() override {
+    int FD;
+    std::error_code EC = sys::fs::openFileForWrite(Path, FD, sys::fs::F_None);
+    if (EC)
+      llvm_unreachable("can't open the file");
+    return llvm::make_unique<llvm::raw_fd_ostream>(FD, true);
+  }
+};
+}
+
+/// Return the desired output filename given a base input name, a flag
+/// indicating whether a temp file should be generated, and an optional task id.
+/// The new filename generated is returned in \p NewFilename.
+static void getOutputFileName(SmallString<128> InFilename,
+                              SmallString<128> &NewFilename, int TaskID = -1) {
+  NewFilename = InFilename;
+  if (TaskID >= 0)
+    NewFilename += utostr(TaskID);
+}
+
+static void undefine(Symbol *S) {
+  replaceBody<Undefined>(S, S->body()->getName(), STV_DEFAULT, S->body()->Type,
+                         nullptr);
+}
+
+// This is for use when debugging LTO.
+static void saveBuffer(StringRef Buffer, const Twine &Path) {
+  std::error_code EC;
+  raw_fd_ostream OS(Path.str(), EC, sys::fs::OpenFlags::F_None);
+  if (EC)
+    error(EC, "cannot create " + Path);
+  OS << Buffer;
+}
+
 // This function is where all the optimizations of link-time
 // optimization happens. When LTO is in use, some input files are
 // not in native object file format but in the LLVM bitcode format.
 // This function compiles bitcode files into a few big native files
 // using LLVM functions and replaces bitcode symbols with the results.
 // Because all bitcode files that consist of a program are passed
 // to the compiler at once, it can do whole-program optimization.
 template <class ELFT> void SymbolTable<ELFT>::addCombinedLtoObject() {
   if (BitcodeFiles.empty())
     return;
 
-  // Compile bitcode files and replace bitcode symbols.
-  Lto.reset(new BitcodeCompiler);
-  for (BitcodeFile *F : BitcodeFiles)
-    Lto->add(*F);
+  std::unique_ptr<lto::LTO> LtoObj = createLTO();
+  if (HasError)
+    return;
 
-  for (InputFile *File : Lto->compile()) {
-    ObjectFile<ELFT> *Obj = cast<ObjectFile<ELFT>>(File);
-    DenseSet<StringRef> DummyGroups;
-    Obj->parse(DummyGroups);
-    ObjectFiles.push_back(Obj);
+  for (BitcodeFile *F : BitcodeFiles) {
+    Expected<std::unique_ptr<lto::InputFile>> ObjOrErr =
+        lto::InputFile::create(F->getBuffer());
+    if (!ObjOrErr)
+      error(toString(ObjOrErr.takeError()).c_str());
+    if (HasError)
+      return;
+    lto::InputFile &Obj = **ObjOrErr;
+    if (Obj.getDataLayoutStr().empty())
+      fatal("invalid bitcode file: " + F->getName() + " has no datalayout");
+
+    unsigned SymNum = 0;
+    std::vector<Symbol *> Syms = F->getSymbols();
+    std::vector<lto::SymbolResolution> Resols(Syms.size());
+    for (LLVM_ATTRIBUTE_UNUSED auto &ObjSym : Obj.symbols()) {
+      Symbol *Sym = Syms[SymNum];
+      lto::SymbolResolution &R = Resols[SymNum];
+      ++SymNum;
+      SymbolBody *B = Sym->body();
+      if (B->File != F)
+        continue;
+      if (Sym->body()->isUndefined())
+        continue;
+      R.Prevailing = Sym->body()->isDefined();
+      R.VisibleToRegularObj = Sym->IsUsedInRegularObj || Sym->includeInDynsym();
+      if (Sym->body()->isDefined())
+        undefine(Sym);
+    }
+    check(LtoObj->add(std::move(*ObjOrErr), Resols));
+    if (HasError)
+      return;
+  }
+
+  SmallString<128> Filename;
+  Filename = Config->OutputFile;
+  unsigned MaxTasks = LtoObj->getMaxTasks();
+  std::vector<SmallString<128>> Filenames(MaxTasks);
+
+  auto AddOutput =
+      [&](size_t Task) -> std::unique_ptr<lto::NativeObjectOutput> {
+    auto &OutputName = Filenames[Task];
+    getOutputFileName(Filename, OutputName, MaxTasks > 1 ? Task : -1);
+    return llvm::make_unique<LTOOutput>(OutputName);
+  };
+
+  check(LtoObj->run(AddOutput));
+  if (HasError)
+    return;
+
+  for (unsigned I = 0; I != MaxTasks; ++I) {
+    if (!Filenames[I].empty()) {
+      auto MBOrErr = MemoryBuffer::getFile(Filenames[I]);
+      if (auto EC = MBOrErr.getError()) {
+        error(EC, "cannot open " + Filenames[I]);
+        return;
+      }
+      MemoryBufferRef MB = (*MBOrErr)->getMemBufferRef();
+
+      // Do we want to move this to the LTO API?
+      if (Config->SaveTemps) {
+        if (MaxTasks == 1)
+          saveBuffer(MB.getBuffer(), Config->OutputFile + ".lto.o");
+        else
+          saveBuffer(MB.getBuffer(), Config->OutputFile + Twine(I) + ".lto.o");
+      }
+
+      CompiledBitcodeFiles.push_back(std::move(*MBOrErr));
+      ObjectFile<ELFT> *Obj = cast<ObjectFile<ELFT>>(createObjectFile(MB));
+      DenseSet<StringRef> DummyGroups;
+      Obj->parse(DummyGroups);
+      ObjectFiles.emplace_back(Obj);
+    }
   }
 }
 
 template <class ELFT>
 DefinedRegular<ELFT> *SymbolTable<ELFT>::addAbsolute(StringRef Name,
                                                      uint8_t Visibility) {
   return cast<DefinedRegular<ELFT>>(
       addRegular(Name, STB_GLOBAL, Visibility)->body());
 }
 
 // Add Name as an "ignored" symbol. An ignored symbol is a regular
 // linker-synthesized defined symbol, but is only defined if needed.
 template <class ELFT>
 DefinedRegular<ELFT> *SymbolTable<ELFT>::addIgnored(StringRef Name,
                                                     uint8_t Visibility) {
   if (!find(Name))
     return nullptr;
   return addAbsolute(Name, Visibility);
 }
 
 // Set a flag for --trace-symbol so that we can print out a log message
 // if a new symbol with the same name is inserted into the symbol table.
 template <class ELFT> void SymbolTable<ELFT>::trace(StringRef Name) {
   Symtab.insert({Name, {-1, true}});
 }
 
 // Rename SYM as __wrap_SYM. The original symbol is preserved as __real_SYM.
 // Used to implement --wrap.
 template <class ELFT> void SymbolTable<ELFT>::wrap(StringRef Name) {
   SymbolBody *B = find(Name);
   if (!B)
     return;
   StringSaver Saver(Alloc);
   Symbol *Sym = B->symbol();
   Symbol *Real = addUndefined(Saver.save("__real_" + Name));
   Symbol *Wrap = addUndefined(Saver.save("__wrap_" + Name));
   // We rename symbols by replacing the old symbol's SymbolBody with the new
   // symbol's SymbolBody. This causes all SymbolBody pointers referring to the
   // old symbol to instead refer to the new symbol.
   memcpy(Real->Body.buffer, Sym->Body.buffer, sizeof(Sym->Body));
   memcpy(Sym->Body.buffer, Wrap->Body.buffer, sizeof(Wrap->Body));
 }
 
 static uint8_t getMinVisibility(uint8_t VA, uint8_t VB) {
   if (VA == STV_DEFAULT)
     return VB;
   if (VB == STV_DEFAULT)
     return VA;
   return std::min(VA, VB);
 }
 
 // Parses a symbol in the form of <name>@<version> or <name>@@<version>.
 static std::pair<StringRef, uint16_t> getSymbolVersion(StringRef S) {
   if (Config->VersionDefinitions.empty())
     return {S, Config->DefaultSymbolVersion};
 
   size_t Pos = S.find('@');
   if (Pos == 0 || Pos == StringRef::npos)
     return {S, Config->DefaultSymbolVersion};
 
   StringRef Name = S.substr(0, Pos);
   StringRef Verstr = S.substr(Pos + 1);
   if (Verstr.empty())
     return {S, Config->DefaultSymbolVersion};
 
   // '@@' in a symbol name means the default version.
   // It is usually the most recent one.
   bool IsDefault = (Verstr[0] == '@');
   if (IsDefault)
     Verstr = Verstr.substr(1);
 
   for (VersionDefinition &V : Config->VersionDefinitions) {
     if (V.Name == Verstr)
       return {Name, IsDefault ? V.Id : (V.Id | VERSYM_HIDDEN)};
   }
 
   // It is an error if the specified version was not defined.
   error("symbol " + S + " has undefined version " + Verstr);
   return {S, Config->DefaultSymbolVersion};
 }
 
 // Find an existing symbol or create and insert a new one.
 template <class ELFT>
 std::pair<Symbol *, bool> SymbolTable<ELFT>::insert(StringRef &Name) {
   auto P = Symtab.insert({Name, SymIndex((int)SymVector.size(), false)});
   SymIndex &V = P.first->second;
   bool IsNew = P.second;
 
   if (V.Idx == -1) {
     IsNew = true;
     V = SymIndex((int)SymVector.size(), true);
   }
 
   Symbol *Sym;
   if (IsNew) {
     Sym = new (Alloc) Symbol;
     Sym->Binding = STB_WEAK;
     Sym->Visibility = STV_DEFAULT;
     Sym->IsUsedInRegularObj = false;
     Sym->HasUnnamedAddr = true;
     Sym->ExportDynamic = false;
     Sym->Traced = V.Traced;
     std::tie(Name, Sym->VersionId) = getSymbolVersion(Name);
     SymVector.push_back(Sym);
   } else {
     Sym = SymVector[V.Idx];
   }
   return {Sym, IsNew};
 }
 
 // Find an existing symbol or create and insert a new one, then apply the given
 // attributes.
 template <class ELFT>
 std::pair<Symbol *, bool>
 SymbolTable<ELFT>::insert(StringRef &Name, uint8_t Type, uint8_t Visibility,
                           bool CanOmitFromDynSym, bool HasUnnamedAddr,
                           InputFile *File) {
   bool IsUsedInRegularObj = !File || File->kind() == InputFile::ObjectKind;
   Symbol *S;
   bool WasInserted;
   std::tie(S, WasInserted) = insert(Name);
 
   // Merge in the new unnamed_addr attribute.
   S->HasUnnamedAddr &= HasUnnamedAddr;
   // Merge in the new symbol's visibility.
   S->Visibility = getMinVisibility(S->Visibility, Visibility);
   if (!CanOmitFromDynSym && (Config->Shared || Config->ExportDynamic))
     S->ExportDynamic = true;
   if (IsUsedInRegularObj)
     S->IsUsedInRegularObj = true;
   if (!WasInserted && S->body()->Type != SymbolBody::UnknownType &&
       ((Type == STT_TLS) != S->body()->isTls()))
     error("TLS attribute mismatch for symbol: " +
           conflictMsg(S->body(), File));
 
   return {S, WasInserted};
 }
 
 // Construct a string in the form of "Sym in File1 and File2".
 // Used to construct an error message.
 template <typename ELFT>
 std::string SymbolTable<ELFT>::conflictMsg(SymbolBody *Existing,
                                            InputFile *NewFile) {
   std::string Sym = Existing->getName();
   if (Config->Demangle)
     Sym = demangle(Sym);
   return Sym + " in " + getFilename(Existing->File) + " and " +
          getFilename(NewFile);
 }
 
 template <class ELFT> Symbol *SymbolTable<ELFT>::addUndefined(StringRef Name) {
   return addUndefined(Name, STB_GLOBAL, STV_DEFAULT, /*Type*/ 0,
                       /*CanOmitFromDynSym*/ false, /*HasUnnamedAddr*/ false,
                       /*File*/ nullptr);
 }
 
 template <class ELFT>
 Symbol *SymbolTable<ELFT>::addUndefined(StringRef Name, uint8_t Binding,
                                         uint8_t StOther, uint8_t Type,
                                         bool CanOmitFromDynSym,
                                         bool HasUnnamedAddr, InputFile *File) {
   Symbol *S;
   bool WasInserted;
   std::tie(S, WasInserted) =
       insert(Name, Type, StOther & 3, CanOmitFromDynSym, HasUnnamedAddr, File);
   if (WasInserted) {
     S->Binding = Binding;
     replaceBody<Undefined>(S, Name, StOther, Type, File);
     return S;
   }
   if (Binding != STB_WEAK) {
     if (S->body()->isShared() || S->body()->isLazy())
       S->Binding = Binding;
     if (auto *SS = dyn_cast<SharedSymbol<ELFT>>(S->body()))
       SS->file()->IsUsed = true;
   }
   if (auto *L = dyn_cast<Lazy>(S->body())) {
     // An undefined weak will not fetch archive members, but we have to remember
     // its type. See also comment in addLazyArchive.
     if (S->isWeak())
       L->Type = Type;
     else if (InputFile *F = L->fetch())
       addFile(F);
   }
   return S;
 }
 
 // We have a new defined symbol with the specified binding. Return 1 if the new
 // symbol should win, -1 if the new symbol should lose, or 0 if both symbols are
 // strong defined symbols.
 static int compareDefined(Symbol *S, bool WasInserted, uint8_t Binding) {
   if (WasInserted)
     return 1;
   SymbolBody *Body = S->body();
   if (Body->isLazy() || Body->isUndefined() || Body->isShared())
     return 1;
   if (Binding == STB_WEAK)
     return -1;
   if (S->isWeak())
     return 1;
   return 0;
 }
 
 // We have a new non-common defined symbol with the specified binding. Return 1
 // if the new symbol should win, -1 if the new symbol should lose, or 0 if there
 // is a conflict. If the new symbol wins, also update the binding.
 static int compareDefinedNonCommon(Symbol *S, bool WasInserted,
                                    uint8_t Binding) {
   if (int Cmp = compareDefined(S, WasInserted, Binding)) {
     if (Cmp > 0)
       S->Binding = Binding;
     return Cmp;
   }
   if (isa<DefinedCommon>(S->body())) {
     // Non-common symbols take precedence over common symbols.
     if (Config->WarnCommon)
       warning("common " + S->body()->getName() + " is overridden");
     return 1;
   }
   return 0;
 }
 
 template <class ELFT>
 Symbol *SymbolTable<ELFT>::addCommon(StringRef N, uint64_t Size,
                                      uint64_t Alignment, uint8_t Binding,
                                      uint8_t StOther, uint8_t Type,
                                      bool HasUnnamedAddr, InputFile *File) {
   Symbol *S;
   bool WasInserted;
   std::tie(S, WasInserted) = insert(
       N, Type, StOther & 3, /*CanOmitFromDynSym*/ false, HasUnnamedAddr, File);
   int Cmp = compareDefined(S, WasInserted, Binding);
   if (Cmp > 0) {
     S->Binding = Binding;
     replaceBody<DefinedCommon>(S, N, Size, Alignment, StOther, Type, File);
   } else if (Cmp == 0) {
     auto *C = dyn_cast<DefinedCommon>(S->body());
     if (!C) {
       // Non-common symbols take precedence over common symbols.
       if (Config->WarnCommon)
         warning("common " + S->body()->getName() + " is overridden");
       return S;
     }
 
     if (Config->WarnCommon)
       warning("multiple common of " + S->body()->getName());
 
     Alignment = C->Alignment = std::max(C->Alignment, Alignment);
     if (Size > C->Size)
       replaceBody<DefinedCommon>(S, N, Size, Alignment, StOther, Type, File);
   }
   return S;
 }
 
 template <class ELFT>
 void SymbolTable<ELFT>::reportDuplicate(SymbolBody *Existing,
                                         InputFile *NewFile) {
   std::string Msg = "duplicate symbol: " + conflictMsg(Existing, NewFile);
   if (Config->AllowMultipleDefinition)
     warning(Msg);
   else
     error(Msg);
 }
 
 template <typename ELFT>
 Symbol *SymbolTable<ELFT>::addRegular(StringRef Name, const Elf_Sym &Sym,
                                       InputSectionBase<ELFT> *Section) {
   Symbol *S;
   bool WasInserted;
   std::tie(S, WasInserted) =
       insert(Name, Sym.getType(), Sym.getVisibility(),
              /*CanOmitFromDynSym*/ false, /*HasUnnamedAddr*/ false,
              Section ? Section->getFile() : nullptr);
   int Cmp = compareDefinedNonCommon(S, WasInserted, Sym.getBinding());
   if (Cmp > 0)
     replaceBody<DefinedRegular<ELFT>>(S, Name, Sym, Section);
   else if (Cmp == 0)
     reportDuplicate(S->body(), Section->getFile());
   return S;
 }
 
 template <typename ELFT>
 Symbol *SymbolTable<ELFT>::addRegular(StringRef Name, uint8_t Binding,
                                       uint8_t StOther) {
   Symbol *S;
   bool WasInserted;
   std::tie(S, WasInserted) =
       insert(Name, STT_NOTYPE, StOther & 3, /*CanOmitFromDynSym*/ false,
              /*HasUnnamedAddr*/ false, nullptr);
   int Cmp = compareDefinedNonCommon(S, WasInserted, Binding);
   if (Cmp > 0)
     replaceBody<DefinedRegular<ELFT>>(S, Name, StOther);
   else if (Cmp == 0)
     reportDuplicate(S->body(), nullptr);
   return S;
 }
 
 template <typename ELFT>
 Symbol *SymbolTable<ELFT>::addSynthetic(StringRef N,
                                         OutputSectionBase<ELFT> *Section,
                                         uintX_t Value, uint8_t StOther) {
   Symbol *S;
   bool WasInserted;
   std::tie(S, WasInserted) = insert(N, STT_NOTYPE, /*Visibility*/ StOther & 0x3,
                                     /*CanOmitFromDynSym*/ false,
                                     /*HasUnnamedAddr*/ false, nullptr);
   int Cmp = compareDefinedNonCommon(S, WasInserted, STB_GLOBAL);
   if (Cmp > 0)
     replaceBody<DefinedSynthetic<ELFT>>(S, N, Value, Section);
   else if (Cmp == 0)
     reportDuplicate(S->body(), nullptr);
   return S;
 }
 
 template <typename ELFT>
 void SymbolTable<ELFT>::addShared(SharedFile<ELFT> *F, StringRef Name,
                                   const Elf_Sym &Sym,
                                   const typename ELFT::Verdef *Verdef) {
   // DSO symbols do not affect visibility in the output, so we pass STV_DEFAULT
   // as the visibility, which will leave the visibility in the symbol table
   // unchanged.
   Symbol *S;
   bool WasInserted;
   std::tie(S, WasInserted) =
       insert(Name, Sym.getType(), STV_DEFAULT, /*CanOmitFromDynSym*/ true,
              /*HasUnnamedAddr*/ false, F);
   // Make sure we preempt DSO symbols with default visibility.
   if (Sym.getVisibility() == STV_DEFAULT)
     S->ExportDynamic = true;
   if (WasInserted || isa<Undefined>(S->body())) {
     replaceBody<SharedSymbol<ELFT>>(S, F, Name, Sym, Verdef);
     if (!S->isWeak())
       F->IsUsed = true;
   }
 }
 
 template <class ELFT>
 Symbol *SymbolTable<ELFT>::addBitcode(StringRef Name, uint8_t Binding,
                                       uint8_t StOther, uint8_t Type,
                                       bool CanOmitFromDynSym,
                                       bool HasUnnamedAddr, BitcodeFile *F) {
   Symbol *S;
   bool WasInserted;
   std::tie(S, WasInserted) =
       insert(Name, Type, StOther & 3, CanOmitFromDynSym, HasUnnamedAddr, F);
   int Cmp = compareDefinedNonCommon(S, WasInserted, Binding);
   if (Cmp > 0)
     replaceBody<DefinedRegular<ELFT>>(S, Name, StOther, Type, F);
   else if (Cmp == 0)
     reportDuplicate(S->body(), F);
   return S;
 }
 
 template <class ELFT> SymbolBody *SymbolTable<ELFT>::find(StringRef Name) {
   auto It = Symtab.find(Name);
   if (It == Symtab.end())
     return nullptr;
   SymIndex V = It->second;
   if (V.Idx == -1)
     return nullptr;
   return SymVector[V.Idx]->body();
 }
 
 // Returns a list of defined symbols that match with a given regex.
 template <class ELFT>
 std::vector<SymbolBody *> SymbolTable<ELFT>::findAll(const Regex &Re) {
   std::vector<SymbolBody *> Res;
   for (Symbol *Sym : SymVector) {
     SymbolBody *B = Sym->body();
     StringRef Name = B->getName();
     if (!B->isUndefined() && const_cast<Regex &>(Re).match(Name))
       Res.push_back(B);
   }
   return Res;
 }
 
 template <class ELFT>
 void SymbolTable<ELFT>::addLazyArchive(ArchiveFile *F,
                                        const object::Archive::Symbol Sym) {
   Symbol *S;
   bool WasInserted;
   StringRef Name = Sym.getName();
   std::tie(S, WasInserted) = insert(Name);
   if (WasInserted) {
     replaceBody<LazyArchive>(S, *F, Sym, SymbolBody::UnknownType);
     return;
   }
   if (!S->body()->isUndefined())
     return;
 
   // Weak undefined symbols should not fetch members from archives. If we were
   // to keep old symbol we would not know that an archive member was available
   // if a strong undefined symbol shows up afterwards in the link. If a strong
   // undefined symbol never shows up, this lazy symbol will get to the end of
   // the link and must be treated as the weak undefined one. We already marked
   // this symbol as used when we added it to the symbol table, but we also need
   // to preserve its type. FIXME: Move the Type field to Symbol.
   if (S->isWeak()) {
     replaceBody<LazyArchive>(S, *F, Sym, S->body()->Type);
     return;
   }
   MemoryBufferRef MBRef = F->getMember(&Sym);
   if (!MBRef.getBuffer().empty())
     addFile(createObjectFile(MBRef, F->getName()));
 }
 
 template <class ELFT>
 void SymbolTable<ELFT>::addLazyObject(StringRef Name, LazyObjectFile &Obj) {
   Symbol *S;
   bool WasInserted;
   std::tie(S, WasInserted) = insert(Name);
   if (WasInserted) {
     replaceBody<LazyObject>(S, Name, Obj, SymbolBody::UnknownType);
     return;
   }
   if (!S->body()->isUndefined())
     return;
 
   // See comment for addLazyArchive above.
   if (S->isWeak()) {
     replaceBody<LazyObject>(S, Name, Obj, S->body()->Type);
   } else {
     MemoryBufferRef MBRef = Obj.getBuffer();
     if (!MBRef.getBuffer().empty())
       addFile(createObjectFile(MBRef));
   }
 }
 
 // Process undefined (-u) flags by loading lazy symbols named by those flags.
 template <class ELFT> void SymbolTable<ELFT>::scanUndefinedFlags() {
   for (StringRef S : Config->Undefined)
     if (auto *L = dyn_cast_or_null<Lazy>(find(S)))
       if (InputFile *File = L->fetch())
         addFile(File);
 }
 
 // This function takes care of the case in which shared libraries depend on
 // the user program (not the other way, which is usual). Shared libraries
 // may have undefined symbols, expecting that the user program provides
 // the definitions for them. An example is BSD's __progname symbol.
 // We need to put such symbols to the main program's .dynsym so that
 // shared libraries can find them.
 // Except this, we ignore undefined symbols in DSOs.
 template <class ELFT> void SymbolTable<ELFT>::scanShlibUndefined() {
   for (SharedFile<ELFT> *File : SharedFiles)
     for (StringRef U : File->getUndefinedSymbols())
       if (SymbolBody *Sym = find(U))
         if (Sym->isDefined())
           Sym->symbol()->ExportDynamic = true;
 }
 
 // This function processes --export-dynamic-symbol and --dynamic-list.
 template <class ELFT> void SymbolTable<ELFT>::scanDynamicList() {
   for (StringRef S : Config->DynamicList)
     if (SymbolBody *B = find(S))
       B->symbol()->ExportDynamic = true;
 }
 
 static void setVersionId(SymbolBody *Body, StringRef VersionName,
                          StringRef Name, uint16_t Version) {
   if (!Body || Body->isUndefined()) {
     if (Config->NoUndefinedVersion)
       error("version script assignment of " + VersionName + " to symbol " +
             Name + " failed: symbol not defined");
     return;
   }
 
   Symbol *Sym = Body->symbol();
   if (Sym->VersionId != Config->DefaultSymbolVersion)
     warning("duplicate symbol " + Name + " in version script");
   Sym->VersionId = Version;
 }
 
 // Returns a map from demangled symbols to symbol objects.
 // The relationship is 1:N instead of 1:1 because with the symbol
 // versioning, more than one symbol may have the same name.
 template <class ELFT>
 std::map<std::string, std::vector<SymbolBody *>>
 SymbolTable<ELFT>::getDemangledSyms() {
   std::map<std::string, std::vector<SymbolBody *>> Result;
   for (Symbol *Sym : SymVector) {
     SymbolBody *B = Sym->body();
     Result[demangle(B->getName())].push_back(B);
   }
   return Result;
 }
 
 static bool hasExternCpp() {
   for (VersionDefinition &V : Config->VersionDefinitions)
     for (SymbolVersion Sym : V.Globals)
       if (Sym.IsExternCpp)
         return true;
   return false;
 }
 
 static ArrayRef<SymbolBody *>
 findDemangled(std::map<std::string, std::vector<SymbolBody *>> &D,
               StringRef Name) {
   auto I = D.find(Name);
   if (I != D.end())
     return I->second;
   return {};
 }
 
 static std::vector<SymbolBody *>
 findAllDemangled(const std::map<std::string, std::vector<SymbolBody *>> &D,
                  const Regex &Re) {
   std::vector<SymbolBody *> Res;
   for (auto &P : D) {
     if (const_cast<Regex &>(Re).match(P.first))
       for (SymbolBody *Body : P.second)
         if (!Body->isUndefined())
           Res.push_back(Body);
   }
   return Res;
 }
 
 // If there's only one anonymous version definition in a version
 // script file, the script does not actullay define any symbol version,
 // but just specifies symbols visibilities. We assume that the script was
 // in the form of { global: foo; bar; local *; }. So, local is default.
 // In this function, we make specified symbols global.
 template <class ELFT> void SymbolTable<ELFT>::handleAnonymousVersion() {
   std::vector<StringRef> Patterns;
   for (SymbolVersion &Sym : Config->VersionScriptGlobals) {
     if (hasWildcard(Sym.Name)) {
       Patterns.push_back(Sym.Name);
       continue;
     }
     if (SymbolBody *B = find(Sym.Name))
       B->symbol()->VersionId = VER_NDX_GLOBAL;
   }
   if (Patterns.empty())
     return;
   Regex Re = compileGlobPatterns(Patterns);
   std::vector<SymbolBody *> Syms = findAll(Re);
   for (SymbolBody *B : Syms)
     B->symbol()->VersionId = VER_NDX_GLOBAL;
 }
 
 // This function processes version scripts by updating VersionId
 // member of symbols.
 template <class ELFT> void SymbolTable<ELFT>::scanVersionScript() {
   // Handle edge cases first.
   if (!Config->VersionScriptGlobals.empty()) {
     handleAnonymousVersion();
     return;
   }
 
   if (Config->VersionDefinitions.empty())
     return;
 
   // Now we have version definitions, so we need to set version ids to symbols.
   // Each version definition has a glob pattern, and all symbols that match
   // with the pattern get that version.
 
   // Users can use "extern C++ {}" directive to match against demangled
   // C++ symbols. For example, you can write a pattern such as
   // "llvm::*::foo(int, ?)". Obviously, there's no way to handle this
   // other than trying to match a regexp against all demangled symbols.
   // So, if "extern C++" feature is used, we demangle all known symbols.
   std::map<std::string, std::vector<SymbolBody *>> Demangled;
   if (hasExternCpp())
     Demangled = getDemangledSyms();
 
   // First, we assign versions to exact matching symbols,
   // i.e. version definitions not containing any glob meta-characters.
   for (VersionDefinition &V : Config->VersionDefinitions) {
     for (SymbolVersion Sym : V.Globals) {
       if (Sym.HasWildcards)
         continue;
 
       StringRef N = Sym.Name;
       if (Sym.IsExternCpp) {
         for (SymbolBody *B : findDemangled(Demangled, N))
           setVersionId(B, V.Name, N, V.Id);
         continue;
       }
       setVersionId(find(N), V.Name, N, V.Id);
     }
   }
 
   // Next, we assign versions to fuzzy matching symbols,
   // i.e. version definitions containing glob meta-characters.
   // Note that because the last match takes precedence over previous matches,
   // we iterate over the definitions in the reverse order.
   for (size_t I = Config->VersionDefinitions.size() - 1; I != (size_t)-1; --I) {
     VersionDefinition &V = Config->VersionDefinitions[I];
     for (SymbolVersion &Sym : V.Globals) {
       if (!Sym.HasWildcards)
         continue;
       Regex Re = compileGlobPatterns({Sym.Name});
       std::vector<SymbolBody *> Syms =
           Sym.IsExternCpp ? findAllDemangled(Demangled, Re) : findAll(Re);
 
       // Exact matching takes precendence over fuzzy matching,
       // so we set a version to a symbol only if no version has been assigned
       // to the symbol. This behavior is compatible with GNU.
       for (SymbolBody *B : Syms)
         if (B->symbol()->VersionId == Config->DefaultSymbolVersion)
           B->symbol()->VersionId = V.Id;
     }
   }
 }
 
 template class elf::SymbolTable<ELF32LE>;
 template class elf::SymbolTable<ELF32BE>;
 template class elf::SymbolTable<ELF64LE>;
 template class elf::SymbolTable<ELF64BE>;
diff --git a/ELF/SymbolTable.h b/ELF/SymbolTable.h
index 8059e61..4272ad5 100644
--- a/ELF/SymbolTable.h
+++ b/ELF/SymbolTable.h
@@ -1,145 +1,145 @@
 //===- SymbolTable.h --------------------------------------------*- C++ -*-===//
 //
 //                             The LLVM Linker
 //
 // This file is distributed under the University of Illinois Open Source
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
 
 #ifndef LLD_ELF_SYMBOL_TABLE_H
 #define LLD_ELF_SYMBOL_TABLE_H
 
 #include "InputFiles.h"
-#include "LTO.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/Support/Regex.h"
 
 namespace lld {
 namespace elf {
 class Lazy;
 template <class ELFT> class OutputSectionBase;
 struct Symbol;
 
 typedef llvm::CachedHash<StringRef> SymName;
 
 // SymbolTable is a bucket of all known symbols, including defined,
 // undefined, or lazy symbols (the last one is symbols in archive
 // files whose archive members are not yet loaded).
 //
 // We put all symbols of all files to a SymbolTable, and the
 // SymbolTable selects the "best" symbols if there are name
 // conflicts. For example, obviously, a defined symbol is better than
 // an undefined symbol. Or, if there's a conflict between a lazy and a
 // undefined, it'll read an archive member to read a real definition
 // to replace the lazy symbol. The logic is implemented in the
 // add*() functions, which are called by input files as they are parsed. There
 // is one add* function per symbol type.
 template <class ELFT> class SymbolTable {
   typedef typename ELFT::Sym Elf_Sym;
   typedef typename ELFT::uint uintX_t;
 
 public:
   void addFile(InputFile *File);
   void addCombinedLtoObject();
 
   llvm::ArrayRef<Symbol *> getSymbols() const { return SymVector; }
 
   const std::vector<ObjectFile<ELFT> *> &getObjectFiles() const {
     return ObjectFiles;
   }
 
   const std::vector<SharedFile<ELFT> *> &getSharedFiles() const {
     return SharedFiles;
   }
 
   DefinedRegular<ELFT> *addAbsolute(StringRef Name,
                                     uint8_t Visibility = llvm::ELF::STV_HIDDEN);
   DefinedRegular<ELFT> *addIgnored(StringRef Name,
                                    uint8_t Visibility = llvm::ELF::STV_HIDDEN);
 
   Symbol *addUndefined(StringRef Name);
   Symbol *addUndefined(StringRef Name, uint8_t Binding, uint8_t StOther,
                        uint8_t Type, bool CanOmitFromDynSym,
                        bool HasUnnamedAddr, InputFile *File);
 
   Symbol *addRegular(StringRef Name, const Elf_Sym &Sym,
                      InputSectionBase<ELFT> *Section);
   Symbol *addRegular(StringRef Name, uint8_t Binding, uint8_t StOther);
   Symbol *addSynthetic(StringRef N, OutputSectionBase<ELFT> *Section,
                        uintX_t Value, uint8_t StOther);
   void addShared(SharedFile<ELFT> *F, StringRef Name, const Elf_Sym &Sym,
                  const typename ELFT::Verdef *Verdef);
 
   void addLazyArchive(ArchiveFile *F, const llvm::object::Archive::Symbol S);
   void addLazyObject(StringRef Name, LazyObjectFile &Obj);
   Symbol *addBitcode(StringRef Name, uint8_t Binding, uint8_t StOther,
                      uint8_t Type, bool CanOmitFromDynSym, bool HasUnnamedAddr,
                      BitcodeFile *File);
 
   Symbol *addCommon(StringRef N, uint64_t Size, uint64_t Alignment,
                     uint8_t Binding, uint8_t StOther, uint8_t Type,
                     bool HasUnnamedAddr, InputFile *File);
 
   void scanUndefinedFlags();
   void scanShlibUndefined();
   void scanDynamicList();
   void scanVersionScript();
 
   SymbolBody *find(StringRef Name);
 
   void trace(StringRef Name);
   void wrap(StringRef Name);
 
 private:
   std::vector<SymbolBody *> findAll(const llvm::Regex &Re);
   std::pair<Symbol *, bool> insert(StringRef &Name);
   std::pair<Symbol *, bool> insert(StringRef &Name, uint8_t Type,
                                    uint8_t Visibility, bool CanOmitFromDynSym,
                                    bool HasUnnamedAddr, InputFile *File);
 
   std::string conflictMsg(SymbolBody *Existing, InputFile *NewFile);
   void reportDuplicate(SymbolBody *Existing, InputFile *NewFile);
 
   std::map<std::string, std::vector<SymbolBody *>> getDemangledSyms();
   void handleAnonymousVersion();
 
   struct SymIndex {
     SymIndex(int Idx, bool Traced) : Idx(Idx), Traced(Traced) {}
     int Idx : 31;
     unsigned Traced : 1;
   };
 
   // The order the global symbols are in is not defined. We can use an arbitrary
   // order, but it has to be reproducible. That is true even when cross linking.
   // The default hashing of StringRef produces different results on 32 and 64
   // bit systems so we use a map to a vector. That is arbitrary, deterministic
   // but a bit inefficient.
   // FIXME: Experiment with passing in a custom hashing or sorting the symbols
   // once symbol resolution is finished.
   llvm::DenseMap<SymName, SymIndex> Symtab;
   std::vector<Symbol *> SymVector;
   llvm::BumpPtrAllocator Alloc;
 
   // Comdat groups define "link once" sections. If two comdat groups have the
   // same name, only one of them is linked, and the other is ignored. This set
   // is used to uniquify them.
   llvm::DenseSet<StringRef> ComdatGroups;
 
   std::vector<ObjectFile<ELFT> *> ObjectFiles;
   std::vector<SharedFile<ELFT> *> SharedFiles;
   std::vector<BitcodeFile *> BitcodeFiles;
 
   // Set of .so files to not link the same shared object file more than once.
   llvm::DenseSet<StringRef> SoNames;
 
-  std::unique_ptr<BitcodeCompiler> Lto;
+  // Set of compiler LTO bitcode files.
+  std::vector<std::unique_ptr<llvm::MemoryBuffer>> CompiledBitcodeFiles;
 };
 
 template <class ELFT> struct Symtab { static SymbolTable<ELFT> *X; };
 template <class ELFT> SymbolTable<ELFT> *Symtab<ELFT>::X;
 
 } // namespace elf
 } // namespace lld
 
 #endif
diff --git a/test/ELF/lto/archive-3.ll b/test/ELF/lto/archive-3.ll
index 350c892..0322e41 100644
--- a/test/ELF/lto/archive-3.ll
+++ b/test/ELF/lto/archive-3.ll
@@ -1,19 +1,19 @@
 ; REQUIRES: x86
 ; RUN: llvm-as %S/Inputs/archive-3.ll -o %t1.o
 ; RUN: llvm-as %s -o %t2.o
 
 ; RUN: ld.lld -m elf_x86_64 %t1.o %t2.o  -o %t3 -save-temps
-; RUN: llvm-dis %t3.lto.bc -o - | FileCheck %s
+; RUN: llvm-dis %t3.0.2.internalize.bc -o - | FileCheck %s
 
 ; RUN: rm -f %t.a
 ; RUN: llvm-ar rcs %t.a %t1.o
 ; RUN: ld.lld -m elf_x86_64 %t.a %t1.o %t2.o  -o %t3 -save-temps
-; RUN: llvm-dis %t3.lto.bc -o - | FileCheck %s
+; RUN: llvm-dis %t3.0.2.internalize.bc -o - | FileCheck %s
 
 ; CHECK: define internal void @foo() {
 
 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
 target triple = "x86_64-unknown-linux-gnu"
 define void @_start() {
   ret void
 }
diff --git a/test/ELF/lto/available-externally.ll b/test/ELF/lto/available-externally.ll
index 74aa860..181042b 100644
--- a/test/ELF/lto/available-externally.ll
+++ b/test/ELF/lto/available-externally.ll
@@ -1,22 +1,22 @@
 ; RUN: llvm-as %s -o %t1.o
 ; RUN: llvm-as %p/Inputs/available-externally.ll -o %t2.o
 ; RUN: ld.lld %t1.o %t2.o -m elf_x86_64 -o %t.so -shared -save-temps
-; RUN: llvm-dis < %t.so.lto.bc | FileCheck %s
+; RUN: llvm-dis < %t.so.0.2.internalize.bc | FileCheck %s
 
 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
 target triple = "x86_64-unknown-linux-gnu"
 
 define void @foo() {
   call void @bar()
   call void @zed()
   ret void
 }
 define available_externally void @bar() {
   ret void
 }
 define available_externally void @zed() {
   ret void
 }
 
 ; CHECK: define available_externally void @bar() {
 ; CHECK: define void @zed() {
diff --git a/test/ELF/lto/common2.ll b/test/ELF/lto/common2.ll
index 6b740c4..b44bbac 100644
--- a/test/ELF/lto/common2.ll
+++ b/test/ELF/lto/common2.ll
@@ -1,27 +1,27 @@
 ; RUN: llvm-as %s -o %t1.o
 ; RUN: ld.lld -m elf_x86_64 %t1.o -o %t -shared -save-temps
-; RUN: llvm-dis < %t.lto.bc | FileCheck %s
+; RUN: llvm-dis < %t.0.2.internalize.bc | FileCheck %s
 ; RUN: llvm-readobj -t %t | FileCheck %s --check-prefix=SHARED
 
 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
 target triple = "x86_64-unknown-linux-gnu"
 
 @a = common global i8 0, align 8
 ; CHECK-DAG: @a = common global i8 0, align 8
 
 @b = common hidden global i32 0, align 4
 define i32 @f() {
   %t = load i32, i32* @b, align 4
   ret i32 %t
 }
 ; CHECK-DAG: @b = internal global i32 0, align 4
 
 ; SHARED: Symbol {
 ; SHARED:   Name: a
 ; SHARED-NEXT:   Value:
 ; SHARED-NEXT:   Size: 1
 ; SHARED-NEXT:   Binding: Global
 ; SHARED-NEXT:   Type: Object
 ; SHARED-NEXT:   Other: 0
 ; SHARED-NEXT:   Section: .bss
 ; SHARED-NEXT: }
diff --git a/test/ELF/lto/common3.ll b/test/ELF/lto/common3.ll
index a6020ca..6d40de5 100644
--- a/test/ELF/lto/common3.ll
+++ b/test/ELF/lto/common3.ll
@@ -1,14 +1,14 @@
 ; RUN: llvm-as %s -o %t1.o
 ; RUN: llvm-as %S/Inputs/common3.ll -o %t2.o
 ; RUN: ld.lld -m elf_x86_64 %t1.o %t2.o -o %t -shared -save-temps
-; RUN: llvm-dis < %t.lto.bc | FileCheck %s
+; RUN: llvm-dis < %t.0.2.internalize.bc | FileCheck %s
 
 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
 target triple = "x86_64-unknown-linux-gnu"
 @a = common hidden global i32 0, align 8
 define i32 @f() {
   %t = load i32, i32* @a, align 4
   ret i32 %t
 }
 
 ; CHECK: @a = internal global i64 0, align 8
diff --git a/test/ELF/lto/discard-value-names.ll b/test/ELF/lto/discard-value-names.ll
index c6cd94f..c71dc38 100644
--- a/test/ELF/lto/discard-value-names.ll
+++ b/test/ELF/lto/discard-value-names.ll
@@ -1,23 +1,23 @@
 ; RUN: llvm-as %s -o %t.o
 
 ; RUN: ld.lld -m elf_x86_64 -shared -save-temps %t.o -o %t2.o
-; RUN: llvm-dis < %t2.o.lto.bc | FileCheck %s
+; RUN: llvm-dis < %t2.o.0.0.preopt.bc | FileCheck %s
 
 ; CHECK: @GlobalValueName
 ; CHECK: @foo(i32 %in)
 ; CHECK: somelabel:
 ; CHECK:  %GV = load i32, i32* @GlobalValueName
 ; CHECK:  %add = add i32 %in, %GV
 ; CHECK:  ret i32 %add
 
 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
 target triple = "x86_64-unknown-linux-gnu"
 
 @GlobalValueName = global i32 0
 
 define i32 @foo(i32 %in) {
 somelabel:
   %GV = load i32, i32* @GlobalValueName
   %add = add i32 %in, %GV
   ret i32 %add
 }
diff --git a/test/ELF/lto/drop-debug-info.ll b/test/ELF/lto/drop-debug-info.ll
index 7a7ed5e..27c0260 100644
--- a/test/ELF/lto/drop-debug-info.ll
+++ b/test/ELF/lto/drop-debug-info.ll
@@ -1,9 +1,9 @@
 ; REQUIRES: x86
 ;
 ; drop-debug-info.bc was created from "void f(void) {}" with clang 3.5 and
 ; -gline-tables-only, so it contains old debug info.
 ;
 ; RUN: ld.lld -m elf_x86_64 -shared %p/Inputs/drop-debug-info.bc \
 ; RUN: -disable-verify 2>&1 | FileCheck %s
-; CHECK: warning: ignoring debug info with an invalid version (1) in {{.*}}drop-debug-info.bc
+; CHECK: ignoring debug info with an invalid version (1) in {{.*}}drop-debug-info.bc
 
diff --git a/test/ELF/lto/drop-linkage.ll b/test/ELF/lto/drop-linkage.ll
index fd111c1..1ff1796 100644
--- a/test/ELF/lto/drop-linkage.ll
+++ b/test/ELF/lto/drop-linkage.ll
@@ -1,14 +1,14 @@
 target triple = "x86_64-unknown-linux-gnu"
 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
 
 ; REQUIRES: x86
 ; RUN: llc %s -o %t.o -filetype=obj
 ; RUN: llvm-as %p/Inputs/drop-linkage.ll -o %t2.o
 ; RUN: ld.lld %t.o %t2.o -o %t.so -save-temps -shared
-; RUN: llvm-dis %t.so.lto.opt.bc -o - | FileCheck %s
+; RUN: llvm-dis %t.so.0.4.opt.bc -o - | FileCheck %s
 
 define void @foo() {
   ret void
 }
 
 ; CHECK: declare void @foo()
diff --git a/test/ELF/lto/internalize-basic.ll b/test/ELF/lto/internalize-basic.ll
index 396b9cb..43c1837 100644
--- a/test/ELF/lto/internalize-basic.ll
+++ b/test/ELF/lto/internalize-basic.ll
@@ -1,21 +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
+; RUN: llvm-dis < %t2.0.2.internalize.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()
diff --git a/test/ELF/lto/internalize-exportdyn.ll b/test/ELF/lto/internalize-exportdyn.ll
index bee9a1e..2034a2b 100644
--- a/test/ELF/lto/internalize-exportdyn.ll
+++ b/test/ELF/lto/internalize-exportdyn.ll
@@ -1,47 +1,47 @@
 ; REQUIRES: x86
 ; RUN: llvm-as %s -o %t.o
 ; 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
+; RUN: llvm-dis < %t2.0.2.internalize.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 void @foo() {
   ret void
 }
 
 define hidden void @bar() {
   ret void
 }
 
 define linkonce_odr void @zed() local_unnamed_addr {
   ret void
 }
 
 define linkonce_odr void @zed2() 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 internal void @zed2()
 ; CHECK: define weak_odr void @bah()
 ; CHECK: define weak_odr void @baz()
diff --git a/test/ELF/lto/internalize-llvmused.ll b/test/ELF/lto/internalize-llvmused.ll
index 46c90a6..253dcb2 100644
--- a/test/ELF/lto/internalize-llvmused.ll
+++ b/test/ELF/lto/internalize-llvmused.ll
@@ -1,20 +1,20 @@
 ; 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
+; RUN: llvm-dis < %t2.0.2.internalize.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 @f() {
   ret void
 }
 
 @llvm.used = appending global [1 x i8*] [ i8* bitcast (void ()* @f to i8*)]
 
 ; Check that f is not internalized.
 ; CHECK: define hidden void @f()
diff --git a/test/ELF/lto/internalize-undef.ll b/test/ELF/lto/internalize-undef.ll
index 5d74c31..f76528b 100644
--- a/test/ELF/lto/internalize-undef.ll
+++ b/test/ELF/lto/internalize-undef.ll
@@ -1,16 +1,16 @@
 ; REQUIRES: x86
 ; RUN: llvm-as %s -o %t.o
 ; RUN: llvm-as %p/Inputs/internalize-undef.ll -o %t2.o
 ; RUN: ld.lld -m elf_x86_64 %t.o %t2.o -o %t -save-temps
-; RUN: llvm-dis < %t.lto.bc | FileCheck %s
+; RUN: llvm-dis < %t.0.2.internalize.bc | FileCheck %s
 
 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
 target triple = "x86_64-unknown-linux-gnu"
 
 declare void @f()
 define void @_start() {
   call void @f()
   ret void
 }
 
 ; CHECK: define internal void @f()
diff --git a/test/ELF/lto/internalize-version-script.ll b/test/ELF/lto/internalize-version-script.ll
index c25328f..c577e43 100644
--- a/test/ELF/lto/internalize-version-script.ll
+++ b/test/ELF/lto/internalize-version-script.ll
@@ -1,22 +1,22 @@
 ; REQUIRES: x86
 ; RUN: llvm-as %s -o %t.o
 ; RUN: echo "{ global: foo; local: *; };" > %t.script
 ; RUN: ld.lld -m elf_x86_64 %t.o -o %t2 -shared --version-script %t.script -save-temps
-; RUN: llvm-dis < %t2.lto.bc | FileCheck %s
+; RUN: llvm-dis < %t2.0.2.internalize.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 @foo() {
   ret void
 }
 
 define void @bar() {
   ret void
 }
 
 ; Check that foo is not internalized.
 ; CHECK: define void @foo()
 
 ; Check that bar is correctly internalized.
 ; CHECK: define internal void @bar()
diff --git a/test/ELF/lto/irmover-error.ll b/test/ELF/lto/irmover-error.ll
index aee4114..8b9836d 100644
--- a/test/ELF/lto/irmover-error.ll
+++ b/test/ELF/lto/irmover-error.ll
@@ -1,12 +1,12 @@
 ; RUN: llvm-as -o %t1.bc %s
 ; RUN: llvm-as -o %t2.bc %S/Inputs/irmover-error.ll
 ; RUN: not ld.lld -m elf_x86_64 %t1.bc %t2.bc -o %t 2>&1 | FileCheck %s
 
-; CHECK: failed to link module {{.*}}2.bc: linking module flags 'foo': IDs have conflicting values
+; CHECK: linking module flags 'foo': IDs have conflicting values
 
 target triple = "x86_64-unknown-linux-gnu"
 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
 
 !0 = !{ i32 1, !"foo", i32 1 }
 
 !llvm.module.flags = !{ !0 }
diff --git a/test/ELF/lto/linkonce-odr.ll b/test/ELF/lto/linkonce-odr.ll
index 569e271..4423351 100644
--- a/test/ELF/lto/linkonce-odr.ll
+++ b/test/ELF/lto/linkonce-odr.ll
@@ -1,17 +1,17 @@
 ; REQUIRES: x86
 ; RUN: llvm-as %p/Inputs/linkonce-odr.ll -o %t1.o
 ; RUN: llc -relocation-model=pic %s -o %t2.o -filetype=obj
 ; RUN: ld.lld %t1.o %t2.o -o %t.so -shared -save-temps
-; RUN: llvm-dis %t.so.lto.opt.bc -o - | FileCheck %s
+; RUN: llvm-dis %t.so.0.4.opt.bc -o - | FileCheck %s
 
 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
 target triple = "x86_64-unknown-linux-gnu"
 declare void @f()
 
 define void @g() {
   call void @f()
   ret void
 }
 
 ; Be sure that 'f' is kept and has weak_odr linkage.
 ; CHECK: define weak_odr void @f()
diff --git a/test/ELF/lto/linkonce.ll b/test/ELF/lto/linkonce.ll
index f980eff..6dba6a3 100644
--- a/test/ELF/lto/linkonce.ll
+++ b/test/ELF/lto/linkonce.ll
@@ -1,17 +1,17 @@
 ; REQUIRES: x86
 ; RUN: llvm-as %p/Inputs/linkonce.ll -o %t1.o
 ; RUN: llc -relocation-model=pic %s -o %t2.o -filetype=obj
 ; RUN: ld.lld %t1.o %t2.o -o %t.so -shared -save-temps
-; RUN: llvm-dis %t.so.lto.opt.bc -o - | FileCheck %s
+; RUN: llvm-dis %t.so.0.4.opt.bc -o - | FileCheck %s
 
 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
 target triple = "x86_64-unknown-linux-gnu"
 declare void @f()
 
 define void @g() {
   call void @f()
   ret void
 }
 
 ; Be sure that 'f' is kept and has weak linkage.
 ; CHECK: define weak void @f()
diff --git a/test/ELF/lto/ltopasses-basic.ll b/test/ELF/lto/ltopasses-basic.ll
index 5bd5f41..0c4ad8b 100644
--- a/test/ELF/lto/ltopasses-basic.ll
+++ b/test/ELF/lto/ltopasses-basic.ll
@@ -1,18 +1,17 @@
 ; REQUIRES: x86
-; RUN: rm -f %t.so.lto.bc %t.so.lto.opt.bc %t.so.lto.o
 ; RUN: llvm-as %s -o %t.o
 ; RUN: ld.lld -m elf_x86_64 %t.o -o %t.so -save-temps -mllvm -debug-pass=Arguments -shared 2>&1 | FileCheck %s --check-prefix=MLLVM
-; RUN: llvm-dis %t.so.lto.opt.bc -o - | FileCheck %s
+; RUN: llvm-dis %t.so.0.4.opt.bc -o - | FileCheck %s
 
 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
 target triple = "x86_64-unknown-linux-gnu"
 
 @llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @ctor, i8* null }]
 define void @ctor() {
   ret void
 }
 
 ; `@ctor` doesn't do anything and so the optimizer should kill it, leaving no ctors
 ; CHECK: @llvm.global_ctors = appending global [0 x { i32, void ()*, i8* }] zeroinitializer
 
 ; MLLVM: Pass Arguments:
diff --git a/test/ELF/lto/ltopasses-custom.ll b/test/ELF/lto/ltopasses-custom.ll
index 3e982e0..faa31e3 100644
--- a/test/ELF/lto/ltopasses-custom.ll
+++ b/test/ELF/lto/ltopasses-custom.ll
@@ -1,30 +1,30 @@
 ; REQUIRES: x86
 ; RUN: llvm-as %s -o %t.o
 ; RUN: ld.lld -m elf_x86_64 %t.o -o %t.so -save-temps --lto-aa-pipeline=basic-aa \
 ; RUN: --lto-newpm-passes=ipsccp -shared
 ; RUN: ld.lld -m elf_x86_64 %t.o -o %t2.so -save-temps --lto-newpm-passes=loweratomic -shared
-; RUN: llvm-dis %t.so.lto.opt.bc -o - | FileCheck %s
-; RUN: llvm-dis %t2.so.lto.opt.bc -o - | FileCheck %s --check-prefix=ATOMIC
+; RUN: llvm-dis %t.so.0.4.opt.bc -o - | FileCheck %s
+; RUN: llvm-dis %t2.so.0.4.opt.bc -o - | FileCheck %s --check-prefix=ATOMIC
 
 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
 target triple = "x86_64-unknown-linux-gnu"
 
 define void @barrier() {
   fence seq_cst
   ret void
 }
 
 ; IPSCCP won't remove the fence.
 ; CHECK: define void @barrier() {
 ; CHECK-NEXT: fence seq_cst
 ; CHECK-NEXT: ret void
 
 ; LowerAtomic will remove the fence.
 ; ATOMIC: define void @barrier() {
 ; ATOMIC-NEXT: ret void
 
 ; Check that invalid passes are rejected gracefully.
 ; RUN: not ld.lld -m elf_x86_64 %t.o -o %t2.so \
 ; RUN:   --lto-newpm-passes=iamnotapass -shared 2>&1 | \
 ; RUN:   FileCheck %s --check-prefix=INVALID
 ; INVALID: unable to parse pass pipeline description: iamnotapass
diff --git a/test/ELF/lto/save-temps.ll b/test/ELF/lto/save-temps.ll
index 0b0f939..f7af99e 100644
--- a/test/ELF/lto/save-temps.ll
+++ b/test/ELF/lto/save-temps.ll
@@ -1,20 +1,20 @@
 ; REQUIRES: x86
 ; RUN: cd %T
 ; RUN: rm -f a.out a.out.lto.bc a.out.lto.o
 ; RUN: llvm-as %s -o %t.o
 ; RUN: llvm-as %p/Inputs/save-temps.ll -o %t2.o
 ; RUN: ld.lld -shared -m elf_x86_64 %t.o %t2.o -save-temps
 ; RUN: llvm-nm a.out | FileCheck %s
-; RUN: llvm-nm a.out.lto.bc | FileCheck %s
+; RUN: llvm-nm a.out.0.0.preopt.bc | FileCheck %s
 ; RUN: llvm-nm a.out.lto.o | FileCheck %s
-; RUN: llvm-dis a.out.lto.bc
+; RUN: llvm-dis a.out.0.0.preopt.bc
 
 target triple = "x86_64-unknown-linux-gnu"
 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
 
 define void @foo() {
   ret void
 }
 
 ; CHECK: T bar
 ; CHECK: T foo
diff --git a/test/ELF/lto/type-merge.ll b/test/ELF/lto/type-merge.ll
index 98db539..d6f196d 100644
--- a/test/ELF/lto/type-merge.ll
+++ b/test/ELF/lto/type-merge.ll
@@ -1,26 +1,26 @@
 ; REQUIRES: x86
 ; RUN: llvm-as %s -o %t.o
 ; RUN: llvm-as %p/Inputs/type-merge.ll -o %t2.o
 ; RUN: ld.lld -m elf_x86_64 %t.o %t2.o -o %t -shared -save-temps
-; RUN: llvm-dis < %t.lto.bc | FileCheck %s
+; RUN: llvm-dis < %t.0.0.preopt.bc | FileCheck %s
 
 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
 target triple = "x86_64-unknown-linux-gnu"
 
 define void @foo()  {
   call void @bar(i8* null)
   ret void
 }
 declare void @bar(i8*)
 
 ; CHECK:      define void @foo() {
 ; CHECK-NEXT:   call void @bar(i8* null)
 ; CHECK-NEXT:   ret void
 ; CHECK-NEXT: }
 
 ; CHECK: declare void @bar(i8*)
 
 ; CHECK:      define void @zed() {
 ; CHECK-NEXT:   call void bitcast (void (i8*)* @bar to void ()*)()
 ; CHECK-NEXT:   ret void
 ; CHECK-NEXT: }
diff --git a/test/ELF/lto/type-merge2.ll b/test/ELF/lto/type-merge2.ll
index f0931dd..45777a7 100644
--- a/test/ELF/lto/type-merge2.ll
+++ b/test/ELF/lto/type-merge2.ll
@@ -1,27 +1,27 @@
 ; RUN: llvm-as %s -o %t.o
 ; RUN: llvm-as %p/Inputs/type-merge2.ll -o %t2.o
 ; RUN: ld.lld -m elf_x86_64 %t.o %t2.o -o %t.so -shared -save-temps
-; RUN: llvm-dis %t.so.lto.bc -o - | FileCheck %s
+; RUN: llvm-dis %t.so.0.0.preopt.bc -o - | FileCheck %s
 
 target triple = "x86_64-unknown-linux-gnu"
 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
 
 %zed = type { i8 }
 define void @foo()  {
   call void @bar(%zed* null)
   ret void
 }
 declare void @bar(%zed*)
 
 ; CHECK:      %zed = type { i8 }
 ; CHECK-NEXT: %zed.0 = type { i16 }
 
 ; CHECK:      define void @foo() {
 ; CHECK-NEXT:   call void bitcast (void (%zed.0*)* @bar to void (%zed*)*)(%zed* null)
 ; CHECK-NEXT:   ret void
 ; CHECK-NEXT: }
 
 ; CHECK:      define void @bar(%zed.0* %this) {
 ; CHECK-NEXT:   store %zed.0* %this, %zed.0** null
 ; CHECK-NEXT:   ret void
 ; CHECK-NEXT: }
diff --git a/test/ELF/lto/unnamed-addr-comdat.ll b/test/ELF/lto/unnamed-addr-comdat.ll
index c8c36de..ed48f3b 100644
--- a/test/ELF/lto/unnamed-addr-comdat.ll
+++ b/test/ELF/lto/unnamed-addr-comdat.ll
@@ -1,11 +1,11 @@
 ; RUN: llvm-as %s -o %t.o
 ; RUN: ld.lld -m elf_x86_64 %t.o %t.o -o %t.so -save-temps -shared
-; RUN: llvm-dis %t.so.lto.bc -o - | FileCheck %s
+; RUN: llvm-dis %t.so.0.2.internalize.bc -o - | FileCheck %s
 
 target triple = "x86_64-unknown-linux-gnu"
 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
 
 $foo = comdat any
 @foo = linkonce_odr unnamed_addr constant i32 42, comdat
 
 ; CHECK: @foo = internal unnamed_addr constant i32 42, comdat
diff --git a/test/ELF/lto/unnamed-addr-drop.ll b/test/ELF/lto/unnamed-addr-drop.ll
index 09bfd11..9142537 100644
--- a/test/ELF/lto/unnamed-addr-drop.ll
+++ b/test/ELF/lto/unnamed-addr-drop.ll
@@ -1,12 +1,12 @@
 ; RUN: llvm-as %s -o %t1.o
 ; RUN: llvm-as %S/Inputs/unnamed-addr-drop.ll -o %t2.o
 ; RUN: ld.lld -m elf_x86_64 %t1.o %t2.o -o %t.so -save-temps -shared
-; RUN: llvm-dis %t.so.lto.bc -o - | FileCheck %s
+; RUN: llvm-dis %t.so.0.2.internalize.bc -o - | FileCheck %s
 
 target triple = "x86_64-unknown-linux-gnu"
 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
 
 @foo = weak constant i32 41
 
 ; Check that unnamed_addr is dropped during the merge.
 ; CHECK: @foo = constant i32 42
diff --git a/test/ELF/lto/unnamed-addr-lib.ll b/test/ELF/lto/unnamed-addr-lib.ll
index fa0fe33..c2bc601 100644
--- a/test/ELF/lto/unnamed-addr-lib.ll
+++ b/test/ELF/lto/unnamed-addr-lib.ll
@@ -1,21 +1,21 @@
 ; REQUIRES: x86
 ; RUN: llvm-as %s -o %t.o
 ; RUN: llvm-mc %p/Inputs/unnamed-addr-lib.s -o %t2.o -filetype=obj -triple=x86_64-pc-linux
 ; RUN: ld.lld %t2.o -shared -o %t2.so
 ; RUN: ld.lld -m elf_x86_64 %t.o %t2.so -o %t.so -save-temps -shared
-; RUN: llvm-dis %t.so.lto.bc -o - | FileCheck %s
+; RUN: llvm-dis %t.so.0.2.internalize.bc -o - | FileCheck %s
 
 ; This documents a small limitation of lld's internalization logic. We decide
 ; that bar should be in the symbol table because if it is it will preempt the
 ; one in the shared library.
 ; We could add one extra bit for ODR so that we know that preemption is not
 ; necessary, but that is probably not worth it.
 
-; CHECK: @foo = internal constant i8 42
-; CHECK: @bar = weak_odr constant i8 42
+; CHECK: @foo = internal unnamed_addr constant i8 42
+; CHECK: @bar = weak_odr unnamed_addr constant i8 42
 
 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
 target triple = "x86_64-unknown-linux-gnu"
 
 @foo = linkonce_odr unnamed_addr constant i8 42
 @bar = linkonce_odr unnamed_addr constant i8 42
diff --git a/test/ELF/lto/unnamed-addr.ll b/test/ELF/lto/unnamed-addr.ll
index a2c0105..6a6dd73 100644
--- a/test/ELF/lto/unnamed-addr.ll
+++ b/test/ELF/lto/unnamed-addr.ll
@@ -1,14 +1,14 @@
 ; RUN: llvm-as %s -o %t.o
 ; RUN: ld.lld -m elf_x86_64 %t.o -o %t.so -save-temps -shared
-; RUN: llvm-dis %t.so.lto.opt.bc -o - | FileCheck %s
+; RUN: llvm-dis %t.so.0.4.opt.bc -o - | FileCheck %s
 
 target triple = "x86_64-unknown-linux-gnu"
 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
 
 @a = internal unnamed_addr constant i8 42
 
 define i8* @f() {
   ret i8* @a
 }
 
 ; CHECK: @a = internal unnamed_addr constant i8 42
diff --git a/test/ELF/lto/version-script.ll b/test/ELF/lto/version-script.ll
index 11a7f07..c43b443 100644
--- a/test/ELF/lto/version-script.ll
+++ b/test/ELF/lto/version-script.ll
@@ -1,50 +1,50 @@
 ; REQUIRES: x86
 ; RUN: llvm-as %s -o %t.o
 ; RUN: echo "VERSION_1.0{ global: foo; local: *; }; VERSION_2.0{ global: bar; local: *; };" > %t.script
 ; RUN: ld.lld -m elf_x86_64 %t.o -o %t2 -shared --version-script %t.script -save-temps
-; RUN: llvm-dis < %t2.lto.bc | FileCheck %s
+; RUN: llvm-dis < %t2.0.0.preopt.bc | FileCheck %s
 ; RUN: llvm-readobj -V -dyn-symbols %t2 | FileCheck --check-prefix=DSO %s
 
 target triple = "x86_64-unknown-linux-gnu"
 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
 
 define void @foo() {
   ret void
 }
 
 define void @bar() {
   ret void
 }
 
 ; CHECK: define void @foo()
 ; CHECK: define void @bar()
 
 ; DSO: DynamicSymbols [
 ; DSO:   Symbol {
 ; DSO:     Name: @ (0)
 ; DSO:     Value: 0x0
 ; DSO:     Size: 0
 ; DSO:     Binding: Local
 ; DSO:     Type: None
 ; DSO:     Other: 0
 ; DSO:     Section: Undefined
 ; DSO:   }
 ; DSO:   Symbol {
 ; DSO:     Name: foo@@VERSION_1.0
 ; DSO:     Value: 0x1000
 ; DSO:     Size: 1
 ; DSO:     Binding: Global
 ; DSO:     Type: Function
 ; DSO:     Other: 0
 ; DSO:     Section: .text
 ; DSO:   }
 ; DSO:   Symbol {
 ; DSO:     Name: bar@@VERSION_2.0
 ; DSO:     Value: 0x1010
 ; DSO:     Size: 1
 ; DSO:     Binding: Global
 ; DSO:     Type: Function
 ; DSO:     Other: 0
 ; DSO:     Section: .text
 ; DSO:   }
 ; DSO: ]


More information about the llvm-commits mailing list