[llvm] r248833 - InstrProf: Support for value profiling in the indexed profile format

Justin Bogner via llvm-commits llvm-commits at lists.llvm.org
Tue Sep 29 19:04:47 PDT 2015


Richard Trieu <rtrieu at google.com> writes:
> On Tue, Sep 29, 2015 at 3:13 PM, Justin Bogner via llvm-commits <
> llvm-commits at lists.llvm.org> wrote:
>
>> Author: bogner
>> Date: Tue Sep 29 17:13:58 2015
>> New Revision: 248833
>>
>> URL: http://llvm.org/viewvc/llvm-project?rev=248833&view=rev
>> Log:
>> InstrProf: Support for value profiling in the indexed profile format
>>
>> Add support to the indexed instrprof reader and writer for the format
>> that will be used for value profiling.
>>
>> Patch by Betul Buyukkurt, with minor modifications.
>>
>> Modified:
>>     llvm/trunk/include/llvm/ProfileData/InstrProf.h
>>     llvm/trunk/include/llvm/ProfileData/InstrProfReader.h
>>     llvm/trunk/include/llvm/ProfileData/InstrProfWriter.h
>>     llvm/trunk/lib/ProfileData/InstrProf.cpp
>>     llvm/trunk/lib/ProfileData/InstrProfIndexed.h
>>     llvm/trunk/lib/ProfileData/InstrProfReader.cpp
>>     llvm/trunk/lib/ProfileData/InstrProfWriter.cpp
>>     llvm/trunk/tools/llvm-profdata/llvm-profdata.cpp
>>     llvm/trunk/unittests/ProfileData/CoverageMappingTest.cpp
>>     llvm/trunk/unittests/ProfileData/InstrProfTest.cpp
>>
>> Modified: llvm/trunk/include/llvm/ProfileData/InstrProf.h
>> URL:
>>
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ProfileData/InstrProf.h?rev=248833&r1=248832&r2=248833&view=diff
>>
>>
> ==============================================================================
>> --- llvm/trunk/include/llvm/ProfileData/InstrProf.h (original)
>> +++ llvm/trunk/include/llvm/ProfileData/InstrProf.h Tue Sep 29 17:13:58
>> 2015
>> @@ -16,8 +16,10 @@
>>  #ifndef LLVM_PROFILEDATA_INSTRPROF_H_
>>  #define LLVM_PROFILEDATA_INSTRPROF_H_
>>
>> -#include "llvm/ADT/StringRef.h"
>> +#include "llvm/ADT/StringSet.h"
>> +#include "llvm/Support/ErrorHandling.h"
>>  #include <cstdint>
>> +#include <list>
>>  #include <system_error>
>>  #include <vector>
>>
>> @@ -25,25 +27,84 @@ namespace llvm {
>>  const std::error_category &instrprof_category();
>>
>>  enum class instrprof_error {
>> -    success = 0,
>> -    eof,
>> -    bad_magic,
>> -    bad_header,
>> -    unsupported_version,
>> -    unsupported_hash_type,
>> -    too_large,
>> -    truncated,
>> -    malformed,
>> -    unknown_function,
>> -    hash_mismatch,
>> -    count_mismatch,
>> -    counter_overflow
>> +  success = 0,
>> +  eof,
>> +  bad_magic,
>> +  bad_header,
>> +  unsupported_version,
>> +  unsupported_hash_type,
>> +  too_large,
>> +  truncated,
>> +  malformed,
>> +  unknown_function,
>> +  hash_mismatch,
>> +  count_mismatch,
>> +  counter_overflow,
>> +  value_site_count_mismatch
>>  };
>>
>>  inline std::error_code make_error_code(instrprof_error E) {
>>    return std::error_code(static_cast<int>(E), instrprof_category());
>>  }
>>
>> +enum InstrProfValueKind : uint32_t {
>> +  IPVK_IndirectCallTarget = 0,
>> +
>> +  IPVK_First = IPVK_IndirectCallTarget,
>> +  IPVK_Last = IPVK_IndirectCallTarget
>> +};
>> +
>> +struct InstrProfStringTable {
>> +  // Set of string values in profiling data.
>> +  StringSet<> StringValueSet;
>> +  InstrProfStringTable() { StringValueSet.clear(); }
>> +  // Get a pointer to internal storage of a string in set
>> +  const char *getStringData(StringRef Str) {
>> +    auto Result = StringValueSet.find(Str);
>> +    return (Result == StringValueSet.end()) ? nullptr :
>> Result->first().data();
>> +  }
>> +  // Insert a string to StringTable
>> +  const char *insertString(StringRef Str) {
>> +    auto Result = StringValueSet.insert(Str);
>> +    return Result.first->first().data();
>> +  }
>> +};
>> +
>> +struct InstrProfValueSiteRecord {
>> +  /// Typedef for a single TargetValue-NumTaken pair.
>> +  typedef std::pair<uint64_t, uint64_t> ValueDataPair;
>> +  /// Value profiling data pairs at a given value site.
>> +  std::list<ValueDataPair> ValueData;
>> +
>> +  InstrProfValueSiteRecord() { ValueData.clear(); }
>> +
>> +  /// Sort ValueData ascending by TargetValue
>> +  void sortByTargetValues() {
>> +    ValueData.sort([](const ValueDataPair &left, const ValueDataPair
>> &right) {
>> +      return left.first < right.first;
>> +    });
>> +  }
>> +
>> +  /// Merge data from another InstrProfValueSiteRecord
>> +  void mergeValueData(InstrProfValueSiteRecord &Input) {
>> +    this->sortByTargetValues();
>> +    Input.sortByTargetValues();
>> +    auto I = ValueData.begin();
>> +    auto IE = ValueData.end();
>> +    for (auto J = Input.ValueData.begin(), JE = Input.ValueData.end(); J
>> != JE;
>> +         ++J) {
>> +      while (I != IE && I->first < J->first)
>> +        ++I;
>> +      if (I != IE && I->first == J->first) {
>> +        I->second += J->second;
>> +        ++I;
>> +        continue;
>> +      }
>> +      ValueData.insert(I, *J);
>> +    }
>> +  }
>> +};
>> +
>>  /// Profiling information for a single function.
>>  struct InstrProfRecord {
>>    InstrProfRecord() {}
>> @@ -52,6 +113,22 @@ struct InstrProfRecord {
>>    StringRef Name;
>>    uint64_t Hash;
>>    std::vector<uint64_t> Counts;
>> +  std::vector<InstrProfValueSiteRecord> IndirectCallSites;
>> +
>> +  const std::vector<InstrProfValueSiteRecord> &
>> +  getValueSitesForKind(uint32_t ValueKind) const {
>> +    switch (ValueKind) {
>> +    case IPVK_IndirectCallTarget:
>> +      return IndirectCallSites;
>> +    }
>> +    llvm_unreachable("Unknown value kind!");
>> +  }
>> +
>> +  std::vector<InstrProfValueSiteRecord> &
>> +  getValueSitesForKind(uint32_t ValueKind) {
>> +    return const_cast<std::vector<InstrProfValueSiteRecord> &>(
>> +        this->getValueSitesForKind(ValueKind));
>> +  }
>>  };
>>
>>  } // end namespace llvm
>>
>> Modified: llvm/trunk/include/llvm/ProfileData/InstrProfReader.h
>> URL:
>>
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ProfileData/InstrProfReader.h?rev=248833&r1=248832&r2=248833&view=diff
>>
>>
> ==============================================================================
>> --- llvm/trunk/include/llvm/ProfileData/InstrProfReader.h (original)
>> +++ llvm/trunk/include/llvm/ProfileData/InstrProfReader.h Tue Sep 29
>> 17:13:58 2015
>> @@ -65,6 +65,9 @@ public:
>>    InstrProfIterator end() { return InstrProfIterator(); }
>>
>>  protected:
>> +  /// String table for holding a unique copy of all the strings in the
>> profile.
>> +  InstrProfStringTable StringTable;
>> +
>>    /// Set the current std::error_code and return same.
>>    std::error_code error(std::error_code EC) {
>>      LastError = EC;
>> @@ -195,6 +198,7 @@ class InstrProfLookupTrait {
>>    std::vector<InstrProfRecord> DataBuffer;
>>    IndexedInstrProf::HashT HashType;
>>    unsigned FormatVersion;
>> +  std::vector<std::pair<uint64_t, const char *>> HashKeys;
>>
>>  public:
>>    InstrProfLookupTrait(IndexedInstrProf::HashT HashType, unsigned
>> FormatVersion)
>> @@ -209,9 +213,13 @@ public:
>>
>>    static bool EqualKey(StringRef A, StringRef B) { return A == B; }
>>    static StringRef GetInternalKey(StringRef K) { return K; }
>> +  static StringRef GetExternalKey(StringRef K) { return K; }
>>
>>    hash_value_type ComputeHash(StringRef K);
>>
>> +  void setHashKeys(std::vector<std::pair<uint64_t, const char *>>
>> HashKeys) {
>> +    this->HashKeys = std::move(HashKeys);
>> +  }
>>    static std::pair<offset_type, offset_type>
>>    ReadKeyDataLength(const unsigned char *&D) {
>>      using namespace support;
>> @@ -224,6 +232,8 @@ public:
>>      return StringRef((const char *)D, N);
>>    }
>>
>> +  bool ReadValueProfilingData(const unsigned char *&D,
>> +                              const unsigned char *const End);
>>    data_type ReadData(StringRef K, const unsigned char *D, offset_type N);
>>  };
>>
>>
>> Modified: llvm/trunk/include/llvm/ProfileData/InstrProfWriter.h
>> URL:
>>
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ProfileData/InstrProfWriter.h?rev=248833&r1=248832&r2=248833&view=diff
>>
>>
> ==============================================================================
>> --- llvm/trunk/include/llvm/ProfileData/InstrProfWriter.h (original)
>> +++ llvm/trunk/include/llvm/ProfileData/InstrProfWriter.h Tue Sep 29
>> 17:13:58 2015
>> @@ -15,33 +15,32 @@
>>  #ifndef LLVM_PROFILEDATA_INSTRPROFWRITER_H
>>  #define LLVM_PROFILEDATA_INSTRPROFWRITER_H
>>
>> -#include "llvm/ADT/ArrayRef.h"
>>  #include "llvm/ADT/DenseMap.h"
>> -#include "llvm/ADT/StringMap.h"
>>  #include "llvm/ProfileData/InstrProf.h"
>>  #include "llvm/Support/DataTypes.h"
>>  #include "llvm/Support/MemoryBuffer.h"
>>  #include "llvm/Support/raw_ostream.h"
>> -#include <vector>
>>
>>  namespace llvm {
>>
>>  /// Writer for instrumentation based profile data.
>>  class InstrProfWriter {
>>  public:
>> -  typedef SmallDenseMap<uint64_t, std::vector<uint64_t>, 1> CounterData;
>> +  typedef SmallDenseMap<uint64_t, InstrProfRecord, 1> ProfilingData;
>> +
>>  private:
>> -  StringMap<CounterData> FunctionData;
>> +  InstrProfStringTable StringTable;
>> +  StringMap<ProfilingData> FunctionData;
>>    uint64_t MaxFunctionCount;
>>  public:
>>    InstrProfWriter() : MaxFunctionCount(0) {}
>>
>> +  /// Update string entries in profile data with references to
>> StringTable.
>> +  void updateStringTableReferences(InstrProfRecord &I);
>>    /// Add function counts for the given function. If there are already
>> counts
>>    /// for this function and the hash and number of counts match, each
>> counter is
>>    /// summed.
>> -  std::error_code addFunctionCounts(StringRef FunctionName,
>> -                                    uint64_t FunctionHash,
>> -                                    ArrayRef<uint64_t> Counters);
>> +  std::error_code addRecord(InstrProfRecord &&I);
>>    /// Write the profile to \c OS
>>    void write(raw_fd_ostream &OS);
>>    /// Write the profile, returning the raw data. For testing.
>>
>> Modified: llvm/trunk/lib/ProfileData/InstrProf.cpp
>> URL:
>>
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ProfileData/InstrProf.cpp?rev=248833&r1=248832&r2=248833&view=diff
>>
>>
> ==============================================================================
>> --- llvm/trunk/lib/ProfileData/InstrProf.cpp (original)
>> +++ llvm/trunk/lib/ProfileData/InstrProf.cpp Tue Sep 29 17:13:58 2015
>> @@ -50,6 +50,8 @@ class InstrProfErrorCategoryType : publi
>>        return "Function count mismatch";
>>      case instrprof_error::counter_overflow:
>>        return "Counter overflow";
>> +    case instrprof_error::value_site_count_mismatch:
>> +      return "Function's value site counts mismatch";
>>      }
>>      llvm_unreachable("A value of instrprof_error has no message.");
>>    }
>>
>> Modified: llvm/trunk/lib/ProfileData/InstrProfIndexed.h
>> URL:
>>
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ProfileData/InstrProfIndexed.h?rev=248833&r1=248832&r2=248833&view=diff
>>
>>
> ==============================================================================
>> --- llvm/trunk/lib/ProfileData/InstrProfIndexed.h (original)
>> +++ llvm/trunk/lib/ProfileData/InstrProfIndexed.h Tue Sep 29 17:13:58 2015
>> @@ -47,7 +47,7 @@ static inline uint64_t ComputeHash(HashT
>>  }
>>
>>  const uint64_t Magic = 0x8169666f72706cff; // "\xfflprofi\x81"
>> -const uint64_t Version = 2;
>> +const uint64_t Version = 3;
>>  const HashT HashType = HashT::MD5;
>>  }
>>
>>
>> Modified: llvm/trunk/lib/ProfileData/InstrProfReader.cpp
>> URL:
>>
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ProfileData/InstrProfReader.cpp?rev=248833&r1=248832&r2=248833&view=diff
>>
>>
> ==============================================================================
>> --- llvm/trunk/lib/ProfileData/InstrProfReader.cpp (original)
>> +++ llvm/trunk/lib/ProfileData/InstrProfReader.cpp Tue Sep 29 17:13:58 2015
>> @@ -302,42 +302,102 @@ InstrProfLookupTrait::ComputeHash(String
>>  typedef InstrProfLookupTrait::data_type data_type;
>>  typedef InstrProfLookupTrait::offset_type offset_type;
>>
>> +bool InstrProfLookupTrait::ReadValueProfilingData(
>> +    const unsigned char *&D, const unsigned char *const End) {
>> +
>> +  using namespace support;
>> +  // Read number of value kinds with value sites.
>> +  if (D + sizeof(uint64_t) > End)
>> +    return false;
>> +  uint64_t ValueKindCount = endian::readNext<uint64_t, little,
>> unaligned>(D);
>> +
>> +  for (uint32_t Kind = 0; Kind < ValueKindCount; ++Kind) {
>> +
>> +    // Read value kind and number of value sites for kind.
>> +    if (D + 2 * sizeof(uint64_t) > End)
>> +      return false;
>> +    uint64_t ValueKind = endian::readNext<uint64_t, little, unaligned>(D);
>> +    uint64_t ValueSiteCount = endian::readNext<uint64_t, little,
>> unaligned>(D);
>> +
>> +    std::vector<InstrProfValueSiteRecord> &ValueSites =
>> +        DataBuffer.back().getValueSitesForKind(ValueKind);
>> +    ValueSites.reserve(ValueSiteCount);
>> +    for (uint64_t VSite = 0; VSite < ValueSiteCount; ++VSite) {
>> +      // Read number of value data pairs at value site.
>> +      if (D + sizeof(uint64_t) > End)
>> +        return false;
>> +      uint64_t ValueDataCount =
>> +          endian::readNext<uint64_t, little, unaligned>(D);
>> +
>> +      // Check if there are as many ValueDataPairs as ValueDataCount in
>> memory.
>> +      if (D + (ValueDataCount << 1) * sizeof(uint64_t) > End)
>> +        return false;
>> +
>> +      InstrProfValueSiteRecord VSiteRecord;
>> +      for (uint64_t VCount = 0; VCount < ValueDataCount; ++VCount) {
>> +        uint64_t Value = endian::readNext<uint64_t, little, unaligned>(D);
>> +        uint64_t NumTaken = endian::readNext<uint64_t, little,
>> unaligned>(D);
>> +        switch (ValueKind) {
>> +        case IPVK_IndirectCallTarget: {
>> +          auto Result =
>> +              std::lower_bound(HashKeys.begin(), HashKeys.end(), Value,
>> +                               [](const std::pair<uint64_t, const char *>
>> &LHS,
>> +                                  uint64_t RHS) { return LHS.first < RHS;
>> });
>> +          assert(Result != HashKeys.end() &&
>> +                 "Hash does not match any known keys\n");
>> +          Value = (uint64_t)Result->second;
>> +          break;
>> +        }
>> +        }
>> +        VSiteRecord.ValueData.push_back(std::make_pair(Value, NumTaken));
>> +      }
>> +      ValueSites.push_back(std::move(VSiteRecord));
>> +    }
>> +  }
>> +  return true;
>> +}
>> +
>>  data_type InstrProfLookupTrait::ReadData(StringRef K, const unsigned char
>> *D,
>>                                           offset_type N) {
>> -
>>    // Check if the data is corrupt. If so, don't try to read it.
>>    if (N % sizeof(uint64_t))
>>      return data_type();
>>
>>    DataBuffer.clear();
>> -  uint64_t NumCounts;
>> -  uint64_t NumEntries = N / sizeof(uint64_t);
>>    std::vector<uint64_t> CounterBuffer;
>> -  for (uint64_t I = 0; I < NumEntries; I += NumCounts) {
>> -    using namespace support;
>> -    // The function hash comes first.
>> -    uint64_t Hash = endian::readNext<uint64_t, little, unaligned>(D);
>>
>> -    if (++I >= NumEntries)
>> +  using namespace support;
>> +  const unsigned char *End = D + N;
>> +  while (D < End) {
>> +    // Read hash
>> +    if (D + sizeof(uint64_t) >= End)
>>        return data_type();
>> +    uint64_t Hash = endian::readNext<uint64_t, little, unaligned>(D);
>>
>> -    // In v1, we have at least one count.
>> -    // Later, we have the number of counts.
>> -    NumCounts = (1 == FormatVersion)
>> -                    ? NumEntries - I
>> -                    : endian::readNext<uint64_t, little, unaligned>(D);
>> -    if (1 != FormatVersion)
>> -      ++I;
>> -
>> -    // If we have more counts than data, this is bogus.
>> -    if (I + NumCounts > NumEntries)
>> +    // Initialize number of counters for FormatVersion == 1
>> +    uint64_t CountsSize = N / sizeof(uint64_t) - 1;
>> +    // If format version is different then read number of counters
>> +    if (FormatVersion != 1) {
>> +      if (D + sizeof(uint64_t) > End)
>> +        return data_type();
>> +      CountsSize = endian::readNext<uint64_t, little, unaligned>(D);
>> +    }
>> +    // Read counter values
>> +    if (D + CountsSize * sizeof(uint64_t) > End)
>>        return data_type();
>>
>>      CounterBuffer.clear();
>> -    for (unsigned J = 0; J < NumCounts; ++J)
>> +    CounterBuffer.reserve(CountsSize);
>> +    for (uint64_t J = 0; J < CountsSize; ++J)
>>        CounterBuffer.push_back(endian::readNext<uint64_t, little,
>> unaligned>(D));
>>
>>      DataBuffer.push_back(InstrProfRecord(K, Hash,
>> std::move(CounterBuffer)));
>> +
>> +    // Read value profiling data
>> +    if (FormatVersion > 2 && !ReadValueProfilingData(D, End)) {
>> +      DataBuffer.clear();
>> +      return data_type();
>> +    }
>>    }
>>    return DataBuffer;
>>  }
>> @@ -384,6 +444,18 @@ std::error_code IndexedInstrProfReader::
>>    Index.reset(InstrProfReaderIndex::Create(
>>        Start + HashOffset, Cur, Start,
>>        InstrProfLookupTrait(HashType, FormatVersion)));
>> +
>> +  // Form the map of hash values to const char* keys in profiling data.
>> +  std::vector<std::pair<uint64_t, const char *>> HashKeys;
>> +  for (auto Key : Index->keys()) {
>> +    const char *KeyTableRef = StringTable.insertString(Key);
>> +    HashKeys.push_back(std::make_pair(ComputeHash(HashType, Key),
>> KeyTableRef));
>> +  }
>> +  std::sort(HashKeys.begin(), HashKeys.end(), less_first());
>> +  std::unique(HashKeys.begin(), HashKeys.end(), less_first());
>> +  HashKeys.erase(std::unique(HashKeys.begin(), HashKeys.end()),
>> HashKeys.end());
>>
>
> 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.

It's simpler than that - this should only call std::unique once. r248872.

>
>> +  // Set the hash key map for the InstrLookupTrait
>> +  Index->getInfoObj().setHashKeys(std::move(HashKeys));
>>    // Set up our iterator for readNextRecord.
>>    RecordIterator = Index->data_begin();
>>
>>
>> Modified: llvm/trunk/lib/ProfileData/InstrProfWriter.cpp
>> URL:
>>
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ProfileData/InstrProfWriter.cpp?rev=248833&r1=248832&r2=248833&view=diff
>>
>>
> ==============================================================================
>> --- llvm/trunk/lib/ProfileData/InstrProfWriter.cpp (original)
>> +++ llvm/trunk/lib/ProfileData/InstrProfWriter.cpp Tue Sep 29 17:13:58 2015
>> @@ -26,8 +26,8 @@ public:
>>    typedef StringRef key_type;
>>    typedef StringRef key_type_ref;
>>
>> -  typedef const InstrProfWriter::CounterData *const data_type;
>> -  typedef const InstrProfWriter::CounterData *const data_type_ref;
>> +  typedef const InstrProfWriter::ProfilingData *const data_type;
>> +  typedef const InstrProfWriter::ProfilingData *const data_type_ref;
>>
>>    typedef uint64_t hash_value_type;
>>    typedef uint64_t offset_type;
>> @@ -45,8 +45,26 @@ public:
>>      LE.write<offset_type>(N);
>>
>>      offset_type M = 0;
>> -    for (const auto &Counts : *V)
>> -      M += (2 + Counts.second.size()) * sizeof(uint64_t);
>> +    for (const auto &ProfileData : *V) {
>> +      M += sizeof(uint64_t); // The function hash
>> +      M += sizeof(uint64_t); // The size of the Counts vector
>> +      M += ProfileData.second.Counts.size() * sizeof(uint64_t);
>> +
>> +      // Value data
>> +      M += sizeof(uint64_t); // Number of value kinds with value sites.
>> +      for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind) {
>> +        const std::vector<InstrProfValueSiteRecord> &ValueSites =
>> +            ProfileData.second.getValueSitesForKind(Kind);
>> +        if (ValueSites.empty())
>> +          continue;
>> +        M += sizeof(uint64_t); // Value kind
>> +        M += sizeof(uint64_t); // The number of value sites for given
>> value kind
>> +        for (InstrProfValueSiteRecord I : ValueSites) {
>> +          M += sizeof(uint64_t); // Number of value data pairs at a value
>> site
>> +          M += 2 * sizeof(uint64_t) * I.ValueData.size(); // Value data
>> pairs
>> +        }
>> +      }
>> +    }
>>      LE.write<offset_type>(M);
>>
>>      return std::make_pair(N, M);
>> @@ -60,52 +78,114 @@ public:
>>                         offset_type) {
>>      using namespace llvm::support;
>>      endian::Writer<little> LE(Out);
>> -
>> -    for (const auto &Counts : *V) {
>> -      LE.write<uint64_t>(Counts.first);
>> -      LE.write<uint64_t>(Counts.second.size());
>> -      for (uint64_t I : Counts.second)
>> +    for (const auto &ProfileData : *V) {
>> +      LE.write<uint64_t>(ProfileData.first); // Function hash
>> +      LE.write<uint64_t>(ProfileData.second.Counts.size());
>> +      for (uint64_t I : ProfileData.second.Counts)
>>          LE.write<uint64_t>(I);
>> +
>> +      // Compute the number of value kinds with value sites.
>> +      uint64_t NumValueKinds = 0;
>> +      for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind)
>> +        NumValueKinds +=
>> +            !(ProfileData.second.getValueSitesForKind(Kind).empty());
>> +      LE.write<uint64_t>(NumValueKinds);
>> +
>> +      // Write value data
>> +      for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind) {
>> +        const std::vector<InstrProfValueSiteRecord> &ValueSites =
>> +            ProfileData.second.getValueSitesForKind(Kind);
>> +        if (ValueSites.empty())
>> +          continue;
>> +        LE.write<uint64_t>(Kind); // Write value kind
>> +        // Write number of value sites for current value kind
>> +        LE.write<uint64_t>(ValueSites.size());
>> +        for (InstrProfValueSiteRecord I : ValueSites) {
>> +          // Write number of value data pairs at this value site
>> +          LE.write<uint64_t>(I.ValueData.size());
>> +          for (auto V : I.ValueData) {
>> +            if (Kind == IPVK_IndirectCallTarget)
>> +              LE.write<uint64_t>(ComputeHash((const char *)V.first));
>> +            else
>> +              LE.write<uint64_t>(V.first);
>> +            LE.write<uint64_t>(V.second);
>> +          }
>> +        }
>> +      }
>>      }
>>    }
>>  };
>>  }
>>
>> -std::error_code
>> -InstrProfWriter::addFunctionCounts(StringRef FunctionName,
>> -                                   uint64_t FunctionHash,
>> -                                   ArrayRef<uint64_t> Counters) {
>> -  auto &CounterData = FunctionData[FunctionName];
>> +static std::error_code combineInstrProfRecords(InstrProfRecord &Dest,
>> +                                               InstrProfRecord &Source,
>> +                                               uint64_t
>> &MaxFunctionCount) {
>> +  // If the number of counters doesn't match we either have bad data
>> +  // or a hash collision.
>> +  if (Dest.Counts.size() != Source.Counts.size())
>> +    return instrprof_error::count_mismatch;
>>
>> -  auto Where = CounterData.find(FunctionHash);
>> -  if (Where == CounterData.end()) {
>> -    // We've never seen a function with this name and hash, add it.
>> -    CounterData[FunctionHash] = Counters;
>> -    // We keep track of the max function count as we go for simplicity.
>> -    if (Counters[0] > MaxFunctionCount)
>> -      MaxFunctionCount = Counters[0];
>> -    return instrprof_error::success;
>> +  for (size_t I = 0, E = Source.Counts.size(); I < E; ++I) {
>> +    if (Dest.Counts[I] + Source.Counts[I] < Dest.Counts[I])
>> +      return instrprof_error::counter_overflow;
>> +    Dest.Counts[I] += Source.Counts[I];
>>    }
>>
>> -  // We're updating a function we've seen before.
>> -  auto &FoundCounters = Where->second;
>> -  // If the number of counters doesn't match we either have bad data or a
>> hash
>> -  // collision.
>> -  if (FoundCounters.size() != Counters.size())
>> -    return instrprof_error::count_mismatch;
>> +  for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind) {
>>
>> -  for (size_t I = 0, E = Counters.size(); I < E; ++I) {
>> -    if (FoundCounters[I] + Counters[I] < FoundCounters[I])
>> -      return instrprof_error::counter_overflow;
>> -    FoundCounters[I] += Counters[I];
>> +    std::vector<InstrProfValueSiteRecord> &SourceValueSites =
>> +        Source.getValueSitesForKind(Kind);
>> +    if (SourceValueSites.empty())
>> +      continue;
>> +
>> +    std::vector<InstrProfValueSiteRecord> &DestValueSites =
>> +        Dest.getValueSitesForKind(Kind);
>> +
>> +    if (DestValueSites.empty()) {
>> +      DestValueSites.swap(SourceValueSites);
>> +      continue;
>> +    }
>> +
>> +    if (DestValueSites.size() != SourceValueSites.size())
>> +      return instrprof_error::value_site_count_mismatch;
>> +    for (size_t I = 0, E = SourceValueSites.size(); I < E; ++I)
>> +      DestValueSites[I].mergeValueData(SourceValueSites[I]);
>>    }
>> +
>>    // We keep track of the max function count as we go for simplicity.
>> -  if (FoundCounters[0] > MaxFunctionCount)
>> -    MaxFunctionCount = FoundCounters[0];
>> +  if (Dest.Counts[0] > MaxFunctionCount)
>> +    MaxFunctionCount = Dest.Counts[0];
>>
>>    return instrprof_error::success;
>>  }
>>
>> +void InstrProfWriter::updateStringTableReferences(InstrProfRecord &I) {
>> +  I.Name = StringTable.insertString(I.Name);
>> +  for (auto &VSite : I.IndirectCallSites)
>> +    for (auto &VData : VSite.ValueData)
>> +      VData.first =
>> +          (uint64_t)StringTable.insertString((const char *)VData.first);
>> +}
>> +
>> +std::error_code InstrProfWriter::addRecord(InstrProfRecord &&I) {
>> +  updateStringTableReferences(I);
>> +  auto &ProfileDataMap = FunctionData[I.Name];
>> +
>> +  auto Where = ProfileDataMap.find(I.Hash);
>> +  if (Where == ProfileDataMap.end()) {
>> +    // We've never seen a function with this name and hash, add it.
>> +    ProfileDataMap[I.Hash] = I;
>> +
>> +    // We keep track of the max function count as we go for simplicity.
>> +    if (I.Counts[0] > MaxFunctionCount)
>> +      MaxFunctionCount = I.Counts[0];
>> +    return instrprof_error::success;
>> +  }
>> +
>> +  // We're updating a function we've seen before.
>> +  return combineInstrProfRecords(Where->second, I, MaxFunctionCount);
>> +}
>> +
>>  std::pair<uint64_t, uint64_t> InstrProfWriter::writeImpl(raw_ostream &OS)
>> {
>>    OnDiskChainedHashTableGenerator<InstrProfRecordTrait> Generator;
>>
>>
>> Modified: llvm/trunk/tools/llvm-profdata/llvm-profdata.cpp
>> URL:
>>
> http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-profdata/llvm-profdata.cpp?rev=248833&r1=248832&r2=248833&view=diff
>>
>>
> ==============================================================================
>> --- llvm/trunk/tools/llvm-profdata/llvm-profdata.cpp (original)
>> +++ llvm/trunk/tools/llvm-profdata/llvm-profdata.cpp Tue Sep 29 17:13:58
>> 2015
>> @@ -58,9 +58,8 @@ static void mergeInstrProfile(const cl::
>>        exitWithError(ec.message(), Filename);
>>
>>      auto Reader = std::move(ReaderOrErr.get());
>> -    for (const auto &I : *Reader)
>> -      if (std::error_code EC =
>> -              Writer.addFunctionCounts(I.Name, I.Hash, I.Counts))
>> +    for (auto &I : *Reader)
>> +      if (std::error_code EC = Writer.addRecord(std::move(I)))
>>          errs() << Filename << ": " << I.Name << ": " << EC.message() <<
>> "\n";
>>      if (Reader->hasError())
>>        exitWithError(Reader->getError().message(), Filename);
>> @@ -134,8 +133,8 @@ static int merge_main(int argc, const ch
>>  }
>>
>>  static int showInstrProfile(std::string Filename, bool ShowCounts,
>> -                            bool ShowAllFunctions, std::string
>> ShowFunction,
>> -                            raw_fd_ostream &OS) {
>> +                            bool ShowIndirectCallTargets, bool
>> ShowAllFunctions,
>> +                            std::string ShowFunction, raw_fd_ostream &OS)
>> {
>>    auto ReaderOrErr = InstrProfReader::create(Filename);
>>    if (std::error_code EC = ReaderOrErr.getError())
>>      exitWithError(EC.message(), Filename);
>> @@ -162,6 +161,9 @@ static int showInstrProfile(std::string
>>           << "    Hash: " << format("0x%016" PRIx64, Func.Hash) << "\n"
>>           << "    Counters: " << Func.Counts.size() << "\n"
>>           << "    Function count: " << Func.Counts[0] << "\n";
>> +      if (ShowIndirectCallTargets)
>> +        OS << "    Indirect Call Site Count: " <<
>> Func.IndirectCallSites.size()
>> +           << "\n";
>>      }
>>
>>      if (Show && ShowCounts)
>> @@ -174,6 +176,16 @@ static int showInstrProfile(std::string
>>      }
>>      if (Show && ShowCounts)
>>        OS << "]\n";
>> +
>> +    if (Show && ShowIndirectCallTargets) {
>> +      OS << "    Indirect Target Results: \n";
>> +      for (size_t I = 0, E = Func.IndirectCallSites.size(); I < E; ++I) {
>> +        for (auto V : Func.IndirectCallSites[I].ValueData) {
>> +          OS << "\t[ " << I << ", ";
>> +          OS << (const char *)V.first << ", " << V.second << " ]\n";
>> +        }
>> +      }
>> +    }
>>    }
>>    if (Reader->hasError())
>>      exitWithError(Reader->getError().message(), Filename);
>> @@ -212,6 +224,9 @@ static int show_main(int argc, const cha
>>
>>    cl::opt<bool> ShowCounts("counts", cl::init(false),
>>                             cl::desc("Show counter values for shown
>> functions"));
>> +  cl::opt<bool> ShowIndirectCallTargets(
>> +      "ic-targets", cl::init(false),
>> +      cl::desc("Show indirect call site target values for shown
>> functions"));
>>    cl::opt<bool> ShowAllFunctions("all-functions", cl::init(false),
>>                                   cl::desc("Details for every function"));
>>    cl::opt<std::string> ShowFunction("function",
>> @@ -240,8 +255,8 @@ static int show_main(int argc, const cha
>>      errs() << "warning: -function argument ignored: showing all
>> functions\n";
>>
>>    if (ProfileKind == instr)
>> -    return showInstrProfile(Filename, ShowCounts, ShowAllFunctions,
>> -                            ShowFunction, OS);
>> +    return showInstrProfile(Filename, ShowCounts, ShowIndirectCallTargets,
>> +                            ShowAllFunctions, ShowFunction, OS);
>>    else
>>      return showSampleProfile(Filename, ShowCounts, ShowAllFunctions,
>>                               ShowFunction, OS);
>>
>> Modified: llvm/trunk/unittests/ProfileData/CoverageMappingTest.cpp
>> URL:
>>
> http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ProfileData/CoverageMappingTest.cpp?rev=248833&r1=248832&r2=248833&view=diff
>>
>>
> ==============================================================================
>> --- llvm/trunk/unittests/ProfileData/CoverageMappingTest.cpp (original)
>> +++ llvm/trunk/unittests/ProfileData/CoverageMappingTest.cpp Tue Sep 29
>> 17:13:58 2015
>> @@ -188,7 +188,8 @@ TEST_F(CoverageMappingTest, expansion_ge
>>  }
>>
>>  TEST_F(CoverageMappingTest, basic_coverage_iteration) {
>> -  ProfileWriter.addFunctionCounts("func", 0x1234, {30, 20, 10, 0});
>> +  InstrProfRecord Record("func", 0x1234, {30, 20, 10, 0});
>> +  ProfileWriter.addRecord(std::move(Record));
>>    readProfCounts();
>>
>>    addCMR(Counter::getCounter(0), "file1", 1, 1, 9, 9);
>> @@ -238,7 +239,8 @@ TEST_F(CoverageMappingTest, uncovered_fu
>>  }
>>
>>  TEST_F(CoverageMappingTest, combine_regions) {
>> -  ProfileWriter.addFunctionCounts("func", 0x1234, {10, 20, 30});
>> +  InstrProfRecord Record("func", 0x1234, {10, 20, 30});
>> +  ProfileWriter.addRecord(std::move(Record));
>>    readProfCounts();
>>
>>    addCMR(Counter::getCounter(0), "file1", 1, 1, 9, 9);
>> @@ -256,7 +258,8 @@ TEST_F(CoverageMappingTest, combine_regi
>>  }
>>
>>  TEST_F(CoverageMappingTest, dont_combine_expansions) {
>> -  ProfileWriter.addFunctionCounts("func", 0x1234, {10, 20});
>> +  InstrProfRecord Record("func", 0x1234, {10, 20});
>> +  ProfileWriter.addRecord(std::move(Record));
>>    readProfCounts();
>>
>>    addCMR(Counter::getCounter(0), "file1", 1, 1, 9, 9);
>> @@ -275,7 +278,8 @@ TEST_F(CoverageMappingTest, dont_combine
>>  }
>>
>>  TEST_F(CoverageMappingTest, strip_filename_prefix) {
>> -  ProfileWriter.addFunctionCounts("file1:func", 0x1234, {10});
>> +  InstrProfRecord Record("file1:func", 0x1234, {10});
>> +  ProfileWriter.addRecord(std::move(Record));
>>    readProfCounts();
>>
>>    addCMR(Counter::getCounter(0), "file1", 1, 1, 9, 9);
>>
>> Modified: llvm/trunk/unittests/ProfileData/InstrProfTest.cpp
>> URL:
>>
> http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ProfileData/InstrProfTest.cpp?rev=248833&r1=248832&r2=248833&view=diff
>>
>>
> ==============================================================================
>> --- llvm/trunk/unittests/ProfileData/InstrProfTest.cpp (original)
>> +++ llvm/trunk/unittests/ProfileData/InstrProfTest.cpp Tue Sep 29 17:13:58
>> 2015
>> @@ -50,7 +50,8 @@ TEST_F(InstrProfTest, write_and_read_emp
>>  }
>>
>>  TEST_F(InstrProfTest, write_and_read_one_function) {
>> -  Writer.addFunctionCounts("foo", 0x1234, {1, 2, 3, 4});
>> +  InstrProfRecord Record("foo", 0x1234, {1, 2, 3, 4});
>> +  Writer.addRecord(std::move(Record));
>>    auto Profile = Writer.writeBuffer();
>>    readProfile(std::move(Profile));
>>
>> @@ -67,8 +68,10 @@ TEST_F(InstrProfTest, write_and_read_one
>>  }
>>
>>  TEST_F(InstrProfTest, get_function_counts) {
>> -  Writer.addFunctionCounts("foo", 0x1234, {1, 2});
>> -  Writer.addFunctionCounts("foo", 0x1235, {3, 4});
>> +  InstrProfRecord Record1("foo", 0x1234, {1, 2});
>> +  InstrProfRecord Record2("foo", 0x1235, {3, 4});
>> +  Writer.addRecord(std::move(Record1));
>> +  Writer.addRecord(std::move(Record2));
>>    auto Profile = Writer.writeBuffer();
>>    readProfile(std::move(Profile));
>>
>> @@ -92,9 +95,12 @@ TEST_F(InstrProfTest, get_function_count
>>  }
>>
>>  TEST_F(InstrProfTest, get_max_function_count) {
>> -  Writer.addFunctionCounts("foo", 0x1234, {1ULL << 31, 2});
>> -  Writer.addFunctionCounts("bar", 0, {1ULL << 63});
>> -  Writer.addFunctionCounts("baz", 0x5678, {0, 0, 0, 0});
>> +  InstrProfRecord Record1("foo", 0x1234, {1ULL << 31, 2});
>> +  InstrProfRecord Record2("bar", 0, {1ULL << 63});
>> +  InstrProfRecord Record3("baz", 0x5678, {0, 0, 0, 0});
>> +  Writer.addRecord(std::move(Record1));
>> +  Writer.addRecord(std::move(Record2));
>> +  Writer.addRecord(std::move(Record3));
>>    auto Profile = Writer.writeBuffer();
>>    readProfile(std::move(Profile));
>>
>>
>>
>> _______________________________________________
>> llvm-commits mailing list
>> llvm-commits at lists.llvm.org
>> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>>


More information about the llvm-commits mailing list