<div dir="rtl"><div dir="ltr">Hi Teresa,</div><div dir="ltr"><br></div><div dir="ltr">Visual C++ 2013 complains about BitcodeReader.cpp(5543): warning C4065: switch statement contains 'default' but no 'case' labels. </div><div dir="ltr"><br></div><div dir="ltr"><div dir="ltr">  switch (Stream.readRecord(Entry.ID, Record)) {</div><div dir="ltr">    default:</div><div dir="ltr">      return error("Invalid record");</div><div dir="ltr">  }</div><div><br></div></div><div dir="ltr"><br></div><div dir="ltr">To keep the build warning-free, could you silence it, maybe by adding a case something: statement just before the default:?</div><div dir="ltr"><br></div><div dir="ltr">Thanks, Yaron</div><div dir="ltr"><br></div><div dir="ltr"><br></div></div><div class="gmail_extra"><br><div class="gmail_quote"><div dir="ltr">2015-10-04 17:33 GMT+03:00 Teresa Johnson via llvm-commits <span dir="ltr"><<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a>></span>:</div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: tejohnson<br>
Date: Sun Oct  4 09:33:43 2015<br>
New Revision: 249270<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=249270&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=249270&view=rev</a><br>
Log:<br>
Support for function summary index bitcode sections and files.<br>
<br>
Summary:<br>
The bitcode format is described in this document:<br>
  <a href="https://drive.google.com/file/d/0B036uwnWM6RWdnBLakxmeDdOeXc/view" rel="noreferrer" target="_blank">https://drive.google.com/file/d/0B036uwnWM6RWdnBLakxmeDdOeXc/view</a><br>
For more info on ThinLTO see:<br>
  <a href="https://sites.google.com/site/llvmthinlto" rel="noreferrer" target="_blank">https://sites.google.com/site/llvmthinlto</a><br>
<br>
The first customer is ThinLTO, however the data structures are designed<br>
and named more generally based on prior feedback. There are a few<br>
comments regarding how certain interfaces are used by ThinLTO, and the<br>
options added here to gold currently have ThinLTO-specific names as the<br>
behavior they provoke is currently ThinLTO-specific.<br>
<br>
This patch includes support for generating per-module function indexes,<br>
the combined index file via the gold plugin, and several tests<br>
(more are included with the associated clang patch D11908).<br>
<br>
Reviewers: dexonsmith, davidxl, joker.eph<br>
<br>
Subscribers: llvm-commits<br>
<br>
Differential Revision: <a href="http://reviews.llvm.org/D13107" rel="noreferrer" target="_blank">http://reviews.llvm.org/D13107</a><br>
<br>
Added:<br>
    llvm/trunk/include/llvm/IR/FunctionInfo.h<br>
    llvm/trunk/include/llvm/Object/FunctionIndexObjectFile.h<br>
    llvm/trunk/lib/IR/FunctionInfo.cpp<br>
    llvm/trunk/lib/Object/FunctionIndexObjectFile.cpp<br>
    llvm/trunk/test/Bitcode/thinlto-function-summary.ll<br>
    llvm/trunk/test/tools/gold/X86/Inputs/thinlto.ll<br>
    llvm/trunk/test/tools/gold/X86/thinlto.ll<br>
Modified:<br>
    llvm/trunk/include/llvm/Bitcode/BitcodeWriterPass.h<br>
    llvm/trunk/include/llvm/Bitcode/BitstreamWriter.h<br>
    llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h<br>
    llvm/trunk/include/llvm/Bitcode/ReaderWriter.h<br>
    llvm/trunk/include/llvm/Object/Binary.h<br>
    llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp<br>
    llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp<br>
    llvm/trunk/lib/Bitcode/Writer/BitcodeWriterPass.cpp<br>
    llvm/trunk/lib/IR/CMakeLists.txt<br>
    llvm/trunk/lib/Object/CMakeLists.txt<br>
    llvm/trunk/tools/gold/gold-plugin.cpp<br>
    llvm/trunk/tools/llvm-as/llvm-as.cpp<br>
    llvm/trunk/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp<br>
<br>
Modified: llvm/trunk/include/llvm/Bitcode/BitcodeWriterPass.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Bitcode/BitcodeWriterPass.h?rev=249270&r1=249269&r2=249270&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Bitcode/BitcodeWriterPass.h?rev=249270&r1=249269&r2=249270&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/Bitcode/BitcodeWriterPass.h (original)<br>
+++ llvm/trunk/include/llvm/Bitcode/BitcodeWriterPass.h Sun Oct  4 09:33:43 2015<br>
@@ -29,8 +29,12 @@ class PreservedAnalyses;<br>
 ///<br>
 /// If \c ShouldPreserveUseListOrder, encode use-list order so it can be<br>
 /// reproduced when deserialized.<br>
+///<br>
+/// If \c EmitFunctionSummary, emit the function summary index (currently<br>
+/// for use in ThinLTO optimization).<br>
 ModulePass *createBitcodeWriterPass(raw_ostream &Str,<br>
-                                    bool ShouldPreserveUseListOrder = false);<br>
+                                    bool ShouldPreserveUseListOrder = false,<br>
+                                    bool EmitFunctionSummary = false);<br>
<br>
 /// \brief Pass for writing a module of IR out to a bitcode file.<br>
 ///<br>
@@ -39,15 +43,21 @@ ModulePass *createBitcodeWriterPass(raw_<br>
 class BitcodeWriterPass {<br>
   raw_ostream &OS;<br>
   bool ShouldPreserveUseListOrder;<br>
+  bool EmitFunctionSummary;<br>
<br>
 public:<br>
   /// \brief Construct a bitcode writer pass around a particular output stream.<br>
   ///<br>
   /// If \c ShouldPreserveUseListOrder, encode use-list order so it can be<br>
   /// reproduced when deserialized.<br>
+  ///<br>
+  /// If \c EmitFunctionSummary, emit the function summary index (currently<br>
+  /// for use in ThinLTO optimization).<br>
   explicit BitcodeWriterPass(raw_ostream &OS,<br>
-                             bool ShouldPreserveUseListOrder = false)<br>
-      : OS(OS), ShouldPreserveUseListOrder(ShouldPreserveUseListOrder) {}<br>
+                             bool ShouldPreserveUseListOrder = false,<br>
+                             bool EmitFunctionSummary = false)<br>
+      : OS(OS), ShouldPreserveUseListOrder(ShouldPreserveUseListOrder),<br>
+        EmitFunctionSummary(EmitFunctionSummary) {}<br>
<br>
   /// \brief Run the bitcode writer pass, and output the module to the selected<br>
   /// output stream.<br>
<br>
Modified: llvm/trunk/include/llvm/Bitcode/BitstreamWriter.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Bitcode/BitstreamWriter.h?rev=249270&r1=249269&r2=249270&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Bitcode/BitstreamWriter.h?rev=249270&r1=249269&r2=249270&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/Bitcode/BitstreamWriter.h (original)<br>
+++ llvm/trunk/include/llvm/Bitcode/BitstreamWriter.h Sun Oct  4 09:33:43 2015<br>
@@ -95,6 +95,9 @@ public:<br>
   /// \brief Retrieve the current position in the stream, in bits.<br>
   uint64_t GetCurrentBitNo() const { return GetBufferOffset() * 8 + CurBit; }<br>
<br>
+  /// \brief Retrieve the number of bits currently used to encode an abbrev ID.<br>
+  unsigned GetAbbrevIDWidth() const { return CurCodeSize; }<br>
+<br>
   //===--------------------------------------------------------------------===//<br>
   // Basic Primitives for emitting bits to the stream.<br>
   //===--------------------------------------------------------------------===//<br>
<br>
Modified: llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h?rev=249270&r1=249269&r2=249270&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h?rev=249270&r1=249269&r2=249270&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h (original)<br>
+++ llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h Sun Oct  4 09:33:43 2015<br>
@@ -150,6 +150,20 @@ namespace bitc {<br>
     VST_CODE_ENTRY   = 1,   // VST_ENTRY: [valueid, namechar x N]<br>
     VST_CODE_BBENTRY = 2,   // VST_BBENTRY: [bbid, namechar x N]<br>
     VST_CODE_FNENTRY = 3,   // VST_FNENTRY: [valueid, offset, namechar x N]<br>
+    // VST_COMBINED_FNENTRY: [offset, namechar x N]<br>
+    VST_CODE_COMBINED_FNENTRY = 4<br>
+  };<br>
+<br>
+  // The module path symbol table only has one code (MST_CODE_ENTRY).<br>
+  enum ModulePathSymtabCodes {<br>
+    MST_CODE_ENTRY   = 1,  // MST_ENTRY: [modid, namechar x N]<br>
+  };<br>
+<br>
+  // The function summary section uses different codes in the per-module<br>
+  // and combined index cases.<br>
+  enum FunctionSummarySymtabCodes {<br>
+    FS_CODE_PERMODULE_ENTRY = 1,  // FS_ENTRY: [valueid, islocal, instcount]<br>
+    FS_CODE_COMBINED_ENTRY  = 2,  // FS_ENTRY: [modid, instcount]<br>
   };<br>
<br>
   enum MetadataCodes {<br>
<br>
Modified: llvm/trunk/include/llvm/Bitcode/ReaderWriter.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Bitcode/ReaderWriter.h?rev=249270&r1=249269&r2=249270&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Bitcode/ReaderWriter.h?rev=249270&r1=249269&r2=249270&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/Bitcode/ReaderWriter.h (original)<br>
+++ llvm/trunk/include/llvm/Bitcode/ReaderWriter.h Sun Oct  4 09:33:43 2015<br>
@@ -15,6 +15,7 @@<br>
 #define LLVM_BITCODE_READERWRITER_H<br>
<br>
 #include "llvm/IR/DiagnosticInfo.h"<br>
+#include "llvm/IR/FunctionInfo.h"<br>
 #include "llvm/Support/Endian.h"<br>
 #include "llvm/Support/ErrorOr.h"<br>
 #include "llvm/Support/MemoryBuffer.h"<br>
@@ -58,6 +59,30 @@ namespace llvm {<br>
   parseBitcodeFile(MemoryBufferRef Buffer, LLVMContext &Context,<br>
                    DiagnosticHandlerFunction DiagnosticHandler = nullptr);<br>
<br>
+  /// Check if the given bitcode buffer contains a function summary block.<br>
+  bool hasFunctionSummary(MemoryBufferRef Buffer, LLVMContext &Context,<br>
+                          DiagnosticHandlerFunction DiagnosticHandler);<br>
+<br>
+  /// Parse the specified bitcode buffer, returning the function info index.<br>
+  /// If IsLazy is true, parse the entire function summary into<br>
+  /// the index. Otherwise skip the function summary section, and only create<br>
+  /// an index object with a map from function name to function summary offset.<br>
+  /// The index is used to perform lazy function summary reading later.<br>
+  ErrorOr<std::unique_ptr<FunctionInfoIndex>> getFunctionInfoIndex(<br>
+      MemoryBufferRef Buffer, LLVMContext &Context,<br>
+      DiagnosticHandlerFunction DiagnosticHandler, bool IsLazy = false);<br>
+<br>
+  /// This method supports lazy reading of function summary data from the<br>
+  /// combined index during function importing. When reading the combined index<br>
+  /// file, getFunctionInfoIndex is first invoked with IsLazy=true.<br>
+  /// Then this method is called for each function considered for importing,<br>
+  /// to parse the summary information for the given function name into<br>
+  /// the index.<br>
+  std::error_code readFunctionSummary(<br>
+      MemoryBufferRef Buffer, LLVMContext &Context,<br>
+      DiagnosticHandlerFunction DiagnosticHandler, StringRef FunctionName,<br>
+      std::unique_ptr<FunctionInfoIndex> Index);<br>
+<br>
   /// \brief Write the specified module to the specified raw output stream.<br>
   ///<br>
   /// For streams where it matters, the given stream should be in "binary"<br>
@@ -66,8 +91,18 @@ namespace llvm {<br>
   /// If \c ShouldPreserveUseListOrder, encode the use-list order for each \a<br>
   /// Value in \c M.  These will be reconstructed exactly when \a M is<br>
   /// deserialized.<br>
+  ///<br>
+  /// If \c EmitFunctionSummary, emit the function summary index (currently<br>
+  /// for use in ThinLTO optimization).<br>
   void WriteBitcodeToFile(const Module *M, raw_ostream &Out,<br>
-                          bool ShouldPreserveUseListOrder = false);<br>
+                          bool ShouldPreserveUseListOrder = false,<br>
+                          bool EmitFunctionSummary = false);<br>
+<br>
+  /// Write the specified function summary index to the given raw output stream,<br>
+  /// where it will be written in a new bitcode block. This is used when<br>
+  /// writing the combined index file for ThinLTO.<br>
+  void WriteFunctionSummaryToFile(const FunctionInfoIndex *Index,<br>
+                                  raw_ostream &Out);<br>
<br>
   /// isBitcodeWrapper - Return true if the given bytes are the magic bytes<br>
   /// for an LLVM IR bitcode wrapper.<br>
<br>
Added: llvm/trunk/include/llvm/IR/FunctionInfo.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/FunctionInfo.h?rev=249270&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/FunctionInfo.h?rev=249270&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/IR/FunctionInfo.h (added)<br>
+++ llvm/trunk/include/llvm/IR/FunctionInfo.h Sun Oct  4 09:33:43 2015<br>
@@ -0,0 +1,230 @@<br>
+//===-- llvm/FunctionInfo.h - Function Info Index ---------------*- C++ -*-===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+//<br>
+/// @file<br>
+/// FunctionInfo.h This file contains the declarations the classes that hold<br>
+///  the function info index and summary.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#ifndef LLVM_IR_FUNCTIONINFO_H<br>
+#define LLVM_IR_FUNCTIONINFO_H<br>
+<br>
+#include "llvm/ADT/SmallString.h"<br>
+#include "llvm/ADT/StringMap.h"<br>
+#include "llvm/IR/Module.h"<br>
+#include "llvm/Support/MemoryBuffer.h"<br>
+#include "llvm/Support/raw_ostream.h"<br>
+<br>
+namespace llvm {<br>
+<br>
+/// \brief Function summary information to aid decisions and implementation of<br>
+/// importing.<br>
+///<br>
+/// This is a separate class from FunctionInfo to enable lazy reading of this<br>
+/// function summary information from the combined index file during imporing.<br>
+class FunctionSummary {<br>
+ private:<br>
+  /// \brief Path of module containing function IR, used to locate module when<br>
+  /// importing this function.<br>
+  ///<br>
+  /// This is only used during parsing of the combined function index, or when<br>
+  /// parsing the per-module index for creation of the combined function index,<br>
+  /// not during writing of the per-module index which doesn't contain a<br>
+  /// module path string table.<br>
+  StringRef ModulePath;<br>
+<br>
+  /// \brief Used to flag functions that have local linkage types and need to<br>
+  /// have module identifier appended before placing into the combined<br>
+  /// index, to disambiguate from other functions with the same name.<br>
+  ///<br>
+  /// This is only used in the per-module function index, as it is consumed<br>
+  /// while creating the combined index.<br>
+  bool IsLocalFunction;<br>
+<br>
+  // The rest of the information is used to help decide whether importing<br>
+  // is likely to be profitable.<br>
+  // Other information will be added as the importing is tuned, such<br>
+  // as hotness (when profile available), and other function characteristics.<br>
+<br>
+  /// Number of instructions (ignoring debug instructions, e.g.) computed<br>
+  /// during the initial compile step when the function index is first built.<br>
+  unsigned InstCount;<br>
+<br>
+ public:<br>
+  /// Construct a summary object from summary data expected for all<br>
+  /// summary records.<br>
+  FunctionSummary(unsigned NumInsts) : InstCount(NumInsts) {}<br>
+<br>
+  /// Set the path to the module containing this function, for use in<br>
+  /// the combined index.<br>
+  void setModulePath(StringRef ModPath) { ModulePath = ModPath; }<br>
+<br>
+  /// Get the path to the module containing this function.<br>
+  StringRef modulePath() const { return ModulePath; }<br>
+<br>
+  /// Record whether this is a local function in the per-module index.<br>
+  void setLocalFunction(bool IsLocal) { IsLocalFunction = IsLocal; }<br>
+<br>
+  /// Check whether this was a local function, for use in creating<br>
+  /// the combined index.<br>
+  bool isLocalFunction() const { return IsLocalFunction; }<br>
+<br>
+  /// Get the instruction count recorded for this function.<br>
+  unsigned instCount() const { return InstCount; }<br>
+};<br>
+<br>
+/// \brief Class to hold pointer to function summary and information required<br>
+/// for parsing it.<br>
+///<br>
+/// For the per-module index, this holds the bitcode offset<br>
+/// of the corresponding function block. For the combined index,<br>
+/// after parsing of the \a ValueSymbolTable, this initially<br>
+/// holds the offset of the corresponding function summary bitcode<br>
+/// record. After parsing the associated summary information from the summary<br>
+/// block the \a FunctionSummary is populated and stored here.<br>
+class FunctionInfo {<br>
+ private:<br>
+  /// Function summary information used to help make ThinLTO importing<br>
+  /// decisions.<br>
+  std::unique_ptr<FunctionSummary> Summary;<br>
+<br>
+  /// \brief The bitcode offset corresponding to either the associated<br>
+  /// function's function body record, or its function summary record,<br>
+  /// depending on whether this is a per-module or combined index.<br>
+  ///<br>
+  /// This bitcode offset is written to or read from the associated<br>
+  /// \a ValueSymbolTable entry for the function.<br>
+  /// For the per-module index this holds the bitcode offset of the<br>
+  /// function's body record  within bitcode module block in its module,<br>
+  /// which is used during lazy function parsing or ThinLTO importing.<br>
+  /// For the combined index this holds the offset of the corresponding<br>
+  /// function summary record, to enable associating the combined index<br>
+  /// VST records with the summary records.<br>
+  uint64_t BitcodeIndex;<br>
+<br>
+ public:<br>
+  /// Constructor used during parsing of VST entries.<br>
+  FunctionInfo(uint64_t FuncOffset)<br>
+      : Summary(nullptr), BitcodeIndex(FuncOffset) {}<br>
+<br>
+  /// Constructor used for per-module index bitcode writing.<br>
+  FunctionInfo(uint64_t FuncOffset,<br>
+               std::unique_ptr<FunctionSummary> FuncSummary)<br>
+      : Summary(std::move(FuncSummary)), BitcodeIndex(FuncOffset) {}<br>
+<br>
+  /// Record the function summary information parsed out of the function<br>
+  /// summary block during parsing or combined index creation.<br>
+  void setFunctionSummary(std::unique_ptr<FunctionSummary> FuncSummary) {<br>
+    Summary = std::move(FuncSummary);<br>
+  }<br>
+<br>
+  /// Get the function summary recorded for this function.<br>
+  FunctionSummary *functionSummary() const { return Summary.get(); }<br>
+<br>
+  /// Get the bitcode index recorded for this function, depending on<br>
+  /// the index type.<br>
+  uint64_t bitcodeIndex() const { return BitcodeIndex; }<br>
+<br>
+  /// Record the bitcode index for this function, depending on<br>
+  /// the index type.<br>
+  void setBitcodeIndex(uint64_t FuncOffset) { BitcodeIndex = FuncOffset; }<br>
+};<br>
+<br>
+/// List of function info structures for a particular function name held<br>
+/// in the FunctionMap. Requires a vector in the case of multiple<br>
+/// COMDAT functions of the same name.<br>
+typedef std::vector<std::unique_ptr<FunctionInfo>> FunctionInfoList;<br>
+<br>
+/// Map from function name to corresponding function info structures.<br>
+typedef StringMap<FunctionInfoList> FunctionInfoMapTy;<br>
+<br>
+/// Type used for iterating through the function info map.<br>
+typedef FunctionInfoMapTy::const_iterator const_funcinfo_iterator;<br>
+typedef FunctionInfoMapTy::iterator funcinfo_iterator;<br>
+<br>
+/// String table to hold/own module path strings, which additionally holds the<br>
+/// module ID assigned to each module during the plugin step. The StringMap<br>
+/// makes a copy of and owns inserted strings.<br>
+typedef StringMap<uint64_t> ModulePathStringTableTy;<br>
+<br>
+/// Class to hold module path string table and function map,<br>
+/// and encapsulate methods for operating on them.<br>
+class FunctionInfoIndex {<br>
+ private:<br>
+  /// Map from function name to list of function information instances<br>
+  /// for functions of that name (may be duplicates in the COMDAT case, e.g.).<br>
+  FunctionInfoMapTy FunctionMap;<br>
+<br>
+  /// Holds strings for combined index, mapping to the corresponding module ID.<br>
+  ModulePathStringTableTy ModulePathStringTable;<br>
+<br>
+ public:<br>
+  FunctionInfoIndex() = default;<br>
+  ~FunctionInfoIndex() = default;<br>
+<br>
+  // Disable the copy constructor and assignment operators, so<br>
+  // no unexpected copying/moving occurs.<br>
+  FunctionInfoIndex(const FunctionInfoIndex &) = delete;<br>
+  void operator=(const FunctionInfoIndex &) = delete;<br>
+<br>
+  funcinfo_iterator begin() { return FunctionMap.begin(); }<br>
+  const_funcinfo_iterator begin() const { return FunctionMap.begin(); }<br>
+  funcinfo_iterator end() { return FunctionMap.end(); }<br>
+  const_funcinfo_iterator end() const { return FunctionMap.end(); }<br>
+<br>
+  /// Get the list of function info objects for a given function.<br>
+  const FunctionInfoList &getFunctionInfoList(StringRef FuncName) {<br>
+    return FunctionMap[FuncName];<br>
+  }<br>
+<br>
+  /// Add a function info for a function of the given name.<br>
+  void addFunctionInfo(StringRef FuncName, std::unique_ptr<FunctionInfo> Info) {<br>
+    FunctionMap[FuncName].push_back(std::move(Info));<br>
+  }<br>
+<br>
+  /// Iterator to allow writer to walk through table during emission.<br>
+  iterator_range<StringMap<uint64_t>::const_iterator> modPathStringEntries()<br>
+      const {<br>
+    return llvm::make_range(ModulePathStringTable.begin(),<br>
+                            ModulePathStringTable.end());<br>
+  }<br>
+<br>
+  /// Get the module ID recorded for the given module path.<br>
+  uint64_t getModuleId(const StringRef ModPath) const {<br>
+    return ModulePathStringTable.lookup(ModPath);<br>
+  }<br>
+<br>
+  /// Add the given per-module index into this function index/summary,<br>
+  /// assigning it the given module ID. Each module merged in should have<br>
+  /// a unique ID, necessary for consistent renaming of promoted<br>
+  /// static (local) variables.<br>
+  void mergeFrom(std::unique_ptr<FunctionInfoIndex> Other,<br>
+                 uint64_t NextModuleId);<br>
+<br>
+  /// Convenience method for creating a promoted global name<br>
+  /// for the given value name of a local, and its original module's ID.<br>
+  static std::string getGlobalNameForLocal(StringRef Name, uint64_t ModId) {<br>
+    SmallString<256> NewName(Name);<br>
+    NewName += ".llvm.";<br>
+    raw_svector_ostream(NewName) << ModId;<br>
+    return NewName.str();<br>
+  }<br>
+<br>
+  /// Add a new module path, mapped to the given module Id, and return StringRef<br>
+  /// owned by string table map.<br>
+  StringRef addModulePath(StringRef ModPath, uint64_t ModId) {<br>
+    return ModulePathStringTable.insert(std::make_pair(ModPath, ModId))<br>
+        .first->first();<br>
+  }<br>
+};<br>
+<br>
+}  // End llvm namespace<br>
+<br>
+#endif<br>
<br>
Modified: llvm/trunk/include/llvm/Object/Binary.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Object/Binary.h?rev=249270&r1=249269&r2=249270&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Object/Binary.h?rev=249270&r1=249269&r2=249270&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/Object/Binary.h (original)<br>
+++ llvm/trunk/include/llvm/Object/Binary.h Sun Oct  4 09:33:43 2015<br>
@@ -43,6 +43,7 @@ protected:<br>
     ID_MachOUniversalBinary,<br>
     ID_COFFImportFile,<br>
     ID_IR, // LLVM IR<br>
+    ID_FunctionIndex, // Function summary index<br>
<br>
     // Object and children.<br>
     ID_StartObjects,<br>
@@ -122,6 +123,10 @@ public:<br>
     return TypeID == ID_IR;<br>
   }<br>
<br>
+  bool isFunctionIndex() const {<br>
+    return TypeID == ID_FunctionIndex;<br>
+  }<br>
+<br>
   bool isLittleEndian() const {<br>
     return !(TypeID == ID_ELF32B || TypeID == ID_ELF64B ||<br>
              TypeID == ID_MachO32B || TypeID == ID_MachO64B);<br>
<br>
Added: llvm/trunk/include/llvm/Object/FunctionIndexObjectFile.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Object/FunctionIndexObjectFile.h?rev=249270&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Object/FunctionIndexObjectFile.h?rev=249270&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/Object/FunctionIndexObjectFile.h (added)<br>
+++ llvm/trunk/include/llvm/Object/FunctionIndexObjectFile.h Sun Oct  4 09:33:43 2015<br>
@@ -0,0 +1,99 @@<br>
+//===- FunctionIndexObjectFile.h - Function index file implementation -----===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+//<br>
+// This file declares the FunctionIndexObjectFile template class.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#ifndef LLVM_OBJECT_FUNCTIONINDEXOBJECTFILE_H<br>
+#define LLVM_OBJECT_FUNCTIONINDEXOBJECTFILE_H<br>
+<br>
+#include "llvm/Object/SymbolicFile.h"<br>
+<br>
+namespace llvm {<br>
+class FunctionInfoIndex;<br>
+<br>
+namespace object {<br>
+class ObjectFile;<br>
+<br>
+/// This class is used to read just the function summary index related<br>
+/// sections out of the given object (which may contain a single module's<br>
+/// bitcode or be a combined index bitcode file). It builds a FunctionInfoIndex<br>
+/// object.<br>
+class FunctionIndexObjectFile : public SymbolicFile {<br>
+  std::unique_ptr<FunctionInfoIndex> Index;<br>
+<br>
+ public:<br>
+  FunctionIndexObjectFile(MemoryBufferRef Object,<br>
+                          std::unique_ptr<FunctionInfoIndex> I);<br>
+  ~FunctionIndexObjectFile() override;<br>
+<br>
+  // TODO: Walk through FunctionMap entries for function symbols.<br>
+  // However, currently these interfaces are not used by any consumers.<br>
+  void moveSymbolNext(DataRefImpl &Symb) const override {<br>
+    llvm_unreachable("not implemented");<br>
+  }<br>
+  std::error_code printSymbolName(raw_ostream &OS,<br>
+                                  DataRefImpl Symb) const override {<br>
+    llvm_unreachable("not implemented");<br>
+    return std::error_code();<br>
+  }<br>
+  uint32_t getSymbolFlags(DataRefImpl Symb) const override {<br>
+    llvm_unreachable("not implemented");<br>
+    return 0;<br>
+  }<br>
+  basic_symbol_iterator symbol_begin_impl() const override {<br>
+    llvm_unreachable("not implemented");<br>
+    return basic_symbol_iterator(BasicSymbolRef());<br>
+  }<br>
+  basic_symbol_iterator symbol_end_impl() const override {<br>
+    llvm_unreachable("not implemented");<br>
+    return basic_symbol_iterator(BasicSymbolRef());<br>
+  }<br>
+<br>
+  const FunctionInfoIndex &getIndex() const {<br>
+    return const_cast<FunctionIndexObjectFile *>(this)->getIndex();<br>
+  }<br>
+  FunctionInfoIndex &getIndex() { return *Index; }<br>
+  std::unique_ptr<FunctionInfoIndex> takeIndex();<br>
+<br>
+  static inline bool classof(const Binary *v) { return v->isFunctionIndex(); }<br>
+<br>
+  /// \brief Finds and returns bitcode embedded in the given object file, or an<br>
+  /// error code if not found.<br>
+  static ErrorOr<MemoryBufferRef> findBitcodeInObject(const ObjectFile &Obj);<br>
+<br>
+  /// \brief Finds and returns bitcode in the given memory buffer (which may<br>
+  /// be either a bitcode file or a native object file with embedded bitcode),<br>
+  /// or an error code if not found.<br>
+  static ErrorOr<MemoryBufferRef> findBitcodeInMemBuffer(<br>
+      MemoryBufferRef Object);<br>
+<br>
+  /// \brief Looks for function summary in the given memory buffer,<br>
+  /// returns true if found, else false.<br>
+  static bool hasFunctionSummaryInMemBuffer(MemoryBufferRef Object,<br>
+                                            LLVMContext &Context);<br>
+<br>
+  /// \brief Parse function index in the given memory buffer.<br>
+  /// Return new FunctionIndexObjectFile instance containing parsed function<br>
+  /// summary/index.<br>
+  static ErrorOr<std::unique_ptr<FunctionIndexObjectFile>> create(<br>
+      MemoryBufferRef Object, LLVMContext &Context, bool IsLazy = false);<br>
+<br>
+  /// \brief Parse the function summary information for function with the<br>
+  /// given name out of the given buffer. Parsed information is<br>
+  /// stored on the index object saved in this object.<br>
+  std::error_code findFunctionSummaryInMemBuffer(MemoryBufferRef Object,<br>
+                                                 LLVMContext &Context,<br>
+                                                 StringRef FunctionName);<br>
+};<br>
+}<br>
+}<br>
+<br>
+#endif<br>
<br>
Modified: llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp?rev=249270&r1=249269&r2=249270&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp?rev=249270&r1=249269&r2=249270&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp (original)<br>
+++ llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp Sun Oct  4 09:33:43 2015<br>
@@ -27,6 +27,7 @@<br>
 #include "llvm/IR/Module.h"<br>
 #include "llvm/IR/OperandTraits.h"<br>
 #include "llvm/IR/Operator.h"<br>
+#include "llvm/IR/FunctionInfo.h"<br>
 #include "llvm/IR/ValueHandle.h"<br>
 #include "llvm/Support/DataStream.h"<br>
 #include "llvm/Support/ManagedStatic.h"<br>
@@ -395,6 +396,96 @@ private:<br>
       Function *F,<br>
       DenseMap<Function *, uint64_t>::iterator DeferredFunctionInfoIterator);<br>
 };<br>
+<br>
+/// Class to manage reading and parsing function summary index bitcode<br>
+/// files/sections.<br>
+class FunctionIndexBitcodeReader {<br>
+  LLVMContext &Context;<br>
+  DiagnosticHandlerFunction DiagnosticHandler;<br>
+<br>
+  /// Eventually points to the function index built during parsing.<br>
+  FunctionInfoIndex *TheIndex = nullptr;<br>
+<br>
+  std::unique_ptr<MemoryBuffer> Buffer;<br>
+  std::unique_ptr<BitstreamReader> StreamFile;<br>
+  BitstreamCursor Stream;<br>
+<br>
+  /// \brief Used to indicate whether we are doing lazy parsing of summary data.<br>
+  ///<br>
+  /// If false, the summary section is fully parsed into the index during<br>
+  /// the initial parse. Otherwise, if true, the caller is expected to<br>
+  /// invoke \a readFunctionSummary for each summary needed, and the summary<br>
+  /// section is thus parsed lazily.<br>
+  bool IsLazy = false;<br>
+<br>
+  /// Used to indicate whether caller only wants to check for the presence<br>
+  /// of the function summary bitcode section. All blocks are skipped,<br>
+  /// but the SeenFuncSummary boolean is set.<br>
+  bool CheckFuncSummaryPresenceOnly = false;<br>
+<br>
+  /// Indicates whether we have encountered a function summary section<br>
+  /// yet during parsing, used when checking if file contains function<br>
+  /// summary section.<br>
+  bool SeenFuncSummary = false;<br>
+<br>
+  /// \brief Map populated during function summary section parsing, and<br>
+  /// consumed during ValueSymbolTable parsing.<br>
+  ///<br>
+  /// Used to correlate summary records with VST entries. For the per-module<br>
+  /// index this maps the ValueID to the parsed function summary, and<br>
+  /// for the combined index this maps the summary record's bitcode<br>
+  /// offset to the function summary (since in the combined index the<br>
+  /// VST records do not hold value IDs but rather hold the function<br>
+  /// summary record offset).<br>
+  DenseMap<uint64_t, std::unique_ptr<FunctionSummary>> SummaryMap;<br>
+<br>
+  /// Map populated during module path string table parsing, from the<br>
+  /// module ID to a string reference owned by the index's module<br>
+  /// path string table, used to correlate with combined index function<br>
+  /// summary records.<br>
+  DenseMap<uint64_t, StringRef> ModuleIdMap;<br>
+<br>
+ public:<br>
+  std::error_code error(BitcodeError E, const Twine &Message);<br>
+  std::error_code error(BitcodeError E);<br>
+  std::error_code error(const Twine &Message);<br>
+<br>
+  FunctionIndexBitcodeReader(MemoryBuffer *Buffer, LLVMContext &Context,<br>
+                             DiagnosticHandlerFunction DiagnosticHandler,<br>
+                             bool IsLazy = false,<br>
+                             bool CheckFuncSummaryPresenceOnly = false);<br>
+  FunctionIndexBitcodeReader(LLVMContext &Context,<br>
+                             DiagnosticHandlerFunction DiagnosticHandler,<br>
+                             bool IsLazy = false,<br>
+                             bool CheckFuncSummaryPresenceOnly = false);<br>
+  ~FunctionIndexBitcodeReader() { freeState(); }<br>
+<br>
+  void freeState();<br>
+<br>
+  void releaseBuffer();<br>
+<br>
+  /// Check if the parser has encountered a function summary section.<br>
+  bool foundFuncSummary() { return SeenFuncSummary; }<br>
+<br>
+  /// \brief Main interface to parsing a bitcode buffer.<br>
+  /// \returns true if an error occurred.<br>
+  std::error_code parseSummaryIndexInto(std::unique_ptr<DataStreamer> Streamer,<br>
+                                        FunctionInfoIndex *I);<br>
+<br>
+  /// \brief Interface for parsing a function summary lazily.<br>
+  std::error_code parseFunctionSummary(std::unique_ptr<DataStreamer> Streamer,<br>
+                                       FunctionInfoIndex *I,<br>
+                                       size_t FunctionSummaryOffset);<br>
+<br>
+ private:<br>
+  std::error_code parseModule();<br>
+  std::error_code parseValueSymbolTable();<br>
+  std::error_code parseEntireSummary();<br>
+  std::error_code parseModuleStringTable();<br>
+  std::error_code initStream(std::unique_ptr<DataStreamer> Streamer);<br>
+  std::error_code initStreamFromBuffer();<br>
+  std::error_code initLazyStream(std::unique_ptr<DataStreamer> Streamer);<br>
+};<br>
 } // namespace<br>
<br>
 BitcodeDiagnosticInfo::BitcodeDiagnosticInfo(std::error_code EC,<br>
@@ -3377,6 +3468,19 @@ std::error_code BitcodeReader::parseModu<br>
   }<br>
 }<br>
<br>
+/// Helper to read the header common to all bitcode files.<br>
+static bool hasValidBitcodeHeader(BitstreamCursor &Stream) {<br>
+  // Sniff for the signature.<br>
+  if (Stream.Read(8) != 'B' ||<br>
+      Stream.Read(8) != 'C' ||<br>
+      Stream.Read(4) != 0x0 ||<br>
+      Stream.Read(4) != 0xC ||<br>
+      Stream.Read(4) != 0xE ||<br>
+      Stream.Read(4) != 0xD)<br>
+    return false;<br>
+  return true;<br>
+}<br>
+<br>
 std::error_code<br>
 BitcodeReader::parseBitcodeInto(std::unique_ptr<DataStreamer> Streamer,<br>
                                 Module *M, bool ShouldLazyLoadMetadata) {<br>
@@ -3386,13 +3490,7 @@ BitcodeReader::parseBitcodeInto(std::uni<br>
     return EC;<br>
<br>
   // Sniff for the signature.<br>
-  if (Stream.Read(8) != 'B' ||<br>
-      Stream.Read(8) != 'C' ||<br>
-      Stream.Read(4) != 0x0 ||<br>
-      Stream.Read(4) != 0xC ||<br>
-      Stream.Read(4) != 0xE ||<br>
-      Stream.Read(4) != 0xD)<br>
-    return error("Invalid bitcode signature");<br>
+  if (!hasValidBitcodeHeader(Stream)) return error("Invalid bitcode signature");<br>
<br>
   // We expect a number of well-defined blocks, though we don't necessarily<br>
   // need to understand them all.<br>
@@ -3459,13 +3557,7 @@ ErrorOr<std::string> BitcodeReader::pars<br>
     return EC;<br>
<br>
   // Sniff for the signature.<br>
-  if (Stream.Read(8) != 'B' ||<br>
-      Stream.Read(8) != 'C' ||<br>
-      Stream.Read(4) != 0x0 ||<br>
-      Stream.Read(4) != 0xC ||<br>
-      Stream.Read(4) != 0xE ||<br>
-      Stream.Read(4) != 0xD)<br>
-    return error("Invalid bitcode signature");<br>
+  if (!hasValidBitcodeHeader(Stream)) return error("Invalid bitcode signature");<br>
<br>
   // We expect a number of well-defined blocks, though we don't necessarily<br>
   // need to understand them all.<br>
@@ -5060,6 +5152,405 @@ BitcodeReader::initLazyStream(std::uniqu<br>
   return std::error_code();<br>
 }<br>
<br>
+std::error_code FunctionIndexBitcodeReader::error(BitcodeError E,<br>
+                                                  const Twine &Message) {<br>
+  return ::error(DiagnosticHandler, make_error_code(E), Message);<br>
+}<br>
+<br>
+std::error_code FunctionIndexBitcodeReader::error(const Twine &Message) {<br>
+  return ::error(DiagnosticHandler,<br>
+                 make_error_code(BitcodeError::CorruptedBitcode), Message);<br>
+}<br>
+<br>
+std::error_code FunctionIndexBitcodeReader::error(BitcodeError E) {<br>
+  return ::error(DiagnosticHandler, make_error_code(E));<br>
+}<br>
+<br>
+FunctionIndexBitcodeReader::FunctionIndexBitcodeReader(<br>
+    MemoryBuffer *Buffer, LLVMContext &Context,<br>
+    DiagnosticHandlerFunction DiagnosticHandler, bool IsLazy,<br>
+    bool CheckFuncSummaryPresenceOnly)<br>
+    : Context(Context),<br>
+      DiagnosticHandler(getDiagHandler(DiagnosticHandler, Context)),<br>
+      Buffer(Buffer),<br>
+      IsLazy(IsLazy),<br>
+      CheckFuncSummaryPresenceOnly(CheckFuncSummaryPresenceOnly) {}<br>
+<br>
+FunctionIndexBitcodeReader::FunctionIndexBitcodeReader(<br>
+    LLVMContext &Context, DiagnosticHandlerFunction DiagnosticHandler,<br>
+    bool IsLazy, bool CheckFuncSummaryPresenceOnly)<br>
+    : Context(Context),<br>
+      DiagnosticHandler(getDiagHandler(DiagnosticHandler, Context)),<br>
+      Buffer(nullptr),<br>
+      IsLazy(IsLazy),<br>
+      CheckFuncSummaryPresenceOnly(CheckFuncSummaryPresenceOnly) {}<br>
+<br>
+void FunctionIndexBitcodeReader::freeState() { Buffer = nullptr; }<br>
+<br>
+void FunctionIndexBitcodeReader::releaseBuffer() { Buffer.release(); }<br>
+<br>
+// Specialized value symbol table parser used when reading function index<br>
+// blocks where we don't actually create global values.<br>
+// At the end of this routine the function index is populated with a map<br>
+// from function name to FunctionInfo. The function info contains<br>
+// the function block's bitcode offset as well as the offset into the<br>
+// function summary section.<br>
+std::error_code FunctionIndexBitcodeReader::parseValueSymbolTable() {<br>
+  if (Stream.EnterSubBlock(bitc::VALUE_SYMTAB_BLOCK_ID))<br>
+    return error("Invalid record");<br>
+<br>
+  SmallVector<uint64_t, 64> Record;<br>
+<br>
+  // Read all the records for this value table.<br>
+  SmallString<128> ValueName;<br>
+  while (1) {<br>
+    BitstreamEntry Entry = Stream.advanceSkippingSubblocks();<br>
+<br>
+    switch (Entry.Kind) {<br>
+      case BitstreamEntry::SubBlock:  // Handled for us already.<br>
+      case BitstreamEntry::Error:<br>
+        return error("Malformed block");<br>
+      case BitstreamEntry::EndBlock:<br>
+        return std::error_code();<br>
+      case BitstreamEntry::Record:<br>
+        // The interesting case.<br>
+        break;<br>
+    }<br>
+<br>
+    // Read a record.<br>
+    Record.clear();<br>
+    switch (Stream.readRecord(Entry.ID, Record)) {<br>
+      default:  // Default behavior: ignore (e.g. VST_CODE_BBENTRY records).<br>
+        break;<br>
+      case bitc::VST_CODE_FNENTRY: {<br>
+        // VST_FNENTRY: [valueid, offset, namechar x N]<br>
+        if (convertToString(Record, 2, ValueName))<br>
+          return error("Invalid record");<br>
+        unsigned ValueID = Record[0];<br>
+        uint64_t FuncOffset = Record[1];<br>
+        std::unique_ptr<FunctionInfo> FuncInfo =<br>
+            llvm::make_unique<FunctionInfo>(FuncOffset);<br>
+        if (foundFuncSummary() && !IsLazy) {<br>
+          DenseMap<uint64_t, std::unique_ptr<FunctionSummary>>::iterator SMI =<br>
+              SummaryMap.find(ValueID);<br>
+          assert(SMI != SummaryMap.end() && "Summary info not found");<br>
+          FuncInfo->setFunctionSummary(std::move(SMI->second));<br>
+        }<br>
+        TheIndex->addFunctionInfo(ValueName, std::move(FuncInfo));<br>
+<br>
+        ValueName.clear();<br>
+        break;<br>
+      }<br>
+      case bitc::VST_CODE_COMBINED_FNENTRY: {<br>
+        // VST_FNENTRY: [offset, namechar x N]<br>
+        if (convertToString(Record, 1, ValueName))<br>
+          return error("Invalid record");<br>
+        uint64_t FuncSummaryOffset = Record[0];<br>
+        std::unique_ptr<FunctionInfo> FuncInfo =<br>
+            llvm::make_unique<FunctionInfo>(FuncSummaryOffset);<br>
+        if (foundFuncSummary() && !IsLazy) {<br>
+          DenseMap<uint64_t, std::unique_ptr<FunctionSummary>>::iterator SMI =<br>
+              SummaryMap.find(FuncSummaryOffset);<br>
+          assert(SMI != SummaryMap.end() && "Summary info not found");<br>
+          FuncInfo->setFunctionSummary(std::move(SMI->second));<br>
+        }<br>
+        TheIndex->addFunctionInfo(ValueName, std::move(FuncInfo));<br>
+<br>
+        ValueName.clear();<br>
+        break;<br>
+      }<br>
+    }<br>
+  }<br>
+}<br>
+<br>
+// Parse just the blocks needed for function index building out of the module.<br>
+// At the end of this routine the function Index is populated with a map<br>
+// from function name to FunctionInfo. The function info contains<br>
+// either the parsed function summary information (when parsing summaries<br>
+// eagerly), or just to the function summary record's offset<br>
+// if parsing lazily (IsLazy).<br>
+std::error_code FunctionIndexBitcodeReader::parseModule() {<br>
+  if (Stream.EnterSubBlock(bitc::MODULE_BLOCK_ID))<br>
+    return error("Invalid record");<br>
+<br>
+  // Read the function index for this module.<br>
+  while (1) {<br>
+    BitstreamEntry Entry = Stream.advance();<br>
+<br>
+    switch (Entry.Kind) {<br>
+      case BitstreamEntry::Error:<br>
+        return error("Malformed block");<br>
+      case BitstreamEntry::EndBlock:<br>
+        return std::error_code();<br>
+<br>
+      case BitstreamEntry::SubBlock:<br>
+        if (CheckFuncSummaryPresenceOnly) {<br>
+          if (Entry.ID == bitc::FUNCTION_SUMMARY_BLOCK_ID)<br>
+            SeenFuncSummary = true;<br>
+          if (Stream.SkipBlock()) return error("Invalid record");<br>
+          // No need to parse the rest since we found the summary.<br>
+          return std::error_code();<br>
+        }<br>
+        switch (Entry.ID) {<br>
+          default:  // Skip unknown content.<br>
+            if (Stream.SkipBlock()) return error("Invalid record");<br>
+            break;<br>
+          case bitc::BLOCKINFO_BLOCK_ID:<br>
+            // Need to parse these to get abbrev ids (e.g. for VST)<br>
+            if (Stream.ReadBlockInfoBlock()) return error("Malformed block");<br>
+            break;<br>
+          case bitc::VALUE_SYMTAB_BLOCK_ID:<br>
+            if (std::error_code EC = parseValueSymbolTable()) return EC;<br>
+            break;<br>
+          case bitc::FUNCTION_SUMMARY_BLOCK_ID:<br>
+            SeenFuncSummary = true;<br>
+            if (IsLazy) {<br>
+              // Lazy parsing of summary info, skip it.<br>
+              if (Stream.SkipBlock()) return error("Invalid record");<br>
+            } else if (std::error_code EC = parseEntireSummary())<br>
+              return EC;<br>
+            break;<br>
+          case bitc::MODULE_STRTAB_BLOCK_ID:<br>
+            if (std::error_code EC = parseModuleStringTable()) return EC;<br>
+            break;<br>
+        }<br>
+        continue;<br>
+<br>
+      case BitstreamEntry::Record:<br>
+        Stream.skipRecord(Entry.ID);<br>
+        continue;<br>
+    }<br>
+  }<br>
+}<br>
+<br>
+// Eagerly parse the entire function summary block (i.e. for all functions<br>
+// in the index). This populates the FunctionSummary objects in<br>
+// the index.<br>
+std::error_code FunctionIndexBitcodeReader::parseEntireSummary() {<br>
+  if (Stream.EnterSubBlock(bitc::FUNCTION_SUMMARY_BLOCK_ID))<br>
+    return error("Invalid record");<br>
+<br>
+  SmallVector<uint64_t, 64> Record;<br>
+<br>
+  while (1) {<br>
+    BitstreamEntry Entry = Stream.advanceSkippingSubblocks();<br>
+<br>
+    switch (Entry.Kind) {<br>
+      case BitstreamEntry::SubBlock:  // Handled for us already.<br>
+      case BitstreamEntry::Error:<br>
+        return error("Malformed block");<br>
+      case BitstreamEntry::EndBlock:<br>
+        return std::error_code();<br>
+      case BitstreamEntry::Record:<br>
+        // The interesting case.<br>
+        break;<br>
+    }<br>
+<br>
+    // Read a record. The record format depends on whether this<br>
+    // is a per-module index or a combined index file. In the per-module<br>
+    // case the records contain the associated value's ID for correlation<br>
+    // with VST entries. In the combined index the correlation is done<br>
+    // via the bitcode offset of the summary records (which were saved<br>
+    // in the combined index VST entries). The records also contain<br>
+    // information used for ThinLTO renaming and importing.<br>
+    Record.clear();<br>
+    uint64_t CurRecordBit = Stream.GetCurrentBitNo();<br>
+    switch (Stream.readRecord(Entry.ID, Record)) {<br>
+      default:  // Default behavior: ignore.<br>
+        break;<br>
+      // FS_PERMODULE_ENTRY: [valueid, islocal, instcount]<br>
+      case bitc::FS_CODE_PERMODULE_ENTRY: {<br>
+        unsigned ValueID = Record[0];<br>
+        bool IsLocal = Record[1];<br>
+        unsigned InstCount = Record[2];<br>
+        std::unique_ptr<FunctionSummary> FS =<br>
+            llvm::make_unique<FunctionSummary>(InstCount);<br>
+        FS->setLocalFunction(IsLocal);<br>
+        // The module path string ref set in the summary must be owned by the<br>
+        // index's module string table. Since we don't have a module path<br>
+        // string table section in the per-module index, we create a single<br>
+        // module path string table entry with an empty (0) ID to take<br>
+        // ownership.<br>
+        FS->setModulePath(<br>
+            TheIndex->addModulePath(Buffer->getBufferIdentifier(), 0));<br>
+        SummaryMap[ValueID] = std::move(FS);<br>
+      }<br>
+      // FS_COMBINED_ENTRY: [modid, instcount]<br>
+      case bitc::FS_CODE_COMBINED_ENTRY: {<br>
+        uint64_t ModuleId = Record[0];<br>
+        unsigned InstCount = Record[1];<br>
+        std::unique_ptr<FunctionSummary> FS =<br>
+            llvm::make_unique<FunctionSummary>(InstCount);<br>
+        FS->setModulePath(ModuleIdMap[ModuleId]);<br>
+        SummaryMap[CurRecordBit] = std::move(FS);<br>
+      }<br>
+    }<br>
+  }<br>
+  llvm_unreachable("Exit infinite loop");<br>
+}<br>
+<br>
+// Parse the  module string table block into the Index.<br>
+// This populates the ModulePathStringTable map in the index.<br>
+std::error_code FunctionIndexBitcodeReader::parseModuleStringTable() {<br>
+  if (Stream.EnterSubBlock(bitc::MODULE_STRTAB_BLOCK_ID))<br>
+    return error("Invalid record");<br>
+<br>
+  SmallVector<uint64_t, 64> Record;<br>
+<br>
+  SmallString<128> ModulePath;<br>
+  while (1) {<br>
+    BitstreamEntry Entry = Stream.advanceSkippingSubblocks();<br>
+<br>
+    switch (Entry.Kind) {<br>
+      case BitstreamEntry::SubBlock:  // Handled for us already.<br>
+      case BitstreamEntry::Error:<br>
+        return error("Malformed block");<br>
+      case BitstreamEntry::EndBlock:<br>
+        return std::error_code();<br>
+      case BitstreamEntry::Record:<br>
+        // The interesting case.<br>
+        break;<br>
+    }<br>
+<br>
+    Record.clear();<br>
+    switch (Stream.readRecord(Entry.ID, Record)) {<br>
+      default:  // Default behavior: ignore.<br>
+        break;<br>
+      case bitc::MST_CODE_ENTRY: {<br>
+        // MST_ENTRY: [modid, namechar x N]<br>
+        if (convertToString(Record, 1, ModulePath))<br>
+          return error("Invalid record");<br>
+        uint64_t ModuleId = Record[0];<br>
+        StringRef ModulePathInMap =<br>
+            TheIndex->addModulePath(ModulePath, ModuleId);<br>
+        ModuleIdMap[ModuleId] = ModulePathInMap;<br>
+        ModulePath.clear();<br>
+        break;<br>
+      }<br>
+    }<br>
+  }<br>
+  llvm_unreachable("Exit infinite loop");<br>
+}<br>
+<br>
+// Parse the function info index from the bitcode streamer into the given index.<br>
+std::error_code FunctionIndexBitcodeReader::parseSummaryIndexInto(<br>
+    std::unique_ptr<DataStreamer> Streamer, FunctionInfoIndex *I) {<br>
+  TheIndex = I;<br>
+<br>
+  if (std::error_code EC = initStream(std::move(Streamer))) return EC;<br>
+<br>
+  // Sniff for the signature.<br>
+  if (!hasValidBitcodeHeader(Stream)) return error("Invalid bitcode signature");<br>
+<br>
+  // We expect a number of well-defined blocks, though we don't necessarily<br>
+  // need to understand them all.<br>
+  while (1) {<br>
+    if (Stream.AtEndOfStream()) {<br>
+      // We didn't really read a proper Module block.<br>
+      return error("Malformed block");<br>
+    }<br>
+<br>
+    BitstreamEntry Entry =<br>
+        Stream.advance(BitstreamCursor::AF_DontAutoprocessAbbrevs);<br>
+<br>
+    if (Entry.Kind != BitstreamEntry::SubBlock) return error("Malformed block");<br>
+<br>
+    // If we see a MODULE_BLOCK, parse it to find the blocks needed for<br>
+    // building the function summary index.<br>
+    if (Entry.ID == bitc::MODULE_BLOCK_ID) return parseModule();<br>
+<br>
+    if (Stream.SkipBlock()) return error("Invalid record");<br>
+  }<br>
+}<br>
+<br>
+// Parse the function information at the given offset in the buffer into<br>
+// the index. Used to support lazy parsing of function summaries from the<br>
+// combined index during importing.<br>
+// TODO: This function is not yet complete as it won't have a consumer<br>
+// until ThinLTO function importing is added.<br>
+std::error_code FunctionIndexBitcodeReader::parseFunctionSummary(<br>
+    std::unique_ptr<DataStreamer> Streamer, FunctionInfoIndex *I,<br>
+    size_t FunctionSummaryOffset) {<br>
+  TheIndex = I;<br>
+<br>
+  if (std::error_code EC = initStream(std::move(Streamer))) return EC;<br>
+<br>
+  // Sniff for the signature.<br>
+  if (!hasValidBitcodeHeader(Stream)) return error("Invalid bitcode signature");<br>
+<br>
+  Stream.JumpToBit(FunctionSummaryOffset);<br>
+<br>
+  BitstreamEntry Entry = Stream.advanceSkippingSubblocks();<br>
+<br>
+  switch (Entry.Kind) {<br>
+    default:<br>
+      return error("Malformed block");<br>
+    case BitstreamEntry::Record:<br>
+      // The expected case.<br>
+      break;<br>
+  }<br>
+<br>
+  // TODO: Read a record. This interface will be completed when ThinLTO<br>
+  // importing is added so that it can be tested.<br>
+  SmallVector<uint64_t, 64> Record;<br>
+  switch (Stream.readRecord(Entry.ID, Record)) {<br>
+    default:<br>
+      return error("Invalid record");<br>
+  }<br>
+<br>
+  return std::error_code();<br>
+}<br>
+<br>
+std::error_code FunctionIndexBitcodeReader::initStream(<br>
+    std::unique_ptr<DataStreamer> Streamer) {<br>
+  if (Streamer) return initLazyStream(std::move(Streamer));<br>
+  return initStreamFromBuffer();<br>
+}<br>
+<br>
+std::error_code FunctionIndexBitcodeReader::initStreamFromBuffer() {<br>
+  const unsigned char *BufPtr = (const unsigned char *)Buffer->getBufferStart();<br>
+  const unsigned char *BufEnd = BufPtr + Buffer->getBufferSize();<br>
+<br>
+  if (Buffer->getBufferSize() & 3) return error("Invalid bitcode signature");<br>
+<br>
+  // If we have a wrapper header, parse it and ignore the non-bc file contents.<br>
+  // The magic number is 0x0B17C0DE stored in little endian.<br>
+  if (isBitcodeWrapper(BufPtr, BufEnd))<br>
+    if (SkipBitcodeWrapperHeader(BufPtr, BufEnd, true))<br>
+      return error("Invalid bitcode wrapper header");<br>
+<br>
+  StreamFile.reset(new BitstreamReader(BufPtr, BufEnd));<br>
+  Stream.init(&*StreamFile);<br>
+<br>
+  return std::error_code();<br>
+}<br>
+<br>
+std::error_code FunctionIndexBitcodeReader::initLazyStream(<br>
+    std::unique_ptr<DataStreamer> Streamer) {<br>
+  // Check and strip off the bitcode wrapper; BitstreamReader expects never to<br>
+  // see it.<br>
+  auto OwnedBytes =<br>
+      llvm::make_unique<StreamingMemoryObject>(std::move(Streamer));<br>
+  StreamingMemoryObject &Bytes = *OwnedBytes;<br>
+  StreamFile = llvm::make_unique<BitstreamReader>(std::move(OwnedBytes));<br>
+  Stream.init(&*StreamFile);<br>
+<br>
+  unsigned char buf[16];<br>
+  if (Bytes.readBytes(buf, 16, 0) != 16)<br>
+    return error("Invalid bitcode signature");<br>
+<br>
+  if (!isBitcode(buf, buf + 16)) return error("Invalid bitcode signature");<br>
+<br>
+  if (isBitcodeWrapper(buf, buf + 4)) {<br>
+    const unsigned char *bitcodeStart = buf;<br>
+    const unsigned char *bitcodeEnd = buf + 16;<br>
+    SkipBitcodeWrapperHeader(bitcodeStart, bitcodeEnd, false);<br>
+    Bytes.dropLeadingBytes(bitcodeStart - buf);<br>
+    Bytes.setKnownObjectSize(bitcodeEnd - bitcodeStart);<br>
+  }<br>
+  return std::error_code();<br>
+}<br>
+<br>
 namespace {<br>
 class BitcodeErrorCategoryType : public std::error_category {<br>
   const char *name() const LLVM_NOEXCEPT override {<br>
@@ -5181,3 +5672,81 @@ llvm::getBitcodeTargetTriple(MemoryBuffe<br>
     return "";<br>
   return Triple.get();<br>
 }<br>
+<br>
+// Parse the specified bitcode buffer, returning the function info index.<br>
+// If IsLazy is false, parse the entire function summary into<br>
+// the index. Otherwise skip the function summary section, and only create<br>
+// an index object with a map from function name to function summary offset.<br>
+// The index is used to perform lazy function summary reading later.<br>
+ErrorOr<std::unique_ptr<FunctionInfoIndex>> llvm::getFunctionInfoIndex(<br>
+    MemoryBufferRef Buffer, LLVMContext &Context,<br>
+    DiagnosticHandlerFunction DiagnosticHandler, bool IsLazy) {<br>
+  std::unique_ptr<MemoryBuffer> Buf = MemoryBuffer::getMemBuffer(Buffer, false);<br>
+  FunctionIndexBitcodeReader R(Buf.get(), Context, DiagnosticHandler, IsLazy);<br>
+<br>
+  std::unique_ptr<FunctionInfoIndex> Index =<br>
+      llvm::make_unique<FunctionInfoIndex>();<br>
+<br>
+  auto cleanupOnError = [&](std::error_code EC) {<br>
+    R.releaseBuffer();  // Never take ownership on error.<br>
+    return EC;<br>
+  };<br>
+<br>
+  if (std::error_code EC = R.parseSummaryIndexInto(nullptr, Index.get()))<br>
+    return cleanupOnError(EC);<br>
+<br>
+  Buf.release();  // The FunctionIndexBitcodeReader owns it now.<br>
+  return std::move(Index);<br>
+}<br>
+<br>
+// Check if the given bitcode buffer contains a function summary block.<br>
+bool llvm::hasFunctionSummary(MemoryBufferRef Buffer, LLVMContext &Context,<br>
+                              DiagnosticHandlerFunction DiagnosticHandler) {<br>
+  std::unique_ptr<MemoryBuffer> Buf = MemoryBuffer::getMemBuffer(Buffer, false);<br>
+  FunctionIndexBitcodeReader R(Buf.get(), Context, DiagnosticHandler, false,<br>
+                               true);<br>
+<br>
+  auto cleanupOnError = [&](std::error_code EC) {<br>
+    R.releaseBuffer();  // Never take ownership on error.<br>
+    return false;<br>
+  };<br>
+<br>
+  if (std::error_code EC = R.parseSummaryIndexInto(nullptr, nullptr))<br>
+    return cleanupOnError(EC);<br>
+<br>
+  Buf.release();  // The FunctionIndexBitcodeReader owns it now.<br>
+  return R.foundFuncSummary();<br>
+}<br>
+<br>
+// This method supports lazy reading of function summary data from the combined<br>
+// index during ThinLTO function importing. When reading the combined index<br>
+// file, getFunctionInfoIndex is first invoked with IsLazy=true.<br>
+// Then this method is called for each function considered for importing,<br>
+// to parse the summary information for the given function name into<br>
+// the index.<br>
+std::error_code llvm::readFunctionSummary(<br>
+    MemoryBufferRef Buffer, LLVMContext &Context,<br>
+    DiagnosticHandlerFunction DiagnosticHandler, StringRef FunctionName,<br>
+    std::unique_ptr<FunctionInfoIndex> Index) {<br>
+  std::unique_ptr<MemoryBuffer> Buf = MemoryBuffer::getMemBuffer(Buffer, false);<br>
+  FunctionIndexBitcodeReader R(Buf.get(), Context, DiagnosticHandler);<br>
+<br>
+  auto cleanupOnError = [&](std::error_code EC) {<br>
+    R.releaseBuffer();  // Never take ownership on error.<br>
+    return EC;<br>
+  };<br>
+<br>
+  // Lookup the given function name in the FunctionMap, which may<br>
+  // contain a list of function infos in the case of a COMDAT. Walk through<br>
+  // and parse each function summary info at the function summary offset<br>
+  // recorded when parsing the value symbol table.<br>
+  for (const auto &FI : Index->getFunctionInfoList(FunctionName)) {<br>
+    size_t FunctionSummaryOffset = FI->bitcodeIndex();<br>
+    if (std::error_code EC =<br>
+            R.parseFunctionSummary(nullptr, Index.get(), FunctionSummaryOffset))<br>
+      return cleanupOnError(EC);<br>
+  }<br>
+<br>
+  Buf.release();  // The FunctionIndexBitcodeReader owns it now.<br>
+  return std::error_code();<br>
+}<br>
<br>
Modified: llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp?rev=249270&r1=249269&r2=249270&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp?rev=249270&r1=249269&r2=249270&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp (original)<br>
+++ llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp Sun Oct  4 09:33:43 2015<br>
@@ -13,6 +13,7 @@<br>
<br>
 #include "llvm/Bitcode/ReaderWriter.h"<br>
 #include "ValueEnumerator.h"<br>
+#include "llvm/ADT/STLExtras.h"<br>
 #include "llvm/ADT/Triple.h"<br>
 #include "llvm/Bitcode/BitstreamWriter.h"<br>
 #include "llvm/Bitcode/LLVMBitCodes.h"<br>
@@ -23,6 +24,7 @@<br>
 #include "llvm/IR/InlineAsm.h"<br>
 #include "llvm/IR/Instructions.h"<br>
 #include "llvm/IR/LLVMContext.h"<br>
+#include "llvm/IR/IntrinsicInst.h"<br>
 #include "llvm/IR/Module.h"<br>
 #include "llvm/IR/Operator.h"<br>
 #include "llvm/IR/UseListOrder.h"<br>
@@ -2187,7 +2189,8 @@ static void WriteValueSymbolTable(<br>
     const ValueSymbolTable &VST, const ValueEnumerator &VE,<br>
     BitstreamWriter &Stream, uint64_t VSTOffsetPlaceholder = 0,<br>
     uint64_t BitcodeStartBit = 0,<br>
-    DenseMap<const Function *, uint64_t> *FunctionIndex = nullptr) {<br>
+    DenseMap<const Function *, std::unique_ptr<FunctionInfo>> *FunctionIndex =<br>
+        nullptr) {<br>
   if (VST.empty()) {<br>
     // WriteValueSymbolTableForwardDecl should have returned early as<br>
     // well. Ensure this handling remains in sync by asserting that<br>
@@ -2282,7 +2285,8 @@ static void WriteValueSymbolTable(<br>
       // Save the word offset of the function (from the start of the<br>
       // actual bitcode written to the stream).<br>
       assert(FunctionIndex->count(F) == 1);<br>
-      uint64_t BitcodeIndex = (*FunctionIndex)[F] - BitcodeStartBit;<br>
+      uint64_t BitcodeIndex =<br>
+          (*FunctionIndex)[F]->bitcodeIndex() - BitcodeStartBit;<br>
       assert((BitcodeIndex & 31) == 0 && "function block not 32-bit aligned");<br>
       NameVals.push_back(BitcodeIndex / 32);<br>
<br>
@@ -2300,9 +2304,7 @@ static void WriteValueSymbolTable(<br>
         AbbrevToUse = VST_ENTRY_7_ABBREV;<br>
     }<br>
<br>
-    for (const char *P = Name.getKeyData(),<br>
-         *E = Name.getKeyData()+Name.getKeyLength(); P != E; ++P)<br>
-      NameVals.push_back((unsigned char)*P);<br>
+    for (const auto P : Name.getKey()) NameVals.push_back((unsigned char)P);<br>
<br>
     // Emit the finished record.<br>
     Stream.EmitRecord(Code, NameVals, AbbrevToUse);<br>
@@ -2311,6 +2313,68 @@ static void WriteValueSymbolTable(<br>
   Stream.ExitBlock();<br>
 }<br>
<br>
+/// Emit function names and summary offsets for the combined index<br>
+/// used by ThinLTO.<br>
+static void WriteCombinedValueSymbolTable(const FunctionInfoIndex *Index,<br>
+                                          BitstreamWriter &Stream) {<br>
+  Stream.EnterSubblock(bitc::VALUE_SYMTAB_BLOCK_ID, 4);<br>
+<br>
+  // 8-bit fixed-width VST_COMBINED_FNENTRY function strings.<br>
+  BitCodeAbbrev *Abbv = new BitCodeAbbrev();<br>
+  Abbv->Add(BitCodeAbbrevOp(bitc::VST_CODE_COMBINED_FNENTRY));<br>
+  Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8));  // value id<br>
+  Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8));  // funcoffset<br>
+  Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));<br>
+  Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 8));<br>
+  unsigned FnEntry8BitAbbrev = Stream.EmitAbbrev(Abbv);<br>
+<br>
+  // 7-bit fixed width VST_COMBINED_FNENTRY function strings.<br>
+  Abbv = new BitCodeAbbrev();<br>
+  Abbv->Add(BitCodeAbbrevOp(bitc::VST_CODE_COMBINED_FNENTRY));<br>
+  Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8));  // value id<br>
+  Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8));  // funcoffset<br>
+  Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));<br>
+  Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 7));<br>
+  unsigned FnEntry7BitAbbrev = Stream.EmitAbbrev(Abbv);<br>
+<br>
+  // 6-bit char6 VST_COMBINED_FNENTRY function strings.<br>
+  Abbv = new BitCodeAbbrev();<br>
+  Abbv->Add(BitCodeAbbrevOp(bitc::VST_CODE_COMBINED_FNENTRY));<br>
+  Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8));  // value id<br>
+  Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8));  // funcoffset<br>
+  Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));<br>
+  Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Char6));<br>
+  unsigned FnEntry6BitAbbrev = Stream.EmitAbbrev(Abbv);<br>
+<br>
+  // FIXME: We know if the type names can use 7-bit ascii.<br>
+  SmallVector<unsigned, 64> NameVals;<br>
+<br>
+  for (const auto &FII : *Index) {<br>
+    for (const auto &FI : FII.getValue()) {<br>
+      NameVals.push_back(FI->bitcodeIndex());<br>
+<br>
+      StringRef FuncName = FII.first();<br>
+<br>
+      // Figure out the encoding to use for the name.<br>
+      StringEncoding Bits = getStringEncoding(FuncName.data(), FuncName.size());<br>
+<br>
+      // VST_COMBINED_FNENTRY: [funcsumoffset, namechar x N]<br>
+      unsigned AbbrevToUse = FnEntry8BitAbbrev;<br>
+      if (Bits == SE_Char6)<br>
+        AbbrevToUse = FnEntry6BitAbbrev;<br>
+      else if (Bits == SE_Fixed7)<br>
+        AbbrevToUse = FnEntry7BitAbbrev;<br>
+<br>
+      for (const auto P : FuncName) NameVals.push_back((unsigned char)P);<br>
+<br>
+      // Emit the finished record.<br>
+      Stream.EmitRecord(bitc::VST_CODE_COMBINED_FNENTRY, NameVals, AbbrevToUse);<br>
+      NameVals.clear();<br>
+    }<br>
+  }<br>
+  Stream.ExitBlock();<br>
+}<br>
+<br>
 static void WriteUseList(ValueEnumerator &VE, UseListOrder &&Order,<br>
                          BitstreamWriter &Stream) {<br>
   assert(Order.Shuffle.size() >= 2 && "Shuffle too small");<br>
@@ -2345,14 +2409,33 @@ static void WriteUseListBlock(const Func<br>
   Stream.ExitBlock();<br>
 }<br>
<br>
-/// WriteFunction - Emit a function body to the module stream.<br>
-static void WriteFunction(const Function &F, ValueEnumerator &VE,<br>
-                          BitstreamWriter &Stream,<br>
-                          DenseMap<const Function *, uint64_t> &FunctionIndex) {<br>
+/// \brief Save information for the given function into the function index.<br>
+///<br>
+/// At a minimum this saves the bitcode index of the function record that<br>
+/// was just written. However, if we are emitting function summary information,<br>
+/// for example for ThinLTO, then a \a FunctionSummary object is created<br>
+/// to hold the provided summary information.<br>
+static void SaveFunctionInfo(<br>
+    const Function &F,<br>
+    DenseMap<const Function *, std::unique_ptr<FunctionInfo>> &FunctionIndex,<br>
+    unsigned NumInsts, uint64_t BitcodeIndex, bool EmitFunctionSummary) {<br>
+  std::unique_ptr<FunctionSummary> FuncSummary;<br>
+  if (EmitFunctionSummary) {<br>
+    FuncSummary = llvm::make_unique<FunctionSummary>(NumInsts);<br>
+    FuncSummary->setLocalFunction(F.hasLocalLinkage());<br>
+  }<br>
+  FunctionIndex[&F] =<br>
+      llvm::make_unique<FunctionInfo>(BitcodeIndex, std::move(FuncSummary));<br>
+}<br>
+<br>
+/// Emit a function body to the module stream.<br>
+static void WriteFunction(<br>
+    const Function &F, ValueEnumerator &VE, BitstreamWriter &Stream,<br>
+    DenseMap<const Function *, std::unique_ptr<FunctionInfo>> &FunctionIndex,<br>
+    bool EmitFunctionSummary) {<br>
   // Save the bitcode index of the start of this function block for recording<br>
   // in the VST.<br>
   uint64_t BitcodeIndex = Stream.GetCurrentBitNo();<br>
-  FunctionIndex[&F] = BitcodeIndex;<br>
<br>
   Stream.EnterSubblock(bitc::FUNCTION_BLOCK_ID, 4);<br>
   VE.incorporateFunction(F);<br>
@@ -2379,6 +2462,7 @@ static void WriteFunction(const Function<br>
   bool NeedsMetadataAttachment = F.hasMetadata();<br>
<br>
   DILocation *LastDL = nullptr;<br>
+  unsigned NumInsts = 0;<br>
<br>
   // Finally, emit all the instructions, in order.<br>
   for (Function::const_iterator BB = F.begin(), E = F.end(); BB != E; ++BB)<br>
@@ -2386,6 +2470,8 @@ static void WriteFunction(const Function<br>
          I != E; ++I) {<br>
       WriteInstruction(*I, InstID, VE, Stream, Vals);<br>
<br>
+      if (!isa<DbgInfoIntrinsic>(I)) ++NumInsts;<br>
+<br>
       if (!I->getType()->isVoidTy())<br>
         ++InstID;<br>
<br>
@@ -2422,6 +2508,9 @@ static void WriteFunction(const Function<br>
     WriteUseListBlock(&F, VE, Stream);<br>
   VE.purgeFunction();<br>
   Stream.ExitBlock();<br>
+<br>
+  SaveFunctionInfo(F, FunctionIndex, NumInsts, BitcodeIndex,<br>
+                   EmitFunctionSummary);<br>
 }<br>
<br>
 // Emit blockinfo, which defines the standard abbreviations etc.<br>
@@ -2599,10 +2688,155 @@ static void WriteBlockInfo(const ValueEn<br>
   Stream.ExitBlock();<br>
 }<br>
<br>
+/// Write the module path strings, currently only used when generating<br>
+/// a combined index file.<br>
+static void WriteModStrings(const FunctionInfoIndex *I,<br>
+                            BitstreamWriter &Stream) {<br>
+  Stream.EnterSubblock(bitc::MODULE_STRTAB_BLOCK_ID, 3);<br>
+<br>
+  // TODO: See which abbrev sizes we actually need to emit<br>
+<br>
+  // 8-bit fixed-width MST_ENTRY strings.<br>
+  BitCodeAbbrev *Abbv = new BitCodeAbbrev();<br>
+  Abbv->Add(BitCodeAbbrevOp(bitc::MST_CODE_ENTRY));<br>
+  Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8));<br>
+  Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));<br>
+  Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 8));<br>
+  unsigned Abbrev8Bit = Stream.EmitAbbrev(Abbv);<br>
+<br>
+  // 7-bit fixed width MST_ENTRY strings.<br>
+  Abbv = new BitCodeAbbrev();<br>
+  Abbv->Add(BitCodeAbbrevOp(bitc::MST_CODE_ENTRY));<br>
+  Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8));<br>
+  Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));<br>
+  Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 7));<br>
+  unsigned Abbrev7Bit = Stream.EmitAbbrev(Abbv);<br>
+<br>
+  // 6-bit char6 MST_ENTRY strings.<br>
+  Abbv = new BitCodeAbbrev();<br>
+  Abbv->Add(BitCodeAbbrevOp(bitc::MST_CODE_ENTRY));<br>
+  Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8));<br>
+  Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));<br>
+  Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Char6));<br>
+  unsigned Abbrev6Bit = Stream.EmitAbbrev(Abbv);<br>
+<br>
+  SmallVector<unsigned, 64> NameVals;<br>
+  for (const StringMapEntry<uint64_t> &MPSE : I->modPathStringEntries()) {<br>
+    StringEncoding Bits =<br>
+        getStringEncoding(MPSE.getKey().data(), MPSE.getKey().size());<br>
+    unsigned AbbrevToUse = Abbrev8Bit;<br>
+    if (Bits == SE_Char6)<br>
+      AbbrevToUse = Abbrev6Bit;<br>
+    else if (Bits == SE_Fixed7)<br>
+      AbbrevToUse = Abbrev7Bit;<br>
+<br>
+    NameVals.push_back(MPSE.getValue());<br>
+<br>
+    for (const auto P : MPSE.getKey()) NameVals.push_back((unsigned char)P);<br>
+<br>
+    // Emit the finished record.<br>
+    Stream.EmitRecord(bitc::MST_CODE_ENTRY, NameVals, AbbrevToUse);<br>
+    NameVals.clear();<br>
+  }<br>
+  Stream.ExitBlock();<br>
+}<br>
+<br>
+// Helper to emit a single function summary record.<br>
+static void WritePerModuleFunctionSummaryRecord(<br>
+    SmallVector<unsigned, 64> &NameVals, FunctionSummary *FS, unsigned ValueID,<br>
+    unsigned FSAbbrev, BitstreamWriter &Stream) {<br>
+  assert(FS);<br>
+  NameVals.push_back(ValueID);<br>
+  NameVals.push_back(FS->isLocalFunction());<br>
+  NameVals.push_back(FS->instCount());<br>
+<br>
+  // Emit the finished record.<br>
+  Stream.EmitRecord(bitc::FS_CODE_PERMODULE_ENTRY, NameVals, FSAbbrev);<br>
+  NameVals.clear();<br>
+}<br>
+<br>
+/// Emit the per-module function summary section alongside the rest of<br>
+/// the module's bitcode.<br>
+static void WritePerModuleFunctionSummary(<br>
+    DenseMap<const Function *, std::unique_ptr<FunctionInfo>> &FunctionIndex,<br>
+    const Module *M, const ValueEnumerator &VE, BitstreamWriter &Stream) {<br>
+  Stream.EnterSubblock(bitc::FUNCTION_SUMMARY_BLOCK_ID, 3);<br>
+<br>
+  // Abbrev for FS_CODE_PERMODULE_ENTRY.<br>
+  BitCodeAbbrev *Abbv = new BitCodeAbbrev();<br>
+  Abbv->Add(BitCodeAbbrevOp(bitc::FS_CODE_PERMODULE_ENTRY));<br>
+  Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8));    // valueid<br>
+  Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1));  // islocal<br>
+  Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8));    // instcount<br>
+  unsigned FSAbbrev = Stream.EmitAbbrev(Abbv);<br>
+<br>
+  SmallVector<unsigned, 64> NameVals;<br>
+  for (auto &I : FunctionIndex) {<br>
+    // Skip anonymous functions. We will emit a function summary for<br>
+    // any aliases below.<br>
+    if (!I.first->hasName()) continue;<br>
+<br>
+    WritePerModuleFunctionSummaryRecord(<br>
+        NameVals, I.second->functionSummary(),<br>
+        VE.getValueID(M->getValueSymbolTable().lookup(I.first->getName())),<br>
+        FSAbbrev, Stream);<br>
+  }<br>
+<br>
+  for (const GlobalAlias &A : M->aliases()) {<br>
+    if (!A.getBaseObject()) continue;<br>
+    const Function *F = dyn_cast<Function>(A.getBaseObject());<br>
+    if (!F || F->isDeclaration()) continue;<br>
+<br>
+    assert(FunctionIndex.count(F) == 1);<br>
+    WritePerModuleFunctionSummaryRecord(<br>
+        NameVals, FunctionIndex[F]->functionSummary(),<br>
+        VE.getValueID(M->getValueSymbolTable().lookup(A.getName())), FSAbbrev,<br>
+        Stream);<br>
+  }<br>
+<br>
+  Stream.ExitBlock();<br>
+}<br>
+<br>
+/// Emit the combined function summary section into the combined index<br>
+/// file.<br>
+static void WriteCombinedFunctionSummary(const FunctionInfoIndex *I,<br>
+                                         BitstreamWriter &Stream) {<br>
+  Stream.EnterSubblock(bitc::FUNCTION_SUMMARY_BLOCK_ID, 3);<br>
+<br>
+  // Abbrev for FS_CODE_COMBINED_ENTRY.<br>
+  BitCodeAbbrev *Abbv = new BitCodeAbbrev();<br>
+  Abbv->Add(BitCodeAbbrevOp(bitc::FS_CODE_COMBINED_ENTRY));<br>
+  Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8));  // modid<br>
+  Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8));  // instcount<br>
+  unsigned FSAbbrev = Stream.EmitAbbrev(Abbv);<br>
+<br>
+  SmallVector<unsigned, 64> NameVals;<br>
+  for (const auto &FII : *I) {<br>
+    for (auto &FI : FII.getValue()) {<br>
+      FunctionSummary *FS = FI->functionSummary();<br>
+      assert(FS);<br>
+<br>
+      NameVals.push_back(I->getModuleId(FS->modulePath()));<br>
+      NameVals.push_back(FS->instCount());<br>
+<br>
+      // Record the starting offset of this summary entry for use<br>
+      // in the VST entry. Add the current code size since the<br>
+      // reader will invoke readRecord after the abbrev id read.<br>
+      FI->setBitcodeIndex(Stream.GetCurrentBitNo() + Stream.GetAbbrevIDWidth());<br>
+<br>
+      // Emit the finished record.<br>
+      Stream.EmitRecord(bitc::FS_CODE_COMBINED_ENTRY, NameVals, FSAbbrev);<br>
+      NameVals.clear();<br>
+    }<br>
+  }<br>
+<br>
+  Stream.ExitBlock();<br>
+}<br>
+<br>
 /// WriteModule - Emit the specified module to the bitstream.<br>
 static void WriteModule(const Module *M, BitstreamWriter &Stream,<br>
                         bool ShouldPreserveUseListOrder,<br>
-                        uint64_t BitcodeStartBit) {<br>
+                        uint64_t BitcodeStartBit, bool EmitFunctionSummary) {<br>
   Stream.EnterSubblock(bitc::MODULE_BLOCK_ID, 3);<br>
<br>
   SmallVector<unsigned, 1> Vals;<br>
@@ -2647,10 +2881,15 @@ static void WriteModule(const Module *M,<br>
   WriteOperandBundleTags(M, Stream);<br>
<br>
   // Emit function bodies.<br>
-  DenseMap<const Function *, uint64_t> FunctionIndex;<br>
+  DenseMap<const Function *, std::unique_ptr<FunctionInfo>> FunctionIndex;<br>
   for (Module::const_iterator F = M->begin(), E = M->end(); F != E; ++F)<br>
     if (!F->isDeclaration())<br>
-      WriteFunction(*F, VE, Stream, FunctionIndex);<br>
+      WriteFunction(*F, VE, Stream, FunctionIndex, EmitFunctionSummary);<br>
+<br>
+  // Need to write after the above call to WriteFunction which populates<br>
+  // the summary information in the index.<br>
+  if (EmitFunctionSummary)<br>
+    WritePerModuleFunctionSummary(FunctionIndex, M, VE, Stream);<br>
<br>
   WriteValueSymbolTable(M->getValueSymbolTable(), VE, Stream,<br>
                         VSTOffsetPlaceholder, BitcodeStartBit, &FunctionIndex);<br>
@@ -2728,10 +2967,22 @@ static void EmitDarwinBCHeaderAndTrailer<br>
     Buffer.push_back(0);<br>
 }<br>
<br>
+/// Helper to write the header common to all bitcode files.<br>
+static void WriteBitcodeHeader(BitstreamWriter &Stream) {<br>
+  // Emit the file header.<br>
+  Stream.Emit((unsigned)'B', 8);<br>
+  Stream.Emit((unsigned)'C', 8);<br>
+  Stream.Emit(0x0, 4);<br>
+  Stream.Emit(0xC, 4);<br>
+  Stream.Emit(0xE, 4);<br>
+  Stream.Emit(0xD, 4);<br>
+}<br>
+<br>
 /// WriteBitcodeToFile - Write the specified module to the specified output<br>
 /// stream.<br>
 void llvm::WriteBitcodeToFile(const Module *M, raw_ostream &Out,<br>
-                              bool ShouldPreserveUseListOrder) {<br>
+                              bool ShouldPreserveUseListOrder,<br>
+                              bool EmitFunctionSummary) {<br>
   SmallVector<char, 0> Buffer;<br>
   Buffer.reserve(256*1024);<br>
<br>
@@ -2751,15 +3002,11 @@ void llvm::WriteBitcodeToFile(const Modu<br>
     uint64_t BitcodeStartBit = Stream.GetCurrentBitNo();<br>
<br>
     // Emit the file header.<br>
-    Stream.Emit((unsigned)'B', 8);<br>
-    Stream.Emit((unsigned)'C', 8);<br>
-    Stream.Emit(0x0, 4);<br>
-    Stream.Emit(0xC, 4);<br>
-    Stream.Emit(0xE, 4);<br>
-    Stream.Emit(0xD, 4);<br>
+    WriteBitcodeHeader(Stream);<br>
<br>
     // Emit the module.<br>
-    WriteModule(M, Stream, ShouldPreserveUseListOrder, BitcodeStartBit);<br>
+    WriteModule(M, Stream, ShouldPreserveUseListOrder, BitcodeStartBit,<br>
+                EmitFunctionSummary);<br>
   }<br>
<br>
   if (TT.isOSDarwin())<br>
@@ -2768,3 +3015,38 @@ void llvm::WriteBitcodeToFile(const Modu<br>
   // Write the generated bitstream to "Out".<br>
   Out.write((char*)&Buffer.front(), Buffer.size());<br>
 }<br>
+<br>
+// Write the specified function summary index to the given raw output stream,<br>
+// where it will be written in a new bitcode block. This is used when<br>
+// writing the combined index file for ThinLTO.<br>
+void llvm::WriteFunctionSummaryToFile(const FunctionInfoIndex *Index,<br>
+                                      raw_ostream &Out) {<br>
+  SmallVector<char, 0> Buffer;<br>
+  Buffer.reserve(256 * 1024);<br>
+<br>
+  BitstreamWriter Stream(Buffer);<br>
+<br>
+  // Emit the bitcode header.<br>
+  WriteBitcodeHeader(Stream);<br>
+<br>
+  Stream.EnterSubblock(bitc::MODULE_BLOCK_ID, 3);<br>
+<br>
+  SmallVector<unsigned, 1> Vals;<br>
+  unsigned CurVersion = 1;<br>
+  Vals.push_back(CurVersion);<br>
+  Stream.EmitRecord(bitc::MODULE_CODE_VERSION, Vals);<br>
+<br>
+  // Write the module paths in the combined index.<br>
+  WriteModStrings(Index, Stream);<br>
+<br>
+  // Write the function summary combined index records.<br>
+  WriteCombinedFunctionSummary(Index, Stream);<br>
+<br>
+  // Need a special VST writer for the combined index (we don't have a<br>
+  // real VST and real values when this is invoked).<br>
+  WriteCombinedValueSymbolTable(Index, Stream);<br>
+<br>
+  Stream.ExitBlock();<br>
+<br>
+  Out.write((char *)&Buffer.front(), Buffer.size());<br>
+}<br>
<br>
Modified: llvm/trunk/lib/Bitcode/Writer/BitcodeWriterPass.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Writer/BitcodeWriterPass.cpp?rev=249270&r1=249269&r2=249270&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Writer/BitcodeWriterPass.cpp?rev=249270&r1=249269&r2=249270&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Bitcode/Writer/BitcodeWriterPass.cpp (original)<br>
+++ llvm/trunk/lib/Bitcode/Writer/BitcodeWriterPass.cpp Sun Oct  4 09:33:43 2015<br>
@@ -19,7 +19,7 @@<br>
 using namespace llvm;<br>
<br>
 PreservedAnalyses BitcodeWriterPass::run(Module &M) {<br>
-  WriteBitcodeToFile(&M, OS, ShouldPreserveUseListOrder);<br>
+  WriteBitcodeToFile(&M, OS, ShouldPreserveUseListOrder, EmitFunctionSummary);<br>
   return PreservedAnalyses::all();<br>
 }<br>
<br>
@@ -27,17 +27,21 @@ namespace {<br>
   class WriteBitcodePass : public ModulePass {<br>
     raw_ostream &OS; // raw_ostream to print on<br>
     bool ShouldPreserveUseListOrder;<br>
+    bool EmitFunctionSummary;<br>
<br>
   public:<br>
     static char ID; // Pass identification, replacement for typeid<br>
-    explicit WriteBitcodePass(raw_ostream &o, bool ShouldPreserveUseListOrder)<br>
+    explicit WriteBitcodePass(raw_ostream &o, bool ShouldPreserveUseListOrder,<br>
+                              bool EmitFunctionSummary)<br>
         : ModulePass(ID), OS(o),<br>
-          ShouldPreserveUseListOrder(ShouldPreserveUseListOrder) {}<br>
+          ShouldPreserveUseListOrder(ShouldPreserveUseListOrder),<br>
+          EmitFunctionSummary(EmitFunctionSummary) {}<br>
<br>
     const char *getPassName() const override { return "Bitcode Writer"; }<br>
<br>
     bool runOnModule(Module &M) override {<br>
-      WriteBitcodeToFile(&M, OS, ShouldPreserveUseListOrder);<br>
+      WriteBitcodeToFile(&M, OS, ShouldPreserveUseListOrder,<br>
+                         EmitFunctionSummary);<br>
       return false;<br>
     }<br>
   };<br>
@@ -46,6 +50,8 @@ namespace {<br>
 char WriteBitcodePass::ID = 0;<br>
<br>
 ModulePass *llvm::createBitcodeWriterPass(raw_ostream &Str,<br>
-                                          bool ShouldPreserveUseListOrder) {<br>
-  return new WriteBitcodePass(Str, ShouldPreserveUseListOrder);<br>
+                                          bool ShouldPreserveUseListOrder,<br>
+                                          bool EmitFunctionSummary) {<br>
+  return new WriteBitcodePass(Str, ShouldPreserveUseListOrder,<br>
+                              EmitFunctionSummary);<br>
 }<br>
<br>
Modified: llvm/trunk/lib/IR/CMakeLists.txt<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/CMakeLists.txt?rev=249270&r1=249269&r2=249270&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/CMakeLists.txt?rev=249270&r1=249269&r2=249270&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/IR/CMakeLists.txt (original)<br>
+++ llvm/trunk/lib/IR/CMakeLists.txt Sun Oct  4 09:33:43 2015<br>
@@ -39,6 +39,7 @@ add_llvm_library(LLVMCore<br>
   PassManager.cpp<br>
   PassRegistry.cpp<br>
   Statepoint.cpp<br>
+  FunctionInfo.cpp<br>
   Type.cpp<br>
   TypeFinder.cpp<br>
   Use.cpp<br>
<br>
Added: llvm/trunk/lib/IR/FunctionInfo.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/FunctionInfo.cpp?rev=249270&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/FunctionInfo.cpp?rev=249270&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/lib/IR/FunctionInfo.cpp (added)<br>
+++ llvm/trunk/lib/IR/FunctionInfo.cpp Sun Oct  4 09:33:43 2015<br>
@@ -0,0 +1,63 @@<br>
+//===-- FunctionInfo.cpp - Function Info Index ----------------------------===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+//<br>
+// This file implements the function info index and summary classes for the<br>
+// IR library.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#include "llvm/IR/FunctionInfo.h"<br>
+#include "llvm/ADT/StringMap.h"<br>
+using namespace llvm;<br>
+<br>
+// Create the combined function index/summary from multiple<br>
+// per-module instances.<br>
+void FunctionInfoIndex::mergeFrom(std::unique_ptr<FunctionInfoIndex> Other,<br>
+                                  uint64_t NextModuleId) {<br>
+<br>
+  StringRef ModPath;<br>
+  for (auto &OtherFuncInfoLists : *Other) {<br>
+    StringRef FuncName = OtherFuncInfoLists.getKey();<br>
+    FunctionInfoList &List = OtherFuncInfoLists.second;<br>
+<br>
+    // Assert that the func info list only has one entry, since we shouldn't<br>
+    // have duplicate names within a single per-module index.<br>
+    assert(List.size() == 1);<br>
+    std::unique_ptr<FunctionInfo> Info = std::move(List.front());<br>
+<br>
+    // Add the module path string ref for this module if we haven't already<br>
+    // saved a reference to it.<br>
+    if (ModPath.empty())<br>
+      ModPath =<br>
+          addModulePath(Info->functionSummary()->modulePath(), NextModuleId);<br>
+    else<br>
+      assert(ModPath == Info->functionSummary()->modulePath() &&<br>
+             "Each module in the combined map should have a unique ID");<br>
+<br>
+    // Note the module path string ref was copied above and is still owned by<br>
+    // the original per-module index. Reset it to the new module path<br>
+    // string reference owned by the combined index.<br>
+    Info->functionSummary()->setModulePath(ModPath);<br>
+<br>
+    // If it is a local function, rename it.<br>
+    if (Info->functionSummary()->isLocalFunction()) {<br>
+      // Any local functions are virtually renamed when being added to the<br>
+      // combined index map, to disambiguate from other functions with<br>
+      // the same name. The symbol table created for the combined index<br>
+      // file should contain the renamed symbols.<br>
+      FuncName =<br>
+          FunctionInfoIndex::getGlobalNameForLocal(FuncName, NextModuleId);<br>
+    }<br>
+<br>
+    // Add new function info to existing list. There may be duplicates when<br>
+    // combining FunctionMap entries, due to COMDAT functions. Any local<br>
+    // functions were virtually renamed above.<br>
+    addFunctionInfo(FuncName, std::move(Info));<br>
+  }<br>
+}<br>
<br>
Modified: llvm/trunk/lib/Object/CMakeLists.txt<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Object/CMakeLists.txt?rev=249270&r1=249269&r2=249270&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Object/CMakeLists.txt?rev=249270&r1=249269&r2=249270&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Object/CMakeLists.txt (original)<br>
+++ llvm/trunk/lib/Object/CMakeLists.txt Sun Oct  4 09:33:43 2015<br>
@@ -16,6 +16,7 @@ add_llvm_library(LLVMObject<br>
   RecordStreamer.cpp<br>
   SymbolicFile.cpp<br>
   SymbolSize.cpp<br>
+  FunctionIndexObjectFile.cpp<br>
<br>
   ADDITIONAL_HEADER_DIRS<br>
   ${LLVM_MAIN_INCLUDE_DIR}/llvm/Object<br>
<br>
Added: llvm/trunk/lib/Object/FunctionIndexObjectFile.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Object/FunctionIndexObjectFile.cpp?rev=249270&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Object/FunctionIndexObjectFile.cpp?rev=249270&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Object/FunctionIndexObjectFile.cpp (added)<br>
+++ llvm/trunk/lib/Object/FunctionIndexObjectFile.cpp Sun Oct  4 09:33:43 2015<br>
@@ -0,0 +1,114 @@<br>
+//===- FunctionIndexObjectFile.cpp - Function index file implementation ----===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+//<br>
+// Part of the FunctionIndexObjectFile class implementation.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#include "llvm/Object/FunctionIndexObjectFile.h"<br>
+#include "llvm/ADT/STLExtras.h"<br>
+#include "llvm/Bitcode/ReaderWriter.h"<br>
+#include "llvm/IR/FunctionInfo.h"<br>
+#include "llvm/MC/MCStreamer.h"<br>
+#include "llvm/Object/ObjectFile.h"<br>
+#include "llvm/Support/MemoryBuffer.h"<br>
+#include "llvm/Support/raw_ostream.h"<br>
+using namespace llvm;<br>
+using namespace object;<br>
+<br>
+FunctionIndexObjectFile::FunctionIndexObjectFile(<br>
+    MemoryBufferRef Object, std::unique_ptr<FunctionInfoIndex> I)<br>
+    : SymbolicFile(Binary::ID_FunctionIndex, Object), Index(std::move(I)) {}<br>
+<br>
+FunctionIndexObjectFile::~FunctionIndexObjectFile() {}<br>
+<br>
+std::unique_ptr<FunctionInfoIndex> FunctionIndexObjectFile::takeIndex() {<br>
+  return std::move(Index);<br>
+}<br>
+<br>
+ErrorOr<MemoryBufferRef> FunctionIndexObjectFile::findBitcodeInObject(<br>
+    const ObjectFile &Obj) {<br>
+  for (const SectionRef &Sec : Obj.sections()) {<br>
+    StringRef SecName;<br>
+    if (std::error_code EC = Sec.getName(SecName)) return EC;<br>
+    if (SecName == ".llvmbc") {<br>
+      StringRef SecContents;<br>
+      if (std::error_code EC = Sec.getContents(SecContents)) return EC;<br>
+      return MemoryBufferRef(SecContents, Obj.getFileName());<br>
+    }<br>
+  }<br>
+<br>
+  return object_error::bitcode_section_not_found;<br>
+}<br>
+<br>
+ErrorOr<MemoryBufferRef> FunctionIndexObjectFile::findBitcodeInMemBuffer(<br>
+    MemoryBufferRef Object) {<br>
+  sys::fs::file_magic Type = sys::fs::identify_magic(Object.getBuffer());<br>
+  switch (Type) {<br>
+    case sys::fs::file_magic::bitcode:<br>
+      return Object;<br>
+    case sys::fs::file_magic::elf_relocatable:<br>
+    case sys::fs::file_magic::macho_object:<br>
+    case sys::fs::file_magic::coff_object: {<br>
+      ErrorOr<std::unique_ptr<ObjectFile>> ObjFile =<br>
+          ObjectFile::createObjectFile(Object, Type);<br>
+      if (!ObjFile) return ObjFile.getError();<br>
+      return findBitcodeInObject(*ObjFile->get());<br>
+    }<br>
+    default:<br>
+      return object_error::invalid_file_type;<br>
+  }<br>
+}<br>
+<br>
+// Looks for function index in the given memory buffer.<br>
+// returns true if found, else false.<br>
+bool FunctionIndexObjectFile::hasFunctionSummaryInMemBuffer(<br>
+    MemoryBufferRef Object, LLVMContext &Context) {<br>
+  ErrorOr<MemoryBufferRef> BCOrErr = findBitcodeInMemBuffer(Object);<br>
+  if (!BCOrErr) return false;<br>
+<br>
+  return hasFunctionSummary(BCOrErr.get(), Context, nullptr);<br>
+}<br>
+<br>
+// Parse function index in the given memory buffer.<br>
+// Return new FunctionIndexObjectFile instance containing parsed<br>
+// function summary/index.<br>
+ErrorOr<std::unique_ptr<FunctionIndexObjectFile>><br>
+FunctionIndexObjectFile::create(MemoryBufferRef Object, LLVMContext &Context,<br>
+                                bool IsLazy) {<br>
+  std::unique_ptr<FunctionInfoIndex> Index;<br>
+<br>
+  ErrorOr<MemoryBufferRef> BCOrErr = findBitcodeInMemBuffer(Object);<br>
+  if (!BCOrErr) return BCOrErr.getError();<br>
+<br>
+  ErrorOr<std::unique_ptr<FunctionInfoIndex>> IOrErr =<br>
+      getFunctionInfoIndex(BCOrErr.get(), Context, nullptr, IsLazy);<br>
+<br>
+  if (std::error_code EC = IOrErr.getError()) return EC;<br>
+<br>
+  Index = std::move(IOrErr.get());<br>
+<br>
+  return llvm::make_unique<FunctionIndexObjectFile>(Object, std::move(Index));<br>
+}<br>
+<br>
+// Parse the function summary information for function with the<br>
+// given name out of the given buffer. Parsed information is<br>
+// stored on the index object saved in this object.<br>
+std::error_code FunctionIndexObjectFile::findFunctionSummaryInMemBuffer(<br>
+    MemoryBufferRef Object, LLVMContext &Context, StringRef FunctionName) {<br>
+  sys::fs::file_magic Type = sys::fs::identify_magic(Object.getBuffer());<br>
+  switch (Type) {<br>
+    case sys::fs::file_magic::bitcode: {<br>
+      return readFunctionSummary(Object, Context, nullptr, FunctionName,<br>
+                                 std::move(Index));<br>
+    }<br>
+    default:<br>
+      return object_error::invalid_file_type;<br>
+  }<br>
+}<br>
<br>
Added: llvm/trunk/test/Bitcode/thinlto-function-summary.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Bitcode/thinlto-function-summary.ll?rev=249270&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Bitcode/thinlto-function-summary.ll?rev=249270&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/test/Bitcode/thinlto-function-summary.ll (added)<br>
+++ llvm/trunk/test/Bitcode/thinlto-function-summary.ll Sun Oct  4 09:33:43 2015<br>
@@ -0,0 +1,45 @@<br>
+; RUN: llvm-as -function-summary < %s | llvm-bcanalyzer -dump | FileCheck %s -check-prefix=BC<br>
+; Check for function summary block/records.<br>
+<br>
+; BC: <FUNCTION_SUMMARY_BLOCK<br>
+; BC-NEXT: <PERMODULE_ENTRY<br>
+; BC-NEXT: <PERMODULE_ENTRY<br>
+; BC-NEXT: <PERMODULE_ENTRY<br>
+; BC-NEXT: </FUNCTION_SUMMARY_BLOCK<br>
+<br>
+; RUN: llvm-as -function-summary < %s | llvm-dis | FileCheck %s<br>
+; Check that this round-trips correctly.<br>
+<br>
+; ModuleID = '<stdin>'<br>
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"<br>
+target triple = "x86_64-unknown-linux-gnu"<br>
+<br>
+; CHECK: define i32 @foo()<br>
+<br>
+; Function Attrs: nounwind uwtable<br>
+define i32 @foo() #0 {<br>
+entry:<br>
+  ret i32 1<br>
+}<br>
+<br>
+; CHECK: define i32 @bar(i32 %x)<br>
+<br>
+; Function Attrs: nounwind uwtable<br>
+define i32 @bar(i32 %x) #0 {<br>
+entry:<br>
+  ret i32 %x<br>
+}<br>
+<br>
+; Check an anonymous function as well, since in that case only the alias<br>
+; ends up in the value symbol table and having a summary.<br>
+@f = alias void (), void ()* @0   ; <void ()*> [#uses=0]<br>
+@h = external global void ()*     ; <void ()*> [#uses=0]<br>
+<br>
+define internal void @0() nounwind {<br>
+entry:<br>
+  store void()* @0, void()** @h<br>
+        br label %return<br>
+<br>
+return:         ; preds = %entry<br>
+        ret void<br>
+}<br>
<br>
Added: llvm/trunk/test/tools/gold/X86/Inputs/thinlto.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/gold/X86/Inputs/thinlto.ll?rev=249270&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/gold/X86/Inputs/thinlto.ll?rev=249270&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/test/tools/gold/X86/Inputs/thinlto.ll (added)<br>
+++ llvm/trunk/test/tools/gold/X86/Inputs/thinlto.ll Sun Oct  4 09:33:43 2015<br>
@@ -0,0 +1,4 @@<br>
+define void @g() {<br>
+entry:<br>
+  ret void<br>
+}<br>
<br>
Added: llvm/trunk/test/tools/gold/X86/thinlto.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/gold/X86/thinlto.ll?rev=249270&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/gold/X86/thinlto.ll?rev=249270&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/test/tools/gold/X86/thinlto.ll (added)<br>
+++ llvm/trunk/test/tools/gold/X86/thinlto.ll Sun Oct  4 09:33:43 2015<br>
@@ -0,0 +1,22 @@<br>
+; RUN: llvm-as -function-summary %s -o %t.o<br>
+; RUN: llvm-as -function-summary %p/Inputs/thinlto.ll -o %t2.o<br>
+<br>
+; RUN: %gold -plugin %llvmshlibdir/LLVMgold.so \<br>
+; RUN:    --plugin-opt=thinlto \<br>
+; RUN:    -shared %t.o %t2.o -o %t3<br>
+; RUN: llvm-bcanalyzer -dump %t3.thinlto.bc | FileCheck %s --check-prefix=COMBINED<br>
+; RUN: not test -e %t3<br>
+<br>
+; COMBINED: <MODULE_STRTAB_BLOCK<br>
+; COMBINED-NEXT: <ENTRY<br>
+; COMBINED-NEXT: <ENTRY<br>
+; COMBINED-NEXT: </MODULE_STRTAB_BLOCK<br>
+; COMBINED-NEXT: <FUNCTION_SUMMARY_BLOCK<br>
+; COMBINED-NEXT: <COMBINED_ENTRY<br>
+; COMBINED-NEXT: <COMBINED_ENTRY<br>
+; COMBINED-NEXT: </FUNCTION_SUMMARY_BLOCK<br>
+<br>
+define void @f() {<br>
+entry:<br>
+  ret void<br>
+}<br>
<br>
Modified: llvm/trunk/tools/gold/gold-plugin.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/gold/gold-plugin.cpp?rev=249270&r1=249269&r2=249270&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/gold/gold-plugin.cpp?rev=249270&r1=249269&r2=249270&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/tools/gold/gold-plugin.cpp (original)<br>
+++ llvm/trunk/tools/gold/gold-plugin.cpp Sun Oct  4 09:33:43 2015<br>
@@ -32,6 +32,7 @@<br>
 #include "llvm/Linker/Linker.h"<br>
 #include "llvm/MC/SubtargetFeature.h"<br>
 #include "llvm/Object/IRObjectFile.h"<br>
+#include "llvm/Object/FunctionIndexObjectFile.h"<br>
 #include "llvm/Support/raw_ostream.h"<br>
 #include "llvm/Support/Host.h"<br>
 #include "llvm/Support/ManagedStatic.h"<br>
@@ -103,6 +104,10 @@ namespace options {<br>
   static std::string extra_library_path;<br>
   static std::string triple;<br>
   static std::string mcpu;<br>
+  // When the thinlto plugin option is specified, only read the function<br>
+  // the information from intermediate files and write a combined<br>
+  // global index for the ThinLTO backends.<br>
+  static bool thinlto = false;<br>
   // Additional options to pass into the code generator.<br>
   // Note: This array will contain all plugin options which are not claimed<br>
   // as plugin exclusive to pass to the code generator.<br>
@@ -132,6 +137,8 @@ namespace options {<br>
       TheOutputType = OT_SAVE_TEMPS;<br>
     } else if (opt == "disable-output") {<br>
       TheOutputType = OT_DISABLE;<br>
+    } else if (opt == "thinlto") {<br>
+      thinlto = true;<br>
     } else if (opt.size() == 2 && opt[0] == 'O') {<br>
       if (opt[1] < '0' || opt[1] > '3')<br>
         message(LDPL_FATAL, "Optimization level must be between 0 and 3");<br>
@@ -376,6 +383,10 @@ static ld_plugin_status claim_file_hook(<br>
<br>
   cf.handle = file->handle;<br>
<br>
+  // If we are doing ThinLTO compilation, don't need to process the symbols.<br>
+  // Later we simply build a combined index file after all files are claimed.<br>
+  if (options::thinlto) return LDPS_OK;<br>
+<br>
   for (auto &Sym : Obj->symbols()) {<br>
     uint32_t Symflags = Sym.getFlags();<br>
     if (shouldSkip(Symflags))<br>
@@ -591,6 +602,30 @@ static void freeSymName(ld_plugin_symbol<br>
   Sym.comdat_key = nullptr;<br>
 }<br>
<br>
+static std::unique_ptr<FunctionInfoIndex> getFunctionIndexForFile(<br>
+    LLVMContext &Context, claimed_file &F, ld_plugin_input_file &Info) {<br>
+<br>
+  if (get_symbols(F.handle, F.syms.size(), &F.syms[0]) != LDPS_OK)<br>
+    message(LDPL_FATAL, "Failed to get symbol information");<br>
+<br>
+  const void *View;<br>
+  if (get_view(F.handle, &View) != LDPS_OK)<br>
+    message(LDPL_FATAL, "Failed to get a view of file");<br>
+<br>
+  MemoryBufferRef BufferRef(StringRef((const char *)View, Info.filesize),<br>
+                            Info.name);<br>
+  ErrorOr<std::unique_ptr<object::FunctionIndexObjectFile>> ObjOrErr =<br>
+      object::FunctionIndexObjectFile::create(BufferRef, Context);<br>
+<br>
+  if (std::error_code EC = ObjOrErr.getError())<br>
+    message(LDPL_FATAL, "Could not read function index bitcode from file : %s",<br>
+            EC.message().c_str());<br>
+<br>
+  object::FunctionIndexObjectFile &Obj = **ObjOrErr;<br>
+<br>
+  return Obj.takeIndex();<br>
+}<br>
+<br>
 static std::unique_ptr<Module><br>
 getModuleForFile(LLVMContext &Context, claimed_file &F,<br>
                  ld_plugin_input_file &Info, raw_fd_ostream *ApiFile,<br>
@@ -857,6 +892,35 @@ static ld_plugin_status allSymbolsReadHo<br>
   LLVMContext Context;<br>
   Context.setDiagnosticHandler(diagnosticHandler, nullptr, true);<br>
<br>
+  // If we are doing ThinLTO compilation, simply build the combined<br>
+  // function index/summary and emit it. We don't need to parse the modules<br>
+  // and link them in this case.<br>
+  if (options::thinlto) {<br>
+    std::unique_ptr<FunctionInfoIndex> CombinedIndex(new FunctionInfoIndex());<br>
+    uint64_t NextModuleId = 0;<br>
+    for (claimed_file &F : Modules) {<br>
+      ld_plugin_input_file File;<br>
+      if (get_input_file(F.handle, &File) != LDPS_OK)<br>
+        message(LDPL_FATAL, "Failed to get file information");<br>
+<br>
+      std::unique_ptr<FunctionInfoIndex> Index =<br>
+          getFunctionIndexForFile(Context, F, File);<br>
+      CombinedIndex->mergeFrom(std::move(Index), ++NextModuleId);<br>
+    }<br>
+<br>
+    std::error_code EC;<br>
+    raw_fd_ostream OS(output_name + ".thinlto.bc", EC,<br>
+                      sys::fs::OpenFlags::F_None);<br>
+    if (EC)<br>
+      message(LDPL_FATAL, "Unable to open %s.thinlto.bc for writing: %s",<br>
+              output_name.data(), EC.message().c_str());<br>
+    WriteFunctionSummaryToFile(CombinedIndex.get(), OS);<br>
+    OS.close();<br>
+<br>
+    cleanup_hook();<br>
+    exit(0);<br>
+  }<br>
+<br>
   std::unique_ptr<Module> Combined(new Module("ld-temp.o", Context));<br>
   Linker L(Combined.get());<br>
<br>
<br>
Modified: llvm/trunk/tools/llvm-as/llvm-as.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-as/llvm-as.cpp?rev=249270&r1=249269&r2=249270&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-as/llvm-as.cpp?rev=249270&r1=249269&r2=249270&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/tools/llvm-as/llvm-as.cpp (original)<br>
+++ llvm/trunk/tools/llvm-as/llvm-as.cpp Sun Oct  4 09:33:43 2015<br>
@@ -45,6 +45,10 @@ static cl::opt<bool><br>
 DisableOutput("disable-output", cl::desc("Disable output"), cl::init(false));<br>
<br>
 static cl::opt<bool><br>
+EmitFunctionSummary("function-summary", cl::desc("Emit function summary index"),<br>
+                    cl::init(false));<br>
+<br>
+static cl::opt<bool><br>
 DumpAsm("d", cl::desc("Print assembly as parsed"), cl::Hidden);<br>
<br>
 static cl::opt<bool><br>
@@ -77,7 +81,8 @@ static void WriteOutputFile(const Module<br>
   }<br>
<br>
   if (Force || !CheckBitcodeOutputToConsole(Out->os(), true))<br>
-    WriteBitcodeToFile(M, Out->os(), PreserveBitcodeUseListOrder);<br>
+    WriteBitcodeToFile(M, Out->os(), PreserveBitcodeUseListOrder,<br>
+                       EmitFunctionSummary);<br>
<br>
   // Declare success.<br>
   Out->keep();<br>
<br>
Modified: llvm/trunk/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp?rev=249270&r1=249269&r2=249270&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp?rev=249270&r1=249269&r2=249270&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp (original)<br>
+++ llvm/trunk/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp Sun Oct  4 09:33:43 2015<br>
@@ -114,6 +114,9 @@ static const char *GetBlockName(unsigned<br>
   case bitc::METADATA_BLOCK_ID:        return "METADATA_BLOCK";<br>
   case bitc::METADATA_ATTACHMENT_ID:   return "METADATA_ATTACHMENT_BLOCK";<br>
   case bitc::USELIST_BLOCK_ID:         return "USELIST_BLOCK_ID";<br>
+  case bitc::FUNCTION_SUMMARY_BLOCK_ID:<br>
+                                       return "FUNCTION_SUMMARY_BLOCK";<br>
+  case bitc::MODULE_STRTAB_BLOCK_ID:   return "MODULE_STRTAB_BLOCK";<br>
   }<br>
 }<br>
<br>
@@ -268,6 +271,18 @@ static const char *GetCodeName(unsigned<br>
     STRINGIFY_CODE(VST_CODE, ENTRY)<br>
     STRINGIFY_CODE(VST_CODE, BBENTRY)<br>
     STRINGIFY_CODE(VST_CODE, FNENTRY)<br>
+    STRINGIFY_CODE(VST_CODE, COMBINED_FNENTRY)<br>
+    }<br>
+  case bitc::MODULE_STRTAB_BLOCK_ID:<br>
+    switch (CodeID) {<br>
+    default: return nullptr;<br>
+    STRINGIFY_CODE(MST_CODE, ENTRY)<br>
+    }<br>
+  case bitc::FUNCTION_SUMMARY_BLOCK_ID:<br>
+    switch (CodeID) {<br>
+    default: return nullptr;<br>
+    STRINGIFY_CODE(FS_CODE, PERMODULE_ENTRY)<br>
+    STRINGIFY_CODE(FS_CODE, COMBINED_ENTRY)<br>
     }<br>
   case bitc::METADATA_ATTACHMENT_ID:<br>
     switch(CodeID) {<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br></div>