mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-24 20:29:53 +00:00
[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:
parent
5009e4f85f
commit
6d6b3df09a
@ -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 {
|
||||||
|
@ -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.
|
||||||
|
@ -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) {
|
||||||
|
Loading…
Reference in New Issue
Block a user