<div dir="ltr">This seems to have gone unused for a year so far - shall we remove it until there's an actual use case?<br><br>I came across this because the sizeof(InstrProfRecord) contributes significantly to the memory footprint of llvm-profdata merge (I've made one big improvement so far (14GB -> 10GB for an example large profile)). I have a change in mind/prototyped that helps that (10GB -> 5GB) by moving the counters into a sub-struct of InstrProfRecord and using only that sub-struct in the InstrProfWriter (since it has the name and hash in the maps its using for lookup during merging - so they don't need to be duplicated in the values too). But this SoftInstrProfErrors is used from the counter-related functions and is quite large, so naively it would have to move into this sub-struct & take up lots of space.<br><br>So at the very least I'd like to revisit the choice to make this a member, and instead go with the earlier version of this patch that wired it through function parameters instead - but given the lack of use, I think maybe it'd be better to remove this unused abstraction & go back to the simpler error handling that was present before.<br><br>- Dave<br><br><div class="gmail_quote"><div dir="ltr">On Wed, May 11, 2016 at 12:48 PM Vedant Kumar via llvm-commits <<a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: vedantk<br>
Date: Wed May 11 14:42:19 2016<br>
New Revision: 269222<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=269222&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=269222&view=rev</a><br>
Log:<br>
[ProfileData] Use SoftInstrProfErrors to count soft errors, NFC<br>
<br>
Differential Revision: <a href="http://reviews.llvm.org/D20082" rel="noreferrer" target="_blank">http://reviews.llvm.org/D20082</a><br>
<br>
Modified:<br>
llvm/trunk/include/llvm/ProfileData/InstrProf.h<br>
llvm/trunk/lib/ProfileData/InstrProf.cpp<br>
llvm/trunk/lib/ProfileData/InstrProfWriter.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=269222&r1=269221&r2=269222&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ProfileData/InstrProf.h?rev=269222&r1=269221&r2=269222&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/ProfileData/InstrProf.h (original)<br>
+++ llvm/trunk/include/llvm/ProfileData/InstrProf.h Wed May 11 14:42:19 2016<br>
@@ -284,15 +284,51 @@ inline std::error_code make_error_code(i<br>
return std::error_code(static_cast<int>(E), instrprof_category());<br>
}<br>
<br>
-inline instrprof_error MergeResult(instrprof_error &Accumulator,<br>
- instrprof_error Result) {<br>
- // Prefer first error encountered as later errors may be secondary effects of<br>
- // the initial problem.<br>
- if (Accumulator == instrprof_error::success &&<br>
- Result != instrprof_error::success)<br>
- Accumulator = Result;<br>
- return Accumulator;<br>
-}<br>
+class SoftInstrProfErrors {<br>
+ /// Count the number of soft instrprof_errors encountered and keep track of<br>
+ /// the first such error for reporting purposes.<br>
+<br>
+ /// The first soft error encountered.<br>
+ instrprof_error FirstError;<br>
+<br>
+ /// The number of hash mismatches.<br>
+ unsigned NumHashMismatches;<br>
+<br>
+ /// The number of count mismatches.<br>
+ unsigned NumCountMismatches;<br>
+<br>
+ /// The number of counter overflows.<br>
+ unsigned NumCounterOverflows;<br>
+<br>
+ /// The number of value site count mismatches.<br>
+ unsigned NumValueSiteCountMismatches;<br>
+<br>
+public:<br>
+ SoftInstrProfErrors()<br>
+ : FirstError(instrprof_error::success), NumHashMismatches(0),<br>
+ NumCountMismatches(0), NumCounterOverflows(0),<br>
+ NumValueSiteCountMismatches(0) {}<br>
+<br>
+ /// Track a soft error (\p IE) and increment its associated counter.<br>
+ void addError(instrprof_error IE);<br>
+<br>
+ /// Get the number of hash mismatches.<br>
+ unsigned getNumHashMismatches() const { return NumHashMismatches; }<br>
+<br>
+ /// Get the number of count mismatches.<br>
+ unsigned getNumCountMismatches() const { return NumCountMismatches; }<br>
+<br>
+ /// Get the number of counter overflows.<br>
+ unsigned getNumCounterOverflows() const { return NumCounterOverflows; }<br>
+<br>
+ /// Get the number of value site count mismatches.<br>
+ unsigned getNumValueSiteCountMismatches() const {<br>
+ return NumValueSiteCountMismatches;<br>
+ }<br>
+<br>
+ /// Return an error code for the first encountered error.<br>
+ std::error_code getError() const { return make_error_code(FirstError); }<br>
+};<br>
<br>
namespace object {<br>
class SectionRef;<br>
@@ -465,19 +501,21 @@ struct InstrProfValueSiteRecord {<br>
<br>
/// Merge data from another InstrProfValueSiteRecord<br>
/// Optionally scale merged counts by \p Weight.<br>
- instrprof_error merge(InstrProfValueSiteRecord &Input, uint64_t Weight = 1);<br>
+ void merge(SoftInstrProfErrors &SIPE, InstrProfValueSiteRecord &Input,<br>
+ uint64_t Weight = 1);<br>
/// Scale up value profile data counts.<br>
- instrprof_error scale(uint64_t Weight);<br>
+ void scale(SoftInstrProfErrors &SIPE, uint64_t Weight);<br>
};<br>
<br>
/// Profiling information for a single function.<br>
struct InstrProfRecord {<br>
- InstrProfRecord() {}<br>
+ InstrProfRecord() : SIPE() {}<br>
InstrProfRecord(StringRef Name, uint64_t Hash, std::vector<uint64_t> Counts)<br>
- : Name(Name), Hash(Hash), Counts(std::move(Counts)) {}<br>
+ : Name(Name), Hash(Hash), Counts(std::move(Counts)), SIPE() {}<br>
StringRef Name;<br>
uint64_t Hash;<br>
std::vector<uint64_t> Counts;<br>
+ SoftInstrProfErrors SIPE;<br>
<br>
typedef std::vector<std::pair<uint64_t, uint64_t>> ValueMapType;<br>
<br>
@@ -512,11 +550,11 @@ struct InstrProfRecord {<br>
<br>
/// Merge the counts in \p Other into this one.<br>
/// Optionally scale merged counts by \p Weight.<br>
- instrprof_error merge(InstrProfRecord &Other, uint64_t Weight = 1);<br>
+ void merge(InstrProfRecord &Other, uint64_t Weight = 1);<br>
<br>
/// Scale up profile counts (including value profile data) by<br>
/// \p Weight.<br>
- instrprof_error scale(uint64_t Weight);<br>
+ void scale(uint64_t Weight);<br>
<br>
/// Sort value profile data (per site) by count.<br>
void sortValueData() {<br>
@@ -533,6 +571,9 @@ struct InstrProfRecord {<br>
getValueSitesForKind(Kind).clear();<br>
}<br>
<br>
+ /// Get the error contained within the record's soft error counter.<br>
+ std::error_code getError() const { return SIPE.getError(); }<br>
+<br>
private:<br>
std::vector<InstrProfValueSiteRecord> IndirectCallSites;<br>
const std::vector<InstrProfValueSiteRecord> &<br>
@@ -559,10 +600,10 @@ private:<br>
<br>
// Merge Value Profile data from Src record to this record for ValueKind.<br>
// Scale merged value counts by \p Weight.<br>
- instrprof_error mergeValueProfData(uint32_t ValueKind, InstrProfRecord &Src,<br>
- uint64_t Weight);<br>
+ void mergeValueProfData(uint32_t ValueKind, InstrProfRecord &Src,<br>
+ uint64_t Weight);<br>
// Scale up value profile data count.<br>
- instrprof_error scaleValueProfData(uint32_t ValueKind, uint64_t Weight);<br>
+ void scaleValueProfData(uint32_t ValueKind, uint64_t Weight);<br>
};<br>
<br>
uint32_t InstrProfRecord::getNumValueKinds() const {<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=269222&r1=269221&r2=269222&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ProfileData/InstrProf.cpp?rev=269222&r1=269221&r2=269222&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/ProfileData/InstrProf.cpp (original)<br>
+++ llvm/trunk/lib/ProfileData/InstrProf.cpp Wed May 11 14:42:19 2016<br>
@@ -80,6 +80,31 @@ const std::error_category &llvm::instrpr<br>
<br>
namespace llvm {<br>
<br>
+void SoftInstrProfErrors::addError(instrprof_error IE) {<br>
+ if (IE == instrprof_error::success)<br>
+ return;<br>
+<br>
+ if (FirstError == instrprof_error::success)<br>
+ FirstError = IE;<br>
+<br>
+ switch (IE) {<br>
+ case instrprof_error::hash_mismatch:<br>
+ ++NumHashMismatches;<br>
+ break;<br>
+ case instrprof_error::count_mismatch:<br>
+ ++NumCountMismatches;<br>
+ break;<br>
+ case instrprof_error::counter_overflow:<br>
+ ++NumCounterOverflows;<br>
+ break;<br>
+ case instrprof_error::value_site_count_mismatch:<br>
+ ++NumValueSiteCountMismatches;<br>
+ break;<br>
+ default:<br>
+ llvm_unreachable("Not a soft error");<br>
+ }<br>
+}<br>
+<br>
std::string getPGOFuncName(StringRef RawFuncName,<br>
GlobalValue::LinkageTypes Linkage,<br>
StringRef FileName,<br>
@@ -291,13 +316,13 @@ std::error_code readPGOFuncNameStrings(S<br>
return make_error_code(instrprof_error::success);<br>
}<br>
<br>
-instrprof_error InstrProfValueSiteRecord::merge(InstrProfValueSiteRecord &Input,<br>
- uint64_t Weight) {<br>
+void InstrProfValueSiteRecord::merge(SoftInstrProfErrors &SIPE,<br>
+ InstrProfValueSiteRecord &Input,<br>
+ uint64_t Weight) {<br>
this->sortByTargetValues();<br>
Input.sortByTargetValues();<br>
auto I = ValueData.begin();<br>
auto IE = ValueData.end();<br>
- instrprof_error Result = instrprof_error::success;<br>
for (auto J = Input.ValueData.begin(), JE = Input.ValueData.end(); J != JE;<br>
++J) {<br>
while (I != IE && I->Value < J->Value)<br>
@@ -306,92 +331,80 @@ instrprof_error InstrProfValueSiteRecord<br>
bool Overflowed;<br>
I->Count = SaturatingMultiplyAdd(J->Count, Weight, I->Count, &Overflowed);<br>
if (Overflowed)<br>
- Result = instrprof_error::counter_overflow;<br>
+ SIPE.addError(instrprof_error::counter_overflow);<br>
++I;<br>
continue;<br>
}<br>
ValueData.insert(I, *J);<br>
}<br>
- return Result;<br>
}<br>
<br>
-instrprof_error InstrProfValueSiteRecord::scale(uint64_t Weight) {<br>
- instrprof_error Result = instrprof_error::success;<br>
+void InstrProfValueSiteRecord::scale(SoftInstrProfErrors &SIPE,<br>
+ uint64_t Weight) {<br>
for (auto I = ValueData.begin(), IE = ValueData.end(); I != IE; ++I) {<br>
bool Overflowed;<br>
I->Count = SaturatingMultiply(I->Count, Weight, &Overflowed);<br>
if (Overflowed)<br>
- Result = instrprof_error::counter_overflow;<br>
+ SIPE.addError(instrprof_error::counter_overflow);<br>
}<br>
- return Result;<br>
}<br>
<br>
// Merge Value Profile data from Src record to this record for ValueKind.<br>
// Scale merged value counts by \p Weight.<br>
-instrprof_error InstrProfRecord::mergeValueProfData(uint32_t ValueKind,<br>
- InstrProfRecord &Src,<br>
- uint64_t Weight) {<br>
+void InstrProfRecord::mergeValueProfData(uint32_t ValueKind,<br>
+ InstrProfRecord &Src,<br>
+ uint64_t Weight) {<br>
uint32_t ThisNumValueSites = getNumValueSites(ValueKind);<br>
uint32_t OtherNumValueSites = Src.getNumValueSites(ValueKind);<br>
- if (ThisNumValueSites != OtherNumValueSites)<br>
- return instrprof_error::value_site_count_mismatch;<br>
+ if (ThisNumValueSites != OtherNumValueSites) {<br>
+ SIPE.addError(instrprof_error::value_site_count_mismatch);<br>
+ return;<br>
+ }<br>
std::vector<InstrProfValueSiteRecord> &ThisSiteRecords =<br>
getValueSitesForKind(ValueKind);<br>
std::vector<InstrProfValueSiteRecord> &OtherSiteRecords =<br>
Src.getValueSitesForKind(ValueKind);<br>
- instrprof_error Result = instrprof_error::success;<br>
for (uint32_t I = 0; I < ThisNumValueSites; I++)<br>
- MergeResult(Result, ThisSiteRecords[I].merge(OtherSiteRecords[I], Weight));<br>
- return Result;<br>
+ ThisSiteRecords[I].merge(SIPE, OtherSiteRecords[I], Weight);<br>
}<br>
<br>
-instrprof_error InstrProfRecord::merge(InstrProfRecord &Other,<br>
- uint64_t Weight) {<br>
+void InstrProfRecord::merge(InstrProfRecord &Other, uint64_t Weight) {<br>
// If the number of counters doesn't match we either have bad data<br>
// or a hash collision.<br>
- if (Counts.size() != Other.Counts.size())<br>
- return instrprof_error::count_mismatch;<br>
-<br>
- instrprof_error Result = instrprof_error::success;<br>
+ if (Counts.size() != Other.Counts.size()) {<br>
+ SIPE.addError(instrprof_error::count_mismatch);<br>
+ return;<br>
+ }<br>
<br>
for (size_t I = 0, E = Other.Counts.size(); I < E; ++I) {<br>
bool Overflowed;<br>
Counts[I] =<br>
SaturatingMultiplyAdd(Other.Counts[I], Weight, Counts[I], &Overflowed);<br>
if (Overflowed)<br>
- Result = instrprof_error::counter_overflow;<br>
+ SIPE.addError(instrprof_error::counter_overflow);<br>
}<br>
<br>
for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind)<br>
- MergeResult(Result, mergeValueProfData(Kind, Other, Weight));<br>
-<br>
- return Result;<br>
+ mergeValueProfData(Kind, Other, Weight);<br>
}<br>
<br>
-instrprof_error InstrProfRecord::scaleValueProfData(uint32_t ValueKind,<br>
- uint64_t Weight) {<br>
+void InstrProfRecord::scaleValueProfData(uint32_t ValueKind, uint64_t Weight) {<br>
uint32_t ThisNumValueSites = getNumValueSites(ValueKind);<br>
std::vector<InstrProfValueSiteRecord> &ThisSiteRecords =<br>
getValueSitesForKind(ValueKind);<br>
- instrprof_error Result = instrprof_error::success;<br>
for (uint32_t I = 0; I < ThisNumValueSites; I++)<br>
- MergeResult(Result, ThisSiteRecords[I].scale(Weight));<br>
- return Result;<br>
+ ThisSiteRecords[I].scale(SIPE, Weight);<br>
}<br>
<br>
-instrprof_error InstrProfRecord::scale(uint64_t Weight) {<br>
- instrprof_error Result = instrprof_error::success;<br>
+void InstrProfRecord::scale(uint64_t Weight) {<br>
for (auto &Count : this->Counts) {<br>
bool Overflowed;<br>
Count = SaturatingMultiply(Count, Weight, &Overflowed);<br>
- if (Overflowed && Result == instrprof_error::success) {<br>
- Result = instrprof_error::counter_overflow;<br>
- }<br>
+ if (Overflowed)<br>
+ SIPE.addError(instrprof_error::counter_overflow);<br>
}<br>
for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind)<br>
- MergeResult(Result, scaleValueProfData(Kind, Weight));<br>
-<br>
- return Result;<br>
+ scaleValueProfData(Kind, Weight);<br>
}<br>
<br>
// Map indirect call target name hash to name string.<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=269222&r1=269221&r2=269222&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ProfileData/InstrProfWriter.cpp?rev=269222&r1=269221&r2=269222&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/ProfileData/InstrProfWriter.cpp (original)<br>
+++ llvm/trunk/lib/ProfileData/InstrProfWriter.cpp Wed May 11 14:42:19 2016<br>
@@ -166,22 +166,21 @@ std::error_code InstrProfWriter::addReco<br>
ProfileDataMap.insert(std::make_pair(I.Hash, InstrProfRecord()));<br>
InstrProfRecord &Dest = Where->second;<br>
<br>
- instrprof_error Result = instrprof_error::success;<br>
if (NewFunc) {<br>
// We've never seen a function with this name and hash, add it.<br>
Dest = std::move(I);<br>
// Fix up the name to avoid dangling reference.<br>
Dest.Name = FunctionData.find(Dest.Name)->getKey();<br>
if (Weight > 1)<br>
- Result = Dest.scale(Weight);<br>
+ Dest.scale(Weight);<br>
} else {<br>
// We're updating a function we've seen before.<br>
- Result = Dest.merge(I, Weight);<br>
+ Dest.merge(I, Weight);<br>
}<br>
<br>
Dest.sortValueData();<br>
<br>
- return Result;<br>
+ return Dest.getError();<br>
}<br>
<br>
bool InstrProfWriter::shouldEncodeData(const ProfilingData &PD) {<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">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></div>