[ProfileData] Use SoftInstrProfErrors to count soft errors, NFC

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

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@269222 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Vedant Kumar 2016-05-11 19:42:19 +00:00
parent 5009e4f85f
commit 6d6b3df09a
3 changed files with 115 additions and 62 deletions

View File

@ -284,15 +284,51 @@ inline std::error_code make_error_code(instrprof_error E) {
return std::error_code(static_cast<int>(E), instrprof_category()); return std::error_code(static_cast<int>(E), instrprof_category());
} }
inline instrprof_error MergeResult(instrprof_error &Accumulator, class SoftInstrProfErrors {
instrprof_error Result) { /// Count the number of soft instrprof_errors encountered and keep track of
// Prefer first error encountered as later errors may be secondary effects of /// the first such error for reporting purposes.
// the initial problem.
if (Accumulator == instrprof_error::success && /// The first soft error encountered.
Result != instrprof_error::success) instrprof_error FirstError;
Accumulator = Result;
return Accumulator; /// The number of hash mismatches.
} unsigned NumHashMismatches;
/// The number of count mismatches.
unsigned NumCountMismatches;
/// The number of counter overflows.
unsigned NumCounterOverflows;
/// The number of value site count mismatches.
unsigned NumValueSiteCountMismatches;
public:
SoftInstrProfErrors()
: FirstError(instrprof_error::success), NumHashMismatches(0),
NumCountMismatches(0), NumCounterOverflows(0),
NumValueSiteCountMismatches(0) {}
/// Track a soft error (\p IE) and increment its associated counter.
void addError(instrprof_error IE);
/// Get the number of hash mismatches.
unsigned getNumHashMismatches() const { return NumHashMismatches; }
/// Get the number of count mismatches.
unsigned getNumCountMismatches() const { return NumCountMismatches; }
/// Get the number of counter overflows.
unsigned getNumCounterOverflows() const { return NumCounterOverflows; }
/// Get the number of value site count mismatches.
unsigned getNumValueSiteCountMismatches() const {
return NumValueSiteCountMismatches;
}
/// Return an error code for the first encountered error.
std::error_code getError() const { return make_error_code(FirstError); }
};
namespace object { namespace object {
class SectionRef; class SectionRef;
@ -465,19 +501,21 @@ struct InstrProfValueSiteRecord {
/// Merge data from another InstrProfValueSiteRecord /// Merge data from another InstrProfValueSiteRecord
/// Optionally scale merged counts by \p Weight. /// Optionally scale merged counts by \p Weight.
instrprof_error merge(InstrProfValueSiteRecord &Input, uint64_t Weight = 1); void merge(SoftInstrProfErrors &SIPE, InstrProfValueSiteRecord &Input,
uint64_t Weight = 1);
/// Scale up value profile data counts. /// Scale up value profile data counts.
instrprof_error scale(uint64_t Weight); void scale(SoftInstrProfErrors &SIPE, uint64_t Weight);
}; };
/// Profiling information for a single function. /// Profiling information for a single function.
struct InstrProfRecord { struct InstrProfRecord {
InstrProfRecord() {} InstrProfRecord() : SIPE() {}
InstrProfRecord(StringRef Name, uint64_t Hash, std::vector<uint64_t> Counts) InstrProfRecord(StringRef Name, uint64_t Hash, std::vector<uint64_t> Counts)
: Name(Name), Hash(Hash), Counts(std::move(Counts)) {} : Name(Name), Hash(Hash), Counts(std::move(Counts)), SIPE() {}
StringRef Name; StringRef Name;
uint64_t Hash; uint64_t Hash;
std::vector<uint64_t> Counts; std::vector<uint64_t> Counts;
SoftInstrProfErrors SIPE;
typedef std::vector<std::pair<uint64_t, uint64_t>> ValueMapType; typedef std::vector<std::pair<uint64_t, uint64_t>> ValueMapType;
@ -512,11 +550,11 @@ struct InstrProfRecord {
/// Merge the counts in \p Other into this one. /// Merge the counts in \p Other into this one.
/// Optionally scale merged counts by \p Weight. /// Optionally scale merged counts by \p Weight.
instrprof_error merge(InstrProfRecord &Other, uint64_t Weight = 1); void merge(InstrProfRecord &Other, uint64_t Weight = 1);
/// Scale up profile counts (including value profile data) by /// Scale up profile counts (including value profile data) by
/// \p Weight. /// \p Weight.
instrprof_error scale(uint64_t Weight); void scale(uint64_t Weight);
/// Sort value profile data (per site) by count. /// Sort value profile data (per site) by count.
void sortValueData() { void sortValueData() {
@ -533,6 +571,9 @@ struct InstrProfRecord {
getValueSitesForKind(Kind).clear(); getValueSitesForKind(Kind).clear();
} }
/// Get the error contained within the record's soft error counter.
std::error_code getError() const { return SIPE.getError(); }
private: private:
std::vector<InstrProfValueSiteRecord> IndirectCallSites; std::vector<InstrProfValueSiteRecord> IndirectCallSites;
const std::vector<InstrProfValueSiteRecord> & const std::vector<InstrProfValueSiteRecord> &
@ -559,10 +600,10 @@ private:
// Merge Value Profile data from Src record to this record for ValueKind. // Merge Value Profile data from Src record to this record for ValueKind.
// Scale merged value counts by \p Weight. // Scale merged value counts by \p Weight.
instrprof_error mergeValueProfData(uint32_t ValueKind, InstrProfRecord &Src, void mergeValueProfData(uint32_t ValueKind, InstrProfRecord &Src,
uint64_t Weight); uint64_t Weight);
// Scale up value profile data count. // Scale up value profile data count.
instrprof_error scaleValueProfData(uint32_t ValueKind, uint64_t Weight); void scaleValueProfData(uint32_t ValueKind, uint64_t Weight);
}; };
uint32_t InstrProfRecord::getNumValueKinds() const { uint32_t InstrProfRecord::getNumValueKinds() const {

View File

@ -80,6 +80,31 @@ const std::error_category &llvm::instrprof_category() {
namespace llvm { namespace llvm {
void SoftInstrProfErrors::addError(instrprof_error IE) {
if (IE == instrprof_error::success)
return;
if (FirstError == instrprof_error::success)
FirstError = IE;
switch (IE) {
case instrprof_error::hash_mismatch:
++NumHashMismatches;
break;
case instrprof_error::count_mismatch:
++NumCountMismatches;
break;
case instrprof_error::counter_overflow:
++NumCounterOverflows;
break;
case instrprof_error::value_site_count_mismatch:
++NumValueSiteCountMismatches;
break;
default:
llvm_unreachable("Not a soft error");
}
}
std::string getPGOFuncName(StringRef RawFuncName, std::string getPGOFuncName(StringRef RawFuncName,
GlobalValue::LinkageTypes Linkage, GlobalValue::LinkageTypes Linkage,
StringRef FileName, StringRef FileName,
@ -291,13 +316,13 @@ std::error_code readPGOFuncNameStrings(StringRef NameStrings,
return make_error_code(instrprof_error::success); return make_error_code(instrprof_error::success);
} }
instrprof_error InstrProfValueSiteRecord::merge(InstrProfValueSiteRecord &Input, void InstrProfValueSiteRecord::merge(SoftInstrProfErrors &SIPE,
InstrProfValueSiteRecord &Input,
uint64_t Weight) { uint64_t Weight) {
this->sortByTargetValues(); this->sortByTargetValues();
Input.sortByTargetValues(); Input.sortByTargetValues();
auto I = ValueData.begin(); auto I = ValueData.begin();
auto IE = ValueData.end(); auto IE = ValueData.end();
instrprof_error Result = instrprof_error::success;
for (auto J = Input.ValueData.begin(), JE = Input.ValueData.end(); J != JE; for (auto J = Input.ValueData.begin(), JE = Input.ValueData.end(); J != JE;
++J) { ++J) {
while (I != IE && I->Value < J->Value) while (I != IE && I->Value < J->Value)
@ -306,92 +331,80 @@ instrprof_error InstrProfValueSiteRecord::merge(InstrProfValueSiteRecord &Input,
bool Overflowed; bool Overflowed;
I->Count = SaturatingMultiplyAdd(J->Count, Weight, I->Count, &Overflowed); I->Count = SaturatingMultiplyAdd(J->Count, Weight, I->Count, &Overflowed);
if (Overflowed) if (Overflowed)
Result = instrprof_error::counter_overflow; SIPE.addError(instrprof_error::counter_overflow);
++I; ++I;
continue; continue;
} }
ValueData.insert(I, *J); ValueData.insert(I, *J);
} }
return Result;
} }
instrprof_error InstrProfValueSiteRecord::scale(uint64_t Weight) { void InstrProfValueSiteRecord::scale(SoftInstrProfErrors &SIPE,
instrprof_error Result = instrprof_error::success; uint64_t Weight) {
for (auto I = ValueData.begin(), IE = ValueData.end(); I != IE; ++I) { for (auto I = ValueData.begin(), IE = ValueData.end(); I != IE; ++I) {
bool Overflowed; bool Overflowed;
I->Count = SaturatingMultiply(I->Count, Weight, &Overflowed); I->Count = SaturatingMultiply(I->Count, Weight, &Overflowed);
if (Overflowed) if (Overflowed)
Result = instrprof_error::counter_overflow; SIPE.addError(instrprof_error::counter_overflow);
} }
return Result;
} }
// Merge Value Profile data from Src record to this record for ValueKind. // Merge Value Profile data from Src record to this record for ValueKind.
// Scale merged value counts by \p Weight. // Scale merged value counts by \p Weight.
instrprof_error InstrProfRecord::mergeValueProfData(uint32_t ValueKind, void InstrProfRecord::mergeValueProfData(uint32_t ValueKind,
InstrProfRecord &Src, InstrProfRecord &Src,
uint64_t Weight) { uint64_t Weight) {
uint32_t ThisNumValueSites = getNumValueSites(ValueKind); uint32_t ThisNumValueSites = getNumValueSites(ValueKind);
uint32_t OtherNumValueSites = Src.getNumValueSites(ValueKind); uint32_t OtherNumValueSites = Src.getNumValueSites(ValueKind);
if (ThisNumValueSites != OtherNumValueSites) if (ThisNumValueSites != OtherNumValueSites) {
return instrprof_error::value_site_count_mismatch; SIPE.addError(instrprof_error::value_site_count_mismatch);
return;
}
std::vector<InstrProfValueSiteRecord> &ThisSiteRecords = std::vector<InstrProfValueSiteRecord> &ThisSiteRecords =
getValueSitesForKind(ValueKind); getValueSitesForKind(ValueKind);
std::vector<InstrProfValueSiteRecord> &OtherSiteRecords = std::vector<InstrProfValueSiteRecord> &OtherSiteRecords =
Src.getValueSitesForKind(ValueKind); Src.getValueSitesForKind(ValueKind);
instrprof_error Result = instrprof_error::success;
for (uint32_t I = 0; I < ThisNumValueSites; I++) for (uint32_t I = 0; I < ThisNumValueSites; I++)
MergeResult(Result, ThisSiteRecords[I].merge(OtherSiteRecords[I], Weight)); ThisSiteRecords[I].merge(SIPE, OtherSiteRecords[I], Weight);
return Result;
} }
instrprof_error InstrProfRecord::merge(InstrProfRecord &Other, void InstrProfRecord::merge(InstrProfRecord &Other, uint64_t Weight) {
uint64_t Weight) {
// If the number of counters doesn't match we either have bad data // If the number of counters doesn't match we either have bad data
// or a hash collision. // or a hash collision.
if (Counts.size() != Other.Counts.size()) if (Counts.size() != Other.Counts.size()) {
return instrprof_error::count_mismatch; SIPE.addError(instrprof_error::count_mismatch);
return;
instrprof_error Result = instrprof_error::success; }
for (size_t I = 0, E = Other.Counts.size(); I < E; ++I) { for (size_t I = 0, E = Other.Counts.size(); I < E; ++I) {
bool Overflowed; bool Overflowed;
Counts[I] = Counts[I] =
SaturatingMultiplyAdd(Other.Counts[I], Weight, Counts[I], &Overflowed); SaturatingMultiplyAdd(Other.Counts[I], Weight, Counts[I], &Overflowed);
if (Overflowed) if (Overflowed)
Result = instrprof_error::counter_overflow; SIPE.addError(instrprof_error::counter_overflow);
} }
for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind) for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind)
MergeResult(Result, mergeValueProfData(Kind, Other, Weight)); mergeValueProfData(Kind, Other, Weight);
return Result;
} }
instrprof_error InstrProfRecord::scaleValueProfData(uint32_t ValueKind, void InstrProfRecord::scaleValueProfData(uint32_t ValueKind, uint64_t Weight) {
uint64_t Weight) {
uint32_t ThisNumValueSites = getNumValueSites(ValueKind); uint32_t ThisNumValueSites = getNumValueSites(ValueKind);
std::vector<InstrProfValueSiteRecord> &ThisSiteRecords = std::vector<InstrProfValueSiteRecord> &ThisSiteRecords =
getValueSitesForKind(ValueKind); getValueSitesForKind(ValueKind);
instrprof_error Result = instrprof_error::success;
for (uint32_t I = 0; I < ThisNumValueSites; I++) for (uint32_t I = 0; I < ThisNumValueSites; I++)
MergeResult(Result, ThisSiteRecords[I].scale(Weight)); ThisSiteRecords[I].scale(SIPE, Weight);
return Result;
} }
instrprof_error InstrProfRecord::scale(uint64_t Weight) { void InstrProfRecord::scale(uint64_t Weight) {
instrprof_error Result = instrprof_error::success;
for (auto &Count : this->Counts) { for (auto &Count : this->Counts) {
bool Overflowed; bool Overflowed;
Count = SaturatingMultiply(Count, Weight, &Overflowed); Count = SaturatingMultiply(Count, Weight, &Overflowed);
if (Overflowed && Result == instrprof_error::success) { if (Overflowed)
Result = instrprof_error::counter_overflow; SIPE.addError(instrprof_error::counter_overflow);
}
} }
for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind) for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind)
MergeResult(Result, scaleValueProfData(Kind, Weight)); scaleValueProfData(Kind, Weight);
return Result;
} }
// Map indirect call target name hash to name string. // Map indirect call target name hash to name string.

View File

@ -166,22 +166,21 @@ std::error_code InstrProfWriter::addRecord(InstrProfRecord &&I,
ProfileDataMap.insert(std::make_pair(I.Hash, InstrProfRecord())); ProfileDataMap.insert(std::make_pair(I.Hash, InstrProfRecord()));
InstrProfRecord &Dest = Where->second; InstrProfRecord &Dest = Where->second;
instrprof_error Result = instrprof_error::success;
if (NewFunc) { if (NewFunc) {
// We've never seen a function with this name and hash, add it. // We've never seen a function with this name and hash, add it.
Dest = std::move(I); Dest = std::move(I);
// Fix up the name to avoid dangling reference. // Fix up the name to avoid dangling reference.
Dest.Name = FunctionData.find(Dest.Name)->getKey(); Dest.Name = FunctionData.find(Dest.Name)->getKey();
if (Weight > 1) if (Weight > 1)
Result = Dest.scale(Weight); Dest.scale(Weight);
} else { } else {
// We're updating a function we've seen before. // We're updating a function we've seen before.
Result = Dest.merge(I, Weight); Dest.merge(I, Weight);
} }
Dest.sortValueData(); Dest.sortValueData();
return Result; return Dest.getError();
} }
bool InstrProfWriter::shouldEncodeData(const ProfilingData &PD) { bool InstrProfWriter::shouldEncodeData(const ProfilingData &PD) {