summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorNathan Slingerland <slingn@gmail.com>2015-12-16 21:45:43 +0000
committerNathan Slingerland <slingn@gmail.com>2015-12-16 21:45:43 +0000
commitfd56824d399633fdf67d9a2dd74200076638437e (patch)
tree5420cc8c2ed8e2fb5bce1a711ae4b54be69257fd /include
parent5af13d7042579ef4447b31c8e893df243321a050 (diff)
[PGO] Handle and report overflow during profile merge for all types of data
Summary: Surface counter overflow when merging profile data. Merging still occurs on overflow but counts saturate to the maximum representable value. Overflow is reported to the user. Reviewers: davidxl, dnovillo, silvas Subscribers: llvm-commits Differential Revision: http://reviews.llvm.org/D15547 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@255825 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'include')
-rw-r--r--include/llvm/ProfileData/InstrProf.h37
-rw-r--r--include/llvm/ProfileData/SampleProf.h97
2 files changed, 88 insertions, 46 deletions
diff --git a/include/llvm/ProfileData/InstrProf.h b/include/llvm/ProfileData/InstrProf.h
index a1d5ed97e0b..dca36a4b63b 100644
--- a/include/llvm/ProfileData/InstrProf.h
+++ b/include/llvm/ProfileData/InstrProf.h
@@ -184,6 +184,16 @@ inline std::error_code make_error_code(instrprof_error E) {
return std::error_code(static_cast<int>(E), instrprof_category());
}
+inline instrprof_error MergeResult(instrprof_error &Accumulator,
+ instrprof_error Result) {
+ // Prefer first error encountered as later errors may be secondary effects of
+ // the initial problem.
+ if (Accumulator == instrprof_error::success &&
+ Result != instrprof_error::success)
+ Accumulator = Result;
+ return Accumulator;
+}
+
enum InstrProfValueKind : uint32_t {
#define VALUE_PROF_KIND(Enumerator, Value) Enumerator = Value,
#include "llvm/ProfileData/InstrProfData.inc"
@@ -224,30 +234,34 @@ struct InstrProfValueSiteRecord {
/// Merge data from another InstrProfValueSiteRecord
/// Optionally scale merged counts by \p Weight.
- void mergeValueData(InstrProfValueSiteRecord &Input, uint64_t Weight = 1) {
+ instrprof_error mergeValueData(InstrProfValueSiteRecord &Input,
+ uint64_t Weight = 1) {
this->sortByTargetValues();
Input.sortByTargetValues();
auto I = ValueData.begin();
auto IE = ValueData.end();
+ instrprof_error Result = instrprof_error::success;
for (auto J = Input.ValueData.begin(), JE = Input.ValueData.end(); J != JE;
++J) {
while (I != IE && I->Value < J->Value)
++I;
if (I != IE && I->Value == J->Value) {
- // FIXME: Improve handling of counter overflow.
uint64_t JCount = J->Count;
bool Overflowed;
if (Weight > 1) {
JCount = SaturatingMultiply(JCount, Weight, &Overflowed);
- assert(!Overflowed && "Value data counter overflowed!");
+ if (Overflowed)
+ Result = instrprof_error::counter_overflow;
}
I->Count = SaturatingAdd(I->Count, JCount, &Overflowed);
- assert(!Overflowed && "Value data counter overflowed!");
+ if (Overflowed)
+ Result = instrprof_error::counter_overflow;
++I;
continue;
}
ValueData.insert(I, *J);
}
+ return Result;
}
};
@@ -352,9 +366,11 @@ private:
getValueSitesForKind(ValueKind);
std::vector<InstrProfValueSiteRecord> &OtherSiteRecords =
Src.getValueSitesForKind(ValueKind);
+ instrprof_error Result = instrprof_error::success;
for (uint32_t I = 0; I < ThisNumValueSites; I++)
- ThisSiteRecords[I].mergeValueData(OtherSiteRecords[I], Weight);
- return instrprof_error::success;
+ MergeResult(Result, ThisSiteRecords[I].mergeValueData(OtherSiteRecords[I],
+ Weight));
+ return Result;
}
};
@@ -461,11 +477,8 @@ instrprof_error InstrProfRecord::merge(InstrProfRecord &Other,
Result = instrprof_error::counter_overflow;
}
- for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind) {
- instrprof_error MergeValueResult = mergeValueProfData(Kind, Other, Weight);
- if (MergeValueResult != instrprof_error::success)
- Result = MergeValueResult;
- }
+ for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind)
+ MergeResult(Result, mergeValueProfData(Kind, Other, Weight));
return Result;
}
@@ -480,7 +493,7 @@ inline support::endianness getHostEndianness() {
#include "llvm/ProfileData/InstrProfData.inc"
/*
- * Initialize the record for runtime value profile data.
+ * Initialize the record for runtime value profile data.
* Return 0 if the initialization is successful, otherwise
* return 1.
*/
diff --git a/include/llvm/ProfileData/SampleProf.h b/include/llvm/ProfileData/SampleProf.h
index 7607e24ec1c..8df3fe80320 100644
--- a/include/llvm/ProfileData/SampleProf.h
+++ b/include/llvm/ProfileData/SampleProf.h
@@ -38,13 +38,24 @@ enum class sampleprof_error {
unrecognized_format,
unsupported_writing_format,
truncated_name_table,
- not_implemented
+ not_implemented,
+ counter_overflow
};
inline std::error_code make_error_code(sampleprof_error E) {
return std::error_code(static_cast<int>(E), sampleprof_category());
}
+inline sampleprof_error MergeResult(sampleprof_error &Accumulator,
+ sampleprof_error Result) {
+ // Prefer first error encountered as later errors may be secondary effects of
+ // the initial problem.
+ if (Accumulator == sampleprof_error::success &&
+ Result != sampleprof_error::success)
+ Accumulator = Result;
+ return Accumulator;
+}
+
} // end namespace llvm
namespace std {
@@ -127,15 +138,18 @@ public:
///
/// Sample counts accumulate using saturating arithmetic, to avoid wrapping
/// around unsigned integers.
- void addSamples(uint64_t S, uint64_t Weight = 1) {
- // FIXME: Improve handling of counter overflow.
+ sampleprof_error addSamples(uint64_t S, uint64_t Weight = 1) {
bool Overflowed;
if (Weight > 1) {
S = SaturatingMultiply(S, Weight, &Overflowed);
- assert(!Overflowed && "Sample counter overflowed!");
+ if (Overflowed)
+ return sampleprof_error::counter_overflow;
}
NumSamples = SaturatingAdd(NumSamples, S, &Overflowed);
- assert(!Overflowed && "Sample counter overflowed!");
+ if (Overflowed)
+ return sampleprof_error::counter_overflow;
+
+ return sampleprof_error::success;
}
/// Add called function \p F with samples \p S.
@@ -143,16 +157,20 @@ public:
///
/// Sample counts accumulate using saturating arithmetic, to avoid wrapping
/// around unsigned integers.
- void addCalledTarget(StringRef F, uint64_t S, uint64_t Weight = 1) {
- // FIXME: Improve handling of counter overflow.
+ sampleprof_error addCalledTarget(StringRef F, uint64_t S,
+ uint64_t Weight = 1) {
uint64_t &TargetSamples = CallTargets[F];
bool Overflowed;
if (Weight > 1) {
S = SaturatingMultiply(S, Weight, &Overflowed);
- assert(!Overflowed && "Called target counter overflowed!");
+ if (Overflowed)
+ return sampleprof_error::counter_overflow;
}
TargetSamples = SaturatingAdd(TargetSamples, S, &Overflowed);
- assert(!Overflowed && "Called target counter overflowed!");
+ if (Overflowed)
+ return sampleprof_error::counter_overflow;
+
+ return sampleprof_error::success;
}
/// Return true if this sample record contains function calls.
@@ -163,10 +181,12 @@ public:
/// Merge the samples in \p Other into this record.
/// Optionally scale sample counts by \p Weight.
- void merge(const SampleRecord &Other, uint64_t Weight = 1) {
- addSamples(Other.getSamples(), Weight);
- for (const auto &I : Other.getCallTargets())
- addCalledTarget(I.first(), I.second, Weight);
+ sampleprof_error merge(const SampleRecord &Other, uint64_t Weight = 1) {
+ sampleprof_error Result = addSamples(Other.getSamples(), Weight);
+ for (const auto &I : Other.getCallTargets()) {
+ MergeResult(Result, addCalledTarget(I.first(), I.second, Weight));
+ }
+ return Result;
}
void print(raw_ostream &OS, unsigned Indent) const;
@@ -193,35 +213,42 @@ public:
FunctionSamples() : TotalSamples(0), TotalHeadSamples(0) {}
void print(raw_ostream &OS = dbgs(), unsigned Indent = 0) const;
void dump() const;
- void addTotalSamples(uint64_t Num, uint64_t Weight = 1) {
- // FIXME: Improve handling of counter overflow.
+ sampleprof_error addTotalSamples(uint64_t Num, uint64_t Weight = 1) {
bool Overflowed;
if (Weight > 1) {
Num = SaturatingMultiply(Num, Weight, &Overflowed);
- assert(!Overflowed && "Total samples counter overflowed!");
+ if (Overflowed)
+ return sampleprof_error::counter_overflow;
}
TotalSamples = SaturatingAdd(TotalSamples, Num, &Overflowed);
- assert(!Overflowed && "Total samples counter overflowed!");
+ if (Overflowed)
+ return sampleprof_error::counter_overflow;
+
+ return sampleprof_error::success;
}
- void addHeadSamples(uint64_t Num, uint64_t Weight = 1) {
- // FIXME: Improve handling of counter overflow.
+ sampleprof_error addHeadSamples(uint64_t Num, uint64_t Weight = 1) {
bool Overflowed;
if (Weight > 1) {
Num = SaturatingMultiply(Num, Weight, &Overflowed);
- assert(!Overflowed && "Total head samples counter overflowed!");
+ if (Overflowed)
+ return sampleprof_error::counter_overflow;
}
TotalHeadSamples = SaturatingAdd(TotalHeadSamples, Num, &Overflowed);
- assert(!Overflowed && "Total head samples counter overflowed!");
+ if (Overflowed)
+ return sampleprof_error::counter_overflow;
+
+ return sampleprof_error::success;
}
- void addBodySamples(uint32_t LineOffset, uint32_t Discriminator, uint64_t Num,
- uint64_t Weight = 1) {
- BodySamples[LineLocation(LineOffset, Discriminator)].addSamples(Num,
- Weight);
+ sampleprof_error addBodySamples(uint32_t LineOffset, uint32_t Discriminator,
+ uint64_t Num, uint64_t Weight = 1) {
+ return BodySamples[LineLocation(LineOffset, Discriminator)].addSamples(
+ Num, Weight);
}
- void addCalledTargetSamples(uint32_t LineOffset, uint32_t Discriminator,
- std::string FName, uint64_t Num,
- uint64_t Weight = 1) {
- BodySamples[LineLocation(LineOffset, Discriminator)].addCalledTarget(
+ sampleprof_error addCalledTargetSamples(uint32_t LineOffset,
+ uint32_t Discriminator,
+ std::string FName, uint64_t Num,
+ uint64_t Weight = 1) {
+ return BodySamples[LineLocation(LineOffset, Discriminator)].addCalledTarget(
FName, Num, Weight);
}
@@ -272,19 +299,21 @@ public:
/// Merge the samples in \p Other into this one.
/// Optionally scale samples by \p Weight.
- void merge(const FunctionSamples &Other, uint64_t Weight = 1) {
- addTotalSamples(Other.getTotalSamples(), Weight);
- addHeadSamples(Other.getHeadSamples(), Weight);
+ sampleprof_error merge(const FunctionSamples &Other, uint64_t Weight = 1) {
+ sampleprof_error Result = sampleprof_error::success;
+ MergeResult(Result, addTotalSamples(Other.getTotalSamples(), Weight));
+ MergeResult(Result, addHeadSamples(Other.getHeadSamples(), Weight));
for (const auto &I : Other.getBodySamples()) {
const LineLocation &Loc = I.first;
const SampleRecord &Rec = I.second;
- BodySamples[Loc].merge(Rec, Weight);
+ MergeResult(Result, BodySamples[Loc].merge(Rec, Weight));
}
for (const auto &I : Other.getCallsiteSamples()) {
const CallsiteLocation &Loc = I.first;
const FunctionSamples &Rec = I.second;
- functionSamplesAt(Loc).merge(Rec, Weight);
+ MergeResult(Result, functionSamplesAt(Loc).merge(Rec, Weight));
}
+ return Result;
}
private: