<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>