[llvm] r278331 - Revert "Resolution-based LTO API."

Teresa Johnson via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 11 06:03:56 PDT 2016


Author: tejohnson
Date: Thu Aug 11 08:03:56 2016
New Revision: 278331

URL: http://llvm.org/viewvc/llvm-project?rev=278331&view=rev
Log:
Revert "Resolution-based LTO API."

This reverts commit r278330.

I made a change to the save temps output that is causing issues with the
bots. Didn't realize this because I had older output files sitting on
disk in my test output directory.

Removed:
    llvm/trunk/include/llvm/LTO/Config.h
    llvm/trunk/include/llvm/LTO/LTOBackend.h
    llvm/trunk/lib/LTO/LTOBackend.cpp
    llvm/trunk/test/LTO/Resolution/X86/Inputs/alias-1.ll
    llvm/trunk/test/LTO/Resolution/X86/Inputs/comdat.ll
    llvm/trunk/test/LTO/Resolution/X86/alias.ll
    llvm/trunk/test/LTO/Resolution/X86/comdat.ll
    llvm/trunk/test/LTO/Resolution/X86/lit.local.cfg
    llvm/trunk/test/tools/llvm-lto2/errors.ll
    llvm/trunk/tools/llvm-lto2/CMakeLists.txt
    llvm/trunk/tools/llvm-lto2/LLVMBuild.txt
    llvm/trunk/tools/llvm-lto2/llvm-lto2.cpp
Modified:
    llvm/trunk/include/llvm/LTO/LTO.h
    llvm/trunk/lib/LTO/CMakeLists.txt
    llvm/trunk/lib/LTO/LLVMBuild.txt
    llvm/trunk/lib/LTO/LTO.cpp
    llvm/trunk/lib/Object/IRObjectFile.cpp
    llvm/trunk/test/CMakeLists.txt
    llvm/trunk/test/lit.cfg
    llvm/trunk/test/tools/gold/X86/coff.ll
    llvm/trunk/test/tools/gold/X86/comdat.ll
    llvm/trunk/test/tools/gold/X86/common.ll
    llvm/trunk/test/tools/gold/X86/emit-llvm.ll
    llvm/trunk/test/tools/gold/X86/opt-level.ll
    llvm/trunk/test/tools/gold/X86/parallel.ll
    llvm/trunk/test/tools/gold/X86/slp-vectorize.ll
    llvm/trunk/test/tools/gold/X86/start-lib-common.ll
    llvm/trunk/test/tools/gold/X86/strip_names.ll
    llvm/trunk/test/tools/gold/X86/thinlto.ll
    llvm/trunk/test/tools/gold/X86/thinlto_alias.ll
    llvm/trunk/test/tools/gold/X86/thinlto_internalize.ll
    llvm/trunk/test/tools/gold/X86/thinlto_linkonceresolution.ll
    llvm/trunk/test/tools/gold/X86/thinlto_weak_resolution.ll
    llvm/trunk/test/tools/gold/X86/type-merge2.ll
    llvm/trunk/test/tools/gold/X86/vectorize.ll
    llvm/trunk/test/tools/gold/X86/visibility.ll
    llvm/trunk/tools/gold/gold-plugin.cpp

Removed: llvm/trunk/include/llvm/LTO/Config.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/LTO/Config.h?rev=278330&view=auto
==============================================================================
--- llvm/trunk/include/llvm/LTO/Config.h (original)
+++ llvm/trunk/include/llvm/LTO/Config.h (removed)
@@ -1,169 +0,0 @@
-//===-Config.h - LLVM Link Time Optimizer Configuration -------------------===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines the lto::Config data structure, which allows clients to
-// configure LTO.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_LTO_CONFIG_H
-#define LLVM_LTO_CONFIG_H
-
-#include "llvm/IR/DiagnosticInfo.h"
-#include "llvm/Target/TargetOptions.h"
-
-#include <functional>
-
-namespace llvm {
-
-class Error;
-class Module;
-class ModuleSummaryIndex;
-class raw_pwrite_stream;
-
-namespace lto {
-
-/// LTO configuration. A linker can configure LTO by setting fields in this data
-/// structure and passing it to the lto::LTO constructor.
-struct Config {
-  std::string CPU;
-  std::string Features;
-  TargetOptions Options;
-  std::vector<std::string> MAttrs;
-  Reloc::Model RelocModel = Reloc::PIC_;
-  CodeModel::Model CodeModel = CodeModel::Default;
-  CodeGenOpt::Level CGOptLevel = CodeGenOpt::Default;
-  unsigned OptLevel = 2;
-  bool DisableVerify = false;
-
-  /// Setting this field will replace target triples in input files with this
-  /// triple.
-  std::string OverrideTriple;
-
-  /// Setting this field will replace unspecified target triples in input files
-  /// with this triple.
-  std::string DefaultTriple;
-
-  bool ShouldDiscardValueNames = true;
-  DiagnosticHandlerFunction DiagHandler;
-
-  /// If this field is set, LTO will write input file paths and symbol
-  /// resolutions here in llvm-lto2 command line flag format. This can be
-  /// used for testing and for running the LTO pipeline outside of the linker
-  /// with llvm-lto2.
-  std::unique_ptr<raw_ostream> ResolutionFile;
-
-  /// The following callbacks deal with tasks, which normally represent the
-  /// entire optimization and code generation pipeline for what will become a
-  /// single native object file. Each task has a unique identifier between 0 and
-  /// getMaxTasks()-1, which is supplied to the callback via the Task parameter.
-  /// A task represents the entire pipeline for ThinLTO and regular
-  /// (non-parallel) LTO, but a parallel code generation task will be split into
-  /// N tasks before code generation, where N is the parallelism level.
-  ///
-  /// LTO may decide to stop processing a task at any time, for example if the
-  /// module is empty or if a module hook (see below) returns false. For this
-  /// reason, the client should not expect to receive exactly getMaxTasks()
-  /// native object files.
-
-  /// A module hook may be used by a linker to perform actions during the LTO
-  /// pipeline. For example, a linker may use this function to implement
-  /// -save-temps, or to add its own resolved symbols to the module. If this
-  /// function returns false, any further processing for that task is aborted.
-  ///
-  /// Module hooks must be thread safe with respect to the linker's internal
-  /// data structures. A module hook will never be called concurrently from
-  /// multiple threads with the same task ID, or the same module.
-  ///
-  /// Note that in out-of-process backend scenarios, none of the hooks will be
-  /// called for ThinLTO tasks.
-  typedef std::function<bool(size_t Task, Module &)> ModuleHookFn;
-
-  /// This module hook is called after linking (regular LTO) or loading
-  /// (ThinLTO) the module, before modifying it.
-  ModuleHookFn PreOptModuleHook;
-
-  /// This hook is called after promoting any internal functions
-  /// (ThinLTO-specific).
-  ModuleHookFn PostPromoteModuleHook;
-
-  /// This hook is called after internalizing the module.
-  ModuleHookFn PostInternalizeModuleHook;
-
-  /// This hook is called after importing from other modules (ThinLTO-specific).
-  ModuleHookFn PostImportModuleHook;
-
-  /// This module hook is called after optimization is complete.
-  ModuleHookFn PostOptModuleHook;
-
-  /// This module hook is called before code generation. It is similar to the
-  /// PostOptModuleHook, but for parallel code generation it is called after
-  /// splitting the module.
-  ModuleHookFn PreCodeGenModuleHook;
-
-  /// A combined index hook is called after all per-module indexes have been
-  /// combined (ThinLTO-specific). It can be used to implement -save-temps for
-  /// the combined index.
-  ///
-  /// If this function returns false, any further processing for ThinLTO tasks
-  /// is aborted.
-  ///
-  /// It is called regardless of whether the backend is in-process, although it
-  /// is not called from individual backend processes.
-  typedef std::function<bool(const ModuleSummaryIndex &Index)>
-      CombinedIndexHookFn;
-  CombinedIndexHookFn CombinedIndexHook;
-
-  /// This is a convenience function that configures this Config object to write
-  /// temporary files named after the given OutputFileName for each of the LTO
-  /// phases to disk. A client can use this function to implement -save-temps.
-  ///
-  /// FIXME: Temporary files derived from ThinLTO backends are currently named
-  /// after the input file name, rather than the output file name.
-  ///
-  /// Specifically, it (1) sets each of the above module hooks and the combined
-  /// index hook to a function that calls the hook function (if any) that was
-  /// present in the appropriate field when the addSaveTemps function was
-  /// called, and writes the module to a bitcode file with a name prefixed by
-  /// the given output file name, and (2) creates a resolution file whose name
-  /// is prefixed by the given output file name and sets ResolutionFile to its
-  /// file handle.
-  Error addSaveTemps(std::string OutputFileName);
-};
-
-/// This type defines a stream callback. A stream callback is used to add a
-/// native object that is generated on the fly. The callee must set up and
-/// return a output stream to write the native object to.
-///
-/// Stream callbacks must be thread safe.
-typedef std::function<std::unique_ptr<raw_pwrite_stream>(size_t Task)>
-    AddStreamFn;
-
-/// A derived class of LLVMContext that initializes itself according to a given
-/// Config object. The purpose of this class is to tie ownership of the
-/// diagnostic handler to the context, as opposed to the Config object (which
-/// may be ephemeral).
-struct LTOLLVMContext : LLVMContext {
-  static void funcDiagHandler(const DiagnosticInfo &DI, void *Context) {
-    auto *Fn = static_cast<DiagnosticHandlerFunction *>(Context);
-    (*Fn)(DI);
-  }
-
-  LTOLLVMContext(const Config &C) : DiagHandler(C.DiagHandler) {
-    setDiscardValueNames(C.ShouldDiscardValueNames);
-    enableDebugTypeODRUniquing();
-    setDiagnosticHandler(funcDiagHandler, &DiagHandler, true);
-  }
-  DiagnosticHandlerFunction DiagHandler;
-};
-
-}
-}
-
-#endif

Modified: llvm/trunk/include/llvm/LTO/LTO.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/LTO/LTO.h?rev=278331&r1=278330&r2=278331&view=diff
==============================================================================
--- llvm/trunk/include/llvm/LTO/LTO.h (original)
+++ llvm/trunk/include/llvm/LTO/LTO.h Thu Aug 11 08:03:56 2016
@@ -16,27 +16,14 @@
 #ifndef LLVM_LTO_LTO_H
 #define LLVM_LTO_LTO_H
 
-#include "llvm/ADT/MapVector.h"
 #include "llvm/ADT/StringMap.h"
-#include "llvm/ADT/StringSet.h"
-#include "llvm/CodeGen/Analysis.h"
-#include "llvm/IR/DiagnosticInfo.h"
 #include "llvm/IR/ModuleSummaryIndex.h"
-#include "llvm/LTO/Config.h"
-#include "llvm/Linker/IRMover.h"
-#include "llvm/Object/IRObjectFile.h"
-#include "llvm/Support/thread.h"
-#include "llvm/Target/TargetOptions.h"
-#include "llvm/Transforms/IPO/FunctionImport.h"
 
 namespace llvm {
 
-class Error;
 class LLVMContext;
 class MemoryBufferRef;
 class Module;
-class Target;
-class raw_pwrite_stream;
 
 /// Helper to load a module from bitcode.
 std::unique_ptr<Module> loadModuleFromBuffer(const MemoryBufferRef &Buffer,
@@ -82,319 +69,6 @@ void thinLTOResolveWeakForLinkerInIndex(
 void thinLTOInternalizeAndPromoteInIndex(
     ModuleSummaryIndex &Index,
     function_ref<bool(StringRef, GlobalValue::GUID)> isExported);
-
-namespace lto {
-
-class LTO;
-struct SymbolResolution;
-class ThinBackendProc;
-
-/// An input file. This is a wrapper for IRObjectFile that exposes only the
-/// information that an LTO client should need in order to do symbol resolution.
-class InputFile {
-  // FIXME: Remove LTO class friendship once we have bitcode symbol tables.
-  friend LTO;
-  InputFile() = default;
-
-  // FIXME: Remove the LLVMContext once we have bitcode symbol tables.
-  LLVMContext Ctx;
-  std::unique_ptr<object::IRObjectFile> Obj;
-
-public:
-  /// Create an InputFile.
-  static Expected<std::unique_ptr<InputFile>> create(MemoryBufferRef Object);
-
-  class symbol_iterator;
-
-  /// This is a wrapper for object::basic_symbol_iterator that exposes only the
-  /// information that an LTO client should need in order to do symbol
-  /// resolution.
-  ///
-  /// This object is ephemeral; it is only valid as long as an iterator obtained
-  /// from symbols() refers to it.
-  class Symbol {
-    friend symbol_iterator;
-    friend LTO;
-
-    object::basic_symbol_iterator I;
-    const GlobalValue *GV;
-    uint32_t Flags;
-    SmallString<64> Name;
-
-    bool shouldSkip() {
-      return !(Flags & object::BasicSymbolRef::SF_Global) ||
-             (Flags & object::BasicSymbolRef::SF_FormatSpecific);
-    }
-
-    void skip() {
-      const object::SymbolicFile *Obj = I->getObject();
-      auto E = Obj->symbol_end();
-      while (I != E) {
-        Flags = I->getFlags();
-        if (!shouldSkip())
-          break;
-        ++I;
-      }
-      if (I == E)
-        return;
-
-      Name.clear();
-      {
-        raw_svector_ostream OS(Name);
-        I->printName(OS);
-      }
-      GV = cast<object::IRObjectFile>(Obj)->getSymbolGV(I->getRawDataRefImpl());
-    }
-
-  public:
-    Symbol(object::basic_symbol_iterator I) : I(I) { skip(); }
-
-    StringRef getName() const { return Name; }
-    StringRef getIRName() const {
-      if (GV)
-        return GV->getName();
-      return StringRef();
-    }
-    uint32_t getFlags() const { return Flags; }
-    GlobalValue::VisibilityTypes getVisibility() const {
-      if (GV)
-        return GV->getVisibility();
-      return GlobalValue::DefaultVisibility;
-    }
-    bool canBeOmittedFromSymbolTable() const {
-      return GV && llvm::canBeOmittedFromSymbolTable(GV);
-    }
-    Expected<const Comdat *> getComdat() const {
-      const GlobalObject *GO;
-      if (auto *GA = dyn_cast<GlobalAlias>(GV)) {
-        GO = GA->getBaseObject();
-        if (!GO)
-          return make_error<StringError>("Unable to determine comdat of alias!",
-                                         inconvertibleErrorCode());
-      } else {
-        GO = cast<GlobalObject>(GV);
-      }
-      if (GV)
-        return GV->getComdat();
-      return nullptr;
-    }
-    size_t getCommonSize() const {
-      assert(Flags & object::BasicSymbolRef::SF_Common);
-      if (!GV)
-        return 0;
-      return GV->getParent()->getDataLayout().getTypeAllocSize(
-          GV->getType()->getElementType());
-    }
-    unsigned getCommonAlignment() const {
-      assert(Flags & object::BasicSymbolRef::SF_Common);
-      if (!GV)
-        return 0;
-      return GV->getAlignment();
-    }
-  };
-
-  class symbol_iterator {
-    Symbol Sym;
-
-  public:
-    symbol_iterator(object::basic_symbol_iterator I) : Sym(I) {}
-
-    symbol_iterator &operator++() {
-      ++Sym.I;
-      Sym.skip();
-      return *this;
-    }
-
-    symbol_iterator operator++(int) {
-      symbol_iterator I = *this;
-      ++*this;
-      return I;
-    }
-
-    const Symbol &operator*() const { return Sym; }
-    const Symbol *operator->() const { return &Sym; }
-
-    bool operator!=(const symbol_iterator &Other) const {
-      return Sym.I != Other.Sym.I;
-    }
-  };
-
-  /// A range over the symbols in this InputFile.
-  iterator_range<symbol_iterator> symbols() {
-    return llvm::make_range(symbol_iterator(Obj->symbol_begin()),
-                            symbol_iterator(Obj->symbol_end()));
-  }
-
-  StringRef getSourceFileName() const {
-    return Obj->getModule().getSourceFileName();
-  }
-};
-
-/// A ThinBackend defines what happens after the thin-link phase during ThinLTO.
-/// The details of this type definition aren't important; clients can only
-/// create a ThinBackend using one of the create*ThinBackend() functions below.
-typedef std::function<std::unique_ptr<ThinBackendProc>(
-    Config &C, ModuleSummaryIndex &CombinedIndex,
-    StringMap<GVSummaryMapTy> &ModuleToDefinedGVSummaries,
-    AddStreamFn AddStream)>
-    ThinBackend;
-
-/// This ThinBackend runs the individual backend jobs in-process.
-ThinBackend createInProcessThinBackend(unsigned ParallelismLevel);
-
-/// This ThinBackend writes individual module indexes to files, instead of
-/// running the individual backend jobs. This backend is for distributed builds
-/// where separate processes will invoke the real backends.
-///
-/// To find the path to write the index to, the backend checks if the path has a
-/// prefix of OldPrefix; if so, it replaces that prefix with NewPrefix. It then
-/// appends ".thinlto.bc" and writes the index to that path. If
-/// ShouldEmitImportsFiles is true it also writes a list of imported files to a
-/// similar path with ".imports" appended instead.
-ThinBackend createWriteIndexesThinBackend(std::string OldPrefix,
-                                          std::string NewPrefix,
-                                          bool ShouldEmitImportsFiles,
-                                          std::string LinkedObjectsFile);
-
-/// This class implements a resolution-based interface to LLVM's LTO
-/// functionality. It supports regular LTO, parallel LTO code generation and
-/// ThinLTO. You can use it from a linker in the following way:
-/// - Set hooks and code generation options (see lto::Config struct defined in
-///   Config.h), and use the lto::Config object to create an lto::LTO object.
-/// - Create lto::InputFile objects using lto::InputFile::create(), then use
-///   the symbols() function to enumerate its symbols and compute a resolution
-///   for each symbol (see SymbolResolution below).
-/// - After the linker has visited each input file (and each regular object
-///   file) and computed a resolution for each symbol, take each lto::InputFile
-///   and pass it and an array of symbol resolutions to the add() function.
-/// - Call the getMaxTasks() function to get an upper bound on the number of
-///   native object files that LTO may add to the link.
-/// - Call the run() function. This function will use the supplied AddStream
-///   function to add up to getMaxTasks() native object files to the link.
-class LTO {
-  friend InputFile;
-
-public:
-  /// Create an LTO object. A default constructed LTO object has a reasonable
-  /// production configuration, but you can customize it by passing arguments to
-  /// this constructor.
-  /// FIXME: We do currently require the DiagHandler field to be set in Conf.
-  /// Until that is fixed, a Config argument is required.
-  LTO(Config Conf, ThinBackend Backend = nullptr,
-      unsigned ParallelCodeGenParallelismLevel = 1);
-
-  /// Add an input file to the LTO link, using the provided symbol resolutions.
-  /// The symbol resolutions must appear in the enumeration order given by
-  /// InputFile::symbols().
-  Error add(std::unique_ptr<InputFile> Obj, ArrayRef<SymbolResolution> Res);
-
-  /// Returns an upper bound on the number of tasks that the client may expect.
-  /// This may only be called after all IR object files have been added. For a
-  /// full description of tasks see LTOBackend.h.
-  size_t getMaxTasks() const;
-
-  /// Runs the LTO pipeline. This function calls the supplied AddStream function
-  /// to add native object files to the link.
-  Error run(AddStreamFn AddStream);
-
-private:
-  Config Conf;
-
-  struct RegularLTOState {
-    RegularLTOState(unsigned ParallelCodeGenParallelismLevel, Config &Conf);
-
-    unsigned ParallelCodeGenParallelismLevel;
-    LTOLLVMContext Ctx;
-    bool HasModule = false;
-    std::unique_ptr<Module> CombinedModule;
-    IRMover Mover;
-  } RegularLTO;
-
-  struct ThinLTOState {
-    ThinLTOState(ThinBackend Backend);
-
-    ThinBackend Backend;
-    ModuleSummaryIndex CombinedIndex;
-    MapVector<StringRef, MemoryBufferRef> ModuleMap;
-    DenseMap<GlobalValue::GUID, StringRef> PrevailingModuleForGUID;
-  } ThinLTO;
-
-  // The global resolution for a particular (mangled) symbol name. This is in
-  // particular necessary to track whether each symbol can be internalized.
-  // Because any input file may introduce a new cross-partition reference, we
-  // cannot make any final internalization decisions until all input files have
-  // been added and the client has called run(). During run() we apply
-  // internalization decisions either directly to the module (for regular LTO)
-  // or to the combined index (for ThinLTO).
-  struct GlobalResolution {
-    /// The unmangled name of the global.
-    std::string IRName;
-
-    bool UnnamedAddr = true;
-
-    /// This field keeps track of the partition number of this global. The
-    /// regular LTO object is partition 0, while each ThinLTO object has its own
-    /// partition number from 1 onwards.
-    ///
-    /// Any global that is defined or used by more than one partition, or that
-    /// is referenced externally, may not be internalized.
-    ///
-    /// Partitions generally have a one-to-one correspondence with tasks, except
-    /// that we use partition 0 for all parallel LTO code generation partitions.
-    /// Any partitioning of the combined LTO object is done internally by the
-    /// LTO backend.
-    size_t Partition = Unknown;
-
-    /// Special partition numbers.
-    enum {
-      /// A partition number has not yet been assigned to this global.
-      Unknown = -1ull,
-
-      /// This global is either used by more than one partition or has an
-      /// external reference, and therefore cannot be internalized.
-      External = -2ull,
-    };
-  };
-
-  // Global mapping from mangled symbol names to resolutions.
-  StringMap<GlobalResolution> GlobalResolutions;
-
-  void writeToResolutionFile(InputFile *Input, ArrayRef<SymbolResolution> Res);
-
-  void addSymbolToGlobalRes(object::IRObjectFile *Obj,
-                            SmallPtrSet<GlobalValue *, 8> &Used,
-                            const InputFile::Symbol &Sym, SymbolResolution Res,
-                            size_t Partition);
-
-  Error addRegularLTO(std::unique_ptr<InputFile> Input,
-                      ArrayRef<SymbolResolution> Res);
-  Error addThinLTO(std::unique_ptr<InputFile> Input,
-                   ArrayRef<SymbolResolution> Res);
-
-  Error runRegularLTO(AddStreamFn AddStream);
-  Error runThinLTO(AddStreamFn AddStream);
-
-  mutable bool CalledGetMaxTasks = false;
-};
-
-/// The resolution for a symbol. The linker must provide a SymbolResolution for
-/// each global symbol based on its internal resolution of that symbol.
-struct SymbolResolution {
-  SymbolResolution()
-      : Prevailing(0), FinalDefinitionInLinkageUnit(0), VisibleToRegularObj(0) {
-  }
-  /// The linker has chosen this definition of the symbol.
-  unsigned Prevailing : 1;
-
-  /// The definition of this symbol is unpreemptable at runtime and is known to
-  /// be in this linkage unit.
-  unsigned FinalDefinitionInLinkageUnit : 1;
-
-  /// The definition of this symbol is visible outside of the LTO unit.
-  unsigned VisibleToRegularObj : 1;
-};
-
-} // namespace lto
-} // namespace llvm
+}
 
 #endif

Removed: llvm/trunk/include/llvm/LTO/LTOBackend.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/LTO/LTOBackend.h?rev=278330&view=auto
==============================================================================
--- llvm/trunk/include/llvm/LTO/LTOBackend.h (original)
+++ llvm/trunk/include/llvm/LTO/LTOBackend.h (removed)
@@ -1,51 +0,0 @@
-//===-LTOBackend.h - LLVM Link Time Optimizer Backend ---------------------===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the "backend" phase of LTO, i.e. it performs
-// optimization and code generation on a loaded module. It is generally used
-// internally by the LTO class but can also be used independently, for example
-// to implement a standalone ThinLTO backend.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_LTO_LTOBACKEND_H
-#define LLVM_LTO_LTOBACKEND_H
-
-#include "llvm/ADT/MapVector.h"
-#include "llvm/IR/DiagnosticInfo.h"
-#include "llvm/IR/ModuleSummaryIndex.h"
-#include "llvm/LTO/Config.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Target/TargetOptions.h"
-#include "llvm/Transforms/IPO/FunctionImport.h"
-
-namespace llvm {
-
-class Error;
-class Module;
-class Target;
-
-namespace lto {
-
-/// Runs a regular LTO backend.
-Error backend(Config &C, AddStreamFn AddStream,
-              unsigned ParallelCodeGenParallelismLevel,
-              std::unique_ptr<Module> M);
-
-/// Runs a ThinLTO backend.
-Error thinBackend(Config &C, size_t Task, AddStreamFn AddStream, Module &M,
-                  ModuleSummaryIndex &CombinedIndex,
-                  const FunctionImporter::ImportMapTy &ImportList,
-                  const GVSummaryMapTy &DefinedGlobals,
-                  MapVector<StringRef, MemoryBufferRef> &ModuleMap);
-
-}
-}
-
-#endif

Modified: llvm/trunk/lib/LTO/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/LTO/CMakeLists.txt?rev=278331&r1=278330&r2=278331&view=diff
==============================================================================
--- llvm/trunk/lib/LTO/CMakeLists.txt (original)
+++ llvm/trunk/lib/LTO/CMakeLists.txt Thu Aug 11 08:03:56 2016
@@ -49,7 +49,6 @@ endif()
 
 add_llvm_library(LLVMLTO
   LTO.cpp
-  LTOBackend.cpp
   LTOModule.cpp
   LTOCodeGenerator.cpp
   UpdateCompilerUsed.cpp

Modified: llvm/trunk/lib/LTO/LLVMBuild.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/LTO/LLVMBuild.txt?rev=278331&r1=278330&r2=278331&view=diff
==============================================================================
--- llvm/trunk/lib/LTO/LLVMBuild.txt (original)
+++ llvm/trunk/lib/LTO/LLVMBuild.txt Thu Aug 11 08:03:56 2016
@@ -34,4 +34,4 @@ required_libraries =
  Scalar
  Support
  Target
- TransformUtils
+ TransformUtils
\ No newline at end of file

Modified: llvm/trunk/lib/LTO/LTO.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/LTO/LTO.cpp?rev=278331&r1=278330&r2=278331&view=diff
==============================================================================
--- llvm/trunk/lib/LTO/LTO.cpp (original)
+++ llvm/trunk/lib/LTO/LTO.cpp Thu Aug 11 08:03:56 2016
@@ -12,39 +12,16 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/LTO/LTO.h"
-#include "llvm/Analysis/TargetLibraryInfo.h"
-#include "llvm/Analysis/TargetTransformInfo.h"
 #include "llvm/Bitcode/ReaderWriter.h"
-#include "llvm/CodeGen/Analysis.h"
-#include "llvm/IR/AutoUpgrade.h"
-#include "llvm/IR/DiagnosticPrinter.h"
-#include "llvm/IR/LegacyPassManager.h"
-#include "llvm/LTO/LTOBackend.h"
-#include "llvm/Linker/IRMover.h"
-#include "llvm/Object/ModuleSummaryIndexObjectFile.h"
-#include "llvm/Support/ManagedStatic.h"
 #include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/Path.h"
 #include "llvm/Support/SourceMgr.h"
-#include "llvm/Support/TargetRegistry.h"
-#include "llvm/Support/ThreadPool.h"
 #include "llvm/Support/raw_ostream.h"
-#include "llvm/Target/TargetMachine.h"
-#include "llvm/Target/TargetOptions.h"
-#include "llvm/Transforms/IPO.h"
-#include "llvm/Transforms/IPO/PassManagerBuilder.h"
-#include "llvm/Transforms/Utils/SplitModule.h"
 
-#include <set>
-
-using namespace llvm;
-using namespace lto;
-using namespace object;
+namespace llvm {
 
 // Simple helper to load a module from bitcode
-std::unique_ptr<Module>
-llvm::loadModuleFromBuffer(const MemoryBufferRef &Buffer, LLVMContext &Context,
-                           bool Lazy) {
+std::unique_ptr<Module> loadModuleFromBuffer(const MemoryBufferRef &Buffer,
+                                             LLVMContext &Context, bool Lazy) {
   SMDiagnostic Err;
   ErrorOr<std::unique_ptr<Module>> ModuleOrErr(nullptr);
   if (Lazy) {
@@ -99,7 +76,7 @@ static void thinLTOResolveWeakForLinkerG
 // current module. However there is a chance that another module is still
 // referencing them because of the import. We make sure we always emit at least
 // one copy.
-void llvm::thinLTOResolveWeakForLinkerInIndex(
+void thinLTOResolveWeakForLinkerInIndex(
     ModuleSummaryIndex &Index,
     function_ref<bool(GlobalValue::GUID, const GlobalValueSummary *)>
         isPrevailing,
@@ -133,513 +110,10 @@ static void thinLTOInternalizeAndPromote
 
 // Update the linkages in the given \p Index to mark exported values
 // as external and non-exported values as internal.
-void llvm::thinLTOInternalizeAndPromoteInIndex(
+void thinLTOInternalizeAndPromoteInIndex(
     ModuleSummaryIndex &Index,
     function_ref<bool(StringRef, GlobalValue::GUID)> isExported) {
   for (auto &I : Index)
     thinLTOInternalizeAndPromoteGUID(I.second, I.first, isExported);
 }
-
-Expected<std::unique_ptr<InputFile>> InputFile::create(MemoryBufferRef Object) {
-  std::unique_ptr<InputFile> File(new InputFile);
-  std::string Msg;
-  auto DiagHandler = [](const DiagnosticInfo &DI, void *MsgP) {
-    auto *Msg = reinterpret_cast<std::string *>(MsgP);
-    raw_string_ostream OS(*Msg);
-    DiagnosticPrinterRawOStream DP(OS);
-    DI.print(DP);
-  };
-  File->Ctx.setDiagnosticHandler(DiagHandler, static_cast<void *>(&Msg));
-
-  ErrorOr<std::unique_ptr<object::IRObjectFile>> IRObj =
-      IRObjectFile::create(Object, File->Ctx);
-  if (!Msg.empty())
-    return make_error<StringError>(Msg, inconvertibleErrorCode());
-  if (!IRObj)
-    return errorCodeToError(IRObj.getError());
-  File->Obj = std::move(*IRObj);
-
-  File->Ctx.setDiagnosticHandler(nullptr, nullptr);
-
-  return std::move(File);
-}
-
-LTO::RegularLTOState::RegularLTOState(unsigned ParallelCodeGenParallelismLevel,
-                                      Config &Conf)
-    : ParallelCodeGenParallelismLevel(ParallelCodeGenParallelismLevel),
-      Ctx(Conf), CombinedModule(make_unique<Module>("ld-temp.o", Ctx)),
-      Mover(*CombinedModule) {}
-
-LTO::ThinLTOState::ThinLTOState(ThinBackend Backend) : Backend(Backend) {
-  if (!Backend)
-    this->Backend = createInProcessThinBackend(thread::hardware_concurrency());
-}
-
-LTO::LTO(Config Conf, ThinBackend Backend,
-         unsigned ParallelCodeGenParallelismLevel)
-    : Conf(std::move(Conf)),
-      RegularLTO(ParallelCodeGenParallelismLevel, this->Conf),
-      ThinLTO(Backend) {}
-
-// Add the given symbol to the GlobalResolutions map, and resolve its partition.
-void LTO::addSymbolToGlobalRes(IRObjectFile *Obj,
-                               SmallPtrSet<GlobalValue *, 8> &Used,
-                               const InputFile::Symbol &Sym,
-                               SymbolResolution Res, size_t Partition) {
-  GlobalValue *GV = Obj->getSymbolGV(Sym.I->getRawDataRefImpl());
-
-  auto &GlobalRes = GlobalResolutions[Sym.getName()];
-  if (GV) {
-    GlobalRes.UnnamedAddr &= GV->hasGlobalUnnamedAddr();
-    if (Res.Prevailing)
-      GlobalRes.IRName = GV->getName();
-  }
-  if (Res.VisibleToRegularObj || (GV && Used.count(GV)) ||
-      (GlobalRes.Partition != GlobalResolution::Unknown &&
-       GlobalRes.Partition != Partition))
-    GlobalRes.Partition = GlobalResolution::External;
-  else
-    GlobalRes.Partition = Partition;
-}
-
-void LTO::writeToResolutionFile(InputFile *Input,
-                                ArrayRef<SymbolResolution> Res) {
-  StringRef Path = Input->Obj->getMemoryBufferRef().getBufferIdentifier();
-  *Conf.ResolutionFile << Path << '\n';
-  auto ResI = Res.begin();
-  for (const InputFile::Symbol &Sym : Input->symbols()) {
-    assert(ResI != Res.end());
-    SymbolResolution Res = *ResI++;
-
-    *Conf.ResolutionFile << "-r=" << Path << ',' << Sym.getName() << ',';
-    if (Res.Prevailing)
-      *Conf.ResolutionFile << 'p';
-    if (Res.FinalDefinitionInLinkageUnit)
-      *Conf.ResolutionFile << 'l';
-    if (Res.VisibleToRegularObj)
-      *Conf.ResolutionFile << 'x';
-    *Conf.ResolutionFile << '\n';
-  }
-  assert(ResI == Res.end());
-}
-
-Error LTO::add(std::unique_ptr<InputFile> Input,
-               ArrayRef<SymbolResolution> Res) {
-  assert(!CalledGetMaxTasks);
-
-  if (Conf.ResolutionFile)
-    writeToResolutionFile(Input.get(), Res);
-
-  Module &M = Input->Obj->getModule();
-  SmallPtrSet<GlobalValue *, 8> Used;
-  collectUsedGlobalVariables(M, Used, /*CompilerUsed*/ false);
-
-  if (!Conf.OverrideTriple.empty())
-    M.setTargetTriple(Conf.OverrideTriple);
-  else if (M.getTargetTriple().empty())
-    M.setTargetTriple(Conf.DefaultTriple);
-
-  MemoryBufferRef MBRef = Input->Obj->getMemoryBufferRef();
-  bool HasThinLTOSummary = hasGlobalValueSummary(MBRef, Conf.DiagHandler);
-
-  if (HasThinLTOSummary)
-    return addThinLTO(std::move(Input), Res);
-  else
-    return addRegularLTO(std::move(Input), Res);
-}
-
-// Add a regular LTO object to the link.
-Error LTO::addRegularLTO(std::unique_ptr<InputFile> Input,
-                         ArrayRef<SymbolResolution> Res) {
-  RegularLTO.HasModule = true;
-
-  ErrorOr<std::unique_ptr<object::IRObjectFile>> ObjOrErr =
-      IRObjectFile::create(Input->Obj->getMemoryBufferRef(), RegularLTO.Ctx);
-  if (!ObjOrErr)
-    return errorCodeToError(ObjOrErr.getError());
-  std::unique_ptr<object::IRObjectFile> Obj = std::move(*ObjOrErr);
-
-  Module &M = Obj->getModule();
-  M.materializeMetadata();
-  UpgradeDebugInfo(M);
-
-  SmallPtrSet<GlobalValue *, 8> Used;
-  collectUsedGlobalVariables(M, Used, /*CompilerUsed*/ false);
-
-  std::vector<GlobalValue *> Keep;
-
-  for (GlobalVariable &GV : M.globals())
-    if (GV.hasAppendingLinkage())
-      Keep.push_back(&GV);
-
-  auto ResI = Res.begin();
-  for (const InputFile::Symbol &Sym :
-       make_range(InputFile::symbol_iterator(Obj->symbol_begin()),
-                  InputFile::symbol_iterator(Obj->symbol_end()))) {
-    assert(ResI != Res.end());
-    SymbolResolution Res = *ResI++;
-    addSymbolToGlobalRes(Obj.get(), Used, Sym, Res, 0);
-
-    GlobalValue *GV = Obj->getSymbolGV(Sym.I->getRawDataRefImpl());
-    if (Res.Prevailing && GV) {
-      Keep.push_back(GV);
-      switch (GV->getLinkage()) {
-      default:
-        break;
-      case GlobalValue::LinkOnceAnyLinkage:
-        GV->setLinkage(GlobalValue::WeakAnyLinkage);
-        break;
-      case GlobalValue::LinkOnceODRLinkage:
-        GV->setLinkage(GlobalValue::WeakODRLinkage);
-        break;
-      }
-    }
-
-    // FIXME: use proposed local attribute for FinalDefinitionInLinkageUnit.
-  }
-  assert(ResI == Res.end());
-
-  return RegularLTO.Mover.move(Obj->takeModule(), Keep,
-                               [](GlobalValue &, IRMover::ValueAdder) {});
-}
-
-// Add a ThinLTO object to the link.
-Error LTO::addThinLTO(std::unique_ptr<InputFile> Input,
-                      ArrayRef<SymbolResolution> Res) {
-  Module &M = Input->Obj->getModule();
-  SmallPtrSet<GlobalValue *, 8> Used;
-  collectUsedGlobalVariables(M, Used, /*CompilerUsed*/ false);
-
-  // We need to initialize the target info for the combined regular LTO module
-  // in case we have no regular LTO objects. In that case we still need to build
-  // it as usual because the client may want to add symbol definitions to it.
-  if (RegularLTO.CombinedModule->getTargetTriple().empty()) {
-    RegularLTO.CombinedModule->setTargetTriple(M.getTargetTriple());
-    RegularLTO.CombinedModule->setDataLayout(M.getDataLayout());
-  }
-
-  MemoryBufferRef MBRef = Input->Obj->getMemoryBufferRef();
-  ErrorOr<std::unique_ptr<object::ModuleSummaryIndexObjectFile>>
-      SummaryObjOrErr =
-          object::ModuleSummaryIndexObjectFile::create(MBRef, Conf.DiagHandler);
-  if (!SummaryObjOrErr)
-    return errorCodeToError(SummaryObjOrErr.getError());
-  ThinLTO.CombinedIndex.mergeFrom((*SummaryObjOrErr)->takeIndex(),
-                                  ThinLTO.ModuleMap.size());
-
-  auto ResI = Res.begin();
-  for (const InputFile::Symbol &Sym : Input->symbols()) {
-    assert(ResI != Res.end());
-    SymbolResolution Res = *ResI++;
-    addSymbolToGlobalRes(Input->Obj.get(), Used, Sym, Res,
-                         ThinLTO.ModuleMap.size() + 1);
-
-    GlobalValue *GV = Input->Obj->getSymbolGV(Sym.I->getRawDataRefImpl());
-    if (Res.Prevailing && GV)
-      ThinLTO.PrevailingModuleForGUID[GV->getGUID()] =
-          MBRef.getBufferIdentifier();
-  }
-  assert(ResI == Res.end());
-
-  ThinLTO.ModuleMap[MBRef.getBufferIdentifier()] = MBRef;
-  return Error();
-}
-
-size_t LTO::getMaxTasks() const {
-  CalledGetMaxTasks = true;
-  return RegularLTO.ParallelCodeGenParallelismLevel + ThinLTO.ModuleMap.size();
-}
-
-Error LTO::run(AddStreamFn AddStream) {
-  // Invoke regular LTO if there was a regular LTO module to start with,
-  // or if there are any hooks that the linker may have used to add
-  // its own resolved symbols to the combined module.
-  if (RegularLTO.HasModule || Conf.PreOptModuleHook ||
-      Conf.PostInternalizeModuleHook || Conf.PostOptModuleHook ||
-      Conf.PreCodeGenModuleHook)
-    if (auto E = runRegularLTO(AddStream))
-      return E;
-  return runThinLTO(AddStream);
-}
-
-Error LTO::runRegularLTO(AddStreamFn AddStream) {
-  if (Conf.PreOptModuleHook &&
-      !Conf.PreOptModuleHook(0, *RegularLTO.CombinedModule))
-    return Error();
-
-  for (const auto &R : GlobalResolutions) {
-    if (R.second.IRName.empty())
-      continue;
-    if (R.second.Partition != 0 &&
-        R.second.Partition != GlobalResolution::External)
-      continue;
-
-    GlobalValue *GV = RegularLTO.CombinedModule->getNamedValue(R.second.IRName);
-    // Ignore symbols defined in other partitions.
-    if (!GV || GV->hasLocalLinkage())
-      continue;
-    GV->setUnnamedAddr(R.second.UnnamedAddr ? GlobalValue::UnnamedAddr::Global
-                                            : GlobalValue::UnnamedAddr::None);
-    if (R.second.Partition == 0)
-      GV->setLinkage(GlobalValue::InternalLinkage);
-  }
-
-  if (Conf.PostInternalizeModuleHook &&
-      !Conf.PostInternalizeModuleHook(0, *RegularLTO.CombinedModule))
-    return Error();
-
-  return backend(Conf, AddStream, RegularLTO.ParallelCodeGenParallelismLevel,
-                 std::move(RegularLTO.CombinedModule));
-}
-
-/// This class defines the interface to the ThinLTO backend.
-class lto::ThinBackendProc {
-protected:
-  Config &Conf;
-  ModuleSummaryIndex &CombinedIndex;
-  AddStreamFn AddStream;
-  StringMap<GVSummaryMapTy> &ModuleToDefinedGVSummaries;
-
-public:
-  ThinBackendProc(Config &Conf, ModuleSummaryIndex &CombinedIndex,
-                  AddStreamFn AddStream,
-                  StringMap<GVSummaryMapTy> &ModuleToDefinedGVSummaries)
-      : Conf(Conf), CombinedIndex(CombinedIndex), AddStream(AddStream),
-        ModuleToDefinedGVSummaries(ModuleToDefinedGVSummaries) {}
-
-  virtual ~ThinBackendProc() {}
-  virtual Error start(size_t Task, MemoryBufferRef MBRef,
-                      StringMap<FunctionImporter::ImportMapTy> &ImportLists,
-                      MapVector<StringRef, MemoryBufferRef> &ModuleMap) = 0;
-  virtual Error wait() = 0;
-};
-
-class InProcessThinBackend : public ThinBackendProc {
-  ThreadPool BackendThreadPool;
-
-  Optional<Error> Err;
-  std::mutex ErrMu;
-
-public:
-  InProcessThinBackend(Config &Conf, ModuleSummaryIndex &CombinedIndex,
-                       unsigned ThinLTOParallelismLevel,
-                       StringMap<GVSummaryMapTy> &ModuleToDefinedGVSummaries,
-                       AddStreamFn AddStream)
-      : ThinBackendProc(Conf, CombinedIndex, AddStream,
-                        ModuleToDefinedGVSummaries),
-        BackendThreadPool(ThinLTOParallelismLevel) {}
-
-  Error
-  runThinLTOBackendThread(AddStreamFn AddStream, size_t Task,
-                          MemoryBufferRef MBRef,
-                          ModuleSummaryIndex &CombinedIndex,
-                          const FunctionImporter::ImportMapTy &ImportList,
-                          const GVSummaryMapTy &DefinedGlobals,
-                          MapVector<StringRef, MemoryBufferRef> &ModuleMap) {
-    LLVMContext BackendContext;
-
-    ErrorOr<std::unique_ptr<Module>> MOrErr =
-        parseBitcodeFile(MBRef, BackendContext);
-    assert(MOrErr && "Unable to load module in thread?");
-
-    return thinBackend(Conf, Task, AddStream, **MOrErr, CombinedIndex,
-                       ImportList, DefinedGlobals, ModuleMap);
-  }
-
-  Error start(size_t Task, MemoryBufferRef MBRef,
-              StringMap<FunctionImporter::ImportMapTy> &ImportLists,
-              MapVector<StringRef, MemoryBufferRef> &ModuleMap) override {
-    StringRef ModulePath = MBRef.getBufferIdentifier();
-    BackendThreadPool.async(
-        [=](MemoryBufferRef MBRef, ModuleSummaryIndex &CombinedIndex,
-            const FunctionImporter::ImportMapTy &ImportList,
-            GVSummaryMapTy &DefinedGlobals,
-            MapVector<StringRef, MemoryBufferRef> &ModuleMap) {
-          Error E =
-              runThinLTOBackendThread(AddStream, Task, MBRef, CombinedIndex,
-                                      ImportList, DefinedGlobals, ModuleMap);
-          if (E) {
-            std::unique_lock<std::mutex> L(ErrMu);
-            if (Err)
-              Err = joinErrors(std::move(*Err), std::move(E));
-            else
-              Err = std::move(E);
-          }
-        },
-        MBRef, std::ref(CombinedIndex), std::ref(ImportLists[ModulePath]),
-        std::ref(ModuleToDefinedGVSummaries[ModulePath]), std::ref(ModuleMap));
-    return Error();
-  }
-
-  Error wait() override {
-    BackendThreadPool.wait();
-    if (Err)
-      return std::move(*Err);
-    else
-      return Error();
-  }
-};
-
-ThinBackend lto::createInProcessThinBackend(unsigned ParallelismLevel) {
-  return [=](Config &Conf, ModuleSummaryIndex &CombinedIndex,
-             StringMap<GVSummaryMapTy> &ModuleToDefinedGVSummaries,
-             AddStreamFn AddStream) {
-    return make_unique<InProcessThinBackend>(
-        Conf, CombinedIndex, ParallelismLevel, ModuleToDefinedGVSummaries,
-        AddStream);
-  };
-}
-
-class WriteIndexesThinBackend : public ThinBackendProc {
-  std::string OldPrefix, NewPrefix;
-  bool ShouldEmitImportsFiles;
-
-  std::string LinkedObjectsFileName;
-  std::unique_ptr<llvm::raw_fd_ostream> LinkedObjectsFile;
-
-public:
-  WriteIndexesThinBackend(Config &Conf, ModuleSummaryIndex &CombinedIndex,
-                          StringMap<GVSummaryMapTy> &ModuleToDefinedGVSummaries,
-                          AddStreamFn AddStream, std::string OldPrefix,
-                          std::string NewPrefix, bool ShouldEmitImportsFiles,
-                          std::string LinkedObjectsFileName)
-      : ThinBackendProc(Conf, CombinedIndex, AddStream,
-                        ModuleToDefinedGVSummaries),
-        OldPrefix(OldPrefix), NewPrefix(NewPrefix),
-        ShouldEmitImportsFiles(ShouldEmitImportsFiles),
-        LinkedObjectsFileName(LinkedObjectsFileName) {}
-
-  /// Given the original \p Path to an output file, replace any path
-  /// prefix matching \p OldPrefix with \p NewPrefix. Also, create the
-  /// resulting directory if it does not yet exist.
-  std::string getThinLTOOutputFile(const std::string &Path,
-                                   const std::string &OldPrefix,
-                                   const std::string &NewPrefix) {
-    if (OldPrefix.empty() && NewPrefix.empty())
-      return Path;
-    SmallString<128> NewPath(Path);
-    llvm::sys::path::replace_path_prefix(NewPath, OldPrefix, NewPrefix);
-    StringRef ParentPath = llvm::sys::path::parent_path(NewPath.str());
-    if (!ParentPath.empty()) {
-      // Make sure the new directory exists, creating it if necessary.
-      if (std::error_code EC = llvm::sys::fs::create_directories(ParentPath))
-        llvm::errs() << "warning: could not create directory '" << ParentPath
-                     << "': " << EC.message() << '\n';
-    }
-    return NewPath.str();
-  }
-
-  Error start(size_t Task, MemoryBufferRef MBRef,
-              StringMap<FunctionImporter::ImportMapTy> &ImportLists,
-              MapVector<StringRef, MemoryBufferRef> &ModuleMap) override {
-    StringRef ModulePath = MBRef.getBufferIdentifier();
-    std::string NewModulePath =
-        getThinLTOOutputFile(ModulePath, OldPrefix, NewPrefix);
-
-    std::error_code EC;
-    if (!LinkedObjectsFileName.empty()) {
-      if (!LinkedObjectsFile) {
-        LinkedObjectsFile = make_unique<raw_fd_ostream>(
-            LinkedObjectsFileName, EC, sys::fs::OpenFlags::F_None);
-        if (EC)
-          return errorCodeToError(EC);
-      }
-      *LinkedObjectsFile << NewModulePath << '\n';
-    }
-
-    std::map<std::string, GVSummaryMapTy> ModuleToSummariesForIndex;
-    gatherImportedSummariesForModule(ModulePath, ModuleToDefinedGVSummaries,
-                                     ImportLists, ModuleToSummariesForIndex);
-
-    raw_fd_ostream OS(NewModulePath + ".thinlto.bc", EC,
-                      sys::fs::OpenFlags::F_None);
-    if (EC)
-      return errorCodeToError(EC);
-    WriteIndexToFile(CombinedIndex, OS, &ModuleToSummariesForIndex);
-
-    if (ShouldEmitImportsFiles)
-      return errorCodeToError(EmitImportsFiles(
-          ModulePath, NewModulePath + ".imports", ImportLists));
-    return Error();
-  }
-
-  Error wait() override { return Error(); }
-};
-
-ThinBackend lto::createWriteIndexesThinBackend(std::string OldPrefix,
-                                               std::string NewPrefix,
-                                               bool ShouldEmitImportsFiles,
-                                               std::string LinkedObjectsFile) {
-  return [=](Config &Conf, ModuleSummaryIndex &CombinedIndex,
-             StringMap<GVSummaryMapTy> &ModuleToDefinedGVSummaries,
-             AddStreamFn AddStream) {
-    return make_unique<WriteIndexesThinBackend>(
-        Conf, CombinedIndex, ModuleToDefinedGVSummaries, AddStream, OldPrefix,
-        NewPrefix, ShouldEmitImportsFiles, LinkedObjectsFile);
-  };
-}
-
-Error LTO::runThinLTO(AddStreamFn AddStream) {
-  if (ThinLTO.ModuleMap.empty())
-    return Error();
-
-  if (Conf.CombinedIndexHook && !Conf.CombinedIndexHook(ThinLTO.CombinedIndex))
-    return Error();
-
-  // Collect for each module the list of function it defines (GUID ->
-  // Summary).
-  StringMap<std::map<GlobalValue::GUID, GlobalValueSummary *>>
-      ModuleToDefinedGVSummaries(ThinLTO.ModuleMap.size());
-  ThinLTO.CombinedIndex.collectDefinedGVSummariesPerModule(
-      ModuleToDefinedGVSummaries);
-
-  StringMap<FunctionImporter::ImportMapTy> ImportLists(
-      ThinLTO.ModuleMap.size());
-  StringMap<FunctionImporter::ExportSetTy> ExportLists(
-      ThinLTO.ModuleMap.size());
-  ComputeCrossModuleImport(ThinLTO.CombinedIndex, ModuleToDefinedGVSummaries,
-                           ImportLists, ExportLists);
-
-  std::set<GlobalValue::GUID> ExportedGUIDs;
-  for (auto &Res : GlobalResolutions) {
-    if (!Res.second.IRName.empty() &&
-        Res.second.Partition == GlobalResolution::External)
-      ExportedGUIDs.insert(GlobalValue::getGUID(Res.second.IRName));
-  }
-
-  auto isPrevailing = [&](GlobalValue::GUID GUID, const GlobalValueSummary *S) {
-    return ThinLTO.PrevailingModuleForGUID[GUID] == S->modulePath();
-  };
-  auto isExported = [&](StringRef ModuleIdentifier, GlobalValue::GUID GUID) {
-    const auto &ExportList = ExportLists.find(ModuleIdentifier);
-    return (ExportList != ExportLists.end() &&
-            ExportList->second.count(GUID)) ||
-           ExportedGUIDs.count(GUID);
-  };
-  thinLTOInternalizeAndPromoteInIndex(ThinLTO.CombinedIndex, isExported);
-  thinLTOResolveWeakForLinkerInIndex(
-      ThinLTO.CombinedIndex, isPrevailing,
-      [](StringRef, GlobalValue::GUID, GlobalValue::LinkageTypes) {});
-
-  std::unique_ptr<ThinBackendProc> BackendProc = ThinLTO.Backend(
-      Conf, ThinLTO.CombinedIndex, ModuleToDefinedGVSummaries, AddStream);
-
-  // Partition numbers for ThinLTO jobs start at 1 (see comments for
-  // GlobalResolution in LTO.h). Task numbers, however, start at
-  // ParallelCodeGenParallelismLevel, as tasks 0 through
-  // ParallelCodeGenParallelismLevel-1 are reserved for parallel code generation
-  // partitions.
-  size_t Task = RegularLTO.ParallelCodeGenParallelismLevel;
-  size_t Partition = 1;
-
-  for (auto &Mod : ThinLTO.ModuleMap) {
-    if (Error E = BackendProc->start(Task, Mod.second, ImportLists,
-                                     ThinLTO.ModuleMap))
-      return E;
-
-    ++Task;
-    ++Partition;
-  }
-
-  return BackendProc->wait();
 }

Removed: llvm/trunk/lib/LTO/LTOBackend.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/LTO/LTOBackend.cpp?rev=278330&view=auto
==============================================================================
--- llvm/trunk/lib/LTO/LTOBackend.cpp (original)
+++ llvm/trunk/lib/LTO/LTOBackend.cpp (removed)
@@ -1,277 +0,0 @@
-//===-LTOBackend.cpp - LLVM Link Time Optimizer Backend -------------------===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the "backend" phase of LTO, i.e. it performs
-// optimization and code generation on a loaded module. It is generally used
-// internally by the LTO class but can also be used independently, for example
-// to implement a standalone ThinLTO backend.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/LTO/LTOBackend.h"
-#include "llvm/Analysis/TargetLibraryInfo.h"
-#include "llvm/Analysis/TargetTransformInfo.h"
-#include "llvm/Bitcode/ReaderWriter.h"
-#include "llvm/IR/LegacyPassManager.h"
-#include "llvm/MC/SubtargetFeature.h"
-#include "llvm/Support/Error.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/TargetRegistry.h"
-#include "llvm/Support/ThreadPool.h"
-#include "llvm/Target/TargetMachine.h"
-#include "llvm/Transforms/IPO.h"
-#include "llvm/Transforms/IPO/PassManagerBuilder.h"
-#include "llvm/Transforms/Utils/FunctionImportUtils.h"
-#include "llvm/Transforms/Utils/SplitModule.h"
-
-using namespace llvm;
-using namespace lto;
-
-Error Config::addSaveTemps(std::string OutputFileName) {
-  ShouldDiscardValueNames = false;
-
-  std::error_code EC;
-  ResolutionFile = make_unique<raw_fd_ostream>(
-      OutputFileName + ".resolution.txt", EC, sys::fs::OpenFlags::F_Text);
-  if (EC)
-    return errorCodeToError(EC);
-
-  auto setHook = [&](std::string PathSuffix, ModuleHookFn &Hook) {
-    // Keep track of the hook provided by the linker, which also needs to run.
-    ModuleHookFn LinkerHook = Hook;
-    Hook = [=](size_t Task, Module &M) {
-      // If the linker's hook returned false, we need to pass that result
-      // through.
-      if (LinkerHook && !LinkerHook(Task, M))
-        return false;
-
-      std::string PathPrefix;
-      PathPrefix = OutputFileName;
-      if (Task != 0)
-        PathPrefix += "." + utostr(Task);
-      std::string Path = PathPrefix + "." + PathSuffix + ".bc";
-      std::error_code EC;
-      raw_fd_ostream OS(Path, EC, sys::fs::OpenFlags::F_None);
-      if (EC) {
-        // Because -save-temps is a debugging feature, we report the error
-        // directly and exit.
-        llvm::errs() << "failed to open " << Path << ": " << EC.message()
-                     << '\n';
-        exit(1);
-      }
-      WriteBitcodeToFile(&M, OS, /*ShouldPreserveUseListOrder=*/false);
-      return true;
-    };
-  };
-
-  setHook("0.preopt", PreOptModuleHook);
-  setHook("1.promote", PostPromoteModuleHook);
-  setHook("2.internalize", PostInternalizeModuleHook);
-  setHook("3.import", PostImportModuleHook);
-  setHook("4.opt", PostOptModuleHook);
-  setHook("5.precodegen", PreCodeGenModuleHook);
-
-  CombinedIndexHook = [=](const ModuleSummaryIndex &Index) {
-    std::string Path = OutputFileName + ".index.bc";
-    std::error_code EC;
-    raw_fd_ostream OS(Path, EC, sys::fs::OpenFlags::F_None);
-    if (EC) {
-      // Because -save-temps is a debugging feature, we report the error
-      // directly and exit.
-      llvm::errs() << "failed to open " << Path << ": " << EC.message() << '\n';
-      exit(1);
-    }
-    WriteIndexToFile(Index, OS);
-    return true;
-  };
-
-  return Error();
-}
-
-namespace {
-
-std::unique_ptr<TargetMachine>
-createTargetMachine(Config &C, StringRef TheTriple, const Target *TheTarget) {
-  SubtargetFeatures Features;
-  Features.getDefaultSubtargetFeatures(Triple(TheTriple));
-  for (const std::string &A : C.MAttrs)
-    Features.AddFeature(A);
-
-  return std::unique_ptr<TargetMachine>(TheTarget->createTargetMachine(
-      TheTriple, C.CPU, Features.getString(), C.Options, C.RelocModel,
-      C.CodeModel, C.CGOptLevel));
-}
-
-bool opt(Config &C, TargetMachine *TM, size_t Task, Module &M, bool IsThinLto) {
-  M.setDataLayout(TM->createDataLayout());
-
-  legacy::PassManager passes;
-  passes.add(createTargetTransformInfoWrapperPass(TM->getTargetIRAnalysis()));
-
-  PassManagerBuilder PMB;
-  PMB.LibraryInfo = new TargetLibraryInfoImpl(Triple(TM->getTargetTriple()));
-  PMB.Inliner = createFunctionInliningPass();
-  // Unconditionally verify input since it is not verified before this
-  // point and has unknown origin.
-  PMB.VerifyInput = true;
-  PMB.VerifyOutput = !C.DisableVerify;
-  PMB.LoopVectorize = true;
-  PMB.SLPVectorize = true;
-  PMB.OptLevel = C.OptLevel;
-  if (IsThinLto)
-    PMB.populateThinLTOPassManager(passes);
-  else
-    PMB.populateLTOPassManager(passes);
-  passes.run(M);
-
-  if (C.PostOptModuleHook && !C.PostOptModuleHook(Task, M))
-    return false;
-
-  return true;
-}
-
-void codegen(Config &C, TargetMachine *TM, AddStreamFn AddStream, size_t Task,
-             Module &M) {
-  if (C.PreCodeGenModuleHook && !C.PreCodeGenModuleHook(Task, M))
-    return;
-
-  std::unique_ptr<raw_pwrite_stream> OS = AddStream(Task);
-  legacy::PassManager CodeGenPasses;
-  if (TM->addPassesToEmitFile(CodeGenPasses, *OS,
-                              TargetMachine::CGFT_ObjectFile))
-    report_fatal_error("Failed to setup codegen");
-  CodeGenPasses.run(M);
-}
-
-void splitCodeGen(Config &C, TargetMachine *TM, AddStreamFn AddStream,
-                  unsigned ParallelCodeGenParallelismLevel,
-                  std::unique_ptr<Module> M) {
-  ThreadPool CodegenThreadPool(ParallelCodeGenParallelismLevel);
-  unsigned ThreadCount = 0;
-  const Target *T = &TM->getTarget();
-
-  SplitModule(
-      std::move(M), ParallelCodeGenParallelismLevel,
-      [&](std::unique_ptr<Module> MPart) {
-        // We want to clone the module in a new context to multi-thread the
-        // codegen. We do it by serializing partition modules to bitcode
-        // (while still on the main thread, in order to avoid data races) and
-        // spinning up new threads which deserialize the partitions into
-        // separate contexts.
-        // FIXME: Provide a more direct way to do this in LLVM.
-        SmallString<0> BC;
-        raw_svector_ostream BCOS(BC);
-        WriteBitcodeToFile(MPart.get(), BCOS);
-
-        // Enqueue the task
-        CodegenThreadPool.async(
-            [&](const SmallString<0> &BC, unsigned ThreadId) {
-              LTOLLVMContext Ctx(C);
-              ErrorOr<std::unique_ptr<Module>> MOrErr = parseBitcodeFile(
-                  MemoryBufferRef(StringRef(BC.data(), BC.size()), "ld-temp.o"),
-                  Ctx);
-              if (!MOrErr)
-                report_fatal_error("Failed to read bitcode");
-              std::unique_ptr<Module> MPartInCtx = std::move(MOrErr.get());
-
-              std::unique_ptr<TargetMachine> TM =
-                  createTargetMachine(C, MPartInCtx->getTargetTriple(), T);
-              codegen(C, TM.get(), AddStream, ThreadId, *MPartInCtx);
-            },
-            // Pass BC using std::move to ensure that it get moved rather than
-            // copied into the thread's context.
-            std::move(BC), ThreadCount++);
-      },
-      false);
-}
-
-Expected<const Target *> initAndLookupTarget(Config &C, Module &M) {
-  if (!C.OverrideTriple.empty())
-    M.setTargetTriple(C.OverrideTriple);
-  else if (M.getTargetTriple().empty())
-    M.setTargetTriple(C.DefaultTriple);
-
-  std::string Msg;
-  const Target *T = TargetRegistry::lookupTarget(M.getTargetTriple(), Msg);
-  if (!T)
-    return make_error<StringError>(Msg, inconvertibleErrorCode());
-  return T;
-}
-
-}
-
-Error lto::backend(Config &C, AddStreamFn AddStream,
-                   unsigned ParallelCodeGenParallelismLevel,
-                   std::unique_ptr<Module> M) {
-  Expected<const Target *> TOrErr = initAndLookupTarget(C, *M);
-  if (!TOrErr)
-    return TOrErr.takeError();
-
-  std::unique_ptr<TargetMachine> TM =
-      createTargetMachine(C, M->getTargetTriple(), *TOrErr);
-
-  if (!opt(C, TM.get(), 0, *M, /*IsThinLto=*/false))
-    return Error();
-
-  if (ParallelCodeGenParallelismLevel == 1)
-    codegen(C, TM.get(), AddStream, 0, *M);
-  else
-    splitCodeGen(C, TM.get(), AddStream, ParallelCodeGenParallelismLevel,
-                 std::move(M));
-  return Error();
-}
-
-Error lto::thinBackend(Config &C, size_t Task, AddStreamFn AddStream, Module &M,
-                       ModuleSummaryIndex &CombinedIndex,
-                       const FunctionImporter::ImportMapTy &ImportList,
-                       const GVSummaryMapTy &DefinedGlobals,
-                       MapVector<StringRef, MemoryBufferRef> &ModuleMap) {
-  Expected<const Target *> TOrErr = initAndLookupTarget(C, M);
-  if (!TOrErr)
-    return TOrErr.takeError();
-
-  std::unique_ptr<TargetMachine> TM =
-      createTargetMachine(C, M.getTargetTriple(), *TOrErr);
-
-  if (C.PreOptModuleHook && !C.PreOptModuleHook(Task, M))
-    return Error();
-
-  thinLTOResolveWeakForLinkerModule(M, DefinedGlobals);
-
-  renameModuleForThinLTO(M, CombinedIndex);
-
-  if (C.PostPromoteModuleHook && !C.PostPromoteModuleHook(Task, M))
-    return Error();
-
-  if (!DefinedGlobals.empty())
-    thinLTOInternalizeModule(M, DefinedGlobals);
-
-  if (C.PostInternalizeModuleHook && !C.PostInternalizeModuleHook(Task, M))
-    return Error();
-
-  auto ModuleLoader = [&](StringRef Identifier) {
-    return std::move(getLazyBitcodeModule(MemoryBuffer::getMemBuffer(
-                                              ModuleMap[Identifier], false),
-                                          M.getContext(),
-                                          /*ShouldLazyLoadMetadata=*/true)
-                         .get());
-  };
-
-  FunctionImporter Importer(CombinedIndex, ModuleLoader);
-  Importer.importFunctions(M, ImportList);
-
-  if (C.PostImportModuleHook && !C.PostImportModuleHook(Task, M))
-    return Error();
-
-  if (!opt(C, TM.get(), Task, M, /*IsThinLto=*/true))
-    return Error();
-
-  codegen(C, TM.get(), AddStream, Task, M);
-  return Error();
-}

Modified: llvm/trunk/lib/Object/IRObjectFile.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Object/IRObjectFile.cpp?rev=278331&r1=278330&r2=278331&view=diff
==============================================================================
--- llvm/trunk/lib/Object/IRObjectFile.cpp (original)
+++ llvm/trunk/lib/Object/IRObjectFile.cpp Thu Aug 11 08:03:56 2016
@@ -324,5 +324,5 @@ llvm::object::IRObjectFile::create(Memor
     return EC;
 
   std::unique_ptr<Module> &M = MOrErr.get();
-  return llvm::make_unique<IRObjectFile>(BCOrErr.get(), std::move(M));
+  return llvm::make_unique<IRObjectFile>(Object, std::move(M));
 }

Modified: llvm/trunk/test/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CMakeLists.txt?rev=278331&r1=278330&r2=278331&view=diff
==============================================================================
--- llvm/trunk/test/CMakeLists.txt (original)
+++ llvm/trunk/test/CMakeLists.txt Thu Aug 11 08:03:56 2016
@@ -43,7 +43,6 @@ set(LLVM_TEST_DEPENDS
           llvm-extract
           llvm-lib
           llvm-link
-          llvm-lto2
           llvm-mc
           llvm-mcmarkup
           llvm-nm

Removed: llvm/trunk/test/LTO/Resolution/X86/Inputs/alias-1.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/LTO/Resolution/X86/Inputs/alias-1.ll?rev=278330&view=auto
==============================================================================
--- llvm/trunk/test/LTO/Resolution/X86/Inputs/alias-1.ll (original)
+++ llvm/trunk/test/LTO/Resolution/X86/Inputs/alias-1.ll (removed)
@@ -1,4 +0,0 @@
-target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
-target triple = "x86_64-unknown-linux-gnu"
-
- at a = global i32 42

Removed: llvm/trunk/test/LTO/Resolution/X86/Inputs/comdat.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/LTO/Resolution/X86/Inputs/comdat.ll?rev=278330&view=auto
==============================================================================
--- llvm/trunk/test/LTO/Resolution/X86/Inputs/comdat.ll (original)
+++ llvm/trunk/test/LTO/Resolution/X86/Inputs/comdat.ll (removed)
@@ -1,28 +0,0 @@
-target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
-target triple = "x86_64-unknown-linux-gnu"
-
-$c2 = comdat any
-$c1 = comdat any
-
-; This is only present in this file. The linker will keep $c1 from the first
-; file and this will be undefined.
- at will_be_undefined = global i32 1, comdat($c1)
-
- at v1 = weak_odr global i32 41, comdat($c2)
-define weak_odr protected i32 @f1(i8* %this) comdat($c2) {
-bb20:
-  store i8* %this, i8** null
-  br label %bb21
-bb21:
-  ret i32 41
-}
-
- at r21 = global i32* @v1
- at r22 = global i32(i8*)* @f1
-
- at a21 = alias i32, i32* @v1
- at a22 = alias i16, bitcast (i32* @v1 to i16*)
-
- at a23 = alias i32(i8*), i32(i8*)* @f1
- at a24 = alias i16, bitcast (i32(i8*)* @f1 to i16*)
- at a25 = alias i16, i16* @a24

Removed: llvm/trunk/test/LTO/Resolution/X86/alias.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/LTO/Resolution/X86/alias.ll?rev=278330&view=auto
==============================================================================
--- llvm/trunk/test/LTO/Resolution/X86/alias.ll (original)
+++ llvm/trunk/test/LTO/Resolution/X86/alias.ll (removed)
@@ -1,22 +0,0 @@
-; RUN: llvm-as %s -o %t1.o
-; RUN: llvm-as %p/Inputs/alias-1.ll -o %t2.o
-; RUN: llvm-lto2 -o %t3.o %t2.o %t1.o -r %t2.o,a,px -r %t1.o,a, -r %t1.o,b,px -save-temps
-; RUN: llvm-dis < %t3.o.0.preopt.bc -o - | FileCheck %s
-; RUN: FileCheck --check-prefix=RES %s < %t3.o.resolution.txt
-
-; CHECK-NOT: alias
-; CHECK: @a = global i32 42
-; CHECK-NEXT: @b = global i32 1
-; CHECK-NOT: alias
-
-; RES: 2.o{{$}}
-; RES: {{^}}-r={{.*}}2.o,a,px{{$}}
-; RES: 1.o{{$}}
-; RES: {{^}}-r={{.*}}1.o,b,px{{$}}
-; RES: {{^}}-r={{.*}}1.o,a,{{$}}
-
-target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
-target triple = "x86_64-unknown-linux-gnu"
-
- at a = weak alias i32, i32* @b
- at b = global i32 1

Removed: llvm/trunk/test/LTO/Resolution/X86/comdat.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/LTO/Resolution/X86/comdat.ll?rev=278330&view=auto
==============================================================================
--- llvm/trunk/test/LTO/Resolution/X86/comdat.ll (original)
+++ llvm/trunk/test/LTO/Resolution/X86/comdat.ll (removed)
@@ -1,86 +0,0 @@
-; RUN: llvm-as %s -o %t.o
-; RUN: llvm-as %p/Inputs/comdat.ll -o %t2.o
-; RUN: llvm-lto2 -save-temps -o %t3.o %t.o %t2.o \
-; RUN:  -r=%t.o,f1,plx \
-; RUN:  -r=%t.o,v1,px \
-; RUN:  -r=%t.o,r11,px \
-; RUN:  -r=%t.o,r12,px \
-; RUN:  -r=%t.o,a11,px \
-; RUN:  -r=%t.o,a12,px \
-; RUN:  -r=%t.o,a13,px \
-; RUN:  -r=%t.o,a14,px \
-; RUN:  -r=%t.o,a15,px \
-; RUN:  -r=%t2.o,f1,l \
-; RUN:  -r=%t2.o,will_be_undefined, \
-; RUN:  -r=%t2.o,v1, \
-; RUN:  -r=%t2.o,r21,px \
-; RUN:  -r=%t2.o,r22,px \
-; RUN:  -r=%t2.o,a21,px \
-; RUN:  -r=%t2.o,a22,px \
-; RUN:  -r=%t2.o,a23,px \
-; RUN:  -r=%t2.o,a24,px \
-; RUN:  -r=%t2.o,a25,px
-; RUN: llvm-dis %t3.o.2.internalize.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"
-
-$c1 = comdat any
-
- at v1 = weak_odr global i32 42, comdat($c1)
-define weak_odr i32 @f1(i8*) comdat($c1) {
-bb10:
-  br label %bb11
-bb11:
-  ret i32 42
-}
-
- at r11 = global i32* @v1
- at r12 = global i32 (i8*)* @f1
-
- at a11 = alias i32, i32* @v1
- at a12 = alias i16, bitcast (i32* @v1 to i16*)
-
- at a13 = alias i32 (i8*), i32 (i8*)* @f1
- at a14 = alias i16, bitcast (i32 (i8*)* @f1 to i16*)
- at a15 = alias i16, i16* @a14
-
-; CHECK: $c1 = comdat any
-; CHECK: $c2 = comdat any
-
-; CHECK-DAG: @v1 = weak_odr global i32 42, comdat($c1)
-
-; CHECK-DAG: @r11 = global i32* @v1{{$}}
-; CHECK-DAG: @r12 = global i32 (i8*)* @f1{{$}}
-
-; CHECK-DAG: @r21 = global i32* @v1{{$}}
-; CHECK-DAG: @r22 = global i32 (i8*)* @f1{{$}}
-
-; CHECK-DAG: @v1.1 = internal global i32 41, comdat($c2)
-
-; CHECK-DAG: @a11 = alias i32, i32* @v1{{$}}
-; CHECK-DAG: @a12 = alias i16, bitcast (i32* @v1 to i16*)
-
-; CHECK-DAG: @a13 = alias i32 (i8*), i32 (i8*)* @f1{{$}}
-; CHECK-DAG: @a14 = alias i16, bitcast (i32 (i8*)* @f1 to i16*)
-
-; CHECK-DAG: @a21 = alias i32, i32* @v1.1{{$}}
-; CHECK-DAG: @a22 = alias i16, bitcast (i32* @v1.1 to i16*)
-
-; CHECK-DAG: @a23 = alias i32 (i8*), i32 (i8*)* @f1.2{{$}}
-; CHECK-DAG: @a24 = alias i16, bitcast (i32 (i8*)* @f1.2 to i16*)
-
-; CHECK:      define weak_odr i32 @f1(i8*) comdat($c1) {
-; CHECK-NEXT: bb10:
-; CHECK-NEXT:   br label %bb11{{$}}
-; CHECK:      bb11:
-; CHECK-NEXT:   ret i32 42
-; CHECK-NEXT: }
-
-; CHECK:      define internal i32 @f1.2(i8* %this) comdat($c2) {
-; CHECK-NEXT: bb20:
-; CHECK-NEXT:   store i8* %this, i8** null
-; CHECK-NEXT:   br label %bb21
-; CHECK:      bb21:
-; CHECK-NEXT:   ret i32 41
-; CHECK-NEXT: }

Removed: llvm/trunk/test/LTO/Resolution/X86/lit.local.cfg
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/LTO/Resolution/X86/lit.local.cfg?rev=278330&view=auto
==============================================================================
--- llvm/trunk/test/LTO/Resolution/X86/lit.local.cfg (original)
+++ llvm/trunk/test/LTO/Resolution/X86/lit.local.cfg (removed)
@@ -1,2 +0,0 @@
-if not 'X86' in config.root.targets:
-  config.unsupported = True

Modified: llvm/trunk/test/lit.cfg
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/lit.cfg?rev=278331&r1=278330&r2=278331&view=diff
==============================================================================
--- llvm/trunk/test/lit.cfg (original)
+++ llvm/trunk/test/lit.cfg Thu Aug 11 08:03:56 2016
@@ -295,7 +295,6 @@ for pattern in [r"\bbugpoint\b(?!-)",
                 r"\bllvm-lib\b",
                 r"\bllvm-link\b",
                 r"\bllvm-lto\b",
-                r"\bllvm-lto2\b",
                 r"\bllvm-mc\b",
                 r"\bllvm-mcmarkup\b",
                 r"\bllvm-nm\b",

Modified: llvm/trunk/test/tools/gold/X86/coff.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/gold/X86/coff.ll?rev=278331&r1=278330&r2=278331&view=diff
==============================================================================
--- llvm/trunk/test/tools/gold/X86/coff.ll (original)
+++ llvm/trunk/test/tools/gold/X86/coff.ll Thu Aug 11 08:03:56 2016
@@ -16,7 +16,7 @@ define hidden void @g() {
   ret void
 }
 
-; CHECK: define internal void @h() {
+; CHECK: define internal void @h() local_unnamed_addr {
 define linkonce_odr void @h() local_unnamed_addr {
   ret void
 }

Modified: llvm/trunk/test/tools/gold/X86/comdat.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/gold/X86/comdat.ll?rev=278331&r1=278330&r2=278331&view=diff
==============================================================================
--- llvm/trunk/test/tools/gold/X86/comdat.ll (original)
+++ llvm/trunk/test/tools/gold/X86/comdat.ll Thu Aug 11 08:03:56 2016
@@ -1,9 +1,8 @@
-; RUN: llvm-as %s -o %t1.o
+; RUN: llvm-as %s -o %t.o
 ; RUN: llvm-as %p/Inputs/comdat.ll -o %t2.o
-; RUN: %gold -shared -o %t3.o -plugin %llvmshlibdir/LLVMgold.so %t1.o %t2.o \
+; RUN: %gold -shared -o %t3.o -plugin %llvmshlibdir/LLVMgold.so %t.o %t2.o \
 ; RUN:  -plugin-opt=save-temps
-; RUN: FileCheck --check-prefix=RES %s < %t3.o.resolution.txt
-; RUN: llvm-readobj -t %t3.o | FileCheck --check-prefix=OBJ %s
+; RUN: llvm-dis %t3.o.bc -o - | FileCheck %s
 
 $c1 = comdat any
 
@@ -25,37 +24,42 @@ bb11:
 @a14 = alias i16, bitcast (i32 (i8*)* @f1 to i16*)
 @a15 = alias i16, i16* @a14
 
-; gold's resolutions should tell us that our $c1 wins, and the other input's $c2
-; wins. f1 is also local due to having protected visibility in the other object.
+; CHECK: $c1 = comdat any
+; CHECK: $c2 = comdat any
 
-; RES: 1.o,f1,plx{{$}}
-; RES: 1.o,v1,px{{$}}
-; RES: 1.o,r11,px{{$}}
-; RES: 1.o,r12,px{{$}}
-; RES: 1.o,a11,px{{$}}
-; RES: 1.o,a12,px{{$}}
-; RES: 1.o,a13,px{{$}}
-; RES: 1.o,a14,px{{$}}
-; RES: 1.o,a15,px{{$}}
-
-; RES: 2.o,f1,l{{$}}
-; RES: 2.o,will_be_undefined,{{$}}
-; RES: 2.o,v1,{{$}}
-; RES: 2.o,r21,px{{$}}
-; RES: 2.o,r22,px{{$}}
-; RES: 2.o,a21,px{{$}}
-; RES: 2.o,a22,px{{$}}
-; RES: 2.o,a23,px{{$}}
-; RES: 2.o,a24,px{{$}}
-; RES: 2.o,a25,px{{$}}
-
-; f1's protected visibility should be reflected in the DSO.
-
-; OBJ:      Name: f1 (
-; OBJ-NEXT: Value:
-; OBJ-NEXT: Size:
-; OBJ-NEXT: Binding:
-; OBJ-NEXT: Type:
-; OBJ-NEXT: Other [
-; OBJ-NEXT:   STV_PROTECTED
-; OBJ-NEXT: ]
+; CHECK-DAG: @v1 = weak_odr global i32 42, comdat($c1)
+
+; CHECK-DAG: @r11 = global i32* @v1{{$}}
+; CHECK-DAG: @r12 = global i32 (i8*)* @f1{{$}}
+
+; CHECK-DAG: @r21 = global i32* @v1{{$}}
+; CHECK-DAG: @r22 = global i32 (i8*)* @f1{{$}}
+
+; CHECK-DAG: @v1.1 = internal global i32 41, comdat($c2)
+
+; CHECK-DAG: @a11 = alias i32, i32* @v1{{$}}
+; CHECK-DAG: @a12 = alias i16, bitcast (i32* @v1 to i16*)
+
+; CHECK-DAG: @a13 = alias i32 (i8*), i32 (i8*)* @f1{{$}}
+; CHECK-DAG: @a14 = alias i16, bitcast (i32 (i8*)* @f1 to i16*)
+
+; CHECK-DAG: @a21 = alias i32, i32* @v1.1{{$}}
+; CHECK-DAG: @a22 = alias i16, bitcast (i32* @v1.1 to i16*)
+
+; CHECK-DAG: @a23 = alias i32 (i8*), i32 (i8*)* @f1.2{{$}}
+; CHECK-DAG: @a24 = alias i16, bitcast (i32 (i8*)* @f1.2 to i16*)
+
+; CHECK:      define weak_odr protected i32 @f1(i8*) comdat($c1) {
+; CHECK-NEXT: bb10:
+; CHECK-NEXT:   br label %bb11{{$}}
+; CHECK:      bb11:
+; CHECK-NEXT:   ret i32 42
+; CHECK-NEXT: }
+
+; CHECK:      define internal i32 @f1.2(i8* %this) comdat($c2) {
+; CHECK-NEXT: bb20:
+; CHECK-NEXT:   store i8* %this, i8** null
+; CHECK-NEXT:   br label %bb21
+; CHECK:      bb21:
+; CHECK-NEXT:   ret i32 41
+; CHECK-NEXT: }

Modified: llvm/trunk/test/tools/gold/X86/common.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/gold/X86/common.ll?rev=278331&r1=278330&r2=278331&view=diff
==============================================================================
--- llvm/trunk/test/tools/gold/X86/common.ll (original)
+++ llvm/trunk/test/tools/gold/X86/common.ll Thu Aug 11 08:03:56 2016
@@ -11,7 +11,7 @@
 ; RUN: llvm-dis %t3.o -o - | FileCheck %s --check-prefix=A
 
 ; Shared library case, we merge @a as common and keep it for the symbol table.
-; A: @a = common global [4 x i8] zeroinitializer, align 8
+; A: @a = common global i32 0, align 8
 
 ; RUN: %gold -plugin %llvmshlibdir/LLVMgold.so \
 ; RUN:    --plugin-opt=emit-llvm \
@@ -19,7 +19,7 @@
 ; RUN: llvm-dis %t3.o -o - | FileCheck %s --check-prefix=B
 
 ; (i16 align 8) + (i8 align 16) = i16 align 16
-; B: @a = common global [2 x i8] zeroinitializer, align 16
+; B: @a = common global i16 0, align 16
 
 ; RUN: %gold -plugin %llvmshlibdir/LLVMgold.so \
 ; RUN:    --plugin-opt=emit-llvm \
@@ -27,7 +27,7 @@
 ; RUN: llvm-dis %t3.o -o - | FileCheck %s --check-prefix=C
 
 ; (i16 align 8) + (i8 align 1) = i16 align 8.
-; C: @a = common global [2 x i8] zeroinitializer, align 8
+; C: @a = common global i16 0, align 8
 
 ; RUN: %gold -plugin %llvmshlibdir/LLVMgold.so \
 ; RUN:    --plugin-opt=emit-llvm \
@@ -35,7 +35,7 @@
 ; RUN: llvm-dis %t3.o -o - | FileCheck --check-prefix=EXEC %s
 
 ; All IR case, we internalize a after merging.
-; EXEC: @a = internal global [4 x i8] zeroinitializer, align 8
+; EXEC: @a = internal global i32 0, align 8
 
 ; RUN: llc %p/Inputs/common.ll -o %t2native.o -filetype=obj
 ; RUN: %gold -plugin %llvmshlibdir/LLVMgold.so \
@@ -44,4 +44,4 @@
 ; RUN: llvm-dis %t3.o -o - | FileCheck --check-prefix=MIXED %s
 
 ; Mixed ELF and IR. We keep ours as common so the linker will finish the merge.
-; MIXED: @a = common global [2 x i8] zeroinitializer, align 8
+; MIXED: @a = common global i16 0, align 8

Modified: llvm/trunk/test/tools/gold/X86/emit-llvm.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/gold/X86/emit-llvm.ll?rev=278331&r1=278330&r2=278331&view=diff
==============================================================================
--- llvm/trunk/test/tools/gold/X86/emit-llvm.ll (original)
+++ llvm/trunk/test/tools/gold/X86/emit-llvm.ll Thu Aug 11 08:03:56 2016
@@ -2,16 +2,17 @@
 
 ; RUN: %gold -plugin %llvmshlibdir/LLVMgold.so \
 ; RUN:    --plugin-opt=emit-llvm \
+; RUN:    --plugin-opt=generate-api-file \
 ; RUN:    -shared %t.o -o %t2.o
 ; RUN: llvm-dis %t2.o -o - | FileCheck %s
+; RUN: FileCheck --check-prefix=API %s < %T/../apifile.txt
 
 ; RUN: %gold -plugin %llvmshlibdir/LLVMgold.so \
 ; RUN:     -m elf_x86_64 --plugin-opt=save-temps \
 ; RUN:    -shared %t.o -o %t3.o
-; RUN: FileCheck --check-prefix=RES %s < %t3.o.resolution.txt
-; RUN: llvm-dis %t3.o.2.internalize.bc -o - | FileCheck %s
-; RUN: llvm-dis %t3.o.4.opt.bc -o - | FileCheck --check-prefix=OPT %s
-; RUN: llvm-dis %t3.o.4.opt.bc -o - | FileCheck --check-prefix=OPT2 %s
+; RUN: llvm-dis %t3.o.bc -o - | FileCheck %s
+; RUN: llvm-dis %t3.o.opt.bc -o - | FileCheck --check-prefix=OPT %s
+; RUN: llvm-dis %t3.o.opt.bc -o - | FileCheck --check-prefix=OPT2 %s
 ; RUN: llvm-nm %t3.o.o | FileCheck --check-prefix=NM %s
 
 ; RUN: rm -f %t4.o
@@ -24,19 +25,19 @@
 
 target triple = "x86_64-unknown-linux-gnu"
 
-; CHECK-DAG: @g1 = weak_odr constant i32 32
+; CHECK-DAG: @g1 = linkonce_odr constant i32 32
 @g1 = linkonce_odr constant i32 32
 
-; CHECK-DAG: @g2 = internal constant i32 32
+; CHECK-DAG: @g2 = internal local_unnamed_addr constant i32 32
 @g2 = linkonce_odr local_unnamed_addr constant i32 32
 
 ; CHECK-DAG: @g3 = internal unnamed_addr constant i32 32
 @g3 = linkonce_odr unnamed_addr constant i32 32
 
-; CHECK-DAG: @g4 = weak_odr global i32 32
+; CHECK-DAG: @g4 = linkonce_odr global i32 32
 @g4 = linkonce_odr global i32 32
 
-; CHECK-DAG: @g5 = weak_odr global i32 32
+; CHECK-DAG: @g5 = linkonce_odr local_unnamed_addr global i32 32
 @g5 = linkonce_odr local_unnamed_addr global i32 32
 
 ; CHECK-DAG: @g6 = internal unnamed_addr global i32 32
@@ -74,8 +75,8 @@ define linkonce_odr void @f4() local_unn
   ret void
 }
 
-; CHECK-DAG: define weak_odr void @f5()
-; OPT-DAG: define weak_odr void @f5()
+; CHECK-DAG: define linkonce_odr void @f5()
+; OPT-DAG: define linkonce_odr void @f5()
 define linkonce_odr void @f5() {
   ret void
 }
@@ -96,21 +97,15 @@ define i32* @f8() {
   ret i32* @g8
 }
 
-; RES: .o,f1,pl{{$}}
-; RES: .o,f2,pl{{$}}
-; RES: .o,f3,px{{$}}
-; RES: .o,f4,p{{$}}
-; RES: .o,f5,px{{$}}
-; RES: .o,f6,p{{$}}
-; RES: .o,f7,px{{$}}
-; RES: .o,f8,px{{$}}
-; RES: .o,g1,px{{$}}
-; RES: .o,g2,p{{$}}
-; RES: .o,g3,p{{$}}
-; RES: .o,g4,px{{$}}
-; RES: .o,g5,px{{$}}
-; RES: .o,g6,p{{$}}
-; RES: .o,g7,{{$}}
-; RES: .o,g8,{{$}}
-; RES: .o,g9,px{{$}}
-; RES: .o,g10,px{{$}}
+; API: f1 PREVAILING_DEF_IRONLY
+; API: f2 PREVAILING_DEF_IRONLY
+; API: f3 PREVAILING_DEF_IRONLY_EXP
+; API: f4 PREVAILING_DEF_IRONLY_EXP
+; API: f5 PREVAILING_DEF_IRONLY_EXP
+; API: f6 PREVAILING_DEF_IRONLY_EXP
+; API: f7 PREVAILING_DEF_IRONLY_EXP
+; API: f8 PREVAILING_DEF_IRONLY_EXP
+; API: g7 UNDEF
+; API: g8 UNDEF
+; API: g9 PREVAILING_DEF_IRONLY_EXP
+; API: g10 PREVAILING_DEF_IRONLY_EXP

Modified: llvm/trunk/test/tools/gold/X86/opt-level.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/gold/X86/opt-level.ll?rev=278331&r1=278330&r2=278331&view=diff
==============================================================================
--- llvm/trunk/test/tools/gold/X86/opt-level.ll (original)
+++ llvm/trunk/test/tools/gold/X86/opt-level.ll Thu Aug 11 08:03:56 2016
@@ -1,13 +1,13 @@
 ; RUN: llvm-as -o %t.bc %s
 ; RUN: %gold -plugin %llvmshlibdir/LLVMgold.so -plugin-opt=save-temps \
 ; RUN:    -plugin-opt=O0 -r -o %t.o %t.bc
-; RUN: llvm-dis < %t.o.4.opt.bc -o - | FileCheck --check-prefix=CHECK-O0 %s
+; RUN: llvm-dis < %t.o.opt.bc -o - | FileCheck --check-prefix=CHECK-O0 %s
 ; RUN: %gold -plugin %llvmshlibdir/LLVMgold.so -plugin-opt=save-temps \
 ; RUN:    -plugin-opt=O1 -r -o %t.o %t.bc
-; RUN: llvm-dis < %t.o.4.opt.bc -o - | FileCheck --check-prefix=CHECK-O1 %s
+; RUN: llvm-dis < %t.o.opt.bc -o - | FileCheck --check-prefix=CHECK-O1 %s
 ; RUN: %gold -plugin %llvmshlibdir/LLVMgold.so -plugin-opt=save-temps \
 ; RUN:    -plugin-opt=O2 -r -o %t.o %t.bc
-; RUN: llvm-dis < %t.o.4.opt.bc -o - | FileCheck --check-prefix=CHECK-O2 %s
+; RUN: llvm-dis < %t.o.opt.bc -o - | FileCheck --check-prefix=CHECK-O2 %s
 
 ; CHECK-O0: define internal void @foo(
 ; CHECK-O1: define internal void @foo(

Modified: llvm/trunk/test/tools/gold/X86/parallel.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/gold/X86/parallel.ll?rev=278331&r1=278330&r2=278331&view=diff
==============================================================================
--- llvm/trunk/test/tools/gold/X86/parallel.ll (original)
+++ llvm/trunk/test/tools/gold/X86/parallel.ll Thu Aug 11 08:03:56 2016
@@ -1,8 +1,7 @@
 ; RUN: llvm-as -o %t.bc %s
-; RUN: rm -f %t.opt.bc0 %t.opt.bc1 %t.o0 %t.o1
 ; RUN: env LD_PRELOAD=%llvmshlibdir/LLVMgold.so %gold -plugin %llvmshlibdir/LLVMgold.so -u foo -u bar -plugin-opt jobs=2 -plugin-opt save-temps -m elf_x86_64 -o %t %t.bc
-; RUN: llvm-dis %t.5.precodegen.bc -o - | FileCheck --check-prefix=CHECK-BC0 %s
-; RUN: llvm-dis %t.1.5.precodegen.bc -o - | FileCheck --check-prefix=CHECK-BC1 %s
+; RUN: llvm-dis %t.opt.bc0 -o - | FileCheck --check-prefix=CHECK-BC0 %s
+; RUN: llvm-dis %t.opt.bc1 -o - | FileCheck --check-prefix=CHECK-BC1 %s
 ; RUN: llvm-nm %t.o0 | FileCheck --check-prefix=CHECK0 %s
 ; RUN: llvm-nm %t.o1 | FileCheck --check-prefix=CHECK1 %s
 

Modified: llvm/trunk/test/tools/gold/X86/slp-vectorize.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/gold/X86/slp-vectorize.ll?rev=278331&r1=278330&r2=278331&view=diff
==============================================================================
--- llvm/trunk/test/tools/gold/X86/slp-vectorize.ll (original)
+++ llvm/trunk/test/tools/gold/X86/slp-vectorize.ll Thu Aug 11 08:03:56 2016
@@ -3,7 +3,7 @@
 ; RUN: %gold -m elf_x86_64 -plugin %llvmshlibdir/LLVMgold.so \
 ; RUN:    --plugin-opt=save-temps \
 ; RUN:    -shared %t.o -o %t2.o
-; RUN: llvm-dis %t2.o.4.opt.bc -o - | FileCheck %s
+; RUN: llvm-dis %t2.o.opt.bc -o - | FileCheck %s
 
 ; test that the vectorizer is run.
 ; CHECK: fadd <4 x float>

Modified: llvm/trunk/test/tools/gold/X86/start-lib-common.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/gold/X86/start-lib-common.ll?rev=278331&r1=278330&r2=278331&view=diff
==============================================================================
--- llvm/trunk/test/tools/gold/X86/start-lib-common.ll (original)
+++ llvm/trunk/test/tools/gold/X86/start-lib-common.ll Thu Aug 11 08:03:56 2016
@@ -19,4 +19,4 @@
 
 ; Check that the common symbol is not dropped completely, which was a regression
 ; in r262676.
-; CHECK: @x = common global [4 x i8] zeroinitializer
+; CHECK: @x = common global i32 0

Modified: llvm/trunk/test/tools/gold/X86/strip_names.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/gold/X86/strip_names.ll?rev=278331&r1=278330&r2=278331&view=diff
==============================================================================
--- llvm/trunk/test/tools/gold/X86/strip_names.ll (original)
+++ llvm/trunk/test/tools/gold/X86/strip_names.ll Thu Aug 11 08:03:56 2016
@@ -3,7 +3,7 @@
 ; RUN: %gold -plugin %llvmshlibdir/LLVMgold.so \
 ; RUN:    --plugin-opt=save-temps \
 ; RUN:    -shared %t.o -o %t2.o
-; RUN: llvm-dis %t2.o.2.internalize.bc -o - | FileCheck %s
+; RUN: llvm-dis %t2.o.bc -o - | FileCheck %s
 
 ; RUN: %gold -plugin %llvmshlibdir/LLVMgold.so \
 ; RUN:    --plugin-opt=emit-llvm \

Modified: llvm/trunk/test/tools/gold/X86/thinlto.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/gold/X86/thinlto.ll?rev=278331&r1=278330&r2=278331&view=diff
==============================================================================
--- llvm/trunk/test/tools/gold/X86/thinlto.ll (original)
+++ llvm/trunk/test/tools/gold/X86/thinlto.ll Thu Aug 11 08:03:56 2016
@@ -25,23 +25,21 @@
 ; RUN: llvm-bcanalyzer -dump %t2.o.thinlto.bc | FileCheck %s --check-prefix=BACKEND2
 ; RUN: not test -e %t3
 
-; Ensure gold generates an index as well as a binary with save-temps in ThinLTO mode.
+; Ensure gold generates an index as well as a binary by default in ThinLTO mode.
 ; First force single-threaded mode
 ; RUN: %gold -plugin %llvmshlibdir/LLVMgold.so \
-; RUN:    --plugin-opt=save-temps \
 ; RUN:    --plugin-opt=thinlto \
 ; RUN:    --plugin-opt=jobs=1 \
 ; RUN:    -shared %t.o %t2.o -o %t4
-; RUN: llvm-bcanalyzer -dump %t4.index.bc | FileCheck %s --check-prefix=COMBINED
+; RUN: llvm-bcanalyzer -dump %t4.thinlto.bc | FileCheck %s --check-prefix=COMBINED
 ; RUN: llvm-nm %t4 | FileCheck %s --check-prefix=NM
 
 ; Next force multi-threaded mode
 ; RUN: %gold -plugin %llvmshlibdir/LLVMgold.so \
-; RUN:    --plugin-opt=save-temps \
 ; RUN:    --plugin-opt=thinlto \
 ; RUN:    --plugin-opt=jobs=2 \
 ; RUN:    -shared %t.o %t2.o -o %t4
-; RUN: llvm-bcanalyzer -dump %t4.index.bc | FileCheck %s --check-prefix=COMBINED
+; RUN: llvm-bcanalyzer -dump %t4.thinlto.bc | FileCheck %s --check-prefix=COMBINED
 ; RUN: llvm-nm %t4 | FileCheck %s --check-prefix=NM
 
 ; Test --plugin-opt=obj-path to ensure unique object files generated.
@@ -50,8 +48,8 @@
 ; RUN:    --plugin-opt=jobs=2 \
 ; RUN:    --plugin-opt=obj-path=%t5.o \
 ; RUN:    -shared %t.o %t2.o -o %t4
+; RUN: llvm-nm %t5.o0 | FileCheck %s --check-prefix=NM2
 ; RUN: llvm-nm %t5.o1 | FileCheck %s --check-prefix=NM2
-; RUN: llvm-nm %t5.o2 | FileCheck %s --check-prefix=NM2
 
 ; NM: T f
 ; NM2: T {{f|g}}

Modified: llvm/trunk/test/tools/gold/X86/thinlto_alias.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/gold/X86/thinlto_alias.ll?rev=278331&r1=278330&r2=278331&view=diff
==============================================================================
--- llvm/trunk/test/tools/gold/X86/thinlto_alias.ll (original)
+++ llvm/trunk/test/tools/gold/X86/thinlto_alias.ll Thu Aug 11 08:03:56 2016
@@ -14,14 +14,8 @@
 ; RUN:     --plugin-opt=save-temps \
 ; RUN:     -o %t3.o %t2.o %t.o
 ; RUN: llvm-nm %t3.o | FileCheck %s
-; RUN: llvm-dis %t.o.4.opt.bc -o - | FileCheck --check-prefix=OPT %s
-; RUN: llvm-dis %t2.o.4.opt.bc -o - | FileCheck --check-prefix=OPT2 %s
-
-; This does not currently pass because the gold plugin now uses the
-; combined summary rather than the IRMover to change the module's linkage
-; during the ThinLTO backend. The internalization step implemented by IRMover
-; for preempted symbols has not yet been implemented for the combined summary.
-; XFAIL: *
+; RUN: llvm-dis %t.o.opt.bc -o - | FileCheck --check-prefix=OPT %s
+; RUN: llvm-dis %t2.o.opt.bc -o - | FileCheck --check-prefix=OPT2 %s
 
 ; CHECK-NOT: U f
 ; OPT: define hidden void @weakfunc.llvm.0()

Modified: llvm/trunk/test/tools/gold/X86/thinlto_internalize.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/gold/X86/thinlto_internalize.ll?rev=278331&r1=278330&r2=278331&view=diff
==============================================================================
--- llvm/trunk/test/tools/gold/X86/thinlto_internalize.ll (original)
+++ llvm/trunk/test/tools/gold/X86/thinlto_internalize.ll Thu Aug 11 08:03:56 2016
@@ -6,7 +6,7 @@
 ; RUN:     --plugin-opt=-import-instr-limit=0 \
 ; RUN:     --plugin-opt=save-temps \
 ; RUN:     -o %t3.o %t2.o %t.o
-; RUN: llvm-dis %t.o.4.opt.bc -o - | FileCheck %s
+; RUN: llvm-dis %t.o.opt.bc -o - | FileCheck %s
 
 ; f() should be internalized and eliminated after inlining
 ; CHECK-NOT: @f()

Modified: llvm/trunk/test/tools/gold/X86/thinlto_linkonceresolution.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/gold/X86/thinlto_linkonceresolution.ll?rev=278331&r1=278330&r2=278331&view=diff
==============================================================================
--- llvm/trunk/test/tools/gold/X86/thinlto_linkonceresolution.ll (original)
+++ llvm/trunk/test/tools/gold/X86/thinlto_linkonceresolution.ll Thu Aug 11 08:03:56 2016
@@ -14,13 +14,13 @@
 ; RUN:     -shared \
 ; RUN:     -o %t3.o %t2.o %t.o
 ; RUN: llvm-nm %t3.o | FileCheck %s
-; RUN: llvm-dis %t.o.4.opt.bc -o - | FileCheck --check-prefix=OPT %s
-; RUN: llvm-dis %t2.o.4.opt.bc -o - | FileCheck --check-prefix=OPT2 %s
+; RUN: llvm-dis %t.o.opt.bc -o - | FileCheck --check-prefix=OPT %s
+; RUN: llvm-dis %t2.o.opt.bc -o - | FileCheck --check-prefix=OPT2 %s
 
 ; Ensure that f() is defined in resulting object file, and also
 ; confirm the weak linkage directly in the saved opt bitcode files.
 ; CHECK-NOT: U f
-; OPT-NOT: @f()
+; OPT: declare hidden void @f()
 ; OPT2: define weak_odr hidden void @f()
 
 target triple = "x86_64-unknown-linux-gnu"

Modified: llvm/trunk/test/tools/gold/X86/thinlto_weak_resolution.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/gold/X86/thinlto_weak_resolution.ll?rev=278331&r1=278330&r2=278331&view=diff
==============================================================================
--- llvm/trunk/test/tools/gold/X86/thinlto_weak_resolution.ll (original)
+++ llvm/trunk/test/tools/gold/X86/thinlto_weak_resolution.ll Thu Aug 11 08:03:56 2016
@@ -13,17 +13,12 @@
 ; RUN: llvm-nm %t3.o | FileCheck %s
 ; CHECK: weakfunc
 
-; Most of the preempted functions should have been eliminated (the plugin will
-; set linkage of odr functions to available_externally and linkonce functions
-; are removed by globaldce). FIXME: Need to introduce combined index linkage
-; that means "drop this function" so we can avoid importing linkonce functions
-; and drop weak functions.
-; RUN: llvm-dis %t2.o.4.opt.bc -o - | FileCheck --check-prefix=OPT2 %s
-; OPT2-NOT: @
-; OPT2: @weakfunc
+; All of the preempted functions should have been eliminated (the plugin will
+; not link them in).
+; RUN: llvm-dis %t2.o.opt.bc -o - | FileCheck --check-prefix=OPT2 %s
 ; OPT2-NOT: @
 
-; RUN: llvm-dis %t.o.4.opt.bc -o - | FileCheck --check-prefix=OPT %s
+; RUN: llvm-dis %t.o.opt.bc -o - | FileCheck --check-prefix=OPT %s
 
 target triple = "x86_64-unknown-linux-gnu"
 

Modified: llvm/trunk/test/tools/gold/X86/type-merge2.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/gold/X86/type-merge2.ll?rev=278331&r1=278330&r2=278331&view=diff
==============================================================================
--- llvm/trunk/test/tools/gold/X86/type-merge2.ll (original)
+++ llvm/trunk/test/tools/gold/X86/type-merge2.ll Thu Aug 11 08:03:56 2016
@@ -3,7 +3,7 @@
 ; RUN: %gold -plugin %llvmshlibdir/LLVMgold.so \
 ; RUN:    --plugin-opt=save-temps \
 ; RUN:    -shared %t.o %t2.o -o %t3.o
-; RUN: llvm-dis %t3.o.2.internalize.bc -o - | FileCheck %s
+; RUN: llvm-dis %t3.o.bc -o - | FileCheck %s
 
 %zed = type { i8 }
 define void @foo()  {

Modified: llvm/trunk/test/tools/gold/X86/vectorize.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/gold/X86/vectorize.ll?rev=278331&r1=278330&r2=278331&view=diff
==============================================================================
--- llvm/trunk/test/tools/gold/X86/vectorize.ll (original)
+++ llvm/trunk/test/tools/gold/X86/vectorize.ll Thu Aug 11 08:03:56 2016
@@ -3,7 +3,7 @@
 ; RUN: %gold -m elf_x86_64 -plugin %llvmshlibdir/LLVMgold.so \
 ; RUN:    --plugin-opt=save-temps \
 ; RUN:    -shared %t.o -o %t2.o
-; RUN: llvm-dis %t2.o.4.opt.bc -o - | FileCheck %s
+; RUN: llvm-dis %t2.o.opt.bc -o - | FileCheck %s
 
 ; test that the vectorizer is run.
 ; CHECK: fadd <4 x float>

Modified: llvm/trunk/test/tools/gold/X86/visibility.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/gold/X86/visibility.ll?rev=278331&r1=278330&r2=278331&view=diff
==============================================================================
--- llvm/trunk/test/tools/gold/X86/visibility.ll (original)
+++ llvm/trunk/test/tools/gold/X86/visibility.ll Thu Aug 11 08:03:56 2016
@@ -5,7 +5,7 @@
 ; RUN:    --plugin-opt=save-temps \
 ; RUN:    -shared %t.o %t2.o -o %t.so
 ; RUN: llvm-readobj -t %t.so | FileCheck %s
-; RUN: llvm-dis %t.so.2.internalize.bc -o - | FileCheck --check-prefix=IR %s
+; RUN: llvm-dis %t.so.bc -o - | FileCheck --check-prefix=IR %s
 
 ; CHECK:      Name: foo
 ; CHECK-NEXT: Value:
@@ -16,7 +16,7 @@
 ; CHECK-NEXT:   STV_PROTECTED
 ; CHECK-NEXT: ]
 
-; IR: define void @foo
+; IR: define protected void @foo
 
 define weak protected void @foo() {
   ret void

Removed: llvm/trunk/test/tools/llvm-lto2/errors.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-lto2/errors.ll?rev=278330&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-lto2/errors.ll (original)
+++ llvm/trunk/test/tools/llvm-lto2/errors.ll (removed)
@@ -1,11 +0,0 @@
-; RUN: llvm-as %s -o %t.bc
-; RUN: not llvm-lto2 -o %t2.o %t.bc 2>&1 | FileCheck --check-prefix=ERR1 %s
-; RUN: not llvm-lto2 -o %t2.o -r %t.bc,foo,p -r %t.bc,bar,p %t.bc 2>&1 | FileCheck --check-prefix=ERR2 %s
-; RUN: not llvm-lto2 -o %t2.o -r %t.bc,foo,q %t.bc 2>&1 | FileCheck --check-prefix=ERR3 %s
-; RUN: not llvm-lto2 -o %t2.o -r foo %t.bc 2>&1 | FileCheck --check-prefix=ERR4 %s
-
-; ERR1: missing symbol resolution for {{.*}}.bc,foo
-; ERR2: unused symbol resolution for {{.*}}.bc,bar
-; ERR3: invalid character q in resolution: {{.*}}.bc,foo
-; ERR4: invalid resolution: foo
- at foo = global i32 0

Modified: llvm/trunk/tools/gold/gold-plugin.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/gold/gold-plugin.cpp?rev=278331&r1=278330&r2=278331&view=diff
==============================================================================
--- llvm/trunk/tools/gold/gold-plugin.cpp (original)
+++ llvm/trunk/tools/gold/gold-plugin.cpp Thu Aug 11 08:03:56 2016
@@ -12,22 +12,44 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "llvm/ADT/StringSet.h"
+#include "llvm/Analysis/TargetLibraryInfo.h"
+#include "llvm/Analysis/TargetTransformInfo.h"
 #include "llvm/Bitcode/ReaderWriter.h"
+#include "llvm/CodeGen/Analysis.h"
 #include "llvm/CodeGen/CommandFlags.h"
+#include "llvm/CodeGen/ParallelCG.h"
 #include "llvm/Config/config.h" // plugin-api.h requires HAVE_STDINT_H
+#include "llvm/IR/AutoUpgrade.h"
 #include "llvm/IR/Constants.h"
+#include "llvm/IR/DiagnosticInfo.h"
 #include "llvm/IR/DiagnosticPrinter.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/LegacyPassManager.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/Verifier.h"
 #include "llvm/LTO/LTO.h"
-#include "llvm/Support/CommandLine.h"
+#include "llvm/Linker/IRMover.h"
+#include "llvm/MC/SubtargetFeature.h"
+#include "llvm/Object/IRObjectFile.h"
+#include "llvm/Object/ModuleSummaryIndexObjectFile.h"
+#include "llvm/Support/Host.h"
 #include "llvm/Support/ManagedStatic.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/Path.h"
+#include "llvm/Support/TargetRegistry.h"
 #include "llvm/Support/TargetSelect.h"
+#include "llvm/Support/ThreadPool.h"
 #include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/thread.h"
+#include "llvm/Transforms/IPO.h"
+#include "llvm/Transforms/IPO/FunctionImport.h"
+#include "llvm/Transforms/IPO/PassManagerBuilder.h"
+#include "llvm/Transforms/Utils/FunctionImportUtils.h"
+#include "llvm/Transforms/Utils/GlobalStatus.h"
+#include "llvm/Transforms/Utils/ValueMapper.h"
 #include <list>
-#include <map>
 #include <plugin-api.h>
-#include <string>
 #include <system_error>
 #include <utility>
 #include <vector>
@@ -39,7 +61,6 @@
 #define LDPT_GET_SYMBOLS_V3 28
 
 using namespace llvm;
-using namespace lto;
 
 static ld_plugin_status discard_message(int level, const char *format, ...) {
   // Die loudly. Recent versions of Gold pass ld_plugin_message as the first
@@ -85,17 +106,38 @@ struct PluginInputFile {
 };
 
 struct ResolutionInfo {
-  bool CanOmitFromDynSym = true;
-  bool DefaultVisibility = true;
+  uint64_t CommonSize = 0;
+  unsigned CommonAlign = 0;
+  bool IsLinkonceOdr = true;
+  GlobalValue::UnnamedAddr UnnamedAddr = GlobalValue::UnnamedAddr::Global;
+  GlobalValue::VisibilityTypes Visibility = GlobalValue::DefaultVisibility;
+  bool CommonInternal = false;
+  bool UseCommon = false;
 };
 
-struct CommonResolution {
-  bool Prevailing = false;
-  bool VisibleToRegularObj = false;
-  uint64_t Size = 0;
-  unsigned Align = 0;
+/// Class to own information used by a task or during its cleanup for a
+/// ThinLTO backend instantiation.
+class ThinLTOTaskInfo {
+  /// The output stream the task will codegen into.
+  std::unique_ptr<raw_fd_ostream> OS;
+
+  /// The file name corresponding to the output stream, used during cleanup.
+  std::string Filename;
+
+  /// Flag indicating whether the output file is a temp file that must be
+  /// added to the cleanup list during cleanup.
+  bool TempOutFile;
+
+public:
+  ThinLTOTaskInfo(std::unique_ptr<raw_fd_ostream> OS, std::string Filename,
+                  bool TempOutFile)
+      : OS(std::move(OS)), Filename(std::move(Filename)),
+        TempOutFile(TempOutFile) {}
+
+  /// Performs task related cleanup activities that must be done
+  /// single-threaded (i.e. call backs to gold).
+  void cleanup();
 };
-
 }
 
 static ld_plugin_add_symbols add_symbols = nullptr;
@@ -103,16 +145,14 @@ static ld_plugin_get_symbols get_symbols
 static ld_plugin_add_input_file add_input_file = nullptr;
 static ld_plugin_set_extra_library_path set_extra_library_path = nullptr;
 static ld_plugin_get_view get_view = nullptr;
-static bool IsExecutable = false;
 static Optional<Reloc::Model> RelocationModel;
 static std::string output_name = "";
 static std::list<claimed_file> Modules;
 static DenseMap<int, void *> FDToLeaderHandle;
 static StringMap<ResolutionInfo> ResInfo;
-static std::map<std::string, CommonResolution> Commons;
 static std::vector<std::string> Cleanup;
 static llvm::TargetOptions TargetOpts;
-static size_t MaxTasks;
+static std::string DefaultTriple = sys::getDefaultTargetTriple();
 
 namespace options {
   enum OutputType {
@@ -121,6 +161,7 @@ namespace options {
     OT_BC_ONLY,
     OT_SAVE_TEMPS
   };
+  static bool generate_api_file = false;
   static OutputType TheOutputType = OT_NORMAL;
   static unsigned OptLevel = 2;
   // Default parallelism of 0 used to indicate that user did not specify.
@@ -172,6 +213,8 @@ namespace options {
   // Additional options to pass into the code generator.
   // Note: This array will contain all plugin options which are not claimed
   // as plugin exclusive to pass to the code generator.
+  // For example, "generate-api-file" and "as"options are for the plugin
+  // use only and will not be passed.
   static std::vector<const char *> extra;
 
   static void process_plugin_option(const char *opt_)
@@ -180,7 +223,9 @@ namespace options {
       return;
     llvm::StringRef opt = opt_;
 
-    if (opt.startswith("mcpu=")) {
+    if (opt == "generate-api-file") {
+      generate_api_file = true;
+    } else if (opt.startswith("mcpu=")) {
       mcpu = opt.substr(strlen("mcpu="));
     } else if (opt.startswith("extra-library-path=")) {
       extra_library_path = opt.substr(strlen("extra_library_path="));
@@ -262,15 +307,10 @@ ld_plugin_status onload(ld_plugin_tv *tv
       switch (tv->tv_u.tv_val) {
       case LDPO_REL: // .o
       case LDPO_DYN: // .so
-        IsExecutable = false;
-        RelocationModel = Reloc::PIC_;
-        break;
       case LDPO_PIE: // position independent executable
-        IsExecutable = true;
         RelocationModel = Reloc::PIC_;
         break;
       case LDPO_EXEC: // .exe
-        IsExecutable = true;
         RelocationModel = Reloc::Static;
         break;
       default:
@@ -364,6 +404,20 @@ ld_plugin_status onload(ld_plugin_tv *tv
   return LDPS_OK;
 }
 
+static const GlobalObject *getBaseObject(const GlobalValue &GV) {
+  if (auto *GA = dyn_cast<GlobalAlias>(&GV))
+    return GA->getBaseObject();
+  return cast<GlobalObject>(&GV);
+}
+
+static bool shouldSkip(uint32_t Symflags) {
+  if (!(Symflags & object::BasicSymbolRef::SF_Global))
+    return true;
+  if (Symflags & object::BasicSymbolRef::SF_FormatSpecific)
+    return true;
+  return false;
+}
+
 static void diagnosticHandler(const DiagnosticInfo &DI) {
   if (const auto *BDI = dyn_cast<BitcodeDiagnosticInfo>(&DI)) {
     std::error_code EC = BDI->getError();
@@ -393,18 +447,21 @@ static void diagnosticHandler(const Diag
   message(Level, "LLVM gold plugin: %s",  ErrStorage.c_str());
 }
 
-static void check(Error E, std::string Msg = "LLVM gold plugin") {
-  handleAllErrors(std::move(E), [&](ErrorInfoBase &EIB) {
-    message(LDPL_FATAL, "%s: %s", Msg.c_str(), EIB.message().c_str());
-    return Error::success();
-  });
+static void diagnosticHandlerForContext(const DiagnosticInfo &DI,
+                                        void *Context) {
+  diagnosticHandler(DI);
 }
 
-template <typename T> static T check(Expected<T> E) {
-  if (E)
-    return std::move(*E);
-  check(E.takeError());
-  return T();
+static GlobalValue::VisibilityTypes
+getMinVisibility(GlobalValue::VisibilityTypes A,
+                 GlobalValue::VisibilityTypes B) {
+  if (A == GlobalValue::HiddenVisibility)
+    return A;
+  if (B == GlobalValue::HiddenVisibility)
+    return B;
+  if (A == GlobalValue::ProtectedVisibility)
+    return A;
+  return B;
 }
 
 /// Called by gold to see whether this file is one that our plugin can handle.
@@ -412,6 +469,7 @@ template <typename T> static T check(Exp
 /// possible.
 static ld_plugin_status claim_file_hook(const ld_plugin_input_file *file,
                                         int *claimed) {
+  LLVMContext Context;
   MemoryBufferRef BufferRef;
   std::unique_ptr<MemoryBuffer> Buffer;
   if (get_view) {
@@ -440,25 +498,22 @@ static ld_plugin_status claim_file_hook(
     BufferRef = Buffer->getMemBufferRef();
   }
 
-  *claimed = 1;
+  Context.setDiagnosticHandler(diagnosticHandlerForContext);
+  ErrorOr<std::unique_ptr<object::IRObjectFile>> ObjOrErr =
+      object::IRObjectFile::create(BufferRef, Context);
+  std::error_code EC = ObjOrErr.getError();
+  if (EC == object::object_error::invalid_file_type ||
+      EC == object::object_error::bitcode_section_not_found)
+    return LDPS_OK;
 
-  Expected<std::unique_ptr<InputFile>> ObjOrErr = InputFile::create(BufferRef);
-  if (!ObjOrErr) {
-    handleAllErrors(ObjOrErr.takeError(), [&](const ErrorInfoBase &EI) {
-      std::error_code EC = EI.convertToErrorCode();
-      if (EC == object::object_error::invalid_file_type ||
-          EC == object::object_error::bitcode_section_not_found)
-        *claimed = 0;
-      else
-        message(LDPL_ERROR,
-                "LLVM gold plugin has failed to create LTO module: %s",
-                EI.message().c_str());
-    });
+  *claimed = 1;
 
-    return *claimed ? LDPS_ERR : LDPS_OK;
+  if (EC) {
+    message(LDPL_ERROR, "LLVM gold plugin has failed to create LTO module: %s",
+            EC.message().c_str());
+    return LDPS_ERR;
   }
-
-  std::unique_ptr<InputFile> Obj = std::move(*ObjOrErr);
+  std::unique_ptr<object::IRObjectFile> Obj = std::move(*ObjOrErr);
 
   Modules.resize(Modules.size() + 1);
   claimed_file &cf = Modules.back();
@@ -480,52 +535,72 @@ static ld_plugin_status claim_file_hook(
   cf.name = file->name;
   if (file->offset)
     cf.name += ".llvm." + std::to_string(file->offset) + "." +
-               sys::path::filename(Obj->getSourceFileName()).str();
+               sys::path::filename(Obj->getModule().getSourceFileName()).str();
 
   for (auto &Sym : Obj->symbols()) {
     uint32_t Symflags = Sym.getFlags();
+    if (shouldSkip(Symflags))
+      continue;
 
     cf.syms.push_back(ld_plugin_symbol());
     ld_plugin_symbol &sym = cf.syms.back();
     sym.version = nullptr;
-    StringRef Name = Sym.getName();
-    sym.name = strdup(Name.str().c_str());
 
-    ResolutionInfo &Res = ResInfo[Name];
+    SmallString<64> Name;
+    {
+      raw_svector_ostream OS(Name);
+      Sym.printName(OS);
+    }
+    sym.name = strdup(Name.c_str());
+
+    const GlobalValue *GV = Obj->getSymbolGV(Sym.getRawDataRefImpl());
 
-    Res.CanOmitFromDynSym &= Sym.canBeOmittedFromSymbolTable();
+    ResolutionInfo &Res = ResInfo[sym.name];
 
     sym.visibility = LDPV_DEFAULT;
-    GlobalValue::VisibilityTypes Vis = Sym.getVisibility();
-    if (Vis != GlobalValue::DefaultVisibility)
-      Res.DefaultVisibility = false;
-    switch (Vis) {
-    case GlobalValue::DefaultVisibility:
-      break;
-    case GlobalValue::HiddenVisibility:
-      sym.visibility = LDPV_HIDDEN;
-      break;
-    case GlobalValue::ProtectedVisibility:
-      sym.visibility = LDPV_PROTECTED;
-      break;
+    if (GV) {
+      Res.UnnamedAddr =
+          GlobalValue::getMinUnnamedAddr(Res.UnnamedAddr, GV->getUnnamedAddr());
+      Res.IsLinkonceOdr &= GV->hasLinkOnceLinkage();
+      Res.Visibility = getMinVisibility(Res.Visibility, GV->getVisibility());
+      switch (GV->getVisibility()) {
+      case GlobalValue::DefaultVisibility:
+        break;
+      case GlobalValue::HiddenVisibility:
+        sym.visibility = LDPV_HIDDEN;
+        break;
+      case GlobalValue::ProtectedVisibility:
+        sym.visibility = LDPV_PROTECTED;
+        break;
+      }
     }
 
     if (Symflags & object::BasicSymbolRef::SF_Undefined) {
       sym.def = LDPK_UNDEF;
-      if (Symflags & object::BasicSymbolRef::SF_Weak)
+      if (GV && GV->hasExternalWeakLinkage())
         sym.def = LDPK_WEAKUNDEF;
-    } else if (Symflags & object::BasicSymbolRef::SF_Common)
-      sym.def = LDPK_COMMON;
-    else if (Symflags & object::BasicSymbolRef::SF_Weak)
-      sym.def = LDPK_WEAKDEF;
-    else
+    } else {
       sym.def = LDPK_DEF;
+      if (GV) {
+        assert(!GV->hasExternalWeakLinkage() &&
+               !GV->hasAvailableExternallyLinkage() && "Not a declaration!");
+        if (GV->hasCommonLinkage())
+          sym.def = LDPK_COMMON;
+        else if (GV->isWeakForLinker())
+          sym.def = LDPK_WEAKDEF;
+      }
+    }
 
     sym.size = 0;
     sym.comdat_key = nullptr;
-    const Comdat *C = check(Sym.getComdat());
-    if (C)
-      sym.comdat_key = strdup(C->getName().str().c_str());
+    if (GV) {
+      const GlobalObject *Base = getBaseObject(*GV);
+      if (!Base)
+        message(LDPL_FATAL, "Unable to determine comdat of alias!");
+      const Comdat *C = Base->getComdat();
+      if (C)
+        sym.comdat_key = strdup(C->getName().str().c_str());
+    }
 
     sym.resolution = LDPR_UNKNOWN;
   }
@@ -540,6 +615,39 @@ static ld_plugin_status claim_file_hook(
   return LDPS_OK;
 }
 
+static void internalize(GlobalValue &GV) {
+  if (GV.isDeclarationForLinker())
+    return; // We get here if there is a matching asm definition.
+  if (!GV.hasLocalLinkage())
+    GV.setLinkage(GlobalValue::InternalLinkage);
+}
+
+static const char *getResolutionName(ld_plugin_symbol_resolution R) {
+  switch (R) {
+  case LDPR_UNKNOWN:
+    return "UNKNOWN";
+  case LDPR_UNDEF:
+    return "UNDEF";
+  case LDPR_PREVAILING_DEF:
+    return "PREVAILING_DEF";
+  case LDPR_PREVAILING_DEF_IRONLY:
+    return "PREVAILING_DEF_IRONLY";
+  case LDPR_PREEMPTED_REG:
+    return "PREEMPTED_REG";
+  case LDPR_PREEMPTED_IR:
+    return "PREEMPTED_IR";
+  case LDPR_RESOLVED_IR:
+    return "RESOLVED_IR";
+  case LDPR_RESOLVED_EXEC:
+    return "RESOLVED_EXEC";
+  case LDPR_RESOLVED_DYN:
+    return "RESOLVED_DYN";
+  case LDPR_PREVAILING_DEF_IRONLY_EXP:
+    return "PREVAILING_DEF_IRONLY_EXP";
+  }
+  llvm_unreachable("Unknown resolution");
+}
+
 static void freeSymName(ld_plugin_symbol &Sym) {
   free(Sym.name);
   free(Sym.comdat_key);
@@ -563,27 +671,120 @@ static const void *getSymbolsAndView(cla
   return View;
 }
 
-static void addModule(LTO &Lto, claimed_file &F, const void *View) {
+static std::unique_ptr<ModuleSummaryIndex>
+getModuleSummaryIndexForFile(claimed_file &F) {
+  const void *View = getSymbolsAndView(F);
+  if (!View)
+    return nullptr;
+
   MemoryBufferRef BufferRef(StringRef((const char *)View, F.filesize), F.name);
-  Expected<std::unique_ptr<InputFile>> ObjOrErr = InputFile::create(BufferRef);
 
-  if (!ObjOrErr)
+  // Don't bother trying to build an index if there is no summary information
+  // in this bitcode file.
+  if (!object::ModuleSummaryIndexObjectFile::hasGlobalValueSummaryInMemBuffer(
+          BufferRef, diagnosticHandler))
+    return std::unique_ptr<ModuleSummaryIndex>(nullptr);
+
+  ErrorOr<std::unique_ptr<object::ModuleSummaryIndexObjectFile>> ObjOrErr =
+      object::ModuleSummaryIndexObjectFile::create(BufferRef,
+                                                   diagnosticHandler);
+
+  if (std::error_code EC = ObjOrErr.getError())
+    message(LDPL_FATAL,
+            "Could not read module summary index bitcode from file : %s",
+            EC.message().c_str());
+
+  object::ModuleSummaryIndexObjectFile &Obj = **ObjOrErr;
+
+  return Obj.takeIndex();
+}
+
+static std::unique_ptr<Module>
+getModuleForFile(LLVMContext &Context, claimed_file &F, const void *View,
+                 StringRef Name, raw_fd_ostream *ApiFile,
+                 StringSet<> &Internalize, std::vector<GlobalValue *> &Keep,
+                 StringMap<unsigned> &Realign) {
+  MemoryBufferRef BufferRef(StringRef((const char *)View, F.filesize), Name);
+  ErrorOr<std::unique_ptr<object::IRObjectFile>> ObjOrErr =
+      object::IRObjectFile::create(BufferRef, Context);
+
+  if (std::error_code EC = ObjOrErr.getError())
     message(LDPL_FATAL, "Could not read bitcode from file : %s",
-            toString(ObjOrErr.takeError()).c_str());
+            EC.message().c_str());
+
+  object::IRObjectFile &Obj = **ObjOrErr;
 
-  InputFile &Obj = **ObjOrErr;
+  Module &M = Obj.getModule();
+
+  M.materializeMetadata();
+  UpgradeDebugInfo(M);
+
+  SmallPtrSet<GlobalValue *, 8> Used;
+  collectUsedGlobalVariables(M, Used, /*CompilerUsed*/ false);
 
   unsigned SymNum = 0;
-  std::vector<SymbolResolution> Resols(F.syms.size());
   for (auto &ObjSym : Obj.symbols()) {
+    GlobalValue *GV = Obj.getSymbolGV(ObjSym.getRawDataRefImpl());
+    if (GV && GV->hasAppendingLinkage())
+      Keep.push_back(GV);
+
+    if (shouldSkip(ObjSym.getFlags()))
+      continue;
     ld_plugin_symbol &Sym = F.syms[SymNum];
-    SymbolResolution &R = Resols[SymNum];
     ++SymNum;
 
     ld_plugin_symbol_resolution Resolution =
         (ld_plugin_symbol_resolution)Sym.resolution;
 
+    if (options::generate_api_file)
+      *ApiFile << Sym.name << ' ' << getResolutionName(Resolution) << '\n';
+
+    if (!GV) {
+      freeSymName(Sym);
+      continue; // Asm symbol.
+    }
+
     ResolutionInfo &Res = ResInfo[Sym.name];
+    if (Resolution == LDPR_PREVAILING_DEF_IRONLY_EXP && !Res.IsLinkonceOdr)
+      Resolution = LDPR_PREVAILING_DEF;
+
+    GV->setUnnamedAddr(Res.UnnamedAddr);
+    GV->setVisibility(Res.Visibility);
+
+    // Override gold's resolution for common symbols. We want the largest
+    // one to win.
+    if (GV->hasCommonLinkage()) {
+      if (Resolution == LDPR_PREVAILING_DEF_IRONLY)
+        Res.CommonInternal = true;
+
+      if (Resolution == LDPR_PREVAILING_DEF_IRONLY ||
+          Resolution == LDPR_PREVAILING_DEF)
+        Res.UseCommon = true;
+
+      const DataLayout &DL = GV->getParent()->getDataLayout();
+      uint64_t Size = DL.getTypeAllocSize(GV->getType()->getElementType());
+      unsigned Align = GV->getAlignment();
+
+      if (Res.UseCommon && Size >= Res.CommonSize) {
+        // Take GV.
+        if (Res.CommonInternal)
+          Resolution = LDPR_PREVAILING_DEF_IRONLY;
+        else
+          Resolution = LDPR_PREVAILING_DEF;
+        cast<GlobalVariable>(GV)->setAlignment(
+            std::max(Res.CommonAlign, Align));
+      } else {
+        // Do not take GV, it's smaller than what we already have in the
+        // combined module.
+        Resolution = LDPR_PREEMPTED_IR;
+        if (Align > Res.CommonAlign)
+          // Need to raise the alignment though.
+          Realign[Sym.name] = Align;
+      }
+
+      Res.CommonSize = std::max(Res.CommonSize, Size);
+      Res.CommonAlign = std::max(Res.CommonAlign, Align);
+    }
 
     switch (Resolution) {
     case LDPR_UNKNOWN:
@@ -594,48 +795,57 @@ static void addModule(LTO &Lto, claimed_
     case LDPR_RESOLVED_DYN:
     case LDPR_PREEMPTED_IR:
     case LDPR_PREEMPTED_REG:
+      break;
+
     case LDPR_UNDEF:
+      if (!GV->isDeclarationForLinker())
+        assert(GV->hasComdat());
       break;
 
-    case LDPR_PREVAILING_DEF_IRONLY:
-      R.Prevailing = true;
+    case LDPR_PREVAILING_DEF_IRONLY: {
+      Keep.push_back(GV);
+      // The IR linker has to be able to map this value to a declaration,
+      // so we can only internalize after linking.
+      if (!Used.count(GV))
+        Internalize.insert(GV->getName());
       break;
+    }
 
     case LDPR_PREVAILING_DEF:
-      R.Prevailing = true;
-      R.VisibleToRegularObj = true;
+      Keep.push_back(GV);
+      // There is a non IR use, so we have to force optimizations to keep this.
+      switch (GV->getLinkage()) {
+      default:
+        break;
+      case GlobalValue::LinkOnceAnyLinkage:
+        GV->setLinkage(GlobalValue::WeakAnyLinkage);
+        break;
+      case GlobalValue::LinkOnceODRLinkage:
+        GV->setLinkage(GlobalValue::WeakODRLinkage);
+        break;
+      }
       break;
 
-    case LDPR_PREVAILING_DEF_IRONLY_EXP:
-      R.Prevailing = true;
-      if (!Res.CanOmitFromDynSym)
-        R.VisibleToRegularObj = true;
+    case LDPR_PREVAILING_DEF_IRONLY_EXP: {
+      Keep.push_back(GV);
+      if (canBeOmittedFromSymbolTable(GV))
+        Internalize.insert(GV->getName());
       break;
     }
-
-    if (Resolution != LDPR_RESOLVED_DYN && Resolution != LDPR_UNDEF &&
-        (IsExecutable || !Res.DefaultVisibility))
-      R.FinalDefinitionInLinkageUnit = true;
-
-    if (ObjSym.getFlags() & object::BasicSymbolRef::SF_Common) {
-      // We ignore gold's resolution for common symbols. A common symbol with
-      // the correct size and alignment is added to the module by the pre-opt
-      // module hook if any common symbol prevailed.
-      CommonResolution &CommonRes = Commons[ObjSym.getIRName()];
-      if (R.Prevailing) {
-        CommonRes.Prevailing = true;
-        CommonRes.VisibleToRegularObj = R.VisibleToRegularObj;
-      }
-      CommonRes.Size = std::max(CommonRes.Size, ObjSym.getCommonSize());
-      CommonRes.Align = std::max(CommonRes.Align, ObjSym.getCommonAlignment());
-      R.Prevailing = false;
     }
 
     freeSymName(Sym);
   }
 
-  check(Lto.add(std::move(*ObjOrErr), Resols),
-        std::string("Failed to link module ") + F.name);
+  return Obj.takeModule();
+}
+
+static void saveBCFile(StringRef Path, Module &M) {
+  std::error_code EC;
+  raw_fd_ostream OS(Path, EC, sys::fs::OpenFlags::F_None);
+  if (EC)
+    message(LDPL_FATAL, "Failed to write the output file.");
+  WriteBitcodeToFile(&M, OS, /* ShouldPreserveUseListOrder */ false);
 }
 
 static void recordFile(std::string Filename, bool TempOutFile) {
@@ -647,6 +857,190 @@ static void recordFile(std::string Filen
     Cleanup.push_back(Filename.c_str());
 }
 
+void ThinLTOTaskInfo::cleanup() {
+  // Close the output file descriptor before we pass it to gold.
+  OS->close();
+
+  recordFile(Filename, TempOutFile);
+}
+
+namespace {
+/// Class to manage optimization and code generation for a module, possibly
+/// in a thread (ThinLTO).
+class CodeGen {
+  /// The module for which this will generate code.
+  std::unique_ptr<llvm::Module> M;
+
+  /// The output stream to generate code into.
+  raw_fd_ostream *OS;
+
+  /// The task ID when this was invoked in a thread (ThinLTO).
+  int TaskID;
+
+  /// The module summary index for ThinLTO tasks.
+  const ModuleSummaryIndex *CombinedIndex;
+
+  /// The target machine for generating code for this module.
+  std::unique_ptr<TargetMachine> TM;
+
+  /// Filename to use as base when save-temps is enabled, used to get
+  /// a unique and identifiable save-temps output file for each ThinLTO backend.
+  std::string SaveTempsFilename;
+
+  /// Map from a module name to the corresponding buffer holding a view of the
+  /// bitcode provided via the get_view gold callback.
+  StringMap<MemoryBufferRef> *ModuleMap;
+
+  // Functions to import into this module.
+  FunctionImporter::ImportMapTy *ImportList;
+
+  // Map of globals defined in this module to their summary.
+  std::map<GlobalValue::GUID, GlobalValueSummary *> *DefinedGlobals;
+
+public:
+  /// Constructor used by full LTO.
+  CodeGen(std::unique_ptr<llvm::Module> M)
+      : M(std::move(M)), OS(nullptr), TaskID(-1), CombinedIndex(nullptr),
+        ModuleMap(nullptr) {
+    initTargetMachine();
+  }
+  /// Constructor used by ThinLTO.
+  CodeGen(std::unique_ptr<llvm::Module> M, raw_fd_ostream *OS, int TaskID,
+          const ModuleSummaryIndex *CombinedIndex, std::string Filename,
+          StringMap<MemoryBufferRef> *ModuleMap,
+          FunctionImporter::ImportMapTy *ImportList,
+          std::map<GlobalValue::GUID, GlobalValueSummary *> *DefinedGlobals)
+      : M(std::move(M)), OS(OS), TaskID(TaskID), CombinedIndex(CombinedIndex),
+        SaveTempsFilename(std::move(Filename)), ModuleMap(ModuleMap),
+        ImportList(ImportList), DefinedGlobals(DefinedGlobals) {
+    assert(options::thinlto == !!CombinedIndex &&
+           "Expected module summary index iff performing ThinLTO");
+    initTargetMachine();
+  }
+
+  /// Invoke LTO passes and the code generator for the module.
+  void runAll();
+
+  /// Invoke the actual code generation to emit Module's object to file.
+  void runCodegenPasses();
+
+private:
+  const Target *TheTarget;
+  std::string TripleStr;
+  std::string FeaturesString;
+  TargetOptions Options;
+
+  /// Create a target machine for the module. Must be unique for each
+  /// module/task.
+  void initTargetMachine();
+
+  std::unique_ptr<TargetMachine> createTargetMachine();
+
+  /// Run all LTO passes on the module.
+  void runLTOPasses();
+
+  /// Sets up output files necessary to perform optional multi-threaded
+  /// split code generation, and invokes the code generation implementation.
+  /// If BCFileName is not empty, saves bitcode for module partitions into
+  /// {BCFileName}0 .. {BCFileName}N.
+  void runSplitCodeGen(const SmallString<128> &BCFilename);
+};
+}
+
+static SubtargetFeatures getFeatures(Triple &TheTriple) {
+  SubtargetFeatures Features;
+  Features.getDefaultSubtargetFeatures(TheTriple);
+  for (const std::string &A : MAttrs)
+    Features.AddFeature(A);
+  return Features;
+}
+
+static CodeGenOpt::Level getCGOptLevel() {
+  switch (options::OptLevel) {
+  case 0:
+    return CodeGenOpt::None;
+  case 1:
+    return CodeGenOpt::Less;
+  case 2:
+    return CodeGenOpt::Default;
+  case 3:
+    return CodeGenOpt::Aggressive;
+  }
+  llvm_unreachable("Invalid optimization level");
+}
+
+void CodeGen::initTargetMachine() {
+  TripleStr = M->getTargetTriple();
+  Triple TheTriple(TripleStr);
+
+  std::string ErrMsg;
+  TheTarget = TargetRegistry::lookupTarget(TripleStr, ErrMsg);
+  if (!TheTarget)
+    message(LDPL_FATAL, "Target not found: %s", ErrMsg.c_str());
+
+  SubtargetFeatures Features = getFeatures(TheTriple);
+  FeaturesString = Features.getString();
+  Options = InitTargetOptionsFromCodeGenFlags();
+
+  // Disable the new X86 relax relocations since gold might not support them.
+  // FIXME: Check the gold version or add a new option to enable them.
+  Options.RelaxELFRelocations = false;
+
+  TM = createTargetMachine();
+}
+
+std::unique_ptr<TargetMachine> CodeGen::createTargetMachine() {
+  CodeGenOpt::Level CGOptLevel = getCGOptLevel();
+
+  return std::unique_ptr<TargetMachine>(TheTarget->createTargetMachine(
+      TripleStr, options::mcpu, FeaturesString, Options, RelocationModel,
+      CodeModel::Default, CGOptLevel));
+}
+
+void CodeGen::runLTOPasses() {
+  M->setDataLayout(TM->createDataLayout());
+
+  if (CombinedIndex) {
+    // Apply summary-based LinkOnce/Weak resolution decisions.
+    thinLTOResolveWeakForLinkerModule(*M, *DefinedGlobals);
+
+    // Apply summary-based internalization decisions. Skip if there are no
+    // defined globals from the summary since not only is it unnecessary, but
+    // if this module did not have a summary section the internalizer will
+    // assert if it finds any definitions in this module that aren't in the
+    // DefinedGlobals set.
+    if (!DefinedGlobals->empty())
+      thinLTOInternalizeModule(*M, *DefinedGlobals);
+
+    // Create a loader that will parse the bitcode from the buffers
+    // in the ModuleMap.
+    ModuleLoader Loader(M->getContext(), *ModuleMap);
+
+    // Perform function importing.
+    FunctionImporter Importer(*CombinedIndex, Loader);
+    Importer.importFunctions(*M, *ImportList);
+  }
+
+  legacy::PassManager passes;
+  passes.add(createTargetTransformInfoWrapperPass(TM->getTargetIRAnalysis()));
+
+  PassManagerBuilder PMB;
+  PMB.LibraryInfo = new TargetLibraryInfoImpl(Triple(TM->getTargetTriple()));
+  PMB.Inliner = createFunctionInliningPass();
+  // Unconditionally verify input since it is not verified before this
+  // point and has unknown origin.
+  PMB.VerifyInput = true;
+  PMB.VerifyOutput = !options::DisableVerify;
+  PMB.LoopVectorize = true;
+  PMB.SLPVectorize = true;
+  PMB.OptLevel = options::OptLevel;
+  if (options::thinlto)
+    PMB.populateThinLTOPassManager(passes);
+  else
+    PMB.populateLTOPassManager(passes);
+  passes.run(*M);
+}
+
 /// Open a file and return the new file descriptor given a base input
 /// file name, a flag indicating whether a temp file should be generated,
 /// and an optional task id. The new filename generated is
@@ -672,44 +1066,220 @@ static int openOutputFile(SmallString<12
   return FD;
 }
 
-/// Add all required common symbols to M, which is expected to be the first
-/// combined module.
-static void addCommons(Module &M) {
-  for (auto &I : Commons) {
-    if (!I.second.Prevailing)
-      continue;
-    ArrayType *Ty =
-        ArrayType::get(Type::getInt8Ty(M.getContext()), I.second.Size);
-    GlobalVariable *OldGV = M.getNamedGlobal(I.first);
-    auto *GV = new GlobalVariable(M, Ty, false, GlobalValue::CommonLinkage,
-                                  ConstantAggregateZero::get(Ty), "");
-    GV->setAlignment(I.second.Align);
-    if (OldGV) {
-      OldGV->replaceAllUsesWith(ConstantExpr::getBitCast(GV, OldGV->getType()));
-      GV->takeName(OldGV);
-      OldGV->eraseFromParent();
-    } else {
-      GV->setName(I.first);
+void CodeGen::runCodegenPasses() {
+  assert(OS && "Output stream must be set before emitting to file");
+  legacy::PassManager CodeGenPasses;
+  if (TM->addPassesToEmitFile(CodeGenPasses, *OS,
+                              TargetMachine::CGFT_ObjectFile))
+    report_fatal_error("Failed to setup codegen");
+  CodeGenPasses.run(*M);
+}
+
+void CodeGen::runSplitCodeGen(const SmallString<128> &BCFilename) {
+  SmallString<128> Filename;
+  // Note that openOutputFile will append a unique ID for each task
+  if (!options::obj_path.empty())
+    Filename = options::obj_path;
+  else if (options::TheOutputType == options::OT_SAVE_TEMPS)
+    Filename = output_name + ".o";
+
+  // Note that the default parallelism is 1 instead of the
+  // hardware_concurrency, as there are behavioral differences between
+  // parallelism levels (e.g. symbol ordering will be different, and some uses
+  // of inline asm currently have issues with parallelism >1).
+  unsigned int MaxThreads = options::Parallelism ? options::Parallelism : 1;
+
+  std::vector<SmallString<128>> Filenames(MaxThreads);
+  std::vector<SmallString<128>> BCFilenames(MaxThreads);
+  bool TempOutFile = Filename.empty();
+  {
+    // Open a file descriptor for each backend task. This is done in a block
+    // so that the output file descriptors are closed before gold opens them.
+    std::list<llvm::raw_fd_ostream> OSs;
+    std::vector<llvm::raw_pwrite_stream *> OSPtrs(MaxThreads);
+    for (unsigned I = 0; I != MaxThreads; ++I) {
+      int FD = openOutputFile(Filename, TempOutFile, Filenames[I],
+                              // Only append ID if there are multiple tasks.
+                              MaxThreads > 1 ? I : -1);
+      OSs.emplace_back(FD, true);
+      OSPtrs[I] = &OSs.back();
     }
-    // We may only internalize commons if there is a single LTO task because
-    // other native object files may require the common.
-    if (MaxTasks == 1 && !I.second.VisibleToRegularObj)
-      GV->setLinkage(GlobalValue::InternalLinkage);
+
+    std::list<llvm::raw_fd_ostream> BCOSs;
+    std::vector<llvm::raw_pwrite_stream *> BCOSPtrs;
+    if (!BCFilename.empty() && MaxThreads > 1) {
+      for (unsigned I = 0; I != MaxThreads; ++I) {
+        int FD = openOutputFile(BCFilename, false, BCFilenames[I], I);
+        BCOSs.emplace_back(FD, true);
+        BCOSPtrs.push_back(&BCOSs.back());
+      }
+    }
+
+    // Run backend tasks.
+    splitCodeGen(std::move(M), OSPtrs, BCOSPtrs,
+                 [&]() { return createTargetMachine(); });
   }
+
+  for (auto &Filename : Filenames)
+    recordFile(Filename.c_str(), TempOutFile);
 }
 
-static CodeGenOpt::Level getCGOptLevel() {
-  switch (options::OptLevel) {
-  case 0:
-    return CodeGenOpt::None;
-  case 1:
-    return CodeGenOpt::Less;
-  case 2:
-    return CodeGenOpt::Default;
-  case 3:
-    return CodeGenOpt::Aggressive;
+void CodeGen::runAll() {
+  runLTOPasses();
+
+  SmallString<128> OptFilename;
+  if (options::TheOutputType == options::OT_SAVE_TEMPS) {
+    OptFilename = output_name;
+    // If the CodeGen client provided a filename, use it. Always expect
+    // a provided filename if we are in a task (i.e. ThinLTO backend).
+    assert(!SaveTempsFilename.empty() || TaskID == -1);
+    if (!SaveTempsFilename.empty())
+      OptFilename = SaveTempsFilename;
+    OptFilename += ".opt.bc";
+    saveBCFile(OptFilename, *M);
+  }
+
+  // If we are already in a thread (i.e. ThinLTO), just perform
+  // codegen passes directly.
+  if (TaskID >= 0)
+    runCodegenPasses();
+  // Otherwise attempt split code gen.
+  else
+    runSplitCodeGen(OptFilename);
+}
+
+/// Links the module in \p View from file \p F into the combined module
+/// saved in the IRMover \p L.
+static void linkInModule(LLVMContext &Context, IRMover &L, claimed_file &F,
+                         const void *View, StringRef Name,
+                         raw_fd_ostream *ApiFile, StringSet<> &Internalize,
+                         bool SetName = false) {
+  std::vector<GlobalValue *> Keep;
+  StringMap<unsigned> Realign;
+  std::unique_ptr<Module> M = getModuleForFile(Context, F, View, Name, ApiFile,
+                                               Internalize, Keep, Realign);
+  if (!M.get())
+    return;
+  if (!options::triple.empty())
+    M->setTargetTriple(options::triple.c_str());
+  else if (M->getTargetTriple().empty()) {
+    M->setTargetTriple(DefaultTriple);
+  }
+
+  // For ThinLTO we want to propagate the source file name to ensure
+  // we can create the correct global identifiers matching those in the
+  // original module.
+  if (SetName)
+    L.getModule().setSourceFileName(M->getSourceFileName());
+
+  if (Error E = L.move(std::move(M), Keep,
+                       [](GlobalValue &, IRMover::ValueAdder) {})) {
+    handleAllErrors(std::move(E), [&](const llvm::ErrorInfoBase &EIB) {
+      message(LDPL_FATAL, "Failed to link module %s: %s", Name.str().c_str(),
+              EIB.message().c_str());
+    });
   }
-  llvm_unreachable("Invalid optimization level");
+
+  for (const auto &I : Realign) {
+    GlobalValue *Dst = L.getModule().getNamedValue(I.first());
+    if (!Dst)
+      continue;
+    cast<GlobalVariable>(Dst)->setAlignment(I.second);
+  }
+}
+
+/// Perform the ThinLTO backend on a single module, invoking the LTO and codegen
+/// pipelines.
+static void thinLTOBackendTask(claimed_file &F, const void *View,
+                               StringRef Name, raw_fd_ostream *ApiFile,
+                               const ModuleSummaryIndex &CombinedIndex,
+                               raw_fd_ostream *OS, unsigned TaskID,
+                               StringMap<MemoryBufferRef> &ModuleMap,
+                               FunctionImporter::ImportMapTy &ImportList,
+                               std::map<GlobalValue::GUID, GlobalValueSummary *> &DefinedGlobals) {
+  // Need to use a separate context for each task
+  LLVMContext Context;
+  Context.setDiscardValueNames(options::TheOutputType !=
+                               options::OT_SAVE_TEMPS);
+  Context.enableDebugTypeODRUniquing(); // Merge debug info types.
+  Context.setDiagnosticHandler(diagnosticHandlerForContext, nullptr, true);
+
+  std::unique_ptr<llvm::Module> NewModule(new llvm::Module(Name, Context));
+  IRMover L(*NewModule.get());
+
+  StringSet<> Dummy;
+  linkInModule(Context, L, F, View, Name, ApiFile, Dummy, true);
+  if (renameModuleForThinLTO(*NewModule, CombinedIndex))
+    message(LDPL_FATAL, "Failed to rename module for ThinLTO");
+
+  CodeGen codeGen(std::move(NewModule), OS, TaskID, &CombinedIndex, Name,
+                  &ModuleMap, &ImportList, &DefinedGlobals);
+  codeGen.runAll();
+}
+
+/// Launch each module's backend pipeline in a separate task in a thread pool.
+static void
+thinLTOBackends(raw_fd_ostream *ApiFile,
+                const ModuleSummaryIndex &CombinedIndex,
+                StringMap<MemoryBufferRef> &ModuleMap,
+                StringMap<FunctionImporter::ImportMapTy> &ImportLists,
+  StringMap<std::map<GlobalValue::GUID, GlobalValueSummary *>>
+      &ModuleToDefinedGVSummaries) {
+  unsigned TaskCount = 0;
+  std::vector<ThinLTOTaskInfo> Tasks;
+  Tasks.reserve(Modules.size());
+  unsigned int MaxThreads = options::Parallelism
+                                ? options::Parallelism
+                                : thread::hardware_concurrency();
+
+  // Create ThreadPool in nested scope so that threads will be joined
+  // on destruction.
+  {
+    ThreadPool ThinLTOThreadPool(MaxThreads);
+    for (claimed_file &F : Modules) {
+      // Do all the gold callbacks in the main thread, since gold is not thread
+      // safe by default.
+      const void *View = getSymbolsAndView(F);
+      if (!View)
+        continue;
+
+      SmallString<128> Filename;
+      if (!options::obj_path.empty())
+        // Note that openOutputFile will append a unique ID for each task
+        Filename = options::obj_path;
+      else if (options::TheOutputType == options::OT_SAVE_TEMPS) {
+        // Use the input file name so that we get a unique and identifiable
+        // output file for each ThinLTO backend task.
+        Filename = F.name;
+        Filename += ".thinlto.o";
+      }
+      bool TempOutFile = Filename.empty();
+
+      SmallString<128> NewFilename;
+      int FD = openOutputFile(Filename, TempOutFile, NewFilename,
+                              // Only append the TaskID if we will use the
+                              // non-unique obj_path.
+                              !options::obj_path.empty() ? TaskCount : -1);
+      TaskCount++;
+      std::unique_ptr<raw_fd_ostream> OS =
+          llvm::make_unique<raw_fd_ostream>(FD, true);
+
+      // Enqueue the task
+      ThinLTOThreadPool.async(thinLTOBackendTask, std::ref(F), View, F.name,
+                              ApiFile, std::ref(CombinedIndex), OS.get(),
+                              TaskCount, std::ref(ModuleMap),
+                              std::ref(ImportLists[F.name]),
+                              std::ref(ModuleToDefinedGVSummaries[F.name]));
+
+      // Record the information needed by the task or during its cleanup
+      // to a ThinLTOTaskInfo instance. For information needed by the task
+      // the unique_ptr ownership is transferred to the ThinLTOTaskInfo.
+      Tasks.emplace_back(std::move(OS), NewFilename.c_str(), TempOutFile);
+    }
+  }
+
+  for (auto &Task : Tasks)
+    Task.cleanup();
 }
 
 /// Parse the thinlto_prefix_replace option into the \p OldPrefix and
@@ -723,130 +1293,266 @@ static void getThinLTOOldAndNewPrefix(st
   NewPrefix = Split.second.str();
 }
 
-static std::unique_ptr<LTO> createLTO() {
-  Config Conf;
-  ThinBackend Backend;
-  unsigned ParallelCodeGenParallelismLevel = 1;
+/// Given the original \p Path to an output file, replace any path
+/// prefix matching \p OldPrefix with \p NewPrefix. Also, create the
+/// resulting directory if it does not yet exist.
+static std::string getThinLTOOutputFile(const std::string &Path,
+                                        const std::string &OldPrefix,
+                                        const std::string &NewPrefix) {
+  if (OldPrefix.empty() && NewPrefix.empty())
+    return Path;
+  SmallString<128> NewPath(Path);
+  llvm::sys::path::replace_path_prefix(NewPath, OldPrefix, NewPrefix);
+  StringRef ParentPath = llvm::sys::path::parent_path(NewPath.str());
+  if (!ParentPath.empty()) {
+    // Make sure the new directory exists, creating it if necessary.
+    if (std::error_code EC = llvm::sys::fs::create_directories(ParentPath))
+      llvm::errs() << "warning: could not create directory '" << ParentPath
+                   << "': " << EC.message() << '\n';
+  }
+  return NewPath.str();
+}
 
-  Conf.CPU = options::mcpu;
-  Conf.Options = InitTargetOptionsFromCodeGenFlags();
+/// Perform ThinLTO link, which creates the combined index file.
+/// Also, either launch backend threads or (under thinlto-index-only)
+/// emit individual index files for distributed backends and exit.
+static ld_plugin_status thinLTOLink(raw_fd_ostream *ApiFile) {
+  // Map from a module name to the corresponding buffer holding a view of the
+  // bitcode provided via the get_view gold callback.
+  StringMap<MemoryBufferRef> ModuleMap;
+  // Map to own RAII objects that manage the file opening and releasing
+  // interfaces with gold.
+  DenseMap<void *, std::unique_ptr<PluginInputFile>> HandleToInputFile;
+
+  // Keep track of symbols that must not be internalized because they
+  // are referenced outside of a single IR module.
+  DenseSet<GlobalValue::GUID> Preserve;
+
+  // Keep track of the prevailing copy for each GUID, for use in resolving
+  // weak linkages.
+  DenseMap<GlobalValue::GUID, const GlobalValueSummary *> PrevailingCopy;
 
-  // Disable the new X86 relax relocations since gold might not support them.
-  // FIXME: Check the gold version or add a new option to enable them.
-  Conf.Options.RelaxELFRelocations = false;
+  ModuleSummaryIndex CombinedIndex;
+  uint64_t NextModuleId = 0;
+  for (claimed_file &F : Modules) {
+    if (!HandleToInputFile.count(F.leader_handle))
+      HandleToInputFile.insert(std::make_pair(
+          F.leader_handle, llvm::make_unique<PluginInputFile>(F.handle)));
+    // Pass this into getModuleSummaryIndexForFile
+    const void *View = getSymbolsAndView(F);
+    if (!View)
+      continue;
+
+    MemoryBufferRef ModuleBuffer(StringRef((const char *)View, F.filesize),
+                                 F.name);
+    assert(ModuleMap.find(ModuleBuffer.getBufferIdentifier()) ==
+               ModuleMap.end() &&
+           "Expect unique Buffer Identifier");
+    ModuleMap[ModuleBuffer.getBufferIdentifier()] = ModuleBuffer;
+
+    std::unique_ptr<ModuleSummaryIndex> Index = getModuleSummaryIndexForFile(F);
+
+    // Use gold's symbol resolution information to identify symbols referenced
+    // by more than a single IR module (i.e. referenced by multiple IR modules
+    // or by a non-IR module). Cross references introduced by importing are
+    // checked separately via the export lists. Also track the prevailing copy
+    // for later symbol resolution.
+    for (auto &Sym : F.syms) {
+      ld_plugin_symbol_resolution Resolution =
+          (ld_plugin_symbol_resolution)Sym.resolution;
+      GlobalValue::GUID SymGUID = GlobalValue::getGUID(Sym.name);
+      if (Resolution != LDPR_PREVAILING_DEF_IRONLY)
+        Preserve.insert(SymGUID);
+
+      if (Index && (Resolution == LDPR_PREVAILING_DEF ||
+                    Resolution == LDPR_PREVAILING_DEF_IRONLY ||
+                    Resolution == LDPR_PREVAILING_DEF_IRONLY_EXP))
+        PrevailingCopy[SymGUID] = Index->getGlobalValueSummary(SymGUID);
+    }
+
+    // Skip files without a module summary.
+    if (Index)
+      CombinedIndex.mergeFrom(std::move(Index), ++NextModuleId);
+  }
+
+  // Collect for each module the list of function it defines (GUID ->
+  // Summary).
+  StringMap<std::map<GlobalValue::GUID, GlobalValueSummary *>>
+      ModuleToDefinedGVSummaries(NextModuleId);
+  CombinedIndex.collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries);
+
+  StringMap<FunctionImporter::ImportMapTy> ImportLists(NextModuleId);
+  StringMap<FunctionImporter::ExportSetTy> ExportLists(NextModuleId);
+  ComputeCrossModuleImport(CombinedIndex, ModuleToDefinedGVSummaries,
+                           ImportLists, ExportLists);
+
+  auto isPrevailing = [&](GlobalValue::GUID GUID, const GlobalValueSummary *S) {
+    const auto &Prevailing = PrevailingCopy.find(GUID);
+    assert(Prevailing != PrevailingCopy.end());
+    return Prevailing->second == S;
+  };
+
+  // Callback for internalization, to prevent internalization of symbols
+  // that were not candidates initially, and those that are being imported
+  // (which introduces new cross references).
+  auto isExported = [&](StringRef ModuleIdentifier, GlobalValue::GUID GUID) {
+    const auto &ExportList = ExportLists.find(ModuleIdentifier);
+    return (ExportList != ExportLists.end() &&
+            ExportList->second.count(GUID)) ||
+           Preserve.count(GUID);
+  };
+
+  thinLTOResolveWeakForLinkerInIndex(
+      CombinedIndex, isPrevailing,
+      [](StringRef ModuleIdentifier, GlobalValue::GUID GUID,
+         GlobalValue::LinkageTypes NewLinkage) {});
+
+  // Use global summary-based analysis to identify symbols that can be
+  // internalized (because they aren't exported or preserved as per callback).
+  // Changes are made in the index, consumed in the ThinLTO backends.
+  thinLTOInternalizeAndPromoteInIndex(CombinedIndex, isExported);
+
+  if (options::thinlto_emit_imports_files && !options::thinlto_index_only)
+    message(LDPL_WARNING,
+            "thinlto-emit-imports-files ignored unless thinlto-index-only");
 
-  Conf.MAttrs = MAttrs;
-  Conf.RelocModel = *RelocationModel;
-  Conf.CGOptLevel = getCGOptLevel();
-  Conf.DisableVerify = options::DisableVerify;
-  Conf.OptLevel = options::OptLevel;
-  if (options::Parallelism) {
-    if (options::thinlto)
-      Backend = createInProcessThinBackend(options::Parallelism);
-    else
-      ParallelCodeGenParallelismLevel = options::Parallelism;
-  }
   if (options::thinlto_index_only) {
+    // If the thinlto-prefix-replace option was specified, parse it and
+    // extract the old and new prefixes.
     std::string OldPrefix, NewPrefix;
     getThinLTOOldAndNewPrefix(OldPrefix, NewPrefix);
-    Backend = createWriteIndexesThinBackend(
-        OldPrefix, NewPrefix, options::thinlto_emit_imports_files,
-        options::thinlto_linked_objects_file);
-  }
 
-  Conf.OverrideTriple = options::triple;
-  Conf.DefaultTriple = sys::getDefaultTargetTriple();
+    // If the user requested a list of objects gold included in the link,
+    // create and open the requested file.
+    raw_fd_ostream *ObjFileOS = nullptr;
+    if (!options::thinlto_linked_objects_file.empty()) {
+      std::error_code EC;
+      ObjFileOS = new raw_fd_ostream(options::thinlto_linked_objects_file, EC,
+                                     sys::fs::OpenFlags::F_None);
+      if (EC)
+        message(LDPL_FATAL, "Unable to open %s for writing: %s",
+                options::thinlto_linked_objects_file.c_str(),
+                EC.message().c_str());
+    }
+    // For each input bitcode file, generate an individual index that
+    // contains summaries only for its own global values, and for any that
+    // should be imported.
+    for (claimed_file &F : Modules) {
+      std::error_code EC;
 
-  Conf.DiagHandler = diagnosticHandler;
+      std::string NewModulePath =
+          getThinLTOOutputFile(F.name, OldPrefix, NewPrefix);
 
-  Conf.PreOptModuleHook = [](size_t Task, Module &M) {
-    if (Task == 0)
-      addCommons(M);
-    return true;
-  };
+      if (!options::thinlto_linked_objects_file.empty()) {
+        // If gold included any symbols from ths file in the link, emit path
+        // to the final object file, which should be included in the final
+        // native link.
+        if (get_symbols(F.handle, F.syms.size(), F.syms.data()) !=
+            LDPS_NO_SYMS) {
+          assert(ObjFileOS);
+          *ObjFileOS << NewModulePath << "\n";
+        }
+      }
 
-  switch (options::TheOutputType) {
-  case options::OT_NORMAL:
-    break;
+      raw_fd_ostream OS((Twine(NewModulePath) + ".thinlto.bc").str(), EC,
+                        sys::fs::OpenFlags::F_None);
+      if (EC)
+        message(LDPL_FATAL, "Unable to open %s.thinlto.bc for writing: %s",
+                NewModulePath.c_str(), EC.message().c_str());
+      // Build a map of module to the GUIDs and summary objects that should
+      // be written to its index.
+      std::map<std::string, GVSummaryMapTy> ModuleToSummariesForIndex;
+      gatherImportedSummariesForModule(F.name, ModuleToDefinedGVSummaries,
+                                       ImportLists, ModuleToSummariesForIndex);
+      WriteIndexToFile(CombinedIndex, OS, &ModuleToSummariesForIndex);
+
+      if (options::thinlto_emit_imports_files) {
+        if ((EC = EmitImportsFiles(F.name,
+                                   (Twine(NewModulePath) + ".imports").str(),
+                                   ImportLists)))
+          message(LDPL_FATAL, "Unable to open %s.imports",
+                  NewModulePath.c_str(), EC.message().c_str());
+      }
+    }
 
-  case options::OT_DISABLE:
-    Conf.PreOptModuleHook = [](size_t Task, Module &M) { return false; };
-    break;
+    if (ObjFileOS)
+      ObjFileOS->close();
 
-  case options::OT_BC_ONLY:
-    Conf.PostInternalizeModuleHook = [](size_t Task, Module &M) {
-      std::error_code EC;
-      raw_fd_ostream OS(output_name, EC, sys::fs::OpenFlags::F_None);
-      if (EC)
-        message(LDPL_FATAL, "Failed to write the output file.");
-      WriteBitcodeToFile(&M, OS, /* ShouldPreserveUseListOrder */ false);
-      return false;
-    };
-    break;
+    cleanup_hook();
+    exit(0);
+  }
 
-  case options::OT_SAVE_TEMPS:
-    check(Conf.addSaveTemps(output_name));
-    break;
+  // Create OS in nested scope so that it will be closed on destruction.
+  {
+    std::error_code EC;
+    raw_fd_ostream OS(output_name + ".thinlto.bc", EC,
+                      sys::fs::OpenFlags::F_None);
+    if (EC)
+      message(LDPL_FATAL, "Unable to open %s.thinlto.bc for writing: %s",
+              output_name.data(), EC.message().c_str());
+    WriteIndexToFile(CombinedIndex, OS);
   }
 
-  return make_unique<LTO>(std::move(Conf), Backend,
-                          ParallelCodeGenParallelismLevel);
+  thinLTOBackends(ApiFile, CombinedIndex, ModuleMap, ImportLists,
+                  ModuleToDefinedGVSummaries);
+  return LDPS_OK;
 }
 
 /// gold informs us that all symbols have been read. At this point, we use
 /// get_symbols to see if any of our definitions have been overridden by a
 /// native object file. Then, perform optimization and codegen.
-static ld_plugin_status allSymbolsReadHook() {
+static ld_plugin_status allSymbolsReadHook(raw_fd_ostream *ApiFile) {
   if (Modules.empty())
     return LDPS_OK;
 
   if (unsigned NumOpts = options::extra.size())
     cl::ParseCommandLineOptions(NumOpts, &options::extra[0]);
 
-  std::unique_ptr<LTO> Lto = createLTO();
+  if (options::thinlto)
+    return thinLTOLink(ApiFile);
 
+  LLVMContext Context;
+  Context.setDiscardValueNames(options::TheOutputType !=
+                               options::OT_SAVE_TEMPS);
+  Context.enableDebugTypeODRUniquing(); // Merge debug info types.
+  Context.setDiagnosticHandler(diagnosticHandlerForContext, nullptr, true);
+
+  std::unique_ptr<Module> Combined(new Module("ld-temp.o", Context));
+  IRMover L(*Combined);
+
+  StringSet<> Internalize;
   for (claimed_file &F : Modules) {
+    // RAII object to manage the file opening and releasing interfaces with
+    // gold.
     PluginInputFile InputFile(F.handle);
     const void *View = getSymbolsAndView(F);
     if (!View)
       continue;
-    addModule(*Lto, F, View);
+    linkInModule(Context, L, F, View, F.name, ApiFile, Internalize);
   }
 
-  SmallString<128> Filename;
-  // Note that openOutputFile will append a unique ID for each task
-  if (!options::obj_path.empty())
-    Filename = options::obj_path;
-  else if (options::TheOutputType == options::OT_SAVE_TEMPS)
-    Filename = output_name + ".o";
-  bool SaveTemps = !Filename.empty();
-
-  MaxTasks = Lto->getMaxTasks();
-  std::vector<uintptr_t> IsTemporary(MaxTasks);
-  std::vector<SmallString<128>> Filenames(MaxTasks);
-
-  auto AddStream = [&](size_t Task) {
-    int FD = openOutputFile(Filename, /*TempOutFile=*/!SaveTemps,
-                            Filenames[Task], MaxTasks > 1 ? Task : -1);
-    IsTemporary[Task] = !SaveTemps;
-
-    return make_unique<llvm::raw_fd_ostream>(FD, true);
-  };
-
-  check(Lto->run(AddStream));
+  for (const auto &Name : Internalize) {
+    GlobalValue *GV = Combined->getNamedValue(Name.first());
+    if (GV)
+      internalize(*GV);
+  }
 
-  if (options::TheOutputType == options::OT_DISABLE ||
-      options::TheOutputType == options::OT_BC_ONLY)
+  if (options::TheOutputType == options::OT_DISABLE)
     return LDPS_OK;
 
-  if (options::thinlto_index_only) {
-    cleanup_hook();
-    exit(0);
+  if (options::TheOutputType != options::OT_NORMAL) {
+    std::string path;
+    if (options::TheOutputType == options::OT_BC_ONLY)
+      path = output_name;
+    else
+      path = output_name + ".bc";
+    saveBCFile(path, *Combined);
+    if (options::TheOutputType == options::OT_BC_ONLY)
+      return LDPS_OK;
   }
 
-  for (unsigned I = 0; I != MaxTasks; ++I)
-    if (!Filenames[I].empty())
-      recordFile(Filenames[I].str(), IsTemporary[I]);
+  CodeGen codeGen(std::move(Combined));
+  codeGen.runAll();
 
   if (!options::extra_library_path.empty() &&
       set_extra_library_path(options::extra_library_path.c_str()) != LDPS_OK)
@@ -856,7 +1562,18 @@ static ld_plugin_status allSymbolsReadHo
 }
 
 static ld_plugin_status all_symbols_read_hook(void) {
-  ld_plugin_status Ret = allSymbolsReadHook();
+  ld_plugin_status Ret;
+  if (!options::generate_api_file) {
+    Ret = allSymbolsReadHook(nullptr);
+  } else {
+    std::error_code EC;
+    raw_fd_ostream ApiFile("apifile.txt", EC, sys::fs::F_None);
+    if (EC)
+      message(LDPL_FATAL, "Unable to open apifile.txt for writing: %s",
+              EC.message().c_str());
+    Ret = allSymbolsReadHook(&ApiFile);
+  }
+
   llvm_shutdown();
 
   if (options::TheOutputType == options::OT_BC_ONLY ||

Removed: llvm/trunk/tools/llvm-lto2/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-lto2/CMakeLists.txt?rev=278330&view=auto
==============================================================================
--- llvm/trunk/tools/llvm-lto2/CMakeLists.txt (original)
+++ llvm/trunk/tools/llvm-lto2/CMakeLists.txt (removed)
@@ -1,10 +0,0 @@
-set(LLVM_LINK_COMPONENTS
-  ${LLVM_TARGETS_TO_BUILD}
-  LTO
-  Object
-  Support
-  )
-
-add_llvm_tool(llvm-lto2
-  llvm-lto2.cpp
-  )

Removed: llvm/trunk/tools/llvm-lto2/LLVMBuild.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-lto2/LLVMBuild.txt?rev=278330&view=auto
==============================================================================
--- llvm/trunk/tools/llvm-lto2/LLVMBuild.txt (original)
+++ llvm/trunk/tools/llvm-lto2/LLVMBuild.txt (removed)
@@ -1,22 +0,0 @@
-;===- ./tools/llvm-lto2/LLVMBuild.txt --------------------------*- Conf -*--===;
-;
-;                     The LLVM Compiler Infrastructure
-;
-; This file is distributed under the University of Illinois Open Source
-; License. See LICENSE.TXT for details.
-;
-;===------------------------------------------------------------------------===;
-;
-; This is an LLVMBuild description file for the components in this subdirectory.
-;
-; For more information on the LLVMBuild system, please see:
-;
-;   http://llvm.org/docs/LLVMBuild.html
-;
-;===------------------------------------------------------------------------===;
-
-[component_0]
-type = Tool
-name = llvm-lto2
-parent = Tools
-required_libraries = LTO Object all-targets

Removed: llvm/trunk/tools/llvm-lto2/llvm-lto2.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-lto2/llvm-lto2.cpp?rev=278330&view=auto
==============================================================================
--- llvm/trunk/tools/llvm-lto2/llvm-lto2.cpp (original)
+++ llvm/trunk/tools/llvm-lto2/llvm-lto2.cpp (removed)
@@ -1,168 +0,0 @@
-//===-- llvm-lto2: test harness for the resolution-based LTO interface ----===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This program takes in a list of bitcode files, links them and performs
-// link-time optimization according to the provided symbol resolutions using the
-// resolution-based LTO interface, and outputs one or more object files.
-//
-// This program is intended to eventually replace llvm-lto which uses the legacy
-// LTO interface.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/LTO/LTO.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/TargetSelect.h"
-
-using namespace llvm;
-using namespace lto;
-using namespace object;
-
-static cl::list<std::string> InputFilenames(cl::Positional, cl::OneOrMore,
-                                            cl::desc("<input bitcode files>"));
-
-static cl::opt<std::string> OutputFilename("o", cl::Required,
-                                           cl::desc("Output filename"),
-                                           cl::value_desc("filename"));
-
-static cl::opt<bool> SaveTemps("save-temps", cl::desc("Save temporary files"));
-
-static cl::list<std::string> SymbolResolutions(
-    "r",
-    cl::desc("Specify a symbol resolution: filename,symbolname,resolution\n"
-             "where \"resolution\" is a sequence (which may be empty) of the\n"
-             "following characters:\n"
-             " p - prevailing: the linker has chosen this definition of the\n"
-             "     symbol\n"
-             " l - local: the definition of this symbol is unpreemptable at\n"
-             "     runtime and is known to be in this linkage unit\n"
-             " x - externally visible: the definition of this symbol is\n"
-             "     visible outside of the LTO unit\n"
-             "A resolution for each symbol must be specified."),
-    cl::ZeroOrMore);
-
-static void check(Error E, std::string Msg) {
-  if (!E)
-    return;
-  handleAllErrors(std::move(E), [&](ErrorInfoBase &EIB) {
-    errs() << "llvm-lto: " << Msg << ": " << EIB.message().c_str() << '\n';
-  });
-  exit(1);
-}
-
-template <typename T> static T check(Expected<T> E, std::string Msg) {
-  if (E)
-    return std::move(*E);
-  check(E.takeError(), Msg);
-  return T();
-}
-
-static void check(std::error_code EC, std::string Msg) {
-  check(errorCodeToError(EC), Msg);
-}
-
-template <typename T> static T check(ErrorOr<T> E, std::string Msg) {
-  if (E)
-    return std::move(*E);
-  check(E.getError(), Msg);
-  return T();
-}
-
-int main(int argc, char **argv) {
-  InitializeAllTargets();
-  InitializeAllTargetMCs();
-  InitializeAllAsmPrinters();
-  InitializeAllAsmParsers();
-
-  cl::ParseCommandLineOptions(argc, argv, "Resolution-based LTO test harness");
-
-  std::map<std::pair<std::string, std::string>, SymbolResolution>
-      CommandLineResolutions;
-  for (std::string R : SymbolResolutions) {
-    StringRef Rest = R;
-    StringRef FileName, SymbolName;
-    std::tie(FileName, Rest) = Rest.split(',');
-    if (Rest.empty()) {
-      llvm::errs() << "invalid resolution: " << R << '\n';
-      return 1;
-    }
-    std::tie(SymbolName, Rest) = Rest.split(',');
-    SymbolResolution Res;
-    for (char C : Rest) {
-      if (C == 'p')
-        Res.Prevailing = true;
-      else if (C == 'l')
-        Res.FinalDefinitionInLinkageUnit = true;
-      else if (C == 'x')
-        Res.VisibleToRegularObj = true;
-      else
-        llvm::errs() << "invalid character " << C << " in resolution: " << R
-                     << '\n';
-    }
-    CommandLineResolutions[{FileName, SymbolName}] = Res;
-  }
-
-  std::vector<std::unique_ptr<MemoryBuffer>> MBs;
-
-  Config Conf;
-  Conf.DiagHandler = [](const DiagnosticInfo &) {
-    exit(1);
-  };
-
-  if (SaveTemps)
-    check(Conf.addSaveTemps(OutputFilename), "Config::addSaveTemps failed");
-
-  LTO Lto(std::move(Conf));
-
-  bool HasErrors = false;
-  for (std::string F : InputFilenames) {
-    std::unique_ptr<MemoryBuffer> MB = check(MemoryBuffer::getFile(F), F);
-    std::unique_ptr<InputFile> Input =
-        check(InputFile::create(MB->getMemBufferRef()), F);
-
-    std::vector<SymbolResolution> Res;
-    for (const InputFile::Symbol &Sym : Input->symbols()) {
-      auto I = CommandLineResolutions.find({F, Sym.getName()});
-      if (I == CommandLineResolutions.end()) {
-        llvm::errs() << argv[0] << ": missing symbol resolution for " << F
-                     << ',' << Sym.getName() << '\n';
-        HasErrors = true;
-      } else {
-        Res.push_back(I->second);
-        CommandLineResolutions.erase(I);
-      }
-    }
-
-    if (HasErrors)
-      continue;
-
-    MBs.push_back(std::move(MB));
-    check(Lto.add(std::move(Input), Res), F);
-  }
-
-  if (!CommandLineResolutions.empty()) {
-    HasErrors = true;
-    for (auto UnusedRes : CommandLineResolutions)
-      llvm::errs() << argv[0] << ": unused symbol resolution for "
-                   << UnusedRes.first.first << ',' << UnusedRes.first.second
-                   << '\n';
-  }
-  if (HasErrors)
-    return 1;
-
-  auto AddStream = [&](size_t Task) {
-    std::string Path = OutputFilename + "." + utostr(Task);
-    std::error_code EC;
-    auto S = make_unique<raw_fd_ostream>(Path, EC, sys::fs::F_None);
-    check(EC, Path);
-    return S;
-  };
-
-  check(Lto.run(AddStream), "LTO::run failed");
-}




More information about the llvm-commits mailing list