Index: llvm/trunk/include/llvm/ProfileData/InstrProf.h =================================================================== --- llvm/trunk/include/llvm/ProfileData/InstrProf.h +++ llvm/trunk/include/llvm/ProfileData/InstrProf.h @@ -284,15 +284,51 @@ return std::error_code(static_cast(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; -} +class SoftInstrProfErrors { + /// Count the number of soft instrprof_errors encountered and keep track of + /// the first such error for reporting purposes. + + /// The first soft error encountered. + instrprof_error FirstError; + + /// 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 { class SectionRef; @@ -465,19 +501,21 @@ /// Merge data from another InstrProfValueSiteRecord /// 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. - instrprof_error scale(uint64_t Weight); + void scale(SoftInstrProfErrors &SIPE, uint64_t Weight); }; /// Profiling information for a single function. struct InstrProfRecord { - InstrProfRecord() {} + InstrProfRecord() : SIPE() {} InstrProfRecord(StringRef Name, uint64_t Hash, std::vector Counts) - : Name(Name), Hash(Hash), Counts(std::move(Counts)) {} + : Name(Name), Hash(Hash), Counts(std::move(Counts)), SIPE() {} StringRef Name; uint64_t Hash; std::vector Counts; + SoftInstrProfErrors SIPE; typedef std::vector> ValueMapType; @@ -512,11 +550,11 @@ /// Merge the counts in \p Other into this one. /// 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 /// \p Weight. - instrprof_error scale(uint64_t Weight); + void scale(uint64_t Weight); /// Sort value profile data (per site) by count. void sortValueData() { @@ -533,6 +571,9 @@ getValueSitesForKind(Kind).clear(); } + /// Get the error contained within the record's soft error counter. + std::error_code getError() const { return SIPE.getError(); } + private: std::vector IndirectCallSites; const std::vector & @@ -559,10 +600,10 @@ // Merge Value Profile data from Src record to this record for ValueKind. // Scale merged value counts by \p Weight. - instrprof_error mergeValueProfData(uint32_t ValueKind, InstrProfRecord &Src, - uint64_t Weight); + void mergeValueProfData(uint32_t ValueKind, InstrProfRecord &Src, + uint64_t Weight); // 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 { Index: llvm/trunk/lib/ProfileData/InstrProf.cpp =================================================================== --- llvm/trunk/lib/ProfileData/InstrProf.cpp +++ llvm/trunk/lib/ProfileData/InstrProf.cpp @@ -80,6 +80,31 @@ 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, GlobalValue::LinkageTypes Linkage, StringRef FileName, @@ -291,13 +316,13 @@ return make_error_code(instrprof_error::success); } -instrprof_error InstrProfValueSiteRecord::merge(InstrProfValueSiteRecord &Input, - uint64_t Weight) { +void InstrProfValueSiteRecord::merge(SoftInstrProfErrors &SIPE, + InstrProfValueSiteRecord &Input, + uint64_t Weight) { 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) @@ -306,92 +331,80 @@ bool Overflowed; I->Count = SaturatingMultiplyAdd(J->Count, Weight, I->Count, &Overflowed); if (Overflowed) - Result = instrprof_error::counter_overflow; + SIPE.addError(instrprof_error::counter_overflow); ++I; continue; } ValueData.insert(I, *J); } - return Result; } -instrprof_error InstrProfValueSiteRecord::scale(uint64_t Weight) { - instrprof_error Result = instrprof_error::success; +void InstrProfValueSiteRecord::scale(SoftInstrProfErrors &SIPE, + uint64_t Weight) { for (auto I = ValueData.begin(), IE = ValueData.end(); I != IE; ++I) { bool Overflowed; I->Count = SaturatingMultiply(I->Count, Weight, &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. // Scale merged value counts by \p Weight. -instrprof_error InstrProfRecord::mergeValueProfData(uint32_t ValueKind, - InstrProfRecord &Src, - uint64_t Weight) { +void InstrProfRecord::mergeValueProfData(uint32_t ValueKind, + InstrProfRecord &Src, + uint64_t Weight) { uint32_t ThisNumValueSites = getNumValueSites(ValueKind); uint32_t OtherNumValueSites = Src.getNumValueSites(ValueKind); - if (ThisNumValueSites != OtherNumValueSites) - return instrprof_error::value_site_count_mismatch; + if (ThisNumValueSites != OtherNumValueSites) { + SIPE.addError(instrprof_error::value_site_count_mismatch); + return; + } std::vector &ThisSiteRecords = getValueSitesForKind(ValueKind); std::vector &OtherSiteRecords = Src.getValueSitesForKind(ValueKind); - instrprof_error Result = instrprof_error::success; for (uint32_t I = 0; I < ThisNumValueSites; I++) - MergeResult(Result, ThisSiteRecords[I].merge(OtherSiteRecords[I], Weight)); - return Result; + ThisSiteRecords[I].merge(SIPE, OtherSiteRecords[I], Weight); } -instrprof_error InstrProfRecord::merge(InstrProfRecord &Other, - uint64_t Weight) { +void InstrProfRecord::merge(InstrProfRecord &Other, uint64_t Weight) { // If the number of counters doesn't match we either have bad data // or a hash collision. - if (Counts.size() != Other.Counts.size()) - return instrprof_error::count_mismatch; - - instrprof_error Result = instrprof_error::success; + if (Counts.size() != Other.Counts.size()) { + SIPE.addError(instrprof_error::count_mismatch); + return; + } for (size_t I = 0, E = Other.Counts.size(); I < E; ++I) { bool Overflowed; Counts[I] = SaturatingMultiplyAdd(Other.Counts[I], Weight, Counts[I], &Overflowed); if (Overflowed) - Result = instrprof_error::counter_overflow; + SIPE.addError(instrprof_error::counter_overflow); } for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind) - MergeResult(Result, mergeValueProfData(Kind, Other, Weight)); - - return Result; + mergeValueProfData(Kind, Other, Weight); } -instrprof_error InstrProfRecord::scaleValueProfData(uint32_t ValueKind, - uint64_t Weight) { +void InstrProfRecord::scaleValueProfData(uint32_t ValueKind, uint64_t Weight) { uint32_t ThisNumValueSites = getNumValueSites(ValueKind); std::vector &ThisSiteRecords = getValueSitesForKind(ValueKind); - instrprof_error Result = instrprof_error::success; for (uint32_t I = 0; I < ThisNumValueSites; I++) - MergeResult(Result, ThisSiteRecords[I].scale(Weight)); - return Result; + ThisSiteRecords[I].scale(SIPE, Weight); } -instrprof_error InstrProfRecord::scale(uint64_t Weight) { - instrprof_error Result = instrprof_error::success; +void InstrProfRecord::scale(uint64_t Weight) { for (auto &Count : this->Counts) { bool Overflowed; Count = SaturatingMultiply(Count, Weight, &Overflowed); - if (Overflowed && Result == instrprof_error::success) { - Result = instrprof_error::counter_overflow; - } + if (Overflowed) + SIPE.addError(instrprof_error::counter_overflow); } for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind) - MergeResult(Result, scaleValueProfData(Kind, Weight)); - - return Result; + scaleValueProfData(Kind, Weight); } // Map indirect call target name hash to name string. Index: llvm/trunk/lib/ProfileData/InstrProfWriter.cpp =================================================================== --- llvm/trunk/lib/ProfileData/InstrProfWriter.cpp +++ llvm/trunk/lib/ProfileData/InstrProfWriter.cpp @@ -166,22 +166,21 @@ ProfileDataMap.insert(std::make_pair(I.Hash, InstrProfRecord())); InstrProfRecord &Dest = Where->second; - instrprof_error Result = instrprof_error::success; if (NewFunc) { // We've never seen a function with this name and hash, add it. Dest = std::move(I); // Fix up the name to avoid dangling reference. Dest.Name = FunctionData.find(Dest.Name)->getKey(); if (Weight > 1) - Result = Dest.scale(Weight); + Dest.scale(Weight); } else { // We're updating a function we've seen before. - Result = Dest.merge(I, Weight); + Dest.merge(I, Weight); } Dest.sortValueData(); - return Result; + return Dest.getError(); } bool InstrProfWriter::shouldEncodeData(const ProfilingData &PD) {