[llvm-profdata] Add merge() to InstrProfRecord

Summary:
This change refactors two aspects of InstrProfRecord:

1) Add a merge() method to InstrProfRecord (previously InstrProfWriter combineInstrProfRecords()) in order to better encapsulate this functionality and to make the InstrProfRecord and SampleRecord APIs more consistent.

2) Make InstrProfRecord mergeValueProfData() a private method since it is only ever called internally by merge().

Reviewers: dnovillo, bogner, davidxl

Subscribers: silvas, vsk, llvm-commits

Differential Revision: http://reviews.llvm.org/D14786

llvm-svn: 253695
This commit is contained in:
Nathan Slingerland 2015-11-20 19:12:43 +00:00
parent 19ff5602da
commit a731829788
2 changed files with 57 additions and 54 deletions

View File

@ -265,9 +265,9 @@ struct InstrProfRecord {
inline void addValueData(uint32_t ValueKind, uint32_t Site,
InstrProfValueData *VData, uint32_t N,
ValueMapType *HashKeys);
/// Merge Value Profile data from Src record to this record for ValueKind.
inline instrprof_error mergeValueProfData(uint32_t ValueKind,
InstrProfRecord &Src);
/// Merge the counts in \p Other into this one.
inline instrprof_error merge(InstrProfRecord &Other);
/// Used by InstrProfWriter: update the value strings to commoned strings in
/// the writer instance.
@ -317,6 +317,21 @@ private:
}
return Value;
}
// Merge Value Profile data from Src record to this record for ValueKind.
instrprof_error mergeValueProfData(uint32_t ValueKind, InstrProfRecord &Src) {
uint32_t ThisNumValueSites = getNumValueSites(ValueKind);
uint32_t OtherNumValueSites = Src.getNumValueSites(ValueKind);
if (ThisNumValueSites != OtherNumValueSites)
return instrprof_error::value_site_count_mismatch;
std::vector<InstrProfValueSiteRecord> &ThisSiteRecords =
getValueSitesForKind(ValueKind);
std::vector<InstrProfValueSiteRecord> &OtherSiteRecords =
Src.getValueSitesForKind(ValueKind);
for (uint32_t I = 0; I < ThisNumValueSites; I++)
ThisSiteRecords[I].mergeValueData(OtherSiteRecords[I]);
return instrprof_error::success;
}
};
uint32_t InstrProfRecord::getNumValueKinds() const {
@ -382,21 +397,6 @@ void InstrProfRecord::reserveSites(uint32_t ValueKind, uint32_t NumValueSites) {
ValueSites.reserve(NumValueSites);
}
instrprof_error InstrProfRecord::mergeValueProfData(uint32_t ValueKind,
InstrProfRecord &Src) {
uint32_t ThisNumValueSites = getNumValueSites(ValueKind);
uint32_t OtherNumValueSites = Src.getNumValueSites(ValueKind);
if (ThisNumValueSites != OtherNumValueSites)
return instrprof_error::value_site_count_mismatch;
std::vector<InstrProfValueSiteRecord> &ThisSiteRecords =
getValueSitesForKind(ValueKind);
std::vector<InstrProfValueSiteRecord> &OtherSiteRecords =
Src.getValueSitesForKind(ValueKind);
for (uint32_t I = 0; I < ThisNumValueSites; I++)
ThisSiteRecords[I].mergeValueData(OtherSiteRecords[I]);
return instrprof_error::success;
}
void InstrProfRecord::updateStrings(InstrProfStringTable *StrTab) {
if (!StrTab)
return;
@ -407,6 +407,27 @@ void InstrProfRecord::updateStrings(InstrProfStringTable *StrTab) {
VData.Value = (uint64_t)StrTab->insertString((const char *)VData.Value);
}
instrprof_error InstrProfRecord::merge(InstrProfRecord &Other) {
// If the number of counters doesn't match we either have bad data
// or a hash collision.
if (Counts.size() != Other.Counts.size())
return instrprof_error::count_mismatch;
for (size_t I = 0, E = Other.Counts.size(); I < E; ++I) {
if (Counts[I] + Other.Counts[I] < Counts[I])
return instrprof_error::counter_overflow;
Counts[I] += Other.Counts[I];
}
for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind) {
instrprof_error result = mergeValueProfData(Kind, Other);
if (result != instrprof_error::success)
return result;
}
return instrprof_error::success;
}
inline support::endianness getHostEndianness() {
return sys::IsLittleEndianHost ? support::little : support::big;
}

View File

@ -87,32 +87,6 @@ public:
};
}
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;
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];
}
for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind) {
if (std::error_code EC = Dest.mergeValueProfData(Kind, Source))
return EC;
}
// We keep track of the max function count as we go for simplicity.
if (Dest.Counts[0] > MaxFunctionCount)
MaxFunctionCount = Dest.Counts[0];
return instrprof_error::success;
}
// Internal interface for testing purpose only.
void InstrProfWriter::setValueProfDataEndianness(
support::endianness Endianness) {
@ -127,19 +101,27 @@ std::error_code InstrProfWriter::addRecord(InstrProfRecord &&I) {
updateStringTableReferences(I);
auto &ProfileDataMap = FunctionData[I.Name];
auto Where = ProfileDataMap.find(I.Hash);
if (Where == ProfileDataMap.end()) {
bool NewFunc;
ProfilingData::iterator Where;
std::tie(Where, NewFunc) =
ProfileDataMap.insert(std::make_pair(I.Hash, InstrProfRecord()));
InstrProfRecord &Dest = Where->second;
if (NewFunc) {
// 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;
Dest = std::move(I);
} else {
// We're updating a function we've seen before.
instrprof_error MergeResult = Dest.merge(I);
if (MergeResult != instrprof_error::success) {
return MergeResult;
}
}
// We're updating a function we've seen before.
return combineInstrProfRecords(Where->second, I, MaxFunctionCount);
// We keep track of the max function count as we go for simplicity.
if (Dest.Counts[0] > MaxFunctionCount)
MaxFunctionCount = Dest.Counts[0];
return instrprof_error::success;
}
std::pair<uint64_t, uint64_t> InstrProfWriter::writeImpl(raw_ostream &OS) {