<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Tue, Sep 29, 2015 at 3:13 PM, Justin Bogner 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: bogner<br>
Date: Tue Sep 29 17:13:58 2015<br>
New Revision: 248833<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=248833&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=248833&view=rev</a><br>
Log:<br>
InstrProf: Support for value profiling in the indexed profile format<br>
<br>
Add support to the indexed instrprof reader and writer for the format<br>
that will be used for value profiling.<br>
<br>
Patch by Betul Buyukkurt, with minor modifications.<br>
<br>
Modified:<br>
    llvm/trunk/include/llvm/ProfileData/InstrProf.h<br>
    llvm/trunk/include/llvm/ProfileData/InstrProfReader.h<br>
    llvm/trunk/include/llvm/ProfileData/InstrProfWriter.h<br>
    llvm/trunk/lib/ProfileData/InstrProf.cpp<br>
    llvm/trunk/lib/ProfileData/InstrProfIndexed.h<br>
    llvm/trunk/lib/ProfileData/InstrProfReader.cpp<br>
    llvm/trunk/lib/ProfileData/InstrProfWriter.cpp<br>
    llvm/trunk/tools/llvm-profdata/llvm-profdata.cpp<br>
    llvm/trunk/unittests/ProfileData/CoverageMappingTest.cpp<br>
    llvm/trunk/unittests/ProfileData/InstrProfTest.cpp<br>
<br>
Modified: llvm/trunk/include/llvm/ProfileData/InstrProf.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ProfileData/InstrProf.h?rev=248833&r1=248832&r2=248833&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ProfileData/InstrProf.h?rev=248833&r1=248832&r2=248833&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/ProfileData/InstrProf.h (original)<br>
+++ llvm/trunk/include/llvm/ProfileData/InstrProf.h Tue Sep 29 17:13:58 2015<br>
@@ -16,8 +16,10 @@<br>
 #ifndef LLVM_PROFILEDATA_INSTRPROF_H_<br>
 #define LLVM_PROFILEDATA_INSTRPROF_H_<br>
<br>
-#include "llvm/ADT/StringRef.h"<br>
+#include "llvm/ADT/StringSet.h"<br>
+#include "llvm/Support/ErrorHandling.h"<br>
 #include <cstdint><br>
+#include <list><br>
 #include <system_error><br>
 #include <vector><br>
<br>
@@ -25,25 +27,84 @@ namespace llvm {<br>
 const std::error_category &instrprof_category();<br>
<br>
 enum class instrprof_error {<br>
-    success = 0,<br>
-    eof,<br>
-    bad_magic,<br>
-    bad_header,<br>
-    unsupported_version,<br>
-    unsupported_hash_type,<br>
-    too_large,<br>
-    truncated,<br>
-    malformed,<br>
-    unknown_function,<br>
-    hash_mismatch,<br>
-    count_mismatch,<br>
-    counter_overflow<br>
+  success = 0,<br>
+  eof,<br>
+  bad_magic,<br>
+  bad_header,<br>
+  unsupported_version,<br>
+  unsupported_hash_type,<br>
+  too_large,<br>
+  truncated,<br>
+  malformed,<br>
+  unknown_function,<br>
+  hash_mismatch,<br>
+  count_mismatch,<br>
+  counter_overflow,<br>
+  value_site_count_mismatch<br>
 };<br>
<br>
 inline std::error_code make_error_code(instrprof_error E) {<br>
   return std::error_code(static_cast<int>(E), instrprof_category());<br>
 }<br>
<br>
+enum InstrProfValueKind : uint32_t {<br>
+  IPVK_IndirectCallTarget = 0,<br>
+<br>
+  IPVK_First = IPVK_IndirectCallTarget,<br>
+  IPVK_Last = IPVK_IndirectCallTarget<br>
+};<br>
+<br>
+struct InstrProfStringTable {<br>
+  // Set of string values in profiling data.<br>
+  StringSet<> StringValueSet;<br>
+  InstrProfStringTable() { StringValueSet.clear(); }<br>
+  // Get a pointer to internal storage of a string in set<br>
+  const char *getStringData(StringRef Str) {<br>
+    auto Result = StringValueSet.find(Str);<br>
+    return (Result == StringValueSet.end()) ? nullptr : Result->first().data();<br>
+  }<br>
+  // Insert a string to StringTable<br>
+  const char *insertString(StringRef Str) {<br>
+    auto Result = StringValueSet.insert(Str);<br>
+    return Result.first->first().data();<br>
+  }<br>
+};<br>
+<br>
+struct InstrProfValueSiteRecord {<br>
+  /// Typedef for a single TargetValue-NumTaken pair.<br>
+  typedef std::pair<uint64_t, uint64_t> ValueDataPair;<br>
+  /// Value profiling data pairs at a given value site.<br>
+  std::list<ValueDataPair> ValueData;<br>
+<br>
+  InstrProfValueSiteRecord() { ValueData.clear(); }<br>
+<br>
+  /// Sort ValueData ascending by TargetValue<br>
+  void sortByTargetValues() {<br>
+    ValueData.sort([](const ValueDataPair &left, const ValueDataPair &right) {<br>
+      return left.first < right.first;<br>
+    });<br>
+  }<br>
+<br>
+  /// Merge data from another InstrProfValueSiteRecord<br>
+  void mergeValueData(InstrProfValueSiteRecord &Input) {<br>
+    this->sortByTargetValues();<br>
+    Input.sortByTargetValues();<br>
+    auto I = ValueData.begin();<br>
+    auto IE = ValueData.end();<br>
+    for (auto J = Input.ValueData.begin(), JE = Input.ValueData.end(); J != JE;<br>
+         ++J) {<br>
+      while (I != IE && I->first < J->first)<br>
+        ++I;<br>
+      if (I != IE && I->first == J->first) {<br>
+        I->second += J->second;<br>
+        ++I;<br>
+        continue;<br>
+      }<br>
+      ValueData.insert(I, *J);<br>
+    }<br>
+  }<br>
+};<br>
+<br>
 /// Profiling information for a single function.<br>
 struct InstrProfRecord {<br>
   InstrProfRecord() {}<br>
@@ -52,6 +113,22 @@ struct InstrProfRecord {<br>
   StringRef Name;<br>
   uint64_t Hash;<br>
   std::vector<uint64_t> Counts;<br>
+  std::vector<InstrProfValueSiteRecord> IndirectCallSites;<br>
+<br>
+  const std::vector<InstrProfValueSiteRecord> &<br>
+  getValueSitesForKind(uint32_t ValueKind) const {<br>
+    switch (ValueKind) {<br>
+    case IPVK_IndirectCallTarget:<br>
+      return IndirectCallSites;<br>
+    }<br>
+    llvm_unreachable("Unknown value kind!");<br>
+  }<br>
+<br>
+  std::vector<InstrProfValueSiteRecord> &<br>
+  getValueSitesForKind(uint32_t ValueKind) {<br>
+    return const_cast<std::vector<InstrProfValueSiteRecord> &>(<br>
+        this->getValueSitesForKind(ValueKind));<br>
+  }<br>
 };<br>
<br>
 } // end namespace llvm<br>
<br>
Modified: llvm/trunk/include/llvm/ProfileData/InstrProfReader.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ProfileData/InstrProfReader.h?rev=248833&r1=248832&r2=248833&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ProfileData/InstrProfReader.h?rev=248833&r1=248832&r2=248833&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/ProfileData/InstrProfReader.h (original)<br>
+++ llvm/trunk/include/llvm/ProfileData/InstrProfReader.h Tue Sep 29 17:13:58 2015<br>
@@ -65,6 +65,9 @@ public:<br>
   InstrProfIterator end() { return InstrProfIterator(); }<br>
<br>
 protected:<br>
+  /// String table for holding a unique copy of all the strings in the profile.<br>
+  InstrProfStringTable StringTable;<br>
+<br>
   /// Set the current std::error_code and return same.<br>
   std::error_code error(std::error_code EC) {<br>
     LastError = EC;<br>
@@ -195,6 +198,7 @@ class InstrProfLookupTrait {<br>
   std::vector<InstrProfRecord> DataBuffer;<br>
   IndexedInstrProf::HashT HashType;<br>
   unsigned FormatVersion;<br>
+  std::vector<std::pair<uint64_t, const char *>> HashKeys;<br>
<br>
 public:<br>
   InstrProfLookupTrait(IndexedInstrProf::HashT HashType, unsigned FormatVersion)<br>
@@ -209,9 +213,13 @@ public:<br>
<br>
   static bool EqualKey(StringRef A, StringRef B) { return A == B; }<br>
   static StringRef GetInternalKey(StringRef K) { return K; }<br>
+  static StringRef GetExternalKey(StringRef K) { return K; }<br>
<br>
   hash_value_type ComputeHash(StringRef K);<br>
<br>
+  void setHashKeys(std::vector<std::pair<uint64_t, const char *>> HashKeys) {<br>
+    this->HashKeys = std::move(HashKeys);<br>
+  }<br>
   static std::pair<offset_type, offset_type><br>
   ReadKeyDataLength(const unsigned char *&D) {<br>
     using namespace support;<br>
@@ -224,6 +232,8 @@ public:<br>
     return StringRef((const char *)D, N);<br>
   }<br>
<br>
+  bool ReadValueProfilingData(const unsigned char *&D,<br>
+                              const unsigned char *const End);<br>
   data_type ReadData(StringRef K, const unsigned char *D, offset_type N);<br>
 };<br>
<br>
<br>
Modified: llvm/trunk/include/llvm/ProfileData/InstrProfWriter.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ProfileData/InstrProfWriter.h?rev=248833&r1=248832&r2=248833&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ProfileData/InstrProfWriter.h?rev=248833&r1=248832&r2=248833&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/ProfileData/InstrProfWriter.h (original)<br>
+++ llvm/trunk/include/llvm/ProfileData/InstrProfWriter.h Tue Sep 29 17:13:58 2015<br>
@@ -15,33 +15,32 @@<br>
 #ifndef LLVM_PROFILEDATA_INSTRPROFWRITER_H<br>
 #define LLVM_PROFILEDATA_INSTRPROFWRITER_H<br>
<br>
-#include "llvm/ADT/ArrayRef.h"<br>
 #include "llvm/ADT/DenseMap.h"<br>
-#include "llvm/ADT/StringMap.h"<br>
 #include "llvm/ProfileData/InstrProf.h"<br>
 #include "llvm/Support/DataTypes.h"<br>
 #include "llvm/Support/MemoryBuffer.h"<br>
 #include "llvm/Support/raw_ostream.h"<br>
-#include <vector><br>
<br>
 namespace llvm {<br>
<br>
 /// Writer for instrumentation based profile data.<br>
 class InstrProfWriter {<br>
 public:<br>
-  typedef SmallDenseMap<uint64_t, std::vector<uint64_t>, 1> CounterData;<br>
+  typedef SmallDenseMap<uint64_t, InstrProfRecord, 1> ProfilingData;<br>
+<br>
 private:<br>
-  StringMap<CounterData> FunctionData;<br>
+  InstrProfStringTable StringTable;<br>
+  StringMap<ProfilingData> FunctionData;<br>
   uint64_t MaxFunctionCount;<br>
 public:<br>
   InstrProfWriter() : MaxFunctionCount(0) {}<br>
<br>
+  /// Update string entries in profile data with references to StringTable.<br>
+  void updateStringTableReferences(InstrProfRecord &I);<br>
   /// Add function counts for the given function. If there are already counts<br>
   /// for this function and the hash and number of counts match, each counter is<br>
   /// summed.<br>
-  std::error_code addFunctionCounts(StringRef FunctionName,<br>
-                                    uint64_t FunctionHash,<br>
-                                    ArrayRef<uint64_t> Counters);<br>
+  std::error_code addRecord(InstrProfRecord &&I);<br>
   /// Write the profile to \c OS<br>
   void write(raw_fd_ostream &OS);<br>
   /// Write the profile, returning the raw data. For testing.<br>
<br>
Modified: llvm/trunk/lib/ProfileData/InstrProf.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ProfileData/InstrProf.cpp?rev=248833&r1=248832&r2=248833&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ProfileData/InstrProf.cpp?rev=248833&r1=248832&r2=248833&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/ProfileData/InstrProf.cpp (original)<br>
+++ llvm/trunk/lib/ProfileData/InstrProf.cpp Tue Sep 29 17:13:58 2015<br>
@@ -50,6 +50,8 @@ class InstrProfErrorCategoryType : publi<br>
       return "Function count mismatch";<br>
     case instrprof_error::counter_overflow:<br>
       return "Counter overflow";<br>
+    case instrprof_error::value_site_count_mismatch:<br>
+      return "Function's value site counts mismatch";<br>
     }<br>
     llvm_unreachable("A value of instrprof_error has no message.");<br>
   }<br>
<br>
Modified: llvm/trunk/lib/ProfileData/InstrProfIndexed.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ProfileData/InstrProfIndexed.h?rev=248833&r1=248832&r2=248833&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ProfileData/InstrProfIndexed.h?rev=248833&r1=248832&r2=248833&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/ProfileData/InstrProfIndexed.h (original)<br>
+++ llvm/trunk/lib/ProfileData/InstrProfIndexed.h Tue Sep 29 17:13:58 2015<br>
@@ -47,7 +47,7 @@ static inline uint64_t ComputeHash(HashT<br>
 }<br>
<br>
 const uint64_t Magic = 0x8169666f72706cff; // "\xfflprofi\x81"<br>
-const uint64_t Version = 2;<br>
+const uint64_t Version = 3;<br>
 const HashT HashType = HashT::MD5;<br>
 }<br>
<br>
<br>
Modified: llvm/trunk/lib/ProfileData/InstrProfReader.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ProfileData/InstrProfReader.cpp?rev=248833&r1=248832&r2=248833&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ProfileData/InstrProfReader.cpp?rev=248833&r1=248832&r2=248833&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/ProfileData/InstrProfReader.cpp (original)<br>
+++ llvm/trunk/lib/ProfileData/InstrProfReader.cpp Tue Sep 29 17:13:58 2015<br>
@@ -302,42 +302,102 @@ InstrProfLookupTrait::ComputeHash(String<br>
 typedef InstrProfLookupTrait::data_type data_type;<br>
 typedef InstrProfLookupTrait::offset_type offset_type;<br>
<br>
+bool InstrProfLookupTrait::ReadValueProfilingData(<br>
+    const unsigned char *&D, const unsigned char *const End) {<br>
+<br>
+  using namespace support;<br>
+  // Read number of value kinds with value sites.<br>
+  if (D + sizeof(uint64_t) > End)<br>
+    return false;<br>
+  uint64_t ValueKindCount = endian::readNext<uint64_t, little, unaligned>(D);<br>
+<br>
+  for (uint32_t Kind = 0; Kind < ValueKindCount; ++Kind) {<br>
+<br>
+    // Read value kind and number of value sites for kind.<br>
+    if (D + 2 * sizeof(uint64_t) > End)<br>
+      return false;<br>
+    uint64_t ValueKind = endian::readNext<uint64_t, little, unaligned>(D);<br>
+    uint64_t ValueSiteCount = endian::readNext<uint64_t, little, unaligned>(D);<br>
+<br>
+    std::vector<InstrProfValueSiteRecord> &ValueSites =<br>
+        DataBuffer.back().getValueSitesForKind(ValueKind);<br>
+    ValueSites.reserve(ValueSiteCount);<br>
+    for (uint64_t VSite = 0; VSite < ValueSiteCount; ++VSite) {<br>
+      // Read number of value data pairs at value site.<br>
+      if (D + sizeof(uint64_t) > End)<br>
+        return false;<br>
+      uint64_t ValueDataCount =<br>
+          endian::readNext<uint64_t, little, unaligned>(D);<br>
+<br>
+      // Check if there are as many ValueDataPairs as ValueDataCount in memory.<br>
+      if (D + (ValueDataCount << 1) * sizeof(uint64_t) > End)<br>
+        return false;<br>
+<br>
+      InstrProfValueSiteRecord VSiteRecord;<br>
+      for (uint64_t VCount = 0; VCount < ValueDataCount; ++VCount) {<br>
+        uint64_t Value = endian::readNext<uint64_t, little, unaligned>(D);<br>
+        uint64_t NumTaken = endian::readNext<uint64_t, little, unaligned>(D);<br>
+        switch (ValueKind) {<br>
+        case IPVK_IndirectCallTarget: {<br>
+          auto Result =<br>
+              std::lower_bound(HashKeys.begin(), HashKeys.end(), Value,<br>
+                               [](const std::pair<uint64_t, const char *> &LHS,<br>
+                                  uint64_t RHS) { return LHS.first < RHS; });<br>
+          assert(Result != HashKeys.end() &&<br>
+                 "Hash does not match any known keys\n");<br>
+          Value = (uint64_t)Result->second;<br>
+          break;<br>
+        }<br>
+        }<br>
+        VSiteRecord.ValueData.push_back(std::make_pair(Value, NumTaken));<br>
+      }<br>
+      ValueSites.push_back(std::move(VSiteRecord));<br>
+    }<br>
+  }<br>
+  return true;<br>
+}<br>
+<br>
 data_type InstrProfLookupTrait::ReadData(StringRef K, const unsigned char *D,<br>
                                          offset_type N) {<br>
-<br>
   // Check if the data is corrupt. If so, don't try to read it.<br>
   if (N % sizeof(uint64_t))<br>
     return data_type();<br>
<br>
   DataBuffer.clear();<br>
-  uint64_t NumCounts;<br>
-  uint64_t NumEntries = N / sizeof(uint64_t);<br>
   std::vector<uint64_t> CounterBuffer;<br>
-  for (uint64_t I = 0; I < NumEntries; I += NumCounts) {<br>
-    using namespace support;<br>
-    // The function hash comes first.<br>
-    uint64_t Hash = endian::readNext<uint64_t, little, unaligned>(D);<br>
<br>
-    if (++I >= NumEntries)<br>
+  using namespace support;<br>
+  const unsigned char *End = D + N;<br>
+  while (D < End) {<br>
+    // Read hash<br>
+    if (D + sizeof(uint64_t) >= End)<br>
       return data_type();<br>
+    uint64_t Hash = endian::readNext<uint64_t, little, unaligned>(D);<br>
<br>
-    // In v1, we have at least one count.<br>
-    // Later, we have the number of counts.<br>
-    NumCounts = (1 == FormatVersion)<br>
-                    ? NumEntries - I<br>
-                    : endian::readNext<uint64_t, little, unaligned>(D);<br>
-    if (1 != FormatVersion)<br>
-      ++I;<br>
-<br>
-    // If we have more counts than data, this is bogus.<br>
-    if (I + NumCounts > NumEntries)<br>
+    // Initialize number of counters for FormatVersion == 1<br>
+    uint64_t CountsSize = N / sizeof(uint64_t) - 1;<br>
+    // If format version is different then read number of counters<br>
+    if (FormatVersion != 1) {<br>
+      if (D + sizeof(uint64_t) > End)<br>
+        return data_type();<br>
+      CountsSize = endian::readNext<uint64_t, little, unaligned>(D);<br>
+    }<br>
+    // Read counter values<br>
+    if (D + CountsSize * sizeof(uint64_t) > End)<br>
       return data_type();<br>
<br>
     CounterBuffer.clear();<br>
-    for (unsigned J = 0; J < NumCounts; ++J)<br>
+    CounterBuffer.reserve(CountsSize);<br>
+    for (uint64_t J = 0; J < CountsSize; ++J)<br>
       CounterBuffer.push_back(endian::readNext<uint64_t, little, unaligned>(D));<br>
<br>
     DataBuffer.push_back(InstrProfRecord(K, Hash, std::move(CounterBuffer)));<br>
+<br>
+    // Read value profiling data<br>
+    if (FormatVersion > 2 && !ReadValueProfilingData(D, End)) {<br>
+      DataBuffer.clear();<br>
+      return data_type();<br>
+    }<br>
   }<br>
   return DataBuffer;<br>
 }<br>
@@ -384,6 +444,18 @@ std::error_code IndexedInstrProfReader::<br>
   Index.reset(InstrProfReaderIndex::Create(<br>
       Start + HashOffset, Cur, Start,<br>
       InstrProfLookupTrait(HashType, FormatVersion)));<br>
+<br>
+  // Form the map of hash values to const char* keys in profiling data.<br>
+  std::vector<std::pair<uint64_t, const char *>> HashKeys;<br>
+  for (auto Key : Index->keys()) {<br>
+    const char *KeyTableRef = StringTable.insertString(Key);<br>
+    HashKeys.push_back(std::make_pair(ComputeHash(HashType, Key), KeyTableRef));<br>
+  }<br>
+  std::sort(HashKeys.begin(), HashKeys.end(), less_first());<br>
+  std::unique(HashKeys.begin(), HashKeys.end(), less_first());<br>
+  HashKeys.erase(std::unique(HashKeys.begin(), HashKeys.end()), HashKeys.end());<br></blockquote><div><br></div><div>The first "HashKeys.end()" should be the return value of the std::unique on the previous line, otherwise the std::unique here will work on specified values at the end of the vector.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+  // Set the hash key map for the InstrLookupTrait<br>
+  Index->getInfoObj().setHashKeys(std::move(HashKeys));<br>
   // Set up our iterator for readNextRecord.<br>
   RecordIterator = Index->data_begin();<br>
<br>
<br>
Modified: llvm/trunk/lib/ProfileData/InstrProfWriter.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ProfileData/InstrProfWriter.cpp?rev=248833&r1=248832&r2=248833&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ProfileData/InstrProfWriter.cpp?rev=248833&r1=248832&r2=248833&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/ProfileData/InstrProfWriter.cpp (original)<br>
+++ llvm/trunk/lib/ProfileData/InstrProfWriter.cpp Tue Sep 29 17:13:58 2015<br>
@@ -26,8 +26,8 @@ public:<br>
   typedef StringRef key_type;<br>
   typedef StringRef key_type_ref;<br>
<br>
-  typedef const InstrProfWriter::CounterData *const data_type;<br>
-  typedef const InstrProfWriter::CounterData *const data_type_ref;<br>
+  typedef const InstrProfWriter::ProfilingData *const data_type;<br>
+  typedef const InstrProfWriter::ProfilingData *const data_type_ref;<br>
<br>
   typedef uint64_t hash_value_type;<br>
   typedef uint64_t offset_type;<br>
@@ -45,8 +45,26 @@ public:<br>
     LE.write<offset_type>(N);<br>
<br>
     offset_type M = 0;<br>
-    for (const auto &Counts : *V)<br>
-      M += (2 + Counts.second.size()) * sizeof(uint64_t);<br>
+    for (const auto &ProfileData : *V) {<br>
+      M += sizeof(uint64_t); // The function hash<br>
+      M += sizeof(uint64_t); // The size of the Counts vector<br>
+      M += ProfileData.second.Counts.size() * sizeof(uint64_t);<br>
+<br>
+      // Value data<br>
+      M += sizeof(uint64_t); // Number of value kinds with value sites.<br>
+      for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind) {<br>
+        const std::vector<InstrProfValueSiteRecord> &ValueSites =<br>
+            ProfileData.second.getValueSitesForKind(Kind);<br>
+        if (ValueSites.empty())<br>
+          continue;<br>
+        M += sizeof(uint64_t); // Value kind<br>
+        M += sizeof(uint64_t); // The number of value sites for given value kind<br>
+        for (InstrProfValueSiteRecord I : ValueSites) {<br>
+          M += sizeof(uint64_t); // Number of value data pairs at a value site<br>
+          M += 2 * sizeof(uint64_t) * I.ValueData.size(); // Value data pairs<br>
+        }<br>
+      }<br>
+    }<br>
     LE.write<offset_type>(M);<br>
<br>
     return std::make_pair(N, M);<br>
@@ -60,52 +78,114 @@ public:<br>
                        offset_type) {<br>
     using namespace llvm::support;<br>
     endian::Writer<little> LE(Out);<br>
-<br>
-    for (const auto &Counts : *V) {<br>
-      LE.write<uint64_t>(Counts.first);<br>
-      LE.write<uint64_t>(Counts.second.size());<br>
-      for (uint64_t I : Counts.second)<br>
+    for (const auto &ProfileData : *V) {<br>
+      LE.write<uint64_t>(ProfileData.first); // Function hash<br>
+      LE.write<uint64_t>(ProfileData.second.Counts.size());<br>
+      for (uint64_t I : ProfileData.second.Counts)<br>
         LE.write<uint64_t>(I);<br>
+<br>
+      // Compute the number of value kinds with value sites.<br>
+      uint64_t NumValueKinds = 0;<br>
+      for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind)<br>
+        NumValueKinds +=<br>
+            !(ProfileData.second.getValueSitesForKind(Kind).empty());<br>
+      LE.write<uint64_t>(NumValueKinds);<br>
+<br>
+      // Write value data<br>
+      for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind) {<br>
+        const std::vector<InstrProfValueSiteRecord> &ValueSites =<br>
+            ProfileData.second.getValueSitesForKind(Kind);<br>
+        if (ValueSites.empty())<br>
+          continue;<br>
+        LE.write<uint64_t>(Kind); // Write value kind<br>
+        // Write number of value sites for current value kind<br>
+        LE.write<uint64_t>(ValueSites.size());<br>
+        for (InstrProfValueSiteRecord I : ValueSites) {<br>
+          // Write number of value data pairs at this value site<br>
+          LE.write<uint64_t>(I.ValueData.size());<br>
+          for (auto V : I.ValueData) {<br>
+            if (Kind == IPVK_IndirectCallTarget)<br>
+              LE.write<uint64_t>(ComputeHash((const char *)V.first));<br>
+            else<br>
+              LE.write<uint64_t>(V.first);<br>
+            LE.write<uint64_t>(V.second);<br>
+          }<br>
+        }<br>
+      }<br>
     }<br>
   }<br>
 };<br>
 }<br>
<br>
-std::error_code<br>
-InstrProfWriter::addFunctionCounts(StringRef FunctionName,<br>
-                                   uint64_t FunctionHash,<br>
-                                   ArrayRef<uint64_t> Counters) {<br>
-  auto &CounterData = FunctionData[FunctionName];<br>
+static std::error_code combineInstrProfRecords(InstrProfRecord &Dest,<br>
+                                               InstrProfRecord &Source,<br>
+                                               uint64_t &MaxFunctionCount) {<br>
+  // If the number of counters doesn't match we either have bad data<br>
+  // or a hash collision.<br>
+  if (Dest.Counts.size() != Source.Counts.size())<br>
+    return instrprof_error::count_mismatch;<br>
<br>
-  auto Where = CounterData.find(FunctionHash);<br>
-  if (Where == CounterData.end()) {<br>
-    // We've never seen a function with this name and hash, add it.<br>
-    CounterData[FunctionHash] = Counters;<br>
-    // We keep track of the max function count as we go for simplicity.<br>
-    if (Counters[0] > MaxFunctionCount)<br>
-      MaxFunctionCount = Counters[0];<br>
-    return instrprof_error::success;<br>
+  for (size_t I = 0, E = Source.Counts.size(); I < E; ++I) {<br>
+    if (Dest.Counts[I] + Source.Counts[I] < Dest.Counts[I])<br>
+      return instrprof_error::counter_overflow;<br>
+    Dest.Counts[I] += Source.Counts[I];<br>
   }<br>
<br>
-  // We're updating a function we've seen before.<br>
-  auto &FoundCounters = Where->second;<br>
-  // If the number of counters doesn't match we either have bad data or a hash<br>
-  // collision.<br>
-  if (FoundCounters.size() != Counters.size())<br>
-    return instrprof_error::count_mismatch;<br>
+  for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind) {<br>
<br>
-  for (size_t I = 0, E = Counters.size(); I < E; ++I) {<br>
-    if (FoundCounters[I] + Counters[I] < FoundCounters[I])<br>
-      return instrprof_error::counter_overflow;<br>
-    FoundCounters[I] += Counters[I];<br>
+    std::vector<InstrProfValueSiteRecord> &SourceValueSites =<br>
+        Source.getValueSitesForKind(Kind);<br>
+    if (SourceValueSites.empty())<br>
+      continue;<br>
+<br>
+    std::vector<InstrProfValueSiteRecord> &DestValueSites =<br>
+        Dest.getValueSitesForKind(Kind);<br>
+<br>
+    if (DestValueSites.empty()) {<br>
+      DestValueSites.swap(SourceValueSites);<br>
+      continue;<br>
+    }<br>
+<br>
+    if (DestValueSites.size() != SourceValueSites.size())<br>
+      return instrprof_error::value_site_count_mismatch;<br>
+    for (size_t I = 0, E = SourceValueSites.size(); I < E; ++I)<br>
+      DestValueSites[I].mergeValueData(SourceValueSites[I]);<br>
   }<br>
+<br>
   // We keep track of the max function count as we go for simplicity.<br>
-  if (FoundCounters[0] > MaxFunctionCount)<br>
-    MaxFunctionCount = FoundCounters[0];<br>
+  if (Dest.Counts[0] > MaxFunctionCount)<br>
+    MaxFunctionCount = Dest.Counts[0];<br>
<br>
   return instrprof_error::success;<br>
 }<br>
<br>
+void InstrProfWriter::updateStringTableReferences(InstrProfRecord &I) {<br>
+  I.Name = StringTable.insertString(I.Name);<br>
+  for (auto &VSite : I.IndirectCallSites)<br>
+    for (auto &VData : VSite.ValueData)<br>
+      VData.first =<br>
+          (uint64_t)StringTable.insertString((const char *)VData.first);<br>
+}<br>
+<br>
+std::error_code InstrProfWriter::addRecord(InstrProfRecord &&I) {<br>
+  updateStringTableReferences(I);<br>
+  auto &ProfileDataMap = FunctionData[I.Name];<br>
+<br>
+  auto Where = ProfileDataMap.find(I.Hash);<br>
+  if (Where == ProfileDataMap.end()) {<br>
+    // We've never seen a function with this name and hash, add it.<br>
+    ProfileDataMap[I.Hash] = I;<br>
+<br>
+    // We keep track of the max function count as we go for simplicity.<br>
+    if (I.Counts[0] > MaxFunctionCount)<br>
+      MaxFunctionCount = I.Counts[0];<br>
+    return instrprof_error::success;<br>
+  }<br>
+<br>
+  // We're updating a function we've seen before.<br>
+  return combineInstrProfRecords(Where->second, I, MaxFunctionCount);<br>
+}<br>
+<br>
 std::pair<uint64_t, uint64_t> InstrProfWriter::writeImpl(raw_ostream &OS) {<br>
   OnDiskChainedHashTableGenerator<InstrProfRecordTrait> Generator;<br>
<br>
<br>
Modified: llvm/trunk/tools/llvm-profdata/llvm-profdata.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-profdata/llvm-profdata.cpp?rev=248833&r1=248832&r2=248833&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-profdata/llvm-profdata.cpp?rev=248833&r1=248832&r2=248833&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/tools/llvm-profdata/llvm-profdata.cpp (original)<br>
+++ llvm/trunk/tools/llvm-profdata/llvm-profdata.cpp Tue Sep 29 17:13:58 2015<br>
@@ -58,9 +58,8 @@ static void mergeInstrProfile(const cl::<br>
       exitWithError(ec.message(), Filename);<br>
<br>
     auto Reader = std::move(ReaderOrErr.get());<br>
-    for (const auto &I : *Reader)<br>
-      if (std::error_code EC =<br>
-              Writer.addFunctionCounts(I.Name, I.Hash, I.Counts))<br>
+    for (auto &I : *Reader)<br>
+      if (std::error_code EC = Writer.addRecord(std::move(I)))<br>
         errs() << Filename << ": " << I.Name << ": " << EC.message() << "\n";<br>
     if (Reader->hasError())<br>
       exitWithError(Reader->getError().message(), Filename);<br>
@@ -134,8 +133,8 @@ static int merge_main(int argc, const ch<br>
 }<br>
<br>
 static int showInstrProfile(std::string Filename, bool ShowCounts,<br>
-                            bool ShowAllFunctions, std::string ShowFunction,<br>
-                            raw_fd_ostream &OS) {<br>
+                            bool ShowIndirectCallTargets, bool ShowAllFunctions,<br>
+                            std::string ShowFunction, raw_fd_ostream &OS) {<br>
   auto ReaderOrErr = InstrProfReader::create(Filename);<br>
   if (std::error_code EC = ReaderOrErr.getError())<br>
     exitWithError(EC.message(), Filename);<br>
@@ -162,6 +161,9 @@ static int showInstrProfile(std::string<br>
          << "    Hash: " << format("0x%016" PRIx64, Func.Hash) << "\n"<br>
          << "    Counters: " << Func.Counts.size() << "\n"<br>
          << "    Function count: " << Func.Counts[0] << "\n";<br>
+      if (ShowIndirectCallTargets)<br>
+        OS << "    Indirect Call Site Count: " << Func.IndirectCallSites.size()<br>
+           << "\n";<br>
     }<br>
<br>
     if (Show && ShowCounts)<br>
@@ -174,6 +176,16 @@ static int showInstrProfile(std::string<br>
     }<br>
     if (Show && ShowCounts)<br>
       OS << "]\n";<br>
+<br>
+    if (Show && ShowIndirectCallTargets) {<br>
+      OS << "    Indirect Target Results: \n";<br>
+      for (size_t I = 0, E = Func.IndirectCallSites.size(); I < E; ++I) {<br>
+        for (auto V : Func.IndirectCallSites[I].ValueData) {<br>
+          OS << "\t[ " << I << ", ";<br>
+          OS << (const char *)V.first << ", " << V.second << " ]\n";<br>
+        }<br>
+      }<br>
+    }<br>
   }<br>
   if (Reader->hasError())<br>
     exitWithError(Reader->getError().message(), Filename);<br>
@@ -212,6 +224,9 @@ static int show_main(int argc, const cha<br>
<br>
   cl::opt<bool> ShowCounts("counts", cl::init(false),<br>
                            cl::desc("Show counter values for shown functions"));<br>
+  cl::opt<bool> ShowIndirectCallTargets(<br>
+      "ic-targets", cl::init(false),<br>
+      cl::desc("Show indirect call site target values for shown functions"));<br>
   cl::opt<bool> ShowAllFunctions("all-functions", cl::init(false),<br>
                                  cl::desc("Details for every function"));<br>
   cl::opt<std::string> ShowFunction("function",<br>
@@ -240,8 +255,8 @@ static int show_main(int argc, const cha<br>
     errs() << "warning: -function argument ignored: showing all functions\n";<br>
<br>
   if (ProfileKind == instr)<br>
-    return showInstrProfile(Filename, ShowCounts, ShowAllFunctions,<br>
-                            ShowFunction, OS);<br>
+    return showInstrProfile(Filename, ShowCounts, ShowIndirectCallTargets,<br>
+                            ShowAllFunctions, ShowFunction, OS);<br>
   else<br>
     return showSampleProfile(Filename, ShowCounts, ShowAllFunctions,<br>
                              ShowFunction, OS);<br>
<br>
Modified: llvm/trunk/unittests/ProfileData/CoverageMappingTest.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ProfileData/CoverageMappingTest.cpp?rev=248833&r1=248832&r2=248833&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ProfileData/CoverageMappingTest.cpp?rev=248833&r1=248832&r2=248833&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/unittests/ProfileData/CoverageMappingTest.cpp (original)<br>
+++ llvm/trunk/unittests/ProfileData/CoverageMappingTest.cpp Tue Sep 29 17:13:58 2015<br>
@@ -188,7 +188,8 @@ TEST_F(CoverageMappingTest, expansion_ge<br>
 }<br>
<br>
 TEST_F(CoverageMappingTest, basic_coverage_iteration) {<br>
-  ProfileWriter.addFunctionCounts("func", 0x1234, {30, 20, 10, 0});<br>
+  InstrProfRecord Record("func", 0x1234, {30, 20, 10, 0});<br>
+  ProfileWriter.addRecord(std::move(Record));<br>
   readProfCounts();<br>
<br>
   addCMR(Counter::getCounter(0), "file1", 1, 1, 9, 9);<br>
@@ -238,7 +239,8 @@ TEST_F(CoverageMappingTest, uncovered_fu<br>
 }<br>
<br>
 TEST_F(CoverageMappingTest, combine_regions) {<br>
-  ProfileWriter.addFunctionCounts("func", 0x1234, {10, 20, 30});<br>
+  InstrProfRecord Record("func", 0x1234, {10, 20, 30});<br>
+  ProfileWriter.addRecord(std::move(Record));<br>
   readProfCounts();<br>
<br>
   addCMR(Counter::getCounter(0), "file1", 1, 1, 9, 9);<br>
@@ -256,7 +258,8 @@ TEST_F(CoverageMappingTest, combine_regi<br>
 }<br>
<br>
 TEST_F(CoverageMappingTest, dont_combine_expansions) {<br>
-  ProfileWriter.addFunctionCounts("func", 0x1234, {10, 20});<br>
+  InstrProfRecord Record("func", 0x1234, {10, 20});<br>
+  ProfileWriter.addRecord(std::move(Record));<br>
   readProfCounts();<br>
<br>
   addCMR(Counter::getCounter(0), "file1", 1, 1, 9, 9);<br>
@@ -275,7 +278,8 @@ TEST_F(CoverageMappingTest, dont_combine<br>
 }<br>
<br>
 TEST_F(CoverageMappingTest, strip_filename_prefix) {<br>
-  ProfileWriter.addFunctionCounts("file1:func", 0x1234, {10});<br>
+  InstrProfRecord Record("file1:func", 0x1234, {10});<br>
+  ProfileWriter.addRecord(std::move(Record));<br>
   readProfCounts();<br>
<br>
   addCMR(Counter::getCounter(0), "file1", 1, 1, 9, 9);<br>
<br>
Modified: llvm/trunk/unittests/ProfileData/InstrProfTest.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ProfileData/InstrProfTest.cpp?rev=248833&r1=248832&r2=248833&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ProfileData/InstrProfTest.cpp?rev=248833&r1=248832&r2=248833&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/unittests/ProfileData/InstrProfTest.cpp (original)<br>
+++ llvm/trunk/unittests/ProfileData/InstrProfTest.cpp Tue Sep 29 17:13:58 2015<br>
@@ -50,7 +50,8 @@ TEST_F(InstrProfTest, write_and_read_emp<br>
 }<br>
<br>
 TEST_F(InstrProfTest, write_and_read_one_function) {<br>
-  Writer.addFunctionCounts("foo", 0x1234, {1, 2, 3, 4});<br>
+  InstrProfRecord Record("foo", 0x1234, {1, 2, 3, 4});<br>
+  Writer.addRecord(std::move(Record));<br>
   auto Profile = Writer.writeBuffer();<br>
   readProfile(std::move(Profile));<br>
<br>
@@ -67,8 +68,10 @@ TEST_F(InstrProfTest, write_and_read_one<br>
 }<br>
<br>
 TEST_F(InstrProfTest, get_function_counts) {<br>
-  Writer.addFunctionCounts("foo", 0x1234, {1, 2});<br>
-  Writer.addFunctionCounts("foo", 0x1235, {3, 4});<br>
+  InstrProfRecord Record1("foo", 0x1234, {1, 2});<br>
+  InstrProfRecord Record2("foo", 0x1235, {3, 4});<br>
+  Writer.addRecord(std::move(Record1));<br>
+  Writer.addRecord(std::move(Record2));<br>
   auto Profile = Writer.writeBuffer();<br>
   readProfile(std::move(Profile));<br>
<br>
@@ -92,9 +95,12 @@ TEST_F(InstrProfTest, get_function_count<br>
 }<br>
<br>
 TEST_F(InstrProfTest, get_max_function_count) {<br>
-  Writer.addFunctionCounts("foo", 0x1234, {1ULL << 31, 2});<br>
-  Writer.addFunctionCounts("bar", 0, {1ULL << 63});<br>
-  Writer.addFunctionCounts("baz", 0x5678, {0, 0, 0, 0});<br>
+  InstrProfRecord Record1("foo", 0x1234, {1ULL << 31, 2});<br>
+  InstrProfRecord Record2("bar", 0, {1ULL << 63});<br>
+  InstrProfRecord Record3("baz", 0x5678, {0, 0, 0, 0});<br>
+  Writer.addRecord(std::move(Record1));<br>
+  Writer.addRecord(std::move(Record2));<br>
+  Writer.addRecord(std::move(Record3));<br>
   auto Profile = Writer.writeBuffer();<br>
   readProfile(std::move(Profile));<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>