X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=blobdiff_plain;f=include%2Fllvm%2FProfileData%2FSampleProf.h;h=6c39cf9458dcb4f39e86303cef6b03b40f5fc4be;hp=a8960cf7bc12032295c11da4a9574afde0f0f188;hb=21314fb7684a3055e440155016b95b91c7cae9bb;hpb=4918b66f8428f0d5b4559da8f966e3aa54c3b1ba diff --git a/include/llvm/ProfileData/SampleProf.h b/include/llvm/ProfileData/SampleProf.h index a8960cf7bc1..6c39cf9458d 100644 --- a/include/llvm/ProfileData/SampleProf.h +++ b/include/llvm/ProfileData/SampleProf.h @@ -15,12 +15,13 @@ #ifndef LLVM_PROFILEDATA_SAMPLEPROF_H_ #define LLVM_PROFILEDATA_SAMPLEPROF_H_ -#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorOr.h" #include "llvm/Support/raw_ostream.h" + +#include #include namespace llvm { @@ -37,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(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 { @@ -77,6 +89,10 @@ struct LineLocation { LineLocation(uint32_t L, uint32_t D) : LineOffset(L), Discriminator(D) {} void print(raw_ostream &OS) const; void dump() const; + bool operator<(const LineLocation &O) const { + return LineOffset < O.LineOffset || + (LineOffset == O.LineOffset && Discriminator < O.Discriminator); + } uint32_t LineOffset; uint32_t Discriminator; @@ -101,57 +117,6 @@ struct CallsiteLocation : public LineLocation { raw_ostream &operator<<(raw_ostream &OS, const CallsiteLocation &Loc); -} // End namespace sampleprof - -template <> struct DenseMapInfo { - typedef DenseMapInfo OffsetInfo; - typedef DenseMapInfo DiscriminatorInfo; - static inline sampleprof::LineLocation getEmptyKey() { - return sampleprof::LineLocation(OffsetInfo::getEmptyKey(), - DiscriminatorInfo::getEmptyKey()); - } - static inline sampleprof::LineLocation getTombstoneKey() { - return sampleprof::LineLocation(OffsetInfo::getTombstoneKey(), - DiscriminatorInfo::getTombstoneKey()); - } - static inline unsigned getHashValue(sampleprof::LineLocation Val) { - return DenseMapInfo>::getHashValue( - std::pair(Val.LineOffset, Val.Discriminator)); - } - static inline bool isEqual(sampleprof::LineLocation LHS, - sampleprof::LineLocation RHS) { - return LHS.LineOffset == RHS.LineOffset && - LHS.Discriminator == RHS.Discriminator; - } -}; - -template <> struct DenseMapInfo { - typedef DenseMapInfo OffsetInfo; - typedef DenseMapInfo DiscriminatorInfo; - typedef DenseMapInfo CalleeNameInfo; - static inline sampleprof::CallsiteLocation getEmptyKey() { - return sampleprof::CallsiteLocation(OffsetInfo::getEmptyKey(), - DiscriminatorInfo::getEmptyKey(), ""); - } - static inline sampleprof::CallsiteLocation getTombstoneKey() { - return sampleprof::CallsiteLocation(OffsetInfo::getTombstoneKey(), - DiscriminatorInfo::getTombstoneKey(), - ""); - } - static inline unsigned getHashValue(sampleprof::CallsiteLocation Val) { - return DenseMapInfo>::getHashValue( - std::pair(Val.LineOffset, Val.Discriminator)); - } - static inline bool isEqual(sampleprof::CallsiteLocation LHS, - sampleprof::CallsiteLocation RHS) { - return LHS.LineOffset == RHS.LineOffset && - LHS.Discriminator == RHS.Discriminator && - LHS.CalleeName.equals(RHS.CalleeName); - } -}; - -namespace sampleprof { - /// Representation of a single sample record. /// /// A sample record is represented by a positive integer value, which @@ -169,20 +134,30 @@ public: SampleRecord() : NumSamples(0), CallTargets() {} /// Increment the number of samples for this record by \p S. + /// Optionally scale sample count \p S by \p Weight. /// /// Sample counts accumulate using saturating arithmetic, to avoid wrapping /// around unsigned integers. - void addSamples(uint64_t S) { - NumSamples = SaturatingAdd(NumSamples, S); + sampleprof_error addSamples(uint64_t S, uint64_t Weight = 1) { + bool Overflowed; + NumSamples = SaturatingMultiplyAdd(S, Weight, NumSamples, &Overflowed); + return Overflowed ? sampleprof_error::counter_overflow + : sampleprof_error::success; } /// Add called function \p F with samples \p S. + /// Optionally scale sample count \p S by \p Weight. /// /// Sample counts accumulate using saturating arithmetic, to avoid wrapping /// around unsigned integers. - void addCalledTarget(StringRef F, uint64_t S) { + sampleprof_error addCalledTarget(StringRef F, uint64_t S, + uint64_t Weight = 1) { uint64_t &TargetSamples = CallTargets[F]; - TargetSamples = SaturatingAdd(TargetSamples, S); + bool Overflowed; + TargetSamples = + SaturatingMultiplyAdd(S, Weight, TargetSamples, &Overflowed); + return Overflowed ? sampleprof_error::counter_overflow + : sampleprof_error::success; } /// Return true if this sample record contains function calls. @@ -192,10 +167,13 @@ public: const CallTargetMap &getCallTargets() const { return CallTargets; } /// Merge the samples in \p Other into this record. - void merge(const SampleRecord &Other) { - addSamples(Other.getSamples()); - for (const auto &I : Other.getCallTargets()) - addCalledTarget(I.first(), I.second); + /// Optionally scale sample counts by \p 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; @@ -208,9 +186,9 @@ private: raw_ostream &operator<<(raw_ostream &OS, const SampleRecord &Sample); -typedef DenseMap BodySampleMap; +typedef std::map BodySampleMap; class FunctionSamples; -typedef DenseMap CallsiteSampleMap; +typedef std::map CallsiteSampleMap; /// Representation of the samples collected for a function. /// @@ -222,16 +200,31 @@ public: FunctionSamples() : TotalSamples(0), TotalHeadSamples(0) {} void print(raw_ostream &OS = dbgs(), unsigned Indent = 0) const; void dump() const; - void addTotalSamples(uint64_t Num) { TotalSamples += Num; } - void addHeadSamples(uint64_t Num) { TotalHeadSamples += Num; } - void addBodySamples(uint32_t LineOffset, uint32_t Discriminator, - uint64_t Num) { - BodySamples[LineLocation(LineOffset, Discriminator)].addSamples(Num); + sampleprof_error addTotalSamples(uint64_t Num, uint64_t Weight = 1) { + bool Overflowed; + TotalSamples = + SaturatingMultiplyAdd(Num, Weight, TotalSamples, &Overflowed); + return Overflowed ? sampleprof_error::counter_overflow + : sampleprof_error::success; + } + sampleprof_error addHeadSamples(uint64_t Num, uint64_t Weight = 1) { + bool Overflowed; + TotalHeadSamples = + SaturatingMultiplyAdd(Num, Weight, TotalHeadSamples, &Overflowed); + return Overflowed ? sampleprof_error::counter_overflow + : sampleprof_error::success; + } + 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) { - BodySamples[LineLocation(LineOffset, Discriminator)].addCalledTarget(FName, - Num); + 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); } /// Return the number of samples collected at the given location. @@ -280,19 +273,22 @@ public: } /// Merge the samples in \p Other into this one. - void merge(const FunctionSamples &Other) { - addTotalSamples(Other.getTotalSamples()); - addHeadSamples(Other.getHeadSamples()); + /// Optionally scale samples by \p 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); + 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); + MergeResult(Result, functionSamplesAt(Loc).merge(Rec, Weight)); } + return Result; } private: @@ -335,6 +331,29 @@ private: raw_ostream &operator<<(raw_ostream &OS, const FunctionSamples &FS); +/// Sort a LocationT->SampleT map by LocationT. +/// +/// It produces a sorted list of records by ascending +/// order of LocationT. +template class SampleSorter { +public: + typedef std::pair SamplesWithLoc; + typedef SmallVector SamplesWithLocList; + + SampleSorter(const std::map &Samples) { + for (const auto &I : Samples) + V.push_back(&I); + std::stable_sort(V.begin(), V.end(), + [](const SamplesWithLoc *A, const SamplesWithLoc *B) { + return A->first < B->first; + }); + } + const SamplesWithLocList &get() const { return V; } + +private: + SamplesWithLocList V; +}; + } // end namespace sampleprof } // end namespace llvm