<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Mar 11, 2016 at 10:52 AM, 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> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: tejohnson<br>
Date: Fri Mar 11 12:52:24 2016<br>
New Revision: 263275<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=263275&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=263275&view=rev</a><br>
Log:<br>
[ThinLTO] Support for reference graph in per-module and combined summary.<br>
<br>
Summary:<br>
This patch adds support for including a full reference graph including<br>
call graph edges and other GV references in the summary.<br>
<br>
The reference graph edges can be used to make importing decisions<br>
without materializing any source modules, can be used in the plugin<br>
to make file staging decisions for distributed build systems, and is<br>
expected to have other uses.<br>
<br>
The call graph edges are recorded in each function summary in the<br>
bitcode via a list of <CalleeValueIds, StaticCount> tuples when no PGO<br>
data exists, or <CalleeValueId, StaticCount, ProfileCount> pairs when<br>
there is PGO, where the ValueId can be mapped to the function GUID via<br>
the ValueSymbolTable. In the function index in memory, the call graph<br>
edges reference the target via the CalleeGUID instead of the<br>
CalleeValueId.<br>
<br>
The reference graph edges are recorded in each summary record with a<br>
list of referenced value IDs, which can be mapped to value GUID via the<br>
ValueSymbolTable.<br>
<br>
Addtionally, a new summary record type is added to record references<br>
from global variable initializers. A number of bitcode records and data<br>
structures have been renamed to reflect the newly expanded scope of the<br>
summary beyond functions. More cleanup will follow.<br>
<br>
Reviewers: joker.eph, davidxl<br>
<br>
Subscribers: joker.eph, llvm-commits<br>
<br>
Differential Revision: <a href="http://reviews.llvm.org/D17212" rel="noreferrer" target="_blank">http://reviews.llvm.org/D17212</a><br>
<br>
Added:<br>
    llvm/trunk/test/Bitcode/Inputs/thinlto-function-summary-callgraph-pgo.ll<br>
    llvm/trunk/test/Bitcode/Inputs/thinlto-function-summary-callgraph.ll<br>
    llvm/trunk/test/Bitcode/thinlto-function-summary-callgraph-pgo.ll<br>
    llvm/trunk/test/Bitcode/thinlto-function-summary-callgraph.ll<br>
    llvm/trunk/test/Bitcode/thinlto-function-summary-refgraph.ll<br>
Modified:<br>
    llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h<br>
    llvm/trunk/include/llvm/Bitcode/ReaderWriter.h<br>
    llvm/trunk/include/llvm/IR/FunctionInfo.h<br>
    llvm/trunk/include/llvm/Object/FunctionIndexObjectFile.h<br>
    llvm/trunk/include/llvm/ProfileData/ProfileCommon.h<br>
    llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp<br>
    llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp<br>
    llvm/trunk/lib/Bitcode/Writer/LLVMBuild.txt<br>
    llvm/trunk/lib/IR/FunctionInfo.cpp<br>
    llvm/trunk/lib/LTO/LTOModule.cpp<br>
    llvm/trunk/lib/LTO/ThinLTOCodeGenerator.cpp<br>
    llvm/trunk/lib/Object/FunctionIndexObjectFile.cpp<br>
    llvm/trunk/lib/Transforms/IPO/FunctionImport.cpp<br>
    llvm/trunk/test/Bitcode/thinlto-function-summary.ll<br>
    llvm/trunk/test/Bitcode/thinlto-summary-linkage-types.ll<br>
    llvm/trunk/test/tools/gold/X86/thinlto.ll<br>
    llvm/trunk/test/tools/llvm-lto/thinlto.ll<br>
    llvm/trunk/tools/gold/gold-plugin.cpp<br>
    llvm/trunk/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp<br>
    llvm/trunk/tools/llvm-lto/llvm-lto.cpp<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=263275&r1=263274&r2=263275&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h?rev=263275&r1=263274&r2=263275&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h (original)<br>
+++ llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h Fri Mar 11 12:52:24 2016<br>
@@ -48,7 +48,7 @@ enum BlockIDs {<br>
   USELIST_BLOCK_ID,<br>
<br>
   MODULE_STRTAB_BLOCK_ID,<br>
-  FUNCTION_SUMMARY_BLOCK_ID,<br>
+  GLOBALVAL_SUMMARY_BLOCK_ID,<br>
<br>
   OPERAND_BUNDLE_TAGS_BLOCK_ID,<br>
<br>
@@ -175,8 +175,10 @@ enum { BITCODE_CURRENT_EPOCH = 0 };<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: [funcsumoffset, funcguid]<br>
-    VST_CODE_COMBINED_FNENTRY = 4<br>
+    // VST_COMBINED_GVDEFENTRY: [valueid, sumoffset, guid]<br>
+    VST_CODE_COMBINED_GVDEFENTRY = 4,<br>
+    // VST_COMBINED_ENTRY: [valueid, refguid]<br>
+    VST_CODE_COMBINED_ENTRY = 5<br>
   };<br>
<br>
   // The module path symbol table only has one code (MST_CODE_ENTRY).<br>
@@ -187,8 +189,24 @@ enum { BITCODE_CURRENT_EPOCH = 0 };<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, linkage, instcount]<br>
-    FS_CODE_COMBINED_ENTRY  = 2,  // FS_ENTRY: [modid, linkage, instcount]<br>
+    // PERMODULE: [valueid, linkage, instcount, numrefs, numrefs x valueid,<br>
+    //             n x (valueid, callsitecount)]<br>
+    FS_PERMODULE = 1,<br>
+    // PERMODULE_PROFILE: [valueid, linkage, instcount, numrefs,<br>
+    //                     numrefs x valueid,<br>
+    //                     n x (valueid, callsitecount, profilecount)]<br>
+    FS_PERMODULE_PROFILE = 2,<br>
+    // PERMODULE_GLOBALVAR_INIT_REFS: [valueid, linkage, n x valueid]<br>
+    FS_PERMODULE_GLOBALVAR_INIT_REFS = 3,<br>
+    // COMBINED: [modid, linkage, instcount, numrefs, numrefs x valueid,<br>
+    //            n x (valueid, callsitecount)]<br>
+    FS_COMBINED = 4,<br>
+    // COMBINED_PROFILE: [modid, linkage, instcount, numrefs,<br>
+    //                    numrefs x valueid,<br>
+    //                    n x (valueid, callsitecount, profilecount)]<br>
+    FS_COMBINED_PROFILE = 5,<br>
+    // COMBINED_GLOBALVAR_INIT_REFS: [modid, linkage, n x valueid]<br>
+    FS_COMBINED_GLOBALVAR_INIT_REFS = 6,<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=263275&r1=263274&r2=263275&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Bitcode/ReaderWriter.h?rev=263275&r1=263274&r2=263275&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/Bitcode/ReaderWriter.h (original)<br>
+++ llvm/trunk/include/llvm/Bitcode/ReaderWriter.h Fri Mar 11 12:52:24 2016<br>
@@ -70,9 +70,9 @@ namespace llvm {<br>
   ErrorOr<std::unique_ptr<Module>> parseBitcodeFile(MemoryBufferRef Buffer,<br>
                                                     LLVMContext &Context);<br>
<br>
-  /// Check if the given bitcode buffer contains a function summary block.<br>
-  bool hasFunctionSummary(MemoryBufferRef Buffer,<br>
-                          DiagnosticHandlerFunction DiagnosticHandler);<br>
+  /// Check if the given bitcode buffer contains a summary block.<br>
+  bool hasGlobalValueSummary(MemoryBufferRef Buffer,<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>
@@ -103,17 +103,16 @@ namespace llvm {<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>
+  /// If \c EmitSummaryIndex, emit the module's summary index (currently<br>
   /// for use in ThinLTO optimization).<br>
   void WriteBitcodeToFile(const Module *M, raw_ostream &Out,<br>
                           bool ShouldPreserveUseListOrder = false,<br>
-                          bool EmitFunctionSummary = false);<br>
+                          bool EmitSummaryIndex = false);<br>
<br>
-  /// Write the specified function summary index to the given raw output stream,<br>
+  /// Write the specified module 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>
+  void WriteIndexToFile(const FunctionInfoIndex &Index, 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>
Modified: 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=263275&r1=263274&r2=263275&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/FunctionInfo.h?rev=263275&r1=263274&r2=263275&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/IR/FunctionInfo.h (original)<br>
+++ llvm/trunk/include/llvm/IR/FunctionInfo.h Fri Mar 11 12:52:24 2016<br>
@@ -9,13 +9,15 @@<br>
 //<br>
 /// @file<br>
 /// FunctionInfo.h This file contains the declarations the classes that hold<br>
-///  the function info index and summary.<br>
+///  the module index and summary for function importing.<br>
 //<br>
 //===----------------------------------------------------------------------===//<br>
<br>
 #ifndef LLVM_IR_FUNCTIONINFO_H<br>
 #define LLVM_IR_FUNCTIONINFO_H<br>
<br>
+#include "llvm/ADT/DenseMap.h"<br>
+#include "llvm/ADT/DenseSet.h"<br>
 #include "llvm/ADT/SmallString.h"<br>
 #include "llvm/ADT/StringMap.h"<br>
 #include "llvm/IR/Function.h"<br>
@@ -25,44 +27,69 @@<br>
<br>
 namespace llvm {<br>
<br>
-/// \brief Function summary information to aid decisions and implementation of<br>
-/// importing.<br>
+/// \brief Class to accumulate and hold information about a callee.<br>
+struct CalleeInfo {<br>
+  /// The static number of callsites calling corresponding function.<br>
+  unsigned CallsiteCount;<br>
+  /// The cumulative profile count of calls to corresponding function<br>
+  /// (if using PGO, otherwise 0).<br>
+  uint64_t ProfileCount;<br>
+  CalleeInfo() = default;<br>
+  CalleeInfo(unsigned CallsiteCount, uint64_t ProfileCount)<br>
+      : CallsiteCount(CallsiteCount), ProfileCount(ProfileCount) {}<br>
+  CalleeInfo &operator+=(uint64_t RHSProfileCount) {<br>
+    CallsiteCount++;<br>
+    ProfileCount += RHSProfileCount;<br>
+    return *this;<br>
+  }<br>
+};<br>
+<br>
+/// \brief Function and variable summary information to aid decisions and<br>
+/// implementation of 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>
+/// This is a separate class from GlobalValueInfo to enable lazy reading of this<br>
+/// summary information from the combined index file during imporing.<br>
+class GlobalValueSummary {<br>
+public:<br>
+  /// \brief Sububclass discriminator (for dyn_cast<> et al.)<br>
+  enum SummaryKind { FunctionKind, GlobalVarKind };<br>
+<br>
 private:<br>
-  /// \brief Path of module containing function IR, used to locate module when<br>
-  /// importing this function.<br>
+  /// Kind of summary for use in dyn_cast<> et al.<br>
+  SummaryKind Kind;<br>
+<br>
+  /// \brief Path of module IR containing value's definition, used to locate<br>
+  /// module during importing.<br>
   ///<br>
-  /// This is only used during parsing of the combined function index, or when<br>
+  /// This is only used during parsing of the combined 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 The linkage type of the associated function.<br>
+  /// \brief The linkage type of the associated global value.<br>
   ///<br>
-  /// One use is to flag functions that have local linkage types and need to<br>
+  /// One use is to flag values 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>
+  /// index, to disambiguate from other values with the same name.<br>
   /// In the future this will be used to update and optimize linkage<br>
   /// types based on global summary-based analysis.<br>
-  GlobalValue::LinkageTypes FunctionLinkage;<br>
+  GlobalValue::LinkageTypes Linkage;<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>
+  /// List of GUIDs of values referenced by this global value's definition<br>
+  /// (either by the initializer of a global variable, or referenced<br>
+  /// from within a function). This does not include functions called, which<br>
+  /// are listed in the derived FunctionSummary object.<br>
+  std::vector<uint64_t> RefEdgeList;<br>
+<br>
+protected:<br>
+  /// GlobalValueSummary constructor.<br>
+  GlobalValueSummary(SummaryKind K, GlobalValue::LinkageTypes Linkage)<br>
+      : Kind(K), Linkage(Linkage) {}<br>
<br>
 public:<br>
-  /// Construct a summary object from summary data expected for all<br>
-  /// summary records.<br>
-  FunctionSummary(unsigned NumInsts) : InstCount(NumInsts) {}<br>
+  /// Which kind of summary subclass this is.<br>
+  SummaryKind getSummaryKind() const { return Kind; }<br>
<br>
   /// Set the path to the module containing this function, for use in<br>
   /// the combined index.<br>
@@ -71,105 +98,164 @@ public:<br>
   /// Get the path to the module containing this function.<br>
   StringRef modulePath() const { return ModulePath; }<br>
<br>
-  /// Record linkage type.<br>
-  void setFunctionLinkage(GlobalValue::LinkageTypes Linkage) {<br>
-    FunctionLinkage = Linkage;<br>
-  }<br>
+  /// Return linkage type recorded for this global value.<br>
+  GlobalValue::LinkageTypes linkage() const { return Linkage; }<br>
+<br>
+  /// Record a reference from this global value to the global value identified<br>
+  /// by \p RefGUID.<br>
+  void addRefEdge(uint64_t RefGUID) { RefEdgeList.push_back(RefGUID); }<br>
+<br>
+  /// Record a reference from this global value to each global value identified<br>
+  /// in \p RefEdges.<br>
+  void addRefEdges(DenseSet<unsigned> &RefEdges) {<br>
+    for (auto &RI : RefEdges)<br>
+      addRefEdge(RI);<br>
+  }<br>
+<br>
+  /// Return the list of GUIDs referenced by this global value definition.<br>
+  std::vector<uint64_t> &refs() { return RefEdgeList; }<br>
+  const std::vector<uint64_t> &refs() const { return RefEdgeList; }<br>
+};<br>
+<br>
+/// \brief Function summary information to aid decisions and implementation of<br>
+/// importing.<br>
+class FunctionSummary : public GlobalValueSummary {<br></blockquote><div><br></div><div>This is a slightly odd inheritance, having no virtual functions (had it had virtual functions the warnings related to missing virtual dtors would've fired).<br><br>Should some functionality be rolled into these classes to generalize their use, that would be virtual? (ie: the only way to use this class is with a dyn_cast to access the members - perhaps the code that dyn_casts could instead be calling a virtual function to dispatch between the two cases?)<br><br>Speaking of dyn casts... </div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+public:<br>
+  /// <CalleeGUID, CalleeInfo> call edge pair.<br>
+  typedef std::pair<uint64_t, CalleeInfo> EdgeTy;<br>
<br>
-  /// Return linkage type recorded for this function.<br>
-  GlobalValue::LinkageTypes getFunctionLinkage() const {<br>
-    return FunctionLinkage;<br>
+private:<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>
+  /// List of <CalleeGUID, CalleeInfo> call edge pairs from this function.<br>
+  std::vector<EdgeTy> CallGraphEdgeList;<br>
+<br>
+public:<br>
+  /// Summary constructors.<br>
+  FunctionSummary(GlobalValue::LinkageTypes Linkage, unsigned NumInsts)<br>
+      : GlobalValueSummary(FunctionKind, Linkage), InstCount(NumInsts) {}<br>
+<br>
+  /// Check if this is a function summary.<br>
+  static bool classof(const GlobalValueSummary *GVS) {<br>
+    return GVS->getSummaryKind() == FunctionKind;<br>
   }<br>
<br>
   /// Get the instruction count recorded for this function.<br>
   unsigned instCount() const { return InstCount; }<br>
+<br>
+  /// Record a call graph edge from this function to the function identified<br>
+  /// by \p CalleeGUID, with \p CalleeInfo including the cumulative profile<br>
+  /// count (across all calls from this function) or 0 if no PGO.<br>
+  void addCallGraphEdge(uint64_t CalleeGUID, CalleeInfo Info) {<br>
+    CallGraphEdgeList.push_back(std::make_pair(CalleeGUID, Info));<br>
+  }<br>
+<br>
+  /// Record a call graph edge from this function to each function recorded<br>
+  /// in \p CallGraphEdges.<br>
+  void addCallGraphEdges(DenseMap<unsigned, CalleeInfo> &CallGraphEdges) {<br>
+    for (auto &EI : CallGraphEdges)<br>
+      addCallGraphEdge(EI.first, EI.second);<br>
+  }<br>
+<br>
+  /// Return the list of <CalleeGUID, ProfileCount> pairs.<br>
+  std::vector<EdgeTy> &edges() { return CallGraphEdgeList; }<br>
+  const std::vector<EdgeTy> &edges() const { return CallGraphEdgeList; }<br>
 };<br>
<br>
-/// \brief Class to hold pointer to function summary and information required<br>
-/// for parsing it.<br>
+/// \brief Global variable summary information to aid decisions and<br>
+/// implementation of importing.<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>
+/// Currently this doesn't add anything to the base \p GlobalValueSummary,<br>
+/// but is a placeholder as additional info may be added to the summary<br>
+/// for variables.<br>
+class GlobalVarSummary : public GlobalValueSummary {<br>
+<br>
+public:<br>
+  /// Summary constructors.<br>
+  GlobalVarSummary(GlobalValue::LinkageTypes Linkage)<br>
+      : GlobalValueSummary(GlobalVarKind, Linkage) {}<br>
+<br>
+  /// Check if this is a global variable summary.<br>
+  static bool classof(const GlobalValueSummary *GVS) {<br>
+    return GVS->getSummaryKind() == GlobalVarKind;<br>
+  }<br>
+};<br>
+<br>
+/// \brief Class to hold pointer to summary object and information required<br>
+/// for parsing or writing it.<br>
+class GlobalValueInfo {<br>
 private:<br>
-  /// Function summary information used to help make ThinLTO importing<br>
-  /// decisions.<br>
-  std::unique_ptr<FunctionSummary> Summary;<br>
+  /// Summary information used to help make ThinLTO importing decisions.<br>
+  std::unique_ptr<GlobalValueSummary> Summary;<br>
<br>
-  /// \brief The bitcode offset corresponding to either the associated<br>
-  /// function's function body record, or its function summary record,<br>
+  /// \brief The bitcode offset corresponding to either an associated<br>
+  /// function's function body record, or to an associated 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>
+  /// \a ValueSymbolTable entry for a function.<br>
+  /// For the per-module index this holds the bitcode offset of a<br>
+  /// function's body record within bitcode module block in its module,<br>
+  /// although this field is currently only used when writing the VST<br>
+  /// (it is set to 0 and also unused when this is a global variable).<br>
   /// For the combined index this holds the offset of the corresponding<br>
-  /// function summary record, to enable associating the combined index<br>
+  /// 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>
+  GlobalValueInfo(uint64_t Offset = 0,<br>
+                  std::unique_ptr<GlobalValueSummary> Summary = nullptr)<br>
+      : Summary(std::move(Summary)), BitcodeIndex(Offset) {}<br>
+<br>
+  /// Record the summary information parsed out of the summary block during<br>
+  /// parsing or combined index creation.<br>
+  void setSummary(std::unique_ptr<GlobalValueSummary> GVSummary) {<br>
+    Summary = std::move(GVSummary);<br>
   }<br>
<br>
-  /// Get the function summary recorded for this function.<br>
-  FunctionSummary *functionSummary() const { return Summary.get(); }<br>
+  /// Get the summary recorded for this global value.<br>
+  GlobalValueSummary *summary() const { return Summary.get(); }<br>
<br>
-  /// Get the bitcode index recorded for this function, depending on<br>
-  /// the index type.<br>
+  /// Get the bitcode index recorded for this value symbol table entry.<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>
+  /// Set the bitcode index recorded for this value symbol table entry.<br>
+  void setBitcodeIndex(uint64_t Offset) { BitcodeIndex = Offset; }<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>
+/// List of global value info structures for a particular value held<br>
+/// in the GlobalValueMap. Requires a vector in the case of multiple<br>
+/// COMDAT values of the same name.<br>
+typedef std::vector<std::unique_ptr<GlobalValueInfo>> GlobalValueInfoList;<br>
<br>
-/// Map from function GUID to corresponding function info structures.<br>
+/// Map from global value GUID to corresponding info structures.<br>
 /// Use a std::map rather than a DenseMap since it will likely incur<br>
 /// less overhead, as the value type is not very small and the size<br>
 /// of the map is unknown, resulting in inefficiencies due to repeated<br>
 /// insertions and resizing.<br>
-typedef std::map<uint64_t, FunctionInfoList> FunctionInfoMapTy;<br>
+typedef std::map<uint64_t, GlobalValueInfoList> GlobalValueInfoMapTy;<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>
+/// Type used for iterating through the global value info map.<br>
+typedef GlobalValueInfoMapTy::const_iterator const_globalvalueinfo_iterator;<br>
+typedef GlobalValueInfoMapTy::iterator globalvalueinfo_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>
+/// Class to hold module path string table and global value map,<br>
 /// and encapsulate methods for operating on them.<br>
+/// FIXME: Rename this and other uses of Function.*Index to something<br>
+/// that reflects the now-expanded scope of the summary beyond just functions.<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>
+  /// Map from value name to list of information instances for values of that<br>
+  /// name (may be duplicates in the COMDAT case, e.g.).<br>
+  GlobalValueInfoMapTy GlobalValueMap;<br>
<br>
   /// Holds strings for combined index, mapping to the corresponding module ID.<br>
   ModulePathStringTableTy ModulePathStringTable;<br>
@@ -182,28 +268,40 @@ public:<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>
+  globalvalueinfo_iterator begin() { return GlobalValueMap.begin(); }<br>
+  const_globalvalueinfo_iterator begin() const {<br>
+    return GlobalValueMap.begin();<br>
+  }<br>
+  globalvalueinfo_iterator end() { return GlobalValueMap.end(); }<br>
+  const_globalvalueinfo_iterator end() const { return GlobalValueMap.end(); }<br>
+<br>
+  /// Get the list of global value info objects for a given value name.<br>
+  const GlobalValueInfoList &getGlobalValueInfoList(StringRef FuncName) {<br>
+    return GlobalValueMap[Function::getGUID(FuncName)];<br>
+  }<br>
<br>
-  /// Get the list of function info objects for a given function.<br>
-  const FunctionInfoList &getFunctionInfoList(StringRef FuncName) {<br>
-    return FunctionMap[Function::getGUID(FuncName)];<br>
+  /// Get the list of global value info objects for a given value name.<br>
+  const const_globalvalueinfo_iterator<br>
+  findGlobalValueInfoList(StringRef ValueName) const {<br>
+    return GlobalValueMap.find(Function::getGUID(ValueName));<br>
   }<br>
<br>
-  /// Get the list of function info objects for a given function.<br>
-  const const_funcinfo_iterator findFunctionInfoList(StringRef FuncName) const {<br>
-    return FunctionMap.find(Function::getGUID(FuncName));<br>
+  /// Get the list of global value info objects for a given value GUID.<br>
+  const const_globalvalueinfo_iterator<br>
+  findGlobalValueInfoList(uint64_t ValueGUID) const {<br>
+    return GlobalValueMap.find(ValueGUID);<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[Function::getGUID(FuncName)].push_back(std::move(Info));<br>
+  /// Add a global value info for a value of the given name.<br>
+  void addGlobalValueInfo(StringRef ValueName,<br>
+                          std::unique_ptr<GlobalValueInfo> Info) {<br>
+    GlobalValueMap[Function::getGUID(ValueName)].push_back(std::move(Info));<br>
   }<br>
<br>
-  void addFunctionInfo(uint64_t FuncGUID, std::unique_ptr<FunctionInfo> Info) {<br>
-    FunctionMap[FuncGUID].push_back(std::move(Info));<br>
+  /// Add a global value info for a value of the given GUID.<br>
+  void addGlobalValueInfo(uint64_t ValueGUID,<br>
+                          std::unique_ptr<GlobalValueInfo> Info) {<br>
+    GlobalValueMap[ValueGUID].push_back(std::move(Info));<br>
   }<br>
<br>
   /// Iterator to allow writer to walk through table during emission.<br>
@@ -218,7 +316,7 @@ public:<br>
     return ModulePathStringTable.lookup(ModPath);<br>
   }<br>
<br>
-  /// Add the given per-module index into this function index/summary,<br>
+  /// Add the given per-module index into this module 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>
@@ -247,6 +345,13 @@ public:<br>
   bool hasExportedFunctions(const Module &M) const {<br>
     return ModulePathStringTable.count(M.getModuleIdentifier());<br>
   }<br>
+<br>
+  /// Remove entries in the GlobalValueMap that have empty summaries due to the<br>
+  /// eager nature of map entry creation during VST parsing. These would<br>
+  /// also be suppressed during combined index generation in mergeFrom(),<br>
+  /// but if there was only one module or this was the first module we might<br>
+  /// not invoke mergeFrom.<br>
+  void removeEmptySummaryEntries();<br>
 };<br>
<br>
 } // End llvm namespace<br>
<br>
Modified: 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=263275&r1=263274&r2=263275&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Object/FunctionIndexObjectFile.h?rev=263275&r1=263274&r2=263275&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/Object/FunctionIndexObjectFile.h (original)<br>
+++ llvm/trunk/include/llvm/Object/FunctionIndexObjectFile.h Fri Mar 11 12:52:24 2016<br>
@@ -77,11 +77,11 @@ public:<br>
   static ErrorOr<MemoryBufferRef><br>
   findBitcodeInMemBuffer(MemoryBufferRef Object);<br>
<br>
-  /// \brief Looks for function summary in the given memory buffer,<br>
+  /// \brief Looks for summary sections in the given memory buffer,<br>
   /// returns true if found, else false.<br>
   static bool<br>
-  hasFunctionSummaryInMemBuffer(MemoryBufferRef Object,<br>
-                                DiagnosticHandlerFunction DiagnosticHandler);<br>
+  hasGlobalValueSummaryInMemBuffer(MemoryBufferRef Object,<br>
+                                   DiagnosticHandlerFunction DiagnosticHandler);<br>
<br>
   /// \brief Parse function index in the given memory buffer.<br>
   /// Return new FunctionIndexObjectFile instance containing parsed function<br>
<br>
Modified: llvm/trunk/include/llvm/ProfileData/ProfileCommon.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ProfileData/ProfileCommon.h?rev=263275&r1=263274&r2=263275&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ProfileData/ProfileCommon.h?rev=263275&r1=263274&r2=263275&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/ProfileData/ProfileCommon.h (original)<br>
+++ llvm/trunk/include/llvm/ProfileData/ProfileCommon.h Fri Mar 11 12:52:24 2016<br>
@@ -15,6 +15,7 @@<br>
 #ifndef LLVM_PROFILEDATA_PROFILE_COMMON_H<br>
 #define LLVM_PROFILEDATA_PROFILE_COMMON_H<br>
<br>
+#include "llvm/ADT/APInt.h"<br>
 #include <cstdint><br>
 #include <functional><br>
 #include <map><br>
@@ -184,5 +185,18 @@ SummaryEntryVector &ProfileSummary::getD<br>
   return DetailedSummary;<br>
 }<br>
<br>
+/// Helper to compute the profile count for a block, based on the<br>
+/// ratio of its frequency to the entry block frequency, multiplied<br>
+/// by the entry block count.<br>
+inline uint64_t getBlockProfileCount(uint64_t BlockFreq, uint64_t EntryFreq,<br>
+                                     uint64_t EntryCount) {<br>
+  APInt ScaledCount(128, EntryCount);<br>
+  APInt BlockFreqAPInt(128, BlockFreq);<br>
+  APInt EntryFreqAPInt(128, EntryFreq);<br>
+  ScaledCount *= BlockFreqAPInt;<br>
+  ScaledCount = ScaledCount.udiv(EntryFreqAPInt);<br>
+  return ScaledCount.getLimitedValue();<br>
+}<br>
+<br>
 } // end namespace llvm<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=263275&r1=263274&r2=263275&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp?rev=263275&r1=263274&r2=263275&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp (original)<br>
+++ llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp Fri Mar 11 12:52:24 2016<br>
@@ -416,7 +416,7 @@ private:<br>
 class FunctionIndexBitcodeReader {<br>
   DiagnosticHandlerFunction DiagnosticHandler;<br>
<br>
-  /// Eventually points to the function index built during parsing.<br>
+  /// Eventually points to the module index built during parsing.<br>
   FunctionInfoIndex *TheIndex = nullptr;<br>
<br>
   std::unique_ptr<MemoryBuffer> Buffer;<br>
@@ -432,29 +432,37 @@ class FunctionIndexBitcodeReader {<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>
+  /// of the global value summary bitcode section. All blocks are skipped,<br>
+  /// but the SeenGlobalValSummary boolean is set.<br>
+  bool CheckGlobalValSummaryPresenceOnly = false;<br>
<br>
-  /// Indicates whether we have encountered a function summary section<br>
-  /// yet during parsing, used when checking if file contains function<br>
+  /// Indicates whether we have encountered a global value summary section<br>
+  /// yet during parsing, used when checking if file contains global value<br>
   /// summary section.<br>
-  bool SeenFuncSummary = false;<br>
+  bool SeenGlobalValSummary = 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>
+  /// Indicates whether we have already parsed the VST, used for error checking.<br>
+  bool SeenValueSymbolTable = false;<br>
+<br>
+  /// Set to the offset of the VST recorded in the MODULE_CODE_VSTOFFSET record.<br>
+  /// Used to enable on-demand parsing of the VST.<br>
+  uint64_t VSTOffset = 0;<br>
+<br>
+  // Map to save ValueId to GUID association that was recorded in the<br>
+  // ValueSymbolTable. It is used after the VST is parsed to convert<br>
+  // call graph edges read from the function summary from referencing<br>
+  // callees by their ValueId to using the GUID instead, which is how<br>
+  // they are recorded in the function index being built.<br>
+  DenseMap<unsigned, uint64_t> ValueIdToCallGraphGUIDMap;<br>
+<br>
+  /// Map to save the association between summary offset in the VST to the<br>
+  /// GlobalValueInfo object created when parsing it. Used to access the<br>
+  /// info object when parsing the summary section.<br>
+  DenseMap<uint64_t, GlobalValueInfo *> SummaryOffsetToInfoMap;<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>
+  /// path string table, used to correlate with combined index<br>
   /// summary records.<br>
   DenseMap<uint64_t, StringRef> ModuleIdMap;<br>
<br>
@@ -469,37 +477,41 @@ public:<br>
   FunctionIndexBitcodeReader(MemoryBuffer *Buffer,<br>
                              DiagnosticHandlerFunction DiagnosticHandler,<br>
                              bool IsLazy = false,<br>
-                             bool CheckFuncSummaryPresenceOnly = false);<br>
+                             bool CheckGlobalValSummaryPresenceOnly = false);<br>
   FunctionIndexBitcodeReader(DiagnosticHandlerFunction DiagnosticHandler,<br>
                              bool IsLazy = false,<br>
-                             bool CheckFuncSummaryPresenceOnly = false);<br>
+                             bool CheckGlobalValSummaryPresenceOnly = 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>
+  /// Check if the parser has encountered a summary section.<br>
+  bool foundGlobalValSummary() { return SeenGlobalValSummary; }<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>
+  /// \brief Interface for parsing a 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 parseValueSymbolTable(<br>
+      uint64_t Offset,<br>
+      DenseMap<unsigned, GlobalValue::LinkageTypes> &ValueIdToLinkageMap);<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>
+  uint64_t getGUIDFromValueId(unsigned ValueId);<br>
+  GlobalValueInfo *getInfoFromSummaryOffset(uint64_t Offset);<br>
 };<br>
 } // end anonymous namespace<br>
<br>
@@ -1727,6 +1739,27 @@ ErrorOr<Value *> BitcodeReader::recordVa<br>
   return V;<br>
 }<br>
<br>
+/// Helper to note and return the current location, and jump to the given<br>
+/// offset.<br>
+static uint64_t jumpToValueSymbolTable(uint64_t Offset,<br>
+                                       BitstreamCursor &Stream) {<br>
+  // Save the current parsing location so we can jump back at the end<br>
+  // of the VST read.<br>
+  uint64_t CurrentBit = Stream.GetCurrentBitNo();<br>
+  Stream.JumpToBit(Offset * 32);<br>
+#ifndef NDEBUG<br>
+  // Do some checking if we are in debug mode.<br>
+  BitstreamEntry Entry = Stream.advance();<br>
+  assert(Entry.Kind == BitstreamEntry::SubBlock);<br>
+  assert(Entry.ID == bitc::VALUE_SYMTAB_BLOCK_ID);<br>
+#else<br>
+  // In NDEBUG mode ignore the output so we don't get an unused variable<br>
+  // warning.<br>
+  Stream.advance();<br>
+#endif<br>
+  return CurrentBit;<br>
+}<br>
+<br>
 /// Parse the value symbol table at either the current parsing location or<br>
 /// at the given bit offset if provided.<br>
 std::error_code BitcodeReader::parseValueSymbolTable(uint64_t Offset) {<br>
@@ -1734,22 +1767,8 @@ std::error_code BitcodeReader::parseValu<br>
   // Pass in the Offset to distinguish between calling for the module-level<br>
   // VST (where we want to jump to the VST offset) and the function-level<br>
   // VST (where we don't).<br>
-  if (Offset > 0) {<br>
-    // Save the current parsing location so we can jump back at the end<br>
-    // of the VST read.<br>
-    CurrentBit = Stream.GetCurrentBitNo();<br>
-    Stream.JumpToBit(Offset * 32);<br>
-#ifndef NDEBUG<br>
-    // Do some checking if we are in debug mode.<br>
-    BitstreamEntry Entry = Stream.advance();<br>
-    assert(Entry.Kind == BitstreamEntry::SubBlock);<br>
-    assert(Entry.ID == bitc::VALUE_SYMTAB_BLOCK_ID);<br>
-#else<br>
-    // In NDEBUG mode ignore the output so we don't get an unused variable<br>
-    // warning.<br>
-    Stream.advance();<br>
-#endif<br>
-  }<br>
+  if (Offset > 0)<br>
+    CurrentBit = jumpToValueSymbolTable(Offset, Stream);<br>
<br>
   // Compute the delta between the bitcode indices in the VST (the word offset<br>
   // to the word-aligned ENTER_SUBBLOCK for the function block, and that<br>
@@ -5411,27 +5430,45 @@ std::error_code FunctionIndexBitcodeRead<br>
<br>
 FunctionIndexBitcodeReader::FunctionIndexBitcodeReader(<br>
     MemoryBuffer *Buffer, DiagnosticHandlerFunction DiagnosticHandler,<br>
-    bool IsLazy, bool CheckFuncSummaryPresenceOnly)<br>
+    bool IsLazy, bool CheckGlobalValSummaryPresenceOnly)<br>
     : DiagnosticHandler(DiagnosticHandler), Buffer(Buffer), IsLazy(IsLazy),<br>
-      CheckFuncSummaryPresenceOnly(CheckFuncSummaryPresenceOnly) {}<br>
+      CheckGlobalValSummaryPresenceOnly(CheckGlobalValSummaryPresenceOnly) {}<br>
<br>
 FunctionIndexBitcodeReader::FunctionIndexBitcodeReader(<br>
     DiagnosticHandlerFunction DiagnosticHandler, bool IsLazy,<br>
-    bool CheckFuncSummaryPresenceOnly)<br>
+    bool CheckGlobalValSummaryPresenceOnly)<br>
     : DiagnosticHandler(DiagnosticHandler), Buffer(nullptr), IsLazy(IsLazy),<br>
-      CheckFuncSummaryPresenceOnly(CheckFuncSummaryPresenceOnly) {}<br>
+      CheckGlobalValSummaryPresenceOnly(CheckGlobalValSummaryPresenceOnly) {}<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>
+uint64_t FunctionIndexBitcodeReader::getGUIDFromValueId(unsigned ValueId) {<br>
+  auto VGI = ValueIdToCallGraphGUIDMap.find(ValueId);<br>
+  assert(VGI != ValueIdToCallGraphGUIDMap.end());<br>
+  return VGI->second;<br>
+}<br>
+<br>
+GlobalValueInfo *<br>
+FunctionIndexBitcodeReader::getInfoFromSummaryOffset(uint64_t Offset) {<br>
+  auto I = SummaryOffsetToInfoMap.find(Offset);<br>
+  assert(I != SummaryOffsetToInfoMap.end());<br>
+  return I->second;<br>
+}<br>
+<br>
+// Specialized value symbol table parser used when reading module 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>
+// At the end of this routine the module index is populated with a map<br>
+// from global value name to GlobalValueInfo. The global value info contains<br>
+// the function block's bitcode offset (if applicable), or the offset into the<br>
+// summary section for the combined index.<br>
+std::error_code FunctionIndexBitcodeReader::parseValueSymbolTable(<br>
+    uint64_t Offset,<br>
+    DenseMap<unsigned, GlobalValue::LinkageTypes> &ValueIdToLinkageMap) {<br>
+  assert(Offset > 0 && "Expected non-zero VST offset");<br>
+  uint64_t CurrentBit = jumpToValueSymbolTable(Offset, Stream);<br>
+<br>
   if (Stream.EnterSubBlock(bitc::VALUE_SYMTAB_BLOCK_ID))<br>
     return error("Invalid record");<br>
<br>
@@ -5447,6 +5484,8 @@ std::error_code FunctionIndexBitcodeRead<br>
     case BitstreamEntry::Error:<br>
       return error("Malformed block");<br>
     case BitstreamEntry::EndBlock:<br>
+      // Done parsing VST, jump back to wherever we came from.<br>
+      Stream.JumpToBit(CurrentBit);<br>
       return std::error_code();<br>
     case BitstreamEntry::Record:<br>
       // The interesting case.<br>
@@ -5458,6 +5497,23 @@ std::error_code FunctionIndexBitcodeRead<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_ENTRY: { // VST_CODE_ENTRY: [valueid, namechar x N]<br>
+      if (convertToString(Record, 1, ValueName))<br>
+        return error("Invalid record");<br>
+      unsigned ValueID = Record[0];<br>
+      std::unique_ptr<GlobalValueInfo> GlobalValInfo =<br>
+          llvm::make_unique<GlobalValueInfo>();<br>
+      assert(!SourceFileName.empty());<br>
+      auto VLI = ValueIdToLinkageMap.find(ValueID);<br>
+      assert(VLI != ValueIdToLinkageMap.end() &&<br>
+             "No linkage found for VST entry?");<br>
+      std::string GlobalId =<br>
+          Function::getGlobalIdentifier(ValueName, VLI->second, SourceFileName);<br>
+      TheIndex->addGlobalValueInfo(GlobalId, std::move(GlobalValInfo));<br>
+      ValueIdToCallGraphGUIDMap[ValueID] = Function::getGUID(GlobalId);<br>
+      ValueName.clear();<br>
+      break;<br>
+    }<br>
     case bitc::VST_CODE_FNENTRY: {<br>
       // VST_CODE_FNENTRY: [valueid, offset, namechar x N]<br>
       if (convertToString(Record, 2, ValueName))<br>
@@ -5465,59 +5521,58 @@ std::error_code FunctionIndexBitcodeRead<br>
       unsigned ValueID = Record[0];<br>
       uint64_t FuncOffset = Record[1];<br>
       assert(!IsLazy && "Lazy summary read only supported for combined index");<br>
-      // Gracefully handle bitcode without a function summary section,<br>
-      // which will simply not populate the index.<br>
-      if (foundFuncSummary()) {<br>
-        DenseMap<uint64_t, std::unique_ptr<FunctionSummary>>::iterator SMI =<br>
-            SummaryMap.find(ValueID);<br>
-        assert(SMI != SummaryMap.end() && "Summary info not found");<br>
-        std::unique_ptr<FunctionInfo> FuncInfo =<br>
-            llvm::make_unique<FunctionInfo>(FuncOffset);<br>
-        FuncInfo->setFunctionSummary(std::move(SMI->second));<br>
-        assert(!SourceFileName.empty());<br>
-        std::string FunctionGlobalId = Function::getGlobalIdentifier(<br>
-            ValueName, FuncInfo->functionSummary()->getFunctionLinkage(),<br>
-            SourceFileName);<br>
-        TheIndex->addFunctionInfo(FunctionGlobalId, std::move(FuncInfo));<br>
-      }<br>
+      std::unique_ptr<GlobalValueInfo> FuncInfo =<br>
+          llvm::make_unique<GlobalValueInfo>(FuncOffset);<br>
+      assert(!SourceFileName.empty());<br>
+      auto VLI = ValueIdToLinkageMap.find(ValueID);<br>
+      assert(VLI != ValueIdToLinkageMap.end() &&<br>
+             "No linkage found for VST entry?");<br>
+      std::string FunctionGlobalId =<br>
+          Function::getGlobalIdentifier(ValueName, VLI->second, SourceFileName);<br>
+      TheIndex->addGlobalValueInfo(FunctionGlobalId, std::move(FuncInfo));<br>
+      ValueIdToCallGraphGUIDMap[ValueID] = Function::getGUID(FunctionGlobalId);<br>
<br>
       ValueName.clear();<br>
       break;<br>
     }<br>
-    case bitc::VST_CODE_COMBINED_FNENTRY: {<br>
-      // VST_CODE_COMBINED_FNENTRY: [offset, funcguid]<br>
-      uint64_t FuncSummaryOffset = Record[0];<br>
-      uint64_t FuncGUID = Record[1];<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(FuncGUID, std::move(FuncInfo));<br>
-<br>
-      ValueName.clear();<br>
+    case bitc::VST_CODE_COMBINED_GVDEFENTRY: {<br>
+      // VST_CODE_COMBINED_GVDEFENTRY: [valueid, offset, guid]<br>
+      unsigned ValueID = Record[0];<br>
+      uint64_t GlobalValSummaryOffset = Record[1];<br>
+      uint64_t GlobalValGUID = Record[2];<br>
+      std::unique_ptr<GlobalValueInfo> GlobalValInfo =<br>
+          llvm::make_unique<GlobalValueInfo>(GlobalValSummaryOffset);<br>
+      SummaryOffsetToInfoMap[GlobalValSummaryOffset] = GlobalValInfo.get();<br>
+      TheIndex->addGlobalValueInfo(GlobalValGUID, std::move(GlobalValInfo));<br>
+      ValueIdToCallGraphGUIDMap[ValueID] = GlobalValGUID;<br>
+      break;<br>
+    }<br>
+    case bitc::VST_CODE_COMBINED_ENTRY: {<br>
+      // VST_CODE_COMBINED_ENTRY: [valueid, refguid]<br>
+      unsigned ValueID = Record[0];<br>
+      uint64_t RefGUID = Record[1];<br>
+      ValueIdToCallGraphGUIDMap[ValueID] = RefGUID;<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>
+// Parse just the blocks needed for building the index out of the module.<br>
+// At the end of this routine the module Index is populated with a map<br>
+// from global value name to GlobalValueInfo. The global value info contains<br>
+// either the parsed summary information (when parsing summaries<br>
+// eagerly), or just to the 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>
   SmallVector<uint64_t, 64> Record;<br>
+  DenseMap<unsigned, GlobalValue::LinkageTypes> ValueIdToLinkageMap;<br>
+  unsigned ValueId = 0;<br>
<br>
-  // Read the function index for this module.<br>
+  // Read the index for this module.<br>
   while (1) {<br>
     BitstreamEntry Entry = Stream.advance();<br>
<br>
@@ -5528,9 +5583,9 @@ std::error_code FunctionIndexBitcodeRead<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 (CheckGlobalValSummaryPresenceOnly) {<br>
+        if (Entry.ID == bitc::GLOBALVAL_SUMMARY_BLOCK_ID) {<br>
+          SeenGlobalValSummary = true;<br>
           // No need to parse the rest since we found the summary.<br>
           return std::error_code();<br>
         }<br>
@@ -5549,11 +5604,23 @@ std::error_code FunctionIndexBitcodeRead<br>
           return error("Malformed block");<br>
         break;<br>
       case bitc::VALUE_SYMTAB_BLOCK_ID:<br>
-        if (std::error_code EC = parseValueSymbolTable())<br>
-          return EC;<br>
+        // Should have been parsed earlier via VSTOffset, unless there<br>
+        // is no summary section.<br>
+        assert(((SeenValueSymbolTable && VSTOffset > 0) ||<br>
+                !SeenGlobalValSummary) &&<br>
+               "Expected early VST parse via VSTOffset record");<br>
+        if (Stream.SkipBlock())<br>
+          return error("Invalid record");<br>
         break;<br>
-      case bitc::FUNCTION_SUMMARY_BLOCK_ID:<br>
-        SeenFuncSummary = true;<br>
+      case bitc::GLOBALVAL_SUMMARY_BLOCK_ID:<br>
+        assert(VSTOffset > 0 && "Expected non-zero VST offset");<br>
+        assert(!SeenValueSymbolTable &&<br>
+               "Already read VST when parsing summary block?");<br>
+        if (std::error_code EC =<br>
+                parseValueSymbolTable(VSTOffset, ValueIdToLinkageMap))<br>
+          return EC;<br>
+        SeenValueSymbolTable = true;<br>
+        SeenGlobalValSummary = true;<br>
         if (IsLazy) {<br>
           // Lazy parsing of summary info, skip it.<br>
           if (Stream.SkipBlock())<br>
@@ -5569,8 +5636,8 @@ std::error_code FunctionIndexBitcodeRead<br>
       continue;<br>
<br>
     case BitstreamEntry::Record:<br>
-      // Once we find the single record of interest, skip the rest.<br>
-      if (!SourceFileName.empty())<br>
+      // Once we find the last record of interest, skip the rest.<br>
+      if (VSTOffset > 0)<br>
         Stream.skipRecord(Entry.ID);<br>
       else {<br>
         Record.clear();<br>
@@ -5579,28 +5646,68 @@ std::error_code FunctionIndexBitcodeRead<br>
         default:<br>
           break; // Default behavior, ignore unknown content.<br>
         /// MODULE_CODE_SOURCE_FILENAME: [namechar x N]<br>
-        case bitc::MODULE_CODE_SOURCE_FILENAME:<br>
+        case bitc::MODULE_CODE_SOURCE_FILENAME: {<br>
           SmallString<128> ValueName;<br>
           if (convertToString(Record, 0, ValueName))<br>
             return error("Invalid record");<br>
           SourceFileName = ValueName.c_str();<br>
           break;<br>
         }<br>
+        /// MODULE_CODE_VSTOFFSET: [offset]<br>
+        case bitc::MODULE_CODE_VSTOFFSET:<br>
+          if (Record.size() < 1)<br>
+            return error("Invalid record");<br>
+          VSTOffset = Record[0];<br>
+          break;<br>
+        // GLOBALVAR: [pointer type, isconst, initid,<br>
+        //             linkage, alignment, section, visibility, threadlocal,<br>
+        //             unnamed_addr, externally_initialized, dllstorageclass,<br>
+        //             comdat]<br>
+        case bitc::MODULE_CODE_GLOBALVAR: {<br>
+          if (Record.size() < 6)<br>
+            return error("Invalid record");<br>
+          uint64_t RawLinkage = Record[3];<br>
+          GlobalValue::LinkageTypes Linkage = getDecodedLinkage(RawLinkage);<br>
+          ValueIdToLinkageMap[ValueId++] = Linkage;<br>
+          break;<br>
+        }<br>
+        // FUNCTION:  [type, callingconv, isproto, linkage, paramattr,<br>
+        //             alignment, section, visibility, gc, unnamed_addr,<br>
+        //             prologuedata, dllstorageclass, comdat, prefixdata]<br>
+        case bitc::MODULE_CODE_FUNCTION: {<br>
+          if (Record.size() < 8)<br>
+            return error("Invalid record");<br>
+          uint64_t RawLinkage = Record[3];<br>
+          GlobalValue::LinkageTypes Linkage = getDecodedLinkage(RawLinkage);<br>
+          ValueIdToLinkageMap[ValueId++] = Linkage;<br>
+          break;<br>
+        }<br>
+        // ALIAS: [alias type, addrspace, aliasee val#, linkage, visibility,<br>
+        // dllstorageclass]<br>
+        case bitc::MODULE_CODE_ALIAS: {<br>
+          if (Record.size() < 6)<br>
+            return error("Invalid record");<br>
+          uint64_t RawLinkage = Record[3];<br>
+          GlobalValue::LinkageTypes Linkage = getDecodedLinkage(RawLinkage);<br>
+          ValueIdToLinkageMap[ValueId++] = Linkage;<br>
+          break;<br>
+        }<br>
+        }<br>
       }<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>
+// Eagerly parse the entire summary block. This populates the GlobalValueSummary<br>
+// objects in the index.<br>
 std::error_code FunctionIndexBitcodeReader::parseEntireSummary() {<br>
-  if (Stream.EnterSubBlock(bitc::FUNCTION_SUMMARY_BLOCK_ID))<br>
+  if (Stream.EnterSubBlock(bitc::GLOBALVAL_SUMMARY_BLOCK_ID))<br>
     return error("Invalid record");<br>
<br>
   SmallVector<uint64_t, 64> Record;<br>
<br>
+  bool Combined = false;<br>
   while (1) {<br>
     BitstreamEntry Entry = Stream.advanceSkippingSubblocks();<br>
<br>
@@ -5609,6 +5716,16 @@ std::error_code FunctionIndexBitcodeRead<br>
     case BitstreamEntry::Error:<br>
       return error("Malformed block");<br>
     case BitstreamEntry::EndBlock:<br>
+      // For a per-module index, remove any entries that still have empty<br>
+      // summaries. The VST parsing creates entries eagerly for all symbols,<br>
+      // but not all have associated summaries (e.g. it doesn't know how to<br>
+      // distinguish between VST_CODE_ENTRY for function declarations vs global<br>
+      // variables with initializers that end up with a summary). Remove those<br>
+      // entries now so that we don't need to rely on the combined index merger<br>
+      // to clean them up (especially since that may not run for the first<br>
+      // module's index if we merge into that).<br>
+      if (!Combined)<br>
+        TheIndex->removeEmptySummaryEntries();<br>
       return std::error_code();<br>
     case BitstreamEntry::Record:<br>
       // The interesting case.<br>
@@ -5624,17 +5741,23 @@ std::error_code FunctionIndexBitcodeRead<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>
+    auto BitCode = Stream.readRecord(Entry.ID, Record);<br>
+    switch (BitCode) {<br>
     default: // Default behavior: ignore.<br>
       break;<br>
-    // FS_PERMODULE_ENTRY: [valueid, linkage, instcount]<br>
-    case bitc::FS_CODE_PERMODULE_ENTRY: {<br>
+    // FS_PERMODULE: [valueid, linkage, instcount, numrefs, numrefs x valueid,<br>
+    //                n x (valueid, callsitecount)]<br>
+    // FS_PERMODULE_PROFILE: [valueid, linkage, instcount, numrefs,<br>
+    //                        numrefs x valueid,<br>
+    //                        n x (valueid, callsitecount, profilecount)]<br>
+    case bitc::FS_PERMODULE:<br>
+    case bitc::FS_PERMODULE_PROFILE: {<br>
       unsigned ValueID = Record[0];<br>
       uint64_t RawLinkage = Record[1];<br>
       unsigned InstCount = Record[2];<br>
-      std::unique_ptr<FunctionSummary> FS =<br>
-          llvm::make_unique<FunctionSummary>(InstCount);<br>
-      FS->setFunctionLinkage(getDecodedLinkage(RawLinkage));<br>
+      unsigned NumRefs = Record[3];<br>
+      std::unique_ptr<FunctionSummary> FS = llvm::make_unique<FunctionSummary>(<br>
+          getDecodedLinkage(RawLinkage), InstCount);<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>
@@ -5642,19 +5765,115 @@ std::error_code FunctionIndexBitcodeRead<br>
       // ownership.<br>
       FS->setModulePath(<br>
           TheIndex->addModulePath(Buffer->getBufferIdentifier(), 0));<br>
-      SummaryMap[ValueID] = std::move(FS);<br>
+      static int RefListStartIndex = 4;<br>
+      int CallGraphEdgeStartIndex = RefListStartIndex + NumRefs;<br>
+      assert(Record.size() >= RefListStartIndex + NumRefs &&<br>
+             "Record size inconsistent with number of references");<br>
+      for (unsigned I = 4, E = CallGraphEdgeStartIndex; I != E; ++I) {<br>
+        unsigned RefValueId = Record[I];<br>
+        uint64_t RefGUID = getGUIDFromValueId(RefValueId);<br>
+        FS->addRefEdge(RefGUID);<br>
+      }<br>
+      bool HasProfile = (BitCode == bitc::FS_PERMODULE_PROFILE);<br>
+      for (unsigned I = CallGraphEdgeStartIndex, E = Record.size(); I != E;<br>
+           ++I) {<br>
+        unsigned CalleeValueId = Record[I];<br>
+        unsigned CallsiteCount = Record[++I];<br>
+        uint64_t ProfileCount = HasProfile ? Record[++I] : 0;<br>
+        uint64_t CalleeGUID = getGUIDFromValueId(CalleeValueId);<br>
+        FS->addCallGraphEdge(CalleeGUID,<br>
+                             CalleeInfo(CallsiteCount, ProfileCount));<br>
+      }<br>
+      uint64_t GUID = getGUIDFromValueId(ValueID);<br>
+      auto InfoList = TheIndex->findGlobalValueInfoList(GUID);<br>
+      assert(InfoList != TheIndex->end() &&<br>
+             "Expected VST parse to create GlobalValueInfo entry");<br>
+      assert(InfoList->second.size() == 1 &&<br>
+             "Expected a single GlobalValueInfo per GUID in module");<br>
+      auto &Info = InfoList->second[0];<br>
+      assert(!Info->summary() && "Expected a single summary per VST entry");<br>
+      Info->setSummary(std::move(FS));<br>
       break;<br>
     }<br>
-    // FS_COMBINED_ENTRY: [modid, linkage, instcount]<br>
-    case bitc::FS_CODE_COMBINED_ENTRY: {<br>
+    // FS_PERMODULE_GLOBALVAR_INIT_REFS: [valueid, linkage, n x valueid]<br>
+    case bitc::FS_PERMODULE_GLOBALVAR_INIT_REFS: {<br>
+      unsigned ValueID = Record[0];<br>
+      uint64_t RawLinkage = Record[1];<br>
+      std::unique_ptr<GlobalVarSummary> FS =<br>
+          llvm::make_unique<GlobalVarSummary>(getDecodedLinkage(RawLinkage));<br>
+      FS->setModulePath(<br>
+          TheIndex->addModulePath(Buffer->getBufferIdentifier(), 0));<br>
+      for (unsigned I = 2, E = Record.size(); I != E; ++I) {<br>
+        unsigned RefValueId = Record[I];<br>
+        uint64_t RefGUID = getGUIDFromValueId(RefValueId);<br>
+        FS->addRefEdge(RefGUID);<br>
+      }<br>
+      uint64_t GUID = getGUIDFromValueId(ValueID);<br>
+      auto InfoList = TheIndex->findGlobalValueInfoList(GUID);<br>
+      assert(InfoList != TheIndex->end() &&<br>
+             "Expected VST parse to create GlobalValueInfo entry");<br>
+      assert(InfoList->second.size() == 1 &&<br>
+             "Expected a single GlobalValueInfo per GUID in module");<br>
+      auto &Info = InfoList->second[0];<br>
+      assert(!Info->summary() && "Expected a single summary per VST entry");<br>
+      Info->setSummary(std::move(FS));<br>
+      break;<br>
+    }<br>
+    // FS_COMBINED: [modid, linkage, instcount, numrefs, numrefs x valueid,<br>
+    //               n x (valueid, callsitecount)]<br>
+    // FS_COMBINED_PROFILE: [modid, linkage, instcount, numrefs,<br>
+    //                       numrefs x valueid,<br>
+    //                       n x (valueid, callsitecount, profilecount)]<br>
+    case bitc::FS_COMBINED:<br>
+    case bitc::FS_COMBINED_PROFILE: {<br>
       uint64_t ModuleId = Record[0];<br>
       uint64_t RawLinkage = Record[1];<br>
       unsigned InstCount = Record[2];<br>
-      std::unique_ptr<FunctionSummary> FS =<br>
-          llvm::make_unique<FunctionSummary>(InstCount);<br>
-      FS->setFunctionLinkage(getDecodedLinkage(RawLinkage));<br>
+      unsigned NumRefs = Record[3];<br>
+      std::unique_ptr<FunctionSummary> FS = llvm::make_unique<FunctionSummary>(<br>
+          getDecodedLinkage(RawLinkage), InstCount);<br>
+      FS->setModulePath(ModuleIdMap[ModuleId]);<br>
+      static int RefListStartIndex = 4;<br>
+      int CallGraphEdgeStartIndex = RefListStartIndex + NumRefs;<br>
+      assert(Record.size() >= RefListStartIndex + NumRefs &&<br>
+             "Record size inconsistent with number of references");<br>
+      for (unsigned I = 4, E = CallGraphEdgeStartIndex; I != E; ++I) {<br>
+        unsigned RefValueId = Record[I];<br>
+        uint64_t RefGUID = getGUIDFromValueId(RefValueId);<br>
+        FS->addRefEdge(RefGUID);<br>
+      }<br>
+      bool HasProfile = (BitCode == bitc::FS_COMBINED_PROFILE);<br>
+      for (unsigned I = CallGraphEdgeStartIndex, E = Record.size(); I != E;<br>
+           ++I) {<br>
+        unsigned CalleeValueId = Record[I];<br>
+        unsigned CallsiteCount = Record[++I];<br>
+        uint64_t ProfileCount = HasProfile ? Record[++I] : 0;<br>
+        uint64_t CalleeGUID = getGUIDFromValueId(CalleeValueId);<br>
+        FS->addCallGraphEdge(CalleeGUID,<br>
+                             CalleeInfo(CallsiteCount, ProfileCount));<br>
+      }<br>
+      auto *Info = getInfoFromSummaryOffset(CurRecordBit);<br>
+      assert(!Info->summary() && "Expected a single summary per VST entry");<br>
+      Info->setSummary(std::move(FS));<br>
+      Combined = true;<br>
+      break;<br>
+    }<br>
+    // FS_COMBINED_GLOBALVAR_INIT_REFS: [modid, linkage, n x valueid]<br>
+    case bitc::FS_COMBINED_GLOBALVAR_INIT_REFS: {<br>
+      uint64_t ModuleId = Record[0];<br>
+      uint64_t RawLinkage = Record[1];<br>
+      std::unique_ptr<GlobalVarSummary> FS =<br>
+          llvm::make_unique<GlobalVarSummary>(getDecodedLinkage(RawLinkage));<br>
       FS->setModulePath(ModuleIdMap[ModuleId]);<br>
-      SummaryMap[CurRecordBit] = std::move(FS);<br>
+      for (unsigned I = 2, E = Record.size(); I != E; ++I) {<br>
+        unsigned RefValueId = Record[I];<br>
+        uint64_t RefGUID = getGUIDFromValueId(RefValueId);<br>
+        FS->addRefEdge(RefGUID);<br>
+      }<br>
+      auto *Info = getInfoFromSummaryOffset(CurRecordBit);<br>
+      assert(!Info->summary() && "Expected a single summary per VST entry");<br>
+      Info->setSummary(std::move(FS));<br>
+      Combined = true;<br>
       break;<br>
     }<br>
     }<br>
@@ -5773,7 +5992,9 @@ std::error_code FunctionIndexBitcodeRead<br>
   // importing is added so that it can be tested.<br>
   SmallVector<uint64_t, 64> Record;<br>
   switch (Stream.readRecord(Entry.ID, Record)) {<br>
-  case bitc::FS_CODE_COMBINED_ENTRY:<br>
+  case bitc::FS_COMBINED:<br>
+  case bitc::FS_COMBINED_PROFILE:<br>
+  case bitc::FS_COMBINED_GLOBALVAR_INIT_REFS:<br>
   default:<br>
     return error("Invalid record");<br>
   }<br>
@@ -5987,9 +6208,9 @@ llvm::getFunctionInfoIndex(MemoryBufferR<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,<br>
-                              DiagnosticHandlerFunction DiagnosticHandler) {<br>
+// Check if the given bitcode buffer contains a global value summary block.<br>
+bool llvm::hasGlobalValueSummary(MemoryBufferRef Buffer,<br>
+                                 DiagnosticHandlerFunction DiagnosticHandler) {<br>
   std::unique_ptr<MemoryBuffer> Buf = MemoryBuffer::getMemBuffer(Buffer, false);<br>
   FunctionIndexBitcodeReader R(Buf.get(), DiagnosticHandler, false, true);<br>
<br>
@@ -6002,7 +6223,7 @@ bool llvm::hasFunctionSummary(MemoryBuff<br>
     return cleanupOnError(EC);<br>
<br>
   Buf.release(); // The FunctionIndexBitcodeReader owns it now.<br>
-  return R.foundFuncSummary();<br>
+  return R.foundGlobalValSummary();<br>
 }<br>
<br>
 // This method supports lazy reading of function summary data from the combined<br>
@@ -6026,7 +6247,7 @@ std::error_code llvm::readFunctionSummar<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>
+  for (const auto &FI : Index->getGlobalValueInfoList(FunctionName)) {<br>
     size_t FunctionSummaryOffset = FI->bitcodeIndex();<br>
     if (std::error_code EC =<br>
             R.parseFunctionSummary(nullptr, Index.get(), FunctionSummaryOffset))<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=263275&r1=263274&r2=263275&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp?rev=263275&r1=263274&r2=263275&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp (original)<br>
+++ llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp Fri Mar 11 12:52:24 2016<br>
@@ -11,24 +11,30 @@<br>
 //<br>
 //===----------------------------------------------------------------------===//<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/Analysis/BlockFrequencyInfo.h"<br>
+#include "llvm/Analysis/BlockFrequencyInfoImpl.h"<br>
+#include "llvm/Analysis/BranchProbabilityInfo.h"<br>
+#include "llvm/Analysis/LoopInfo.h"<br>
 #include "llvm/Bitcode/BitstreamWriter.h"<br>
 #include "llvm/Bitcode/LLVMBitCodes.h"<br>
+#include "llvm/Bitcode/ReaderWriter.h"<br>
 #include "llvm/IR/CallSite.h"<br>
 #include "llvm/IR/Constants.h"<br>
 #include "llvm/IR/DebugInfoMetadata.h"<br>
 #include "llvm/IR/DerivedTypes.h"<br>
+#include "llvm/IR/Dominators.h"<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/LLVMContext.h"<br>
 #include "llvm/IR/Module.h"<br>
 #include "llvm/IR/Operator.h"<br>
 #include "llvm/IR/UseListOrder.h"<br>
 #include "llvm/IR/ValueSymbolTable.h"<br>
+#include "llvm/ProfileData/ProfileCommon.h"<br>
 #include "llvm/Support/CommandLine.h"<br>
 #include "llvm/Support/ErrorHandling.h"<br>
 #include "llvm/Support/MathExtras.h"<br>
@@ -591,11 +597,7 @@ static void writeComdats(const ValueEnum<br>
 /// Write a record that will eventually hold the word offset of the<br>
 /// module-level VST. For now the offset is 0, which will be backpatched<br>
 /// after the real VST is written. Returns the bit offset to backpatch.<br>
-static uint64_t WriteValueSymbolTableForwardDecl(const ValueSymbolTable &VST,<br>
-                                                 BitstreamWriter &Stream) {<br>
-  if (VST.empty())<br>
-    return 0;<br>
-<br>
+static uint64_t WriteValueSymbolTableForwardDecl(BitstreamWriter &Stream) {<br>
   // Write a placeholder value in for the offset of the real VST,<br>
   // which is written after the function blocks so that it can include<br>
   // the offset of each function. The placeholder offset will be<br>
@@ -844,9 +846,11 @@ static uint64_t WriteModuleInfo(const Mo<br>
     Vals.clear();<br>
   }<br>
<br>
-  uint64_t VSTOffsetPlaceholder =<br>
-      WriteValueSymbolTableForwardDecl(M->getValueSymbolTable(), Stream);<br>
-  return VSTOffsetPlaceholder;<br>
+  // If we have a VST, write the VSTOFFSET record placeholder and return<br>
+  // its offset.<br>
+  if (M->getValueSymbolTable().empty())<br>
+    return 0;<br>
+  return WriteValueSymbolTableForwardDecl(Stream);<br>
 }<br>
<br>
 static uint64_t GetOptimizationFlags(const Value *V) {<br>
@@ -2248,8 +2252,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 *, std::unique_ptr<FunctionInfo>> *FunctionIndex =<br>
-        nullptr) {<br>
+    DenseMap<const Function *, std::unique_ptr<GlobalValueInfo>><br>
+        *FunctionIndex = nullptr) {<br>
   if (VST.empty()) {<br>
     // WriteValueSymbolTableForwardDecl should have returned early as<br>
     // well. Ensure this handling remains in sync by asserting that<br>
@@ -2375,33 +2379,61 @@ static void WriteValueSymbolTable(<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>
+static void<br>
+WriteCombinedValueSymbolTable(const FunctionInfoIndex &Index,<br>
+                              BitstreamWriter &Stream,<br>
+                              std::map<uint64_t, unsigned> &GUIDToValueIdMap,<br>
+                              uint64_t VSTOffsetPlaceholder) {<br>
+  assert(VSTOffsetPlaceholder > 0 && "Expected non-zero VSTOffsetPlaceholder");<br>
+  // Get the offset of the VST we are writing, and backpatch it into<br>
+  // the VST forward declaration record.<br>
+  uint64_t VSTOffset = Stream.GetCurrentBitNo();<br>
+  assert((VSTOffset & 31) == 0 && "VST block not 32-bit aligned");<br>
+  Stream.BackpatchWord(VSTOffsetPlaceholder, VSTOffset / 32);<br>
+<br>
   Stream.EnterSubblock(bitc::VALUE_SYMTAB_BLOCK_ID, 4);<br>
<br>
   BitCodeAbbrev *Abbv = new BitCodeAbbrev();<br>
-  Abbv->Add(BitCodeAbbrevOp(bitc::VST_CODE_COMBINED_FNENTRY));<br>
-  Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // funcsumoffset<br>
-  Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // funcguid<br>
-  unsigned FnEntryAbbrev = Stream.EmitAbbrev(Abbv);<br>
+  Abbv->Add(BitCodeAbbrevOp(bitc::VST_CODE_COMBINED_GVDEFENTRY));<br>
+  Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // valueid<br>
+  Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // sumoffset<br>
+  Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // guid<br>
+  unsigned DefEntryAbbrev = Stream.EmitAbbrev(Abbv);<br>
+<br>
+  Abbv = new BitCodeAbbrev();<br>
+  Abbv->Add(BitCodeAbbrevOp(bitc::VST_CODE_COMBINED_ENTRY));<br>
+  Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // valueid<br>
+  Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // refguid<br>
+  unsigned EntryAbbrev = Stream.EmitAbbrev(Abbv);<br>
<br>
   SmallVector<uint64_t, 64> NameVals;<br>
<br>
   for (const auto &FII : Index) {<br>
+    uint64_t FuncGUID = FII.first;<br>
+    const auto &VMI = GUIDToValueIdMap.find(FuncGUID);<br>
+    assert(VMI != GUIDToValueIdMap.end());<br>
+<br>
     for (const auto &FI : FII.second) {<br>
+      // VST_CODE_COMBINED_GVDEFENTRY: [valueid, sumoffset, guid]<br>
+      NameVals.push_back(VMI->second);<br>
       NameVals.push_back(FI->bitcodeIndex());<br>
-<br>
-      uint64_t FuncGUID = FII.first;<br>
-<br>
-      // VST_CODE_COMBINED_FNENTRY: [funcsumoffset, funcguid]<br>
-      unsigned AbbrevToUse = FnEntryAbbrev;<br>
-<br>
       NameVals.push_back(FuncGUID);<br>
<br>
       // Emit the finished record.<br>
-      Stream.EmitRecord(bitc::VST_CODE_COMBINED_FNENTRY, NameVals, AbbrevToUse);<br>
+      Stream.EmitRecord(bitc::VST_CODE_COMBINED_GVDEFENTRY, NameVals,<br>
+                        DefEntryAbbrev);<br>
       NameVals.clear();<br>
     }<br>
+    GUIDToValueIdMap.erase(VMI);<br>
+  }<br>
+  for (const auto &GVI : GUIDToValueIdMap) {<br>
+    // VST_CODE_COMBINED_ENTRY: [valueid, refguid]<br>
+    NameVals.push_back(GVI.second);<br>
+    NameVals.push_back(GVI.first);<br>
+<br>
+    // Emit the finished record.<br>
+    Stream.EmitRecord(bitc::VST_CODE_COMBINED_ENTRY, NameVals, EntryAbbrev);<br>
+    NameVals.clear();<br>
   }<br>
   Stream.ExitBlock();<br>
 }<br>
@@ -2440,34 +2472,61 @@ static void WriteUseListBlock(const Func<br>
   Stream.ExitBlock();<br>
 }<br>
<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->setFunctionLinkage(F.getLinkage());<br>
+// Walk through the operands of a given User via worklist iteration and populate<br>
+// the set of GlobalValue references encountered. Invoked either on an<br>
+// Instruction or a GlobalVariable (which walks its initializer).<br>
+static void findRefEdges(const User *CurUser, const ValueEnumerator &VE,<br>
+                         DenseSet<unsigned> &RefEdges,<br>
+                         SmallPtrSet<const User *, 8> &Visited) {<br>
+  SmallVector<const User *, 32> Worklist;<br>
+  Worklist.push_back(CurUser);<br>
+<br>
+  while (!Worklist.empty()) {<br>
+    const User *U = Worklist.pop_back_val();<br>
+<br>
+    if (!Visited.insert(U).second)<br>
+      continue;<br>
+<br>
+    ImmutableCallSite CS(U);<br>
+<br>
+    for (const auto &OI : U->operands()) {<br>
+      const User *Operand = dyn_cast<User>(OI);<br>
+      if (!Operand)<br>
+        continue;<br>
+      if (isa<BlockAddress>(Operand))<br>
+        continue;<br>
+      if (isa<GlobalValue>(Operand)) {<br>
+        // We have a reference to a global value. This should be added to<br>
+        // the reference set unless it is a callee. Callees are handled<br>
+        // specially by WriteFunction and are added to a separate list.<br>
+        if (!(CS && CS.isCallee(&OI)))<br>
+          RefEdges.insert(VE.getValueID(Operand));<br>
+        continue;<br>
+      }<br>
+      Worklist.push_back(Operand);<br>
+    }<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>
+    const Function &F, const Module *M, ValueEnumerator &VE,<br>
+    BitstreamWriter &Stream,<br>
+    DenseMap<const Function *, std::unique_ptr<GlobalValueInfo>> &FunctionIndex,<br>
+    bool EmitSummaryIndex) {<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>
<br>
+  bool HasProfileData = F.getEntryCount().hasValue();<br>
+  std::unique_ptr<BlockFrequencyInfo> BFI;<br>
+  if (EmitSummaryIndex && HasProfileData) {<br>
+    Function &Func = const_cast<Function &>(F);<br>
+    LoopInfo LI{DominatorTree(Func)};<br>
+    BranchProbabilityInfo BPI{Func, LI};<br>
+    BFI = llvm::make_unique<BlockFrequencyInfo>(Func, BPI, LI);<br>
+  }<br>
+<br>
   Stream.EnterSubblock(bitc::FUNCTION_BLOCK_ID, 4);<br>
   VE.incorporateFunction(F);<br>
<br>
@@ -2494,7 +2553,12 @@ static void WriteFunction(<br>
<br>
   DILocation *LastDL = nullptr;<br>
   unsigned NumInsts = 0;<br>
+  // Map from callee ValueId to profile count. Used to accumulate profile<br>
+  // counts for all static calls to a given callee.<br>
+  DenseMap<unsigned, CalleeInfo> CallGraphEdges;<br>
+  DenseSet<unsigned> RefEdges;<br>
<br>
+  SmallPtrSet<const User *, 8> Visited;<br>
   // Finally, emit all the instructions, in order.<br>
   for (Function::const_iterator BB = F.begin(), E = F.end(); BB != E; ++BB)<br>
     for (BasicBlock::const_iterator I = BB->begin(), E = BB->end();<br>
@@ -2507,6 +2571,24 @@ static void WriteFunction(<br>
       if (!I->getType()->isVoidTy())<br>
         ++InstID;<br>
<br>
+      if (EmitSummaryIndex) {<br>
+        if (auto CS = ImmutableCallSite(&*I)) {<br>
+          auto *CalledFunction = CS.getCalledFunction();<br>
+          if (CalledFunction && CalledFunction->hasName() &&<br>
+              !CalledFunction->isIntrinsic()) {<br>
+            uint64_t ScaledCount = 0;<br>
+            if (HasProfileData)<br>
+              ScaledCount = getBlockProfileCount(<br>
+                  BFI->getBlockFreq(&(*BB)).getFrequency(), BFI->getEntryFreq(),<br>
+                  F.getEntryCount().getValue());<br>
+            unsigned CalleeId = VE.getValueID(<br>
+                M->getValueSymbolTable().lookup(CalledFunction->getName()));<br>
+            CallGraphEdges[CalleeId] += ScaledCount;<br>
+          }<br>
+        }<br>
+        findRefEdges(&*I, VE, RefEdges, Visited);<br>
+      }<br>
+<br>
       // If the instruction has metadata, write a metadata attachment later.<br>
       NeedsMetadataAttachment |= I->hasMetadataOtherThanDebugLoc();<br>
<br>
@@ -2531,6 +2613,15 @@ static void WriteFunction(<br>
       LastDL = DL;<br>
     }<br>
<br>
+  std::unique_ptr<FunctionSummary> FuncSummary;<br>
+  if (EmitSummaryIndex) {<br>
+    FuncSummary = llvm::make_unique<FunctionSummary>(F.getLinkage(), NumInsts);<br>
+    FuncSummary->addCallGraphEdges(CallGraphEdges);<br>
+    FuncSummary->addRefEdges(RefEdges);<br>
+  }<br>
+  FunctionIndex[&F] =<br>
+      llvm::make_unique<GlobalValueInfo>(BitcodeIndex, std::move(FuncSummary));<br>
+<br>
   // Emit names for all the instructions etc.<br>
   WriteValueSymbolTable(F.getValueSymbolTable(), VE, Stream);<br>
<br>
@@ -2540,9 +2631,6 @@ static void WriteFunction(<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>
@@ -2776,34 +2864,103 @@ static void WriteModStrings(const Functi<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>
+    SmallVector<uint64_t, 64> &NameVals, FunctionSummary *FS, unsigned ValueID,<br>
+    unsigned FSCallsAbbrev, unsigned FSCallsProfileAbbrev,<br>
+    BitstreamWriter &Stream, const Function &F) {<br>
   assert(FS);<br>
   NameVals.push_back(ValueID);<br>
-  NameVals.push_back(getEncodedLinkage(FS->getFunctionLinkage()));<br>
+  NameVals.push_back(getEncodedLinkage(FS->linkage()));<br>
   NameVals.push_back(FS->instCount());<br>
+  NameVals.push_back(FS->refs().size());<br>
+<br>
+  for (auto &RI : FS->refs())<br>
+    NameVals.push_back(RI);<br>
+<br>
+  bool HasProfileData = F.getEntryCount().hasValue();<br>
+  for (auto &ECI : FS->edges()) {<br>
+    NameVals.push_back(ECI.first);<br>
+    assert(ECI.second.CallsiteCount > 0 && "Expected at least one callsite");<br>
+    NameVals.push_back(ECI.second.CallsiteCount);<br>
+    if (HasProfileData)<br>
+      NameVals.push_back(ECI.second.ProfileCount);<br>
+  }<br>
+<br>
+  unsigned FSAbbrev = (HasProfileData ? FSCallsProfileAbbrev : FSCallsAbbrev);<br>
+  unsigned Code =<br>
+      (HasProfileData ? bitc::FS_PERMODULE_PROFILE : bitc::FS_PERMODULE);<br>
<br>
   // Emit the finished record.<br>
-  Stream.EmitRecord(bitc::FS_CODE_PERMODULE_ENTRY, NameVals, FSAbbrev);<br>
+  Stream.EmitRecord(Code, NameVals, FSAbbrev);<br>
   NameVals.clear();<br>
 }<br>
<br>
-/// Emit the per-module function summary section alongside the rest of<br>
+// Collect the global value references in the given variable's initializer,<br>
+// and emit them in a summary record.<br>
+static void WriteModuleLevelReferences(const GlobalVariable &V,<br>
+                                       const ValueEnumerator &VE,<br>
+                                       SmallVector<uint64_t, 64> &NameVals,<br>
+                                       unsigned FSModRefsAbbrev,<br>
+                                       BitstreamWriter &Stream) {<br>
+  DenseSet<unsigned> RefEdges;<br>
+  SmallPtrSet<const User *, 8> Visited;<br>
+  findRefEdges(&V, VE, RefEdges, Visited);<br>
+  unsigned RefCount = RefEdges.size();<br>
+  if (RefCount) {<br>
+    NameVals.push_back(VE.getValueID(&V));<br>
+    NameVals.push_back(getEncodedLinkage(V.getLinkage()));<br>
+    for (auto RefId : RefEdges) {<br>
+      NameVals.push_back(RefId);<br>
+    }<br>
+    Stream.EmitRecord(bitc::FS_PERMODULE_GLOBALVAR_INIT_REFS, NameVals,<br>
+                      FSModRefsAbbrev);<br>
+    NameVals.clear();<br>
+  }<br>
+}<br>
+<br>
+/// Emit the per-module 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>
+static void WritePerModuleGlobalValueSummary(<br>
+    DenseMap<const Function *, std::unique_ptr<GlobalValueInfo>> &FunctionIndex,<br>
     const Module *M, const ValueEnumerator &VE, BitstreamWriter &Stream) {<br>
-  Stream.EnterSubblock(bitc::FUNCTION_SUMMARY_BLOCK_ID, 3);<br>
+  if (M->empty())<br>
+    return;<br>
<br>
-  // Abbrev for FS_CODE_PERMODULE_ENTRY.<br>
+  Stream.EnterSubblock(bitc::GLOBALVAL_SUMMARY_BLOCK_ID, 3);<br>
+<br>
+  // Abbrev for FS_PERMODULE.<br>
   BitCodeAbbrev *Abbv = new BitCodeAbbrev();<br>
-  Abbv->Add(BitCodeAbbrevOp(bitc::FS_CODE_PERMODULE_ENTRY));<br>
+  Abbv->Add(BitCodeAbbrevOp(bitc::FS_PERMODULE));<br>
   Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8));   // valueid<br>
   Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 5)); // linkage<br>
   Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8));   // instcount<br>
-  unsigned FSAbbrev = Stream.EmitAbbrev(Abbv);<br>
+  Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 4));   // numrefs<br>
+  // numrefs x valueid, n x (valueid, callsitecount)<br>
+  Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));<br>
+  Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8));<br>
+  unsigned FSCallsAbbrev = Stream.EmitAbbrev(Abbv);<br>
<br>
-  SmallVector<unsigned, 64> NameVals;<br>
+  // Abbrev for FS_PERMODULE_PROFILE.<br>
+  Abbv = new BitCodeAbbrev();<br>
+  Abbv->Add(BitCodeAbbrevOp(bitc::FS_PERMODULE_PROFILE));<br>
+  Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8));   // valueid<br>
+  Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 5)); // linkage<br>
+  Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8));   // instcount<br>
+  Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 4));   // numrefs<br>
+  // numrefs x valueid, n x (valueid, callsitecount, profilecount)<br>
+  Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));<br>
+  Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8));<br>
+  unsigned FSCallsProfileAbbrev = Stream.EmitAbbrev(Abbv);<br>
+<br>
+  // Abbrev for FS_PERMODULE_GLOBALVAR_INIT_REFS.<br>
+  Abbv = new BitCodeAbbrev();<br>
+  Abbv->Add(BitCodeAbbrevOp(bitc::FS_PERMODULE_GLOBALVAR_INIT_REFS));<br>
+  Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // valueid<br>
+  Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 5)); // linkage<br>
+  Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));  // valueids<br>
+  Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8));<br>
+  unsigned FSModRefsAbbrev = Stream.EmitAbbrev(Abbv);<br>
+<br>
+  SmallVector<uint64_t, 64> NameVals;<br>
   // Iterate over the list of functions instead of the FunctionIndex map to<br>
   // ensure the ordering is stable.<br>
   for (const Function &F : *M) {<br>
@@ -2817,9 +2974,9 @@ static void WritePerModuleFunctionSummar<br>
     assert(FunctionIndex.count(&F) == 1);<br>
<br>
     WritePerModuleFunctionSummaryRecord(<br>
-        NameVals, FunctionIndex[&F]->functionSummary(),<br>
-        VE.getValueID(M->getValueSymbolTable().lookup(F.getName())), FSAbbrev,<br>
-        Stream);<br>
+        NameVals, dyn_cast<FunctionSummary>(FunctionIndex[&F]->summary()),<br></blockquote><div><br></div><div>Given this is a FunctionIndex, I assume all its summaries are FunctionSummaries? So presumably this could be a cast instead of a dyn_cast?</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+        VE.getValueID(M->getValueSymbolTable().lookup(F.getName())),<br>
+        FSCallsAbbrev, FSCallsProfileAbbrev, Stream, F);<br>
   }<br>
<br>
   for (const GlobalAlias &A : M->aliases()) {<br>
@@ -2830,10 +2987,25 @@ static void WritePerModuleFunctionSummar<br>
       continue;<br>
<br>
     assert(FunctionIndex.count(F) == 1);<br>
+    FunctionSummary *FS =<br>
+        dyn_cast<FunctionSummary>(FunctionIndex[F]->summary());<br></blockquote><div><br>Looks like this ^ should be a cast, not a dyn_cast, since the result is immediately dereferenced in the following line \/<br> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+    // Add the alias to the reference list of aliasee function.<br>
+    FS->addRefEdge(<br>
+        VE.getValueID(M->getValueSymbolTable().lookup(A.getName())));<br>
     WritePerModuleFunctionSummaryRecord(<br>
-        NameVals, FunctionIndex[F]->functionSummary(),<br>
-        VE.getValueID(M->getValueSymbolTable().lookup(A.getName())), FSAbbrev,<br>
-        Stream);<br>
+        NameVals, FS,<br>
+        VE.getValueID(M->getValueSymbolTable().lookup(A.getName())),<br>
+        FSCallsAbbrev, FSCallsProfileAbbrev, Stream, *F);<br>
+  }<br>
+<br>
+  // Capture references from GlobalVariable initializers, which are outside<br>
+  // of a function scope.<br>
+  for (const GlobalVariable &G : M->globals())<br>
+    WriteModuleLevelReferences(G, VE, NameVals, FSModRefsAbbrev, Stream);<br>
+  for (const GlobalAlias &A : M->aliases()) {<br>
+    const auto *GV = dyn_cast<GlobalVariable>(A.getBaseObject());<br>
+    if (GV)<br></blockquote><div><br></div><div>If you like, you could roll this ^ declaration into the if. (& then drop the {} around the loop too, if that suits)</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+      WriteModuleLevelReferences(*GV, VE, NameVals, FSModRefsAbbrev, Stream);<br>
   }<br>
<br>
   Stream.ExitBlock();<br>
@@ -2841,35 +3013,132 @@ static void WritePerModuleFunctionSummar<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>
+static void WriteCombinedGlobalValueSummary(<br>
+    const FunctionInfoIndex &I, BitstreamWriter &Stream,<br>
+    std::map<uint64_t, unsigned> &GUIDToValueIdMap, unsigned GlobalValueId) {<br>
+  Stream.EnterSubblock(bitc::GLOBALVAL_SUMMARY_BLOCK_ID, 3);<br>
<br>
-  // Abbrev for FS_CODE_COMBINED_ENTRY.<br>
+  // Abbrev for FS_COMBINED.<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(bitc::FS_COMBINED));<br>
+  Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8));   // modid<br>
   Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 5)); // linkage<br>
-  Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // instcount<br>
-  unsigned FSAbbrev = Stream.EmitAbbrev(Abbv);<br>
+  Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8));   // instcount<br>
+  Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 4));   // numrefs<br>
+  // numrefs x valueid, n x (valueid, callsitecount)<br>
+  Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));<br>
+  Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8));<br>
+  unsigned FSCallsAbbrev = Stream.EmitAbbrev(Abbv);<br>
<br>
-  SmallVector<unsigned, 64> NameVals;<br>
+  // Abbrev for FS_COMBINED_PROFILE.<br>
+  Abbv = new BitCodeAbbrev();<br>
+  Abbv->Add(BitCodeAbbrevOp(bitc::FS_COMBINED_PROFILE));<br>
+  Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8));   // modid<br>
+  Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 5)); // linkage<br>
+  Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8));   // instcount<br>
+  Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 4));   // numrefs<br>
+  // numrefs x valueid, n x (valueid, callsitecount, profilecount)<br>
+  Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));<br>
+  Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8));<br>
+  unsigned FSCallsProfileAbbrev = Stream.EmitAbbrev(Abbv);<br>
+<br>
+  // Abbrev for FS_COMBINED_GLOBALVAR_INIT_REFS.<br>
+  Abbv = new BitCodeAbbrev();<br>
+  Abbv->Add(BitCodeAbbrevOp(bitc::FS_COMBINED_GLOBALVAR_INIT_REFS));<br>
+  Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8));   // modid<br>
+  Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 5)); // linkage<br>
+  Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));    // valueids<br>
+  Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8));<br>
+  unsigned FSModRefsAbbrev = Stream.EmitAbbrev(Abbv);<br>
+<br>
+  SmallVector<uint64_t, 64> NameVals;<br>
   for (const auto &FII : I) {<br>
     for (auto &FI : FII.second) {<br>
-      FunctionSummary *FS = FI->functionSummary();<br>
-      assert(FS);<br>
+      GlobalValueSummary *S = FI->summary();<br>
+      assert(S);<br>
+<br>
+      if (auto *VS = dyn_cast<GlobalVarSummary>(S)) {<br>
+        assert(!VS->refs().empty() && "Expected at least one ref edge");<br>
+        NameVals.push_back(I.getModuleId(VS->modulePath()));<br>
+        NameVals.push_back(getEncodedLinkage(VS->linkage()));<br>
+        for (auto &RI : VS->refs()) {<br>
+          const auto &VMI = GUIDToValueIdMap.find(RI);<br>
+          unsigned RefId;<br>
+          // If this GUID doesn't have an entry, assign one.<br>
+          if (VMI == GUIDToValueIdMap.end()) {<br>
+            GUIDToValueIdMap[RI] = ++GlobalValueId;<br>
+            RefId = GlobalValueId;<br>
+          } else {<br>
+            RefId = VMI->second;<br>
+          }<br>
+          NameVals.push_back(RefId);<br>
+        }<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() +<br>
+                            Stream.GetAbbrevIDWidth());<br>
+<br>
+        // Emit the finished record.<br>
+        Stream.EmitRecord(bitc::FS_COMBINED_GLOBALVAR_INIT_REFS, NameVals,<br>
+                          FSModRefsAbbrev);<br>
+        NameVals.clear();<br>
+        continue;<br>
+      }<br>
<br>
+      auto *FS = dyn_cast<FunctionSummary>(S);<br>
+      assert(FS);<br></blockquote><div><br></div><div>Replace dyn_cast + assert with cast.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
       NameVals.push_back(I.getModuleId(FS->modulePath()));<br>
-      NameVals.push_back(getEncodedLinkage(FS->getFunctionLinkage()));<br>
+      NameVals.push_back(getEncodedLinkage(FS->linkage()));<br>
       NameVals.push_back(FS->instCount());<br>
+      NameVals.push_back(FS->refs().size());<br>
+<br>
+      for (auto &RI : FS->refs()) {<br>
+        const auto &VMI = GUIDToValueIdMap.find(RI);<br>
+        unsigned RefId;<br>
+        // If this GUID doesn't have an entry, assign one.<br>
+        if (VMI == GUIDToValueIdMap.end()) {<br>
+          GUIDToValueIdMap[RI] = ++GlobalValueId;<br>
+          RefId = GlobalValueId;<br>
+        } else {<br>
+          RefId = VMI->second;<br>
+        }<br>
+        NameVals.push_back(RefId);<br>
+      }<br>
+<br>
+      bool HasProfileData = false;<br>
+      for (auto &EI : FS->edges()) {<br>
+        HasProfileData |= EI.second.ProfileCount != 0;<br>
+        if (HasProfileData)<br>
+          break;<br>
+      }<br>
+<br>
+      for (auto &EI : FS->edges()) {<br>
+        const auto &VMI = GUIDToValueIdMap.find(EI.first);<br>
+        // If this GUID doesn't have an entry, it doesn't have a function<br>
+        // summary and we don't need to record any calls to it.<br>
+        if (VMI == GUIDToValueIdMap.end())<br>
+          continue;<br>
+        NameVals.push_back(VMI->second);<br>
+        assert(EI.second.CallsiteCount > 0 && "Expected at least one callsite");<br>
+        NameVals.push_back(EI.second.CallsiteCount);<br>
+        if (HasProfileData)<br>
+          NameVals.push_back(EI.second.ProfileCount);<br>
+      }<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>
+      unsigned FSAbbrev =<br>
+          (HasProfileData ? FSCallsProfileAbbrev : FSCallsAbbrev);<br>
+      unsigned Code =<br>
+          (HasProfileData ? bitc::FS_COMBINED_PROFILE : bitc::FS_COMBINED);<br>
+<br>
       // Emit the finished record.<br>
-      Stream.EmitRecord(bitc::FS_CODE_COMBINED_ENTRY, NameVals, FSAbbrev);<br>
+      Stream.EmitRecord(Code, NameVals, FSAbbrev);<br>
       NameVals.clear();<br>
     }<br>
   }<br>
@@ -2904,7 +3173,7 @@ static void WriteIdentificationBlock(con<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, bool EmitFunctionSummary) {<br>
+                        uint64_t BitcodeStartBit, bool EmitSummaryIndex) {<br>
   Stream.EnterSubblock(bitc::MODULE_BLOCK_ID, 3);<br>
<br>
   SmallVector<unsigned, 1> Vals;<br>
@@ -2949,15 +3218,15 @@ static void WriteModule(const Module *M,<br>
   WriteOperandBundleTags(M, Stream);<br>
<br>
   // Emit function bodies.<br>
-  DenseMap<const Function *, std::unique_ptr<FunctionInfo>> FunctionIndex;<br>
+  DenseMap<const Function *, std::unique_ptr<GlobalValueInfo>> 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, EmitFunctionSummary);<br>
+      WriteFunction(*F, M, VE, Stream, FunctionIndex, EmitSummaryIndex);<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>
+  if (EmitSummaryIndex)<br>
+    WritePerModuleGlobalValueSummary(FunctionIndex, M, VE, Stream);<br>
<br>
   WriteValueSymbolTable(M->getValueSymbolTable(), VE, Stream,<br>
                         VSTOffsetPlaceholder, BitcodeStartBit, &FunctionIndex);<br>
@@ -3046,7 +3315,7 @@ static void WriteBitcodeHeader(Bitstream<br>
 /// stream.<br>
 void llvm::WriteBitcodeToFile(const Module *M, raw_ostream &Out,<br>
                               bool ShouldPreserveUseListOrder,<br>
-                              bool EmitFunctionSummary) {<br>
+                              bool EmitSummaryIndex) {<br>
   SmallVector<char, 0> Buffer;<br>
   Buffer.reserve(256*1024);<br>
<br>
@@ -3072,7 +3341,7 @@ void llvm::WriteBitcodeToFile(const Modu<br>
<br>
     // Emit the module.<br>
     WriteModule(M, Stream, ShouldPreserveUseListOrder, BitcodeStartBit,<br>
-                EmitFunctionSummary);<br>
+                EmitSummaryIndex);<br>
   }<br>
<br>
   if (TT.isOSDarwin() || TT.isOSBinFormatMachO())<br>
@@ -3082,11 +3351,10 @@ void llvm::WriteBitcodeToFile(const Modu<br>
   Out.write((char*)&Buffer.front(), Buffer.size());<br>
 }<br>
<br>
-// Write the specified function summary index to the given raw output stream,<br>
+// Write the specified module 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>
+void llvm::WriteIndexToFile(const FunctionInfoIndex &Index, raw_ostream &Out) {<br>
   SmallVector<char, 0> Buffer;<br>
   Buffer.reserve(256 * 1024);<br>
<br>
@@ -3102,15 +3370,30 @@ void llvm::WriteFunctionSummaryToFile(co<br>
   Vals.push_back(CurVersion);<br>
   Stream.EmitRecord(bitc::MODULE_CODE_VERSION, Vals);<br>
<br>
+  // If we have a VST, write the VSTOFFSET record placeholder and record<br>
+  // its offset.<br>
+  uint64_t VSTOffsetPlaceholder = WriteValueSymbolTableForwardDecl(Stream);<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>
+  // Assign unique value ids to all functions in the index for use<br>
+  // in writing out the call graph edges. Save the mapping from GUID<br>
+  // to the new global value id to use when writing those edges, which<br>
+  // are currently saved in the index in terms of GUID.<br>
+  std::map<uint64_t, unsigned> GUIDToValueIdMap;<br>
+  unsigned GlobalValueId = 0;<br>
+  for (auto &II : Index)<br>
+    GUIDToValueIdMap[II.first] = ++GlobalValueId;<br>
+<br>
+  // Write the summary combined index records.<br>
+  WriteCombinedGlobalValueSummary(Index, Stream, GUIDToValueIdMap,<br>
+                                  GlobalValueId);<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>
+  WriteCombinedValueSymbolTable(Index, Stream, GUIDToValueIdMap,<br>
+                                VSTOffsetPlaceholder);<br>
<br>
   Stream.ExitBlock();<br>
<br>
<br>
Modified: llvm/trunk/lib/Bitcode/Writer/LLVMBuild.txt<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Writer/LLVMBuild.txt?rev=263275&r1=263274&r2=263275&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Writer/LLVMBuild.txt?rev=263275&r1=263274&r2=263275&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Bitcode/Writer/LLVMBuild.txt (original)<br>
+++ llvm/trunk/lib/Bitcode/Writer/LLVMBuild.txt Fri Mar 11 12:52:24 2016<br>
@@ -19,4 +19,4 @@<br>
 type = Library<br>
 name = BitWriter<br>
 parent = Bitcode<br>
-required_libraries = Core Support<br>
+required_libraries = Analysis Core Support<br>
<br>
Modified: llvm/trunk/lib/IR/FunctionInfo.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/FunctionInfo.cpp?rev=263275&r1=263274&r2=263275&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/FunctionInfo.cpp?rev=263275&r1=263274&r2=263275&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/IR/FunctionInfo.cpp (original)<br>
+++ llvm/trunk/lib/IR/FunctionInfo.cpp Fri Mar 11 12:52:24 2016<br>
@@ -7,7 +7,7 @@<br>
 //<br>
 //===----------------------------------------------------------------------===//<br>
 //<br>
-// This file implements the function info index and summary classes for the<br>
+// This file implements the module index and summary classes for the<br>
 // IR library.<br>
 //<br>
 //===----------------------------------------------------------------------===//<br>
@@ -16,42 +16,53 @@<br>
 #include "llvm/ADT/StringMap.h"<br>
 using namespace llvm;<br>
<br>
-// Create the combined function index/summary from multiple<br>
+// Create the combined module 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>
-    uint64_t FuncGUID = OtherFuncInfoLists.first;<br>
-    FunctionInfoList &List = OtherFuncInfoLists.second;<br>
+  for (auto &OtherGlobalValInfoLists : *Other) {<br>
+    uint64_t ValueGUID = OtherGlobalValInfoLists.first;<br>
+    GlobalValueInfoList &List = OtherGlobalValInfoLists.second;<br>
<br>
-    // Assert that the func info list only has one entry, since we shouldn't<br>
+    // Assert that the value 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>
+    std::unique_ptr<GlobalValueInfo> Info = std::move(List.front());<br>
<br>
-    // Skip if there was no function summary section.<br>
-    if (!Info->functionSummary())<br>
+    // Skip if there was no summary section.<br>
+    if (!Info->summary())<br>
       continue;<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>
+      ModPath = addModulePath(Info->summary()->modulePath(), NextModuleId);<br>
     else<br>
-      assert(ModPath == Info->functionSummary()->modulePath() &&<br>
+      assert(ModPath == Info->summary()->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>
+    Info->summary()->setModulePath(ModPath);<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 given unique global IDs.<br>
-    addFunctionInfo(FuncGUID, std::move(Info));<br>
+    // Add new value info to existing list. There may be duplicates when<br>
+    // combining GlobalValueMap entries, due to COMDAT values. Any local<br>
+    // values were given unique global IDs.<br>
+    addGlobalValueInfo(ValueGUID, std::move(Info));<br>
+  }<br>
+}<br>
+<br>
+void FunctionInfoIndex::removeEmptySummaryEntries() {<br>
+  for (auto MI = begin(), MIE = end(); MI != MIE;) {<br>
+    // Only expect this to be called on a per-module index, which has a single<br>
+    // entry per value entry list.<br>
+    assert(MI->second.size() == 1);<br>
+    if (!MI->second[0]->summary())<br>
+      MI = GlobalValueMap.erase(MI);<br>
+    else<br>
+      ++MI;<br>
   }<br>
 }<br>
<br>
Modified: llvm/trunk/lib/LTO/LTOModule.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/LTO/LTOModule.cpp?rev=263275&r1=263274&r2=263275&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/LTO/LTOModule.cpp?rev=263275&r1=263274&r2=263275&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/LTO/LTOModule.cpp (original)<br>
+++ llvm/trunk/lib/LTO/LTOModule.cpp Fri Mar 11 12:52:24 2016<br>
@@ -78,7 +78,7 @@ bool LTOModule::isBitcodeFile(const char<br>
 bool LTOModule::isThinLTO() {<br>
   // Right now the detection is only based on the summary presence. We may want<br>
   // to add a dedicated flag at some point.<br>
-  return hasFunctionSummary(IRFile->getMemoryBufferRef(),<br>
+  return hasGlobalValueSummary(IRFile->getMemoryBufferRef(),<br>
                             [](const DiagnosticInfo &DI) {<br>
                               DiagnosticPrinterRawOStream DP(errs());<br>
                               DI.print(DP);<br>
<br>
Modified: llvm/trunk/lib/LTO/ThinLTOCodeGenerator.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/LTO/ThinLTOCodeGenerator.cpp?rev=263275&r1=263274&r2=263275&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/LTO/ThinLTOCodeGenerator.cpp?rev=263275&r1=263274&r2=263275&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/LTO/ThinLTOCodeGenerator.cpp (original)<br>
+++ llvm/trunk/lib/LTO/ThinLTOCodeGenerator.cpp Fri Mar 11 12:52:24 2016<br>
@@ -349,7 +349,7 @@ void ThinLTOCodeGenerator::run() {<br>
     if (EC)<br>
       report_fatal_error(Twine("Failed to open ") + SaveTempPath +<br>
                          " to save optimized bitcode\n");<br>
-    WriteFunctionSummaryToFile(*Index, OS);<br>
+    WriteIndexToFile(*Index, OS);<br>
   }<br>
<br>
   // Prepare the resulting object vector<br>
<br>
Modified: llvm/trunk/lib/Object/FunctionIndexObjectFile.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Object/FunctionIndexObjectFile.cpp?rev=263275&r1=263274&r2=263275&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Object/FunctionIndexObjectFile.cpp?rev=263275&r1=263274&r2=263275&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Object/FunctionIndexObjectFile.cpp (original)<br>
+++ llvm/trunk/lib/Object/FunctionIndexObjectFile.cpp Fri Mar 11 12:52:24 2016<br>
@@ -66,15 +66,15 @@ FunctionIndexObjectFile::findBitcodeInMe<br>
   }<br>
 }<br>
<br>
-// Looks for function index in the given memory buffer.<br>
+// Looks for module summary index in the given memory buffer.<br>
 // returns true if found, else false.<br>
-bool FunctionIndexObjectFile::hasFunctionSummaryInMemBuffer(<br>
+bool FunctionIndexObjectFile::hasGlobalValueSummaryInMemBuffer(<br>
     MemoryBufferRef Object, DiagnosticHandlerFunction DiagnosticHandler) {<br>
   ErrorOr<MemoryBufferRef> BCOrErr = findBitcodeInMemBuffer(Object);<br>
   if (!BCOrErr)<br>
     return false;<br>
<br>
-  return hasFunctionSummary(BCOrErr.get(), DiagnosticHandler);<br>
+  return hasGlobalValueSummary(BCOrErr.get(), DiagnosticHandler);<br>
 }<br>
<br>
 // Parse function index in the given memory buffer.<br>
<br>
Modified: llvm/trunk/lib/Transforms/IPO/FunctionImport.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/FunctionImport.cpp?rev=263275&r1=263274&r2=263275&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/FunctionImport.cpp?rev=263275&r1=263274&r2=263275&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Transforms/IPO/FunctionImport.cpp (original)<br>
+++ llvm/trunk/lib/Transforms/IPO/FunctionImport.cpp Fri Mar 11 12:52:24 2016<br>
@@ -205,7 +205,7 @@ GetImportList(Module &DestModule,<br>
                  << "\n");<br>
<br>
     // Try to get a summary for this function call.<br>
-    auto InfoList = Index.findFunctionInfoList(CalledFunctionName);<br>
+    auto InfoList = Index.findGlobalValueInfoList(CalledFunctionName);<br>
     if (InfoList == Index.end()) {<br>
       DEBUG(dbgs() << DestModule.getModuleIdentifier() << ": No summary for "<br>
                    << CalledFunctionName << " Ignoring.\n");<br>
@@ -217,7 +217,7 @@ GetImportList(Module &DestModule,<br>
     auto &Info = InfoList->second[0];<br>
     assert(Info && "Nullptr in list, error importing summaries?\n");<br>
<br>
-    auto *Summary = Info->functionSummary();<br>
+    auto *Summary = dyn_cast<FunctionSummary>(Info->summary());<br>
     if (!Summary) {<br>
       // FIXME: in case we are lazyloading summaries, we can do it now.<br>
       DEBUG(dbgs() << DestModule.getModuleIdentifier()<br>
<br>
Added: llvm/trunk/test/Bitcode/Inputs/thinlto-function-summary-callgraph-pgo.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Bitcode/Inputs/thinlto-function-summary-callgraph-pgo.ll?rev=263275&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Bitcode/Inputs/thinlto-function-summary-callgraph-pgo.ll?rev=263275&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/test/Bitcode/Inputs/thinlto-function-summary-callgraph-pgo.ll (added)<br>
+++ llvm/trunk/test/Bitcode/Inputs/thinlto-function-summary-callgraph-pgo.ll Fri Mar 11 12:52:24 2016<br>
@@ -0,0 +1,11 @@<br>
+; ModuleID = 'thinlto-function-summary-callgraph2.ll'<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>
+; Function Attrs: nounwind uwtable<br>
+define void @func() #0 !prof !2 {<br>
+entry:<br>
+    ret void<br>
+}<br>
+<br>
+!2 = !{!"function_entry_count", i64 1}<br>
<br>
Added: llvm/trunk/test/Bitcode/Inputs/thinlto-function-summary-callgraph.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Bitcode/Inputs/thinlto-function-summary-callgraph.ll?rev=263275&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Bitcode/Inputs/thinlto-function-summary-callgraph.ll?rev=263275&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/test/Bitcode/Inputs/thinlto-function-summary-callgraph.ll (added)<br>
+++ llvm/trunk/test/Bitcode/Inputs/thinlto-function-summary-callgraph.ll Fri Mar 11 12:52:24 2016<br>
@@ -0,0 +1,10 @@<br>
+; ModuleID = 'thinlto-function-summary-callgraph2.ll'<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>
+; Function Attrs: nounwind uwtable<br>
+define void @func() #0 {<br>
+entry:<br>
+    ret void<br>
+}<br>
+<br>
<br>
Added: llvm/trunk/test/Bitcode/thinlto-function-summary-callgraph-pgo.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Bitcode/thinlto-function-summary-callgraph-pgo.ll?rev=263275&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Bitcode/thinlto-function-summary-callgraph-pgo.ll?rev=263275&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/test/Bitcode/thinlto-function-summary-callgraph-pgo.ll (added)<br>
+++ llvm/trunk/test/Bitcode/thinlto-function-summary-callgraph-pgo.ll Fri Mar 11 12:52:24 2016<br>
@@ -0,0 +1,44 @@<br>
+; Test to check the callgraph in summary when there is PGO<br>
+; RUN: llvm-as -function-summary %s -o %t.o<br>
+; RUN: llvm-bcanalyzer -dump %t.o | FileCheck %s<br>
+; RUN: llvm-as -function-summary %p/Inputs/thinlto-function-summary-callgraph.ll -o %t2.o<br>
+; RUN: llvm-lto -thinlto -o %t3 %t.o %t2.o<br>
+; RUN: llvm-bcanalyzer -dump %t3.thinlto.bc | FileCheck %s --check-prefix=COMBINED<br>
+<br>
+; CHECK:       <GLOBALVAL_SUMMARY_BLOCK<br>
+; See if the call to func is registered, using the expected callsite count<br>
+; and profile count, with value id matching the subsequent value symbol table.<br>
+; CHECK-NEXT:    <PERMODULE_PROFILE {{.*}} op4=[[FUNCID:[0-9]+]] op5=1 op6=1/><br>
+; CHECK-NEXT:  </GLOBALVAL_SUMMARY_BLOCK><br>
+; CHECK-NEXT:  <VALUE_SYMTAB<br>
+; CHECK-NEXT:    <FNENTRY {{.*}} record string = 'main'<br>
+; External function func should have entry with value id FUNCID<br>
+; CHECK-NEXT:    <ENTRY {{.*}} op0=[[FUNCID]] {{.*}} record string = 'func'<br>
+; CHECK-NEXT:  </VALUE_SYMTAB><br>
+<br>
+; COMBINED:       <GLOBALVAL_SUMMARY_BLOCK<br>
+; COMBINED-NEXT:    <COMBINED<br>
+; See if the call to func is registered, using the expected callsite count<br>
+; and profile count, with value id matching the subsequent value symbol table.<br>
+; COMBINED-NEXT:    <COMBINED_PROFILE {{.*}} op4=[[FUNCID:[0-9]+]] op5=1 op6=1/><br>
+; COMBINED-NEXT:  </GLOBALVAL_SUMMARY_BLOCK><br>
+; COMBINED-NEXT:  <VALUE_SYMTAB<br>
+; Entry for function func should have entry with value id FUNCID<br>
+; COMBINED-NEXT:    <COMBINED_GVDEFENTRY {{.*}} op0=[[FUNCID]] {{.*}} op2=7289175272376759421/><br>
+; COMBINED-NEXT:    <COMBINED_GVDEFENTRY<br>
+; COMBINED-NEXT:  </VALUE_SYMTAB><br>
+<br>
+; ModuleID = 'thinlto-function-summary-callgraph.ll'<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>
+; Function Attrs: nounwind uwtable<br>
+define i32 @main() #0 !prof !2 {<br>
+entry:<br>
+    call void (...) @func()<br>
+    ret i32 0<br>
+}<br>
+<br>
+declare void @func(...) #1<br>
+<br>
+!2 = !{!"function_entry_count", i64 1}<br>
<br>
Added: llvm/trunk/test/Bitcode/thinlto-function-summary-callgraph.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Bitcode/thinlto-function-summary-callgraph.ll?rev=263275&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Bitcode/thinlto-function-summary-callgraph.ll?rev=263275&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/test/Bitcode/thinlto-function-summary-callgraph.ll (added)<br>
+++ llvm/trunk/test/Bitcode/thinlto-function-summary-callgraph.ll Fri Mar 11 12:52:24 2016<br>
@@ -0,0 +1,42 @@<br>
+; Test to check the callgraph in summary<br>
+; RUN: llvm-as -function-summary %s -o %t.o<br>
+; RUN: llvm-bcanalyzer -dump %t.o | FileCheck %s<br>
+; RUN: llvm-as -function-summary %p/Inputs/thinlto-function-summary-callgraph.ll -o %t2.o<br>
+; RUN: llvm-lto -thinlto -o %t3 %t.o %t2.o<br>
+; RUN: llvm-bcanalyzer -dump %t3.thinlto.bc | FileCheck %s --check-prefix=COMBINED<br>
+<br>
+; CHECK:       <GLOBALVAL_SUMMARY_BLOCK<br>
+; See if the call to func is registered, using the expected callsite count<br>
+; and value id matching the subsequent value symbol table.<br>
+; CHECK-NEXT:    <PERMODULE {{.*}} op4=[[FUNCID:[0-9]+]] op5=1/><br>
+; CHECK-NEXT:  </GLOBALVAL_SUMMARY_BLOCK><br>
+; CHECK-NEXT:  <VALUE_SYMTAB<br>
+; CHECK-NEXT:    <FNENTRY {{.*}} record string = 'main'<br>
+; External function func should have entry with value id FUNCID<br>
+; CHECK-NEXT:    <ENTRY {{.*}} op0=[[FUNCID]] {{.*}} record string = 'func'<br>
+; CHECK-NEXT:  </VALUE_SYMTAB><br>
+<br>
+; COMBINED:       <GLOBALVAL_SUMMARY_BLOCK<br>
+; COMBINED-NEXT:    <COMBINED<br>
+; See if the call to func is registered, using the expected callsite count<br>
+; and value id matching the subsequent value symbol table.<br>
+; COMBINED-NEXT:    <COMBINED {{.*}} op4=[[FUNCID:[0-9]+]] op5=1/><br>
+; COMBINED-NEXT:  </GLOBALVAL_SUMMARY_BLOCK><br>
+; COMBINED-NEXT:  <VALUE_SYMTAB<br>
+; Entry for function func should have entry with value id FUNCID<br>
+; COMBINED-NEXT:    <COMBINED_GVDEFENTRY {{.*}} op0=[[FUNCID]] {{.*}} op2=7289175272376759421/><br>
+; COMBINED-NEXT:    <COMBINED_GVDEFENTRY<br>
+; COMBINED-NEXT:  </VALUE_SYMTAB><br>
+<br>
+; ModuleID = 'thinlto-function-summary-callgraph.ll'<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>
+; Function Attrs: nounwind uwtable<br>
+define i32 @main() #0 {<br>
+entry:<br>
+    call void (...) @func()<br>
+    ret i32 0<br>
+}<br>
+<br>
+declare void @func(...) #1<br>
<br>
Added: llvm/trunk/test/Bitcode/thinlto-function-summary-refgraph.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Bitcode/thinlto-function-summary-refgraph.ll?rev=263275&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Bitcode/thinlto-function-summary-refgraph.ll?rev=263275&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/test/Bitcode/thinlto-function-summary-refgraph.ll (added)<br>
+++ llvm/trunk/test/Bitcode/thinlto-function-summary-refgraph.ll Fri Mar 11 12:52:24 2016<br>
@@ -0,0 +1,121 @@<br>
+; Test to check both the callgraph and refgraph in summary<br>
+; RUN: llvm-as -function-summary %s -o %t.o<br>
+; RUN: llvm-bcanalyzer -dump %t.o | FileCheck %s<br>
+<br>
+; See if the calls and other references are recorded properly using the<br>
+; expected value id and other information as appropriate (callsite cout<br>
+; for calls). Use different linkage types for the various test cases to<br>
+; distinguish the test cases here (op1 contains the linkage type).<br>
+; Note that op3 contains the # non-call references.<br>
+; This also ensures that we didn't include a call or reference to intrinsic<br>
+; llvm.ctpop.i8.<br>
+; CHECK:       <GLOBALVAL_SUMMARY_BLOCK<br>
+; Function main contains call to func, as well as address reference to func:<br>
+; CHECK-DAG:    <PERMODULE {{.*}} op0=[[MAINID:[0-9]+]] op1=0 {{.*}} op3=1 op4=[[FUNCID:[0-9]+]] op5=[[FUNCID]] op6=1/><br>
+; Function W contains a call to func3 as well as a reference to globalvar:<br>
+; CHECK-DAG:    <PERMODULE {{.*}} op0=[[WID:[0-9]+]] op1=17 {{.*}} op3=1 op4=[[GLOBALVARID:[0-9]+]] op5=[[FUNC3ID:[0-9]+]] op6=1/><br>
+; Function X contains call to foo, as well as address reference to foo<br>
+; which is in the same instruction as the call:<br>
+; CHECK-DAG:    <PERMODULE {{.*}} op0=[[XID:[0-9]+]] op1=12 {{.*}} op3=1 op4=[[FOOID:[0-9]+]] op5=[[FOOID]] op6=1/><br>
+; Function Y contains call to func2, and ensures we don't incorrectly add<br>
+; a reference to it when reached while earlier analyzing the phi using its<br>
+; return value:<br>
+; CHECK-DAG:    <PERMODULE {{.*}} op0=[[YID:[0-9]+]] op1=9 {{.*}} op3=0 op4=[[FUNC2ID:[0-9]+]] op5=1/><br>
+; Function Z contains call to func2, and ensures we don't incorrectly add<br>
+; a reference to it when reached while analyzing subsequent use of its return<br>
+; value:<br>
+; CHECK-DAG:    <PERMODULE {{.*}} op0=[[ZID:[0-9]+]] op1=19 {{.*}} op3=0 op4=[[FUNC2ID:[0-9]+]] op5=1/><br>
+; Variable bar initialization contains address reference to func:<br>
+; CHECK-DAG:    <PERMODULE_GLOBALVAR_INIT_REFS {{.*}} op0=[[BARID:[0-9]+]] op1=0 op2=[[FUNCID]]/><br>
+; CHECK:  </GLOBALVAL_SUMMARY_BLOCK><br>
+<br>
+; CHECK-NEXT:  <VALUE_SYMTAB<br>
+; CHECK-DAG:    <ENTRY {{.*}} op0=[[BARID]] {{.*}} record string = 'bar'<br>
+; CHECK-DAG:    <ENTRY {{.*}} op0=[[FUNCID]] {{.*}} record string = 'func'<br>
+; CHECK-DAG:    <ENTRY {{.*}} op0=[[FOOID]] {{.*}} record string = 'foo'<br>
+; CHECK-DAG:    <FNENTRY {{.*}} op0=[[MAINID]] {{.*}} record string = 'main'<br>
+; CHECK-DAG:    <FNENTRY {{.*}} op0=[[WID]] {{.*}} record string = 'W'<br>
+; CHECK-DAG:    <FNENTRY {{.*}} op0=[[XID]] {{.*}} record string = 'X'<br>
+; CHECK-DAG:    <FNENTRY {{.*}} op0=[[YID]] {{.*}} record string = 'Y'<br>
+; CHECK-DAG:    <FNENTRY {{.*}} op0=[[ZID]] {{.*}} record string = 'Z'<br>
+; CHECK-DAG:    <ENTRY {{.*}} op0=[[FUNC2ID]] {{.*}} record string = 'func2'<br>
+; CHECK-DAG:    <ENTRY {{.*}} op0=[[FUNC3ID]] {{.*}} record string = 'func3'<br>
+; CHECK-DAG:    <ENTRY {{.*}} op0=[[GLOBALVARID]] {{.*}} record string = 'globalvar'<br>
+; CHECK:  </VALUE_SYMTAB><br>
+<br>
+; ModuleID = 'thinlto-function-summary-refgraph.ll'<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>
+@bar = global void (...)* bitcast (void ()* @func to void (...)*), align 8<br>
+<br>
+@globalvar = global i32 0, align 4<br>
+<br>
+declare void @func() #0<br>
+declare i32 @func2(...) #1<br>
+declare void @foo(i8* %F) #0<br>
+declare i32 @func3(i32* dereferenceable(4)) #2<br>
+<br>
+; Function Attrs: nounwind uwtable<br>
+define weak_odr void @W() #0 {<br>
+entry:<br>
+  %call = tail call i32 @func3(i32* nonnull dereferenceable(4) @globalvar)<br>
+  ret void<br>
+}<br>
+<br>
+; Function Attrs: nounwind uwtable<br>
+define available_externally void @X() #0 {<br>
+entry:<br>
+  call void @foo(i8* bitcast (void (i8*)* @foo to i8*))<br>
+  ret void<br>
+}<br>
+<br>
+; Function Attrs: nounwind uwtable<br>
+define private i32 @Y(i32 %i) #0 {<br>
+entry:<br>
+  %cmp3 = icmp slt i32 %i, 10<br>
+  br i1 %cmp3, label %while.body.preheader, label %while.end<br>
+<br>
+while.body.preheader:                             ; preds = %entry<br>
+  br label %while.body<br>
+<br>
+while.body:                                       ; preds = %while.body.preheader, %while.body<br>
+  %j.05 = phi i32 [ %add, %while.body ], [ 0, %while.body.preheader ]<br>
+  %i.addr.04 = phi i32 [ %inc, %while.body ], [ %i, %while.body.preheader ]<br>
+  %inc = add nsw i32 %i.addr.04, 1<br>
+  %call = tail call i32 (...) @func2() #2<br>
+  %add = add nsw i32 %call, %j.05<br>
+  %exitcond = icmp eq i32 %inc, 10<br>
+  br i1 %exitcond, label %while.end.loopexit, label %while.body<br>
+<br>
+while.end.loopexit:                               ; preds = %while.body<br>
+  %add.lcssa = phi i32 [ %add, %while.body ]<br>
+  br label %while.end<br>
+<br>
+while.end:                                        ; preds = %while.end.loopexit, %entry<br>
+  %j.0.lcssa = phi i32 [ 0, %entry ], [ %add.lcssa, %while.end.loopexit ]<br>
+  ret i32 %j.0.lcssa<br>
+}<br>
+<br>
+; Function Attrs: nounwind uwtable<br>
+define linkonce_odr i32 @Z() #0 {<br>
+entry:<br>
+  %call = tail call i32 (...) @func2() #2<br>
+  ret i32 %call<br>
+}<br>
+<br>
+declare i8 @llvm.ctpop.i8(i8)<br>
+<br>
+; Function Attrs: nounwind uwtable<br>
+define i32 @main() #0 {<br>
+entry:<br>
+  %retval = alloca i32, align 4<br>
+  %foo = alloca void (...)*, align 8<br>
+  store i32 0, i32* %retval, align 4<br>
+  store void (...)* bitcast (void ()* @func to void (...)*), void (...)** %foo, align 8<br>
+  %0 = load void (...)*, void (...)** %foo, align 8<br>
+  call void (...) %0()<br>
+  call void @func()<br>
+  call i8  @llvm.ctpop.i8( i8 10 )<br>
+  ret i32 0<br>
+}<br>
<br>
Modified: 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=263275&r1=263274&r2=263275&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Bitcode/thinlto-function-summary.ll?rev=263275&r1=263274&r2=263275&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/Bitcode/thinlto-function-summary.ll (original)<br>
+++ llvm/trunk/test/Bitcode/thinlto-function-summary.ll Fri Mar 11 12:52:24 2016<br>
@@ -4,11 +4,11 @@<br>
 ; Check the value ids in the function summary entries against the<br>
 ; same in the ValueSumbolTable, to ensure the ordering is stable.<br>
 ; Also check the linkage field on the summary entries.<br>
-; BC: <FUNCTION_SUMMARY_BLOCK<br>
-; BC-NEXT: <PERMODULE_ENTRY {{.*}} op0=1 op1=0<br>
-; BC-NEXT: <PERMODULE_ENTRY {{.*}} op0=2 op1=0<br>
-; BC-NEXT: <PERMODULE_ENTRY {{.*}} op0=4 op1=3<br>
-; BC-NEXT: </FUNCTION_SUMMARY_BLOCK<br>
+; BC: <GLOBALVAL_SUMMARY_BLOCK<br>
+; BC-NEXT: <PERMODULE {{.*}} op0=1 op1=0<br>
+; BC-NEXT: <PERMODULE {{.*}} op0=2 op1=0<br>
+; BC-NEXT: <PERMODULE {{.*}} op0=4 op1=3<br>
+; BC-NEXT: </GLOBALVAL_SUMMARY_BLOCK<br>
 ; BC-NEXT: <VALUE_SYMTAB<br>
 ; BC-NEXT: <FNENTRY {{.*}} op0=1 {{.*}}> record string = 'foo'<br>
 ; BC-NEXT: <FNENTRY {{.*}} op0=2 {{.*}}> record string = 'bar'<br>
<br>
Modified: llvm/trunk/test/Bitcode/thinlto-summary-linkage-types.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Bitcode/thinlto-summary-linkage-types.ll?rev=263275&r1=263274&r2=263275&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Bitcode/thinlto-summary-linkage-types.ll?rev=263275&r1=263274&r2=263275&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/Bitcode/thinlto-summary-linkage-types.ll (original)<br>
+++ llvm/trunk/test/Bitcode/thinlto-summary-linkage-types.ll Fri Mar 11 12:52:24 2016<br>
@@ -5,57 +5,57 @@<br>
 ; RUN: llvm-bcanalyzer -dump %t2.thinlto.bc | FileCheck %s --check-prefix=COMBINED<br>
<br>
 define private void @private()<br>
-; CHECK: <PERMODULE_ENTRY {{.*}} op1=9<br>
-; COMBINED-DAG: <COMBINED_ENTRY {{.*}} op1=9<br>
+; CHECK: <PERMODULE {{.*}} op1=9<br>
+; COMBINED-DAG: <COMBINED {{.*}} op1=9<br>
 {<br>
   ret void<br>
 }<br>
<br>
 define internal void @internal()<br>
-; CHECK: <PERMODULE_ENTRY {{.*}} op1=3<br>
-; COMBINED-DAG: <COMBINED_ENTRY {{.*}} op1=3<br>
+; CHECK: <PERMODULE {{.*}} op1=3<br>
+; COMBINED-DAG: <COMBINED {{.*}} op1=3<br>
 {<br>
   ret void<br>
 }<br>
<br>
 define available_externally void @available_externally()<br>
-; CHECK: <PERMODULE_ENTRY {{.*}} op1=12<br>
-; COMBINED-DAG: <COMBINED_ENTRY {{.*}} op1=12<br>
+; CHECK: <PERMODULE {{.*}} op1=12<br>
+; COMBINED-DAG: <COMBINED {{.*}} op1=12<br>
 {<br>
   ret void<br>
 }<br>
<br>
 define linkonce void @linkonce()<br>
-; CHECK: <PERMODULE_ENTRY {{.*}} op1=18<br>
-; COMBINED-DAG: <COMBINED_ENTRY {{.*}} op1=18<br>
+; CHECK: <PERMODULE {{.*}} op1=18<br>
+; COMBINED-DAG: <COMBINED {{.*}} op1=18<br>
 {<br>
   ret void<br>
 }<br>
<br>
 define weak void @weak()<br>
-; CHECK: <PERMODULE_ENTRY {{.*}} op1=16<br>
-; COMBINED-DAG: <COMBINED_ENTRY {{.*}} op1=16<br>
+; CHECK: <PERMODULE {{.*}} op1=16<br>
+; COMBINED-DAG: <COMBINED {{.*}} op1=16<br>
 {<br>
   ret void<br>
 }<br>
<br>
 define linkonce_odr void @linkonce_odr()<br>
-; CHECK: <PERMODULE_ENTRY {{.*}} op1=19<br>
-; COMBINED-DAG: <COMBINED_ENTRY {{.*}} op1=19<br>
+; CHECK: <PERMODULE {{.*}} op1=19<br>
+; COMBINED-DAG: <COMBINED {{.*}} op1=19<br>
 {<br>
   ret void<br>
 }<br>
<br>
 define weak_odr void @weak_odr()<br>
-; CHECK: <PERMODULE_ENTRY {{.*}} op1=17<br>
-; COMBINED-DAG: <COMBINED_ENTRY {{.*}} op1=17<br>
+; CHECK: <PERMODULE {{.*}} op1=17<br>
+; COMBINED-DAG: <COMBINED {{.*}} op1=17<br>
 {<br>
   ret void<br>
 }<br>
<br>
 define external void @external()<br>
-; CHECK: <PERMODULE_ENTRY {{.*}} op1=0<br>
-; COMBINED-DAG: <COMBINED_ENTRY {{.*}} op1=0<br>
+; CHECK: <PERMODULE {{.*}} op1=0<br>
+; COMBINED-DAG: <COMBINED {{.*}} op1=0<br>
 {<br>
   ret void<br>
 }<br>
<br>
Modified: 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=263275&r1=263274&r2=263275&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/gold/X86/thinlto.ll?rev=263275&r1=263274&r2=263275&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/tools/gold/X86/thinlto.ll (original)<br>
+++ llvm/trunk/test/tools/gold/X86/thinlto.ll Fri Mar 11 12:52:24 2016<br>
@@ -57,15 +57,15 @@<br>
 ; COMBINED-NEXT: <ENTRY {{.*}} record string = '{{.*}}/test/tools/gold/X86/Output/thinlto.ll.tmp{{.*}}.o'<br>
 ; COMBINED-NEXT: <ENTRY {{.*}} record string = '{{.*}}/test/tools/gold/X86/Output/thinlto.ll.tmp{{.*}}.o'<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>
+; COMBINED-NEXT: <GLOBALVAL_SUMMARY_BLOCK<br>
+; COMBINED-NEXT: <COMBINED<br>
+; COMBINED-NEXT: <COMBINED<br>
+; COMBINED-NEXT: </GLOBALVAL_SUMMARY_BLOCK<br>
 ; COMBINED-NEXT: <VALUE_SYMTAB<br>
-; Check that the format is: op0=offset, op1=funcguid, where funcguid is<br>
-; the lower 64 bits of the function name MD5.<br>
-; COMBINED-NEXT: <COMBINED_FNENTRY abbrevid={{[0-9]+}} op0={{[0-9]+}} op1={{-3706093650706652785|-5300342847281564238}}<br>
-; COMBINED-NEXT: <COMBINED_FNENTRY abbrevid={{[0-9]+}} op0={{[0-9]+}} op1={{-3706093650706652785|-5300342847281564238}}<br>
+; Check that the format is: op0=valueid, op1=offset, op2=funcguid,<br>
+; where funcguid is the lower 64 bits of the function name MD5.<br>
+; COMBINED-NEXT: <COMBINED_GVDEFENTRY abbrevid={{[0-9]+}} op0={{1|2}} op1={{[0-9]+}} op2={{-3706093650706652785|-5300342847281564238}}<br>
+; COMBINED-NEXT: <COMBINED_GVDEFENTRY abbrevid={{[0-9]+}} op0={{1|2}} op1={{[0-9]+}} op2={{-3706093650706652785|-5300342847281564238}}<br>
 ; COMBINED-NEXT: </VALUE_SYMTAB<br>
<br>
 declare void @g(...)<br>
<br>
Modified: llvm/trunk/test/tools/llvm-lto/thinlto.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-lto/thinlto.ll?rev=263275&r1=263274&r2=263275&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-lto/thinlto.ll?rev=263275&r1=263274&r2=263275&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/tools/llvm-lto/thinlto.ll (original)<br>
+++ llvm/trunk/test/tools/llvm-lto/thinlto.ll Fri Mar 11 12:52:24 2016<br>
@@ -9,15 +9,15 @@<br>
 ; COMBINED-NEXT: <ENTRY {{.*}} record string = '{{.*}}thinlto.ll.tmp{{.*}}.o'<br>
 ; COMBINED-NEXT: <ENTRY {{.*}} record string = '{{.*}}thinlto.ll.tmp{{.*}}.o'<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>
+; COMBINED-NEXT: <GLOBALVAL_SUMMARY_BLOCK<br>
+; COMBINED-NEXT: <COMBINED<br>
+; COMBINED-NEXT: <COMBINED<br>
+; COMBINED-NEXT: </GLOBALVAL_SUMMARY_BLOCK<br>
 ; COMBINED-NEXT: <VALUE_SYMTAB<br>
-; Check that the format is: op0=offset, op1=funcguid, where funcguid is<br>
-; the lower 64 bits of the function name MD5.<br>
-; COMBINED-NEXT: <COMBINED_FNENTRY abbrevid={{[0-9]+}} op0={{[0-9]+}} op1={{-3706093650706652785|-5300342847281564238}}<br>
-; COMBINED-NEXT: <COMBINED_FNENTRY abbrevid={{[0-9]+}} op0={{[0-9]+}} op1={{-3706093650706652785|-5300342847281564238}}<br>
+; Check that the format is: op0=valueid, op1=offset, op2=funcguid,<br>
+; where funcguid is the lower 64 bits of the function name MD5.<br>
+; COMBINED-NEXT: <COMBINED_GVDEFENTRY abbrevid={{[0-9]+}} op0={{1|2}} op1={{[0-9]+}} op2={{-3706093650706652785|-5300342847281564238}}<br>
+; COMBINED-NEXT: <COMBINED_GVDEFENTRY abbrevid={{[0-9]+}} op0={{1|2}} op1={{[0-9]+}} op2={{-3706093650706652785|-5300342847281564238}}<br>
 ; COMBINED-NEXT: </VALUE_SYMTAB<br>
<br>
 define void @f() {<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=263275&r1=263274&r2=263275&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/gold/gold-plugin.cpp?rev=263275&r1=263274&r2=263275&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/tools/gold/gold-plugin.cpp (original)<br>
+++ llvm/trunk/tools/gold/gold-plugin.cpp Fri Mar 11 12:52:24 2016<br>
@@ -635,7 +635,7 @@ getFunctionIndexForFile(claimed_file &F,<br>
<br>
   // Don't bother trying to build an index if there is no summary information<br>
   // in this bitcode file.<br>
-  if (!object::FunctionIndexObjectFile::hasFunctionSummaryInMemBuffer(<br>
+  if (!object::FunctionIndexObjectFile::hasGlobalValueSummaryInMemBuffer(<br>
           BufferRef, diagnosticHandler))<br>
     return std::unique_ptr<FunctionInfoIndex>(nullptr);<br>
<br>
@@ -1206,7 +1206,7 @@ static ld_plugin_status allSymbolsReadHo<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, OS);<br>
+    WriteIndexToFile(CombinedIndex, OS);<br>
     OS.close();<br>
<br>
     if (options::thinlto_index_only) {<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=263275&r1=263274&r2=263275&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp?rev=263275&r1=263274&r2=263275&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp (original)<br>
+++ llvm/trunk/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp Fri Mar 11 12:52:24 2016<br>
@@ -117,8 +117,8 @@ static const char *GetBlockName(unsigned<br>
   case bitc::METADATA_KIND_BLOCK_ID:   return "METADATA_KIND_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::GLOBALVAL_SUMMARY_BLOCK_ID:<br>
+    return "GLOBALVAL_SUMMARY_BLOCK";<br>
   case bitc::MODULE_STRTAB_BLOCK_ID:   return "MODULE_STRTAB_BLOCK";<br>
   }<br>
 }<br>
@@ -280,7 +280,8 @@ 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>
+    STRINGIFY_CODE(VST_CODE, COMBINED_GVDEFENTRY)<br>
+    STRINGIFY_CODE(VST_CODE, COMBINED_ENTRY)<br>
     }<br>
   case bitc::MODULE_STRTAB_BLOCK_ID:<br>
     switch (CodeID) {<br>
@@ -288,12 +289,16 @@ static const char *GetCodeName(unsigned<br>
       return nullptr;<br>
       STRINGIFY_CODE(MST_CODE, ENTRY)<br>
     }<br>
-  case bitc::FUNCTION_SUMMARY_BLOCK_ID:<br>
+  case bitc::GLOBALVAL_SUMMARY_BLOCK_ID:<br>
     switch (CodeID) {<br>
     default:<br>
       return nullptr;<br>
-      STRINGIFY_CODE(FS_CODE, PERMODULE_ENTRY)<br>
-      STRINGIFY_CODE(FS_CODE, COMBINED_ENTRY)<br>
+      STRINGIFY_CODE(FS, PERMODULE)<br>
+      STRINGIFY_CODE(FS, PERMODULE_PROFILE)<br>
+      STRINGIFY_CODE(FS, PERMODULE_GLOBALVAR_INIT_REFS)<br>
+      STRINGIFY_CODE(FS, COMBINED)<br>
+      STRINGIFY_CODE(FS, COMBINED_PROFILE)<br>
+      STRINGIFY_CODE(FS, COMBINED_GLOBALVAR_INIT_REFS)<br>
     }<br>
   case bitc::METADATA_ATTACHMENT_ID:<br>
     switch(CodeID) {<br>
<br>
Modified: llvm/trunk/tools/llvm-lto/llvm-lto.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-lto/llvm-lto.cpp?rev=263275&r1=263274&r2=263275&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-lto/llvm-lto.cpp?rev=263275&r1=263274&r2=263275&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/tools/llvm-lto/llvm-lto.cpp (original)<br>
+++ llvm/trunk/tools/llvm-lto/llvm-lto.cpp Fri Mar 11 12:52:24 2016<br>
@@ -270,7 +270,7 @@ static void createCombinedFunctionIndex(<br>
   raw_fd_ostream OS(OutputFilename + ".thinlto.bc", EC,<br>
                     sys::fs::OpenFlags::F_None);<br>
   error(EC, "error opening the file '" + OutputFilename + ".thinlto.bc'");<br>
-  WriteFunctionSummaryToFile(CombinedIndex, OS);<br>
+  WriteIndexToFile(CombinedIndex, OS);<br>
   OS.close();<br>
 }<br>
<br>
@@ -367,7 +367,7 @@ private:<br>
     std::error_code EC;<br>
     raw_fd_ostream OS(OutputFilename, EC, sys::fs::OpenFlags::F_None);<br>
     error(EC, "error opening the file '" + OutputFilename + "'");<br>
-    WriteFunctionSummaryToFile(*CombinedIndex, OS);<br>
+    WriteIndexToFile(*CombinedIndex, OS);<br>
     return;<br>
   }<br>
<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></div>