diff options
author | Nathan Slingerland <slingn@gmail.com> | 2015-12-16 21:45:43 +0000 |
---|---|---|
committer | Nathan Slingerland <slingn@gmail.com> | 2015-12-16 21:45:43 +0000 |
commit | fd56824d399633fdf67d9a2dd74200076638437e (patch) | |
tree | 5420cc8c2ed8e2fb5bce1a711ae4b54be69257fd /include | |
parent | 5af13d7042579ef4447b31c8e893df243321a050 (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.h | 37 | ||||
-rw-r--r-- | include/llvm/ProfileData/SampleProf.h | 97 |
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: |