Index: llvm/include/llvm/ProfileData/InstrProfReader.h =================================================================== --- llvm/include/llvm/ProfileData/InstrProfReader.h +++ llvm/include/llvm/ProfileData/InstrProfReader.h @@ -619,9 +619,14 @@ /// Read a single record. Error readNextRecord(NamedInstrProfRecord &Record) override; - /// Return the NamedInstrProfRecord associated with FuncName and FuncHash - Expected getInstrProfRecord(StringRef FuncName, - uint64_t FuncHash); + /// Return the NamedInstrProfRecord associated with FuncName and FuncHash. + /// When return a hash_mismatch error and MismatchedFuncSum is not nullptr, + /// the sum of all counters in the mismatched function will be set to + /// MismatchedFuncSum. If there are multiple instances of mismatched + /// functions, MismatchedFuncSum returns the maximum. + Expected + getInstrProfRecord(StringRef FuncName, uint64_t FuncHash, + uint64_t *MismatchedFuncSum = nullptr); /// Return the memprof record for the function identified by /// llvm::md5(Name). Index: llvm/lib/ProfileData/InstrProfReader.cpp =================================================================== --- llvm/lib/ProfileData/InstrProfReader.cpp +++ llvm/lib/ProfileData/InstrProfReader.cpp @@ -1026,19 +1026,35 @@ return *Symtab; } -Expected -IndexedInstrProfReader::getInstrProfRecord(StringRef FuncName, - uint64_t FuncHash) { +Expected IndexedInstrProfReader::getInstrProfRecord( + StringRef FuncName, uint64_t FuncHash, uint64_t *MismatchedFuncSum) { ArrayRef Data; + uint64_t FuncSum = 0; Error Err = Remapper->getRecords(FuncName, Data); if (Err) return std::move(Err); // Found it. Look for counters with the right hash. + auto getFuncSum = [](const std::vector &Counts) { + uint64_t ValueSum = 0; + for (unsigned I = 0, S = Counts.size(); I < S; I++) { + uint64_t CountValue = Counts[I]; + if (CountValue == (uint64_t)-1) + continue; + ValueSum += CountValue; + } + return ValueSum; + }; + for (const NamedInstrProfRecord &I : Data) { // Check for a match and fill the vector if there is one. if (I.Hash == FuncHash) return std::move(I); + if (MismatchedFuncSum == nullptr) + continue; + FuncSum = std::max(FuncSum, getFuncSum(I.Counts)); } + if (MismatchedFuncSum != nullptr) + *MismatchedFuncSum = FuncSum; return error(instrprof_error::hash_mismatch); } Index: llvm/lib/Transforms/Instrumentation/PGOInstrumentation.cpp =================================================================== --- llvm/lib/Transforms/Instrumentation/PGOInstrumentation.cpp +++ llvm/lib/Transforms/Instrumentation/PGOInstrumentation.cpp @@ -1216,8 +1216,9 @@ bool PGOUseFunc::readCounters(IndexedInstrProfReader *PGOReader, bool &AllZeros, bool &AllMinusOnes) { auto &Ctx = M->getContext(); - Expected Result = - PGOReader->getInstrProfRecord(FuncInfo.FuncName, FuncInfo.FunctionHash); + uint64_t MismatchedFuncSum = 0; + Expected Result = PGOReader->getInstrProfRecord( + FuncInfo.FuncName, FuncInfo.FunctionHash, &MismatchedFuncSum); if (Error E = Result.takeError()) { handleAllErrors(std::move(E), [&](const InstrProfError &IPE) { auto Err = IPE.get(); @@ -1245,9 +1246,11 @@ if (SkipWarning) return; - std::string Msg = IPE.message() + std::string(" ") + F.getName().str() + - std::string(" Hash = ") + - std::to_string(FuncInfo.FunctionHash); + std::string Msg = + IPE.message() + std::string(" ") + F.getName().str() + + std::string(" Hash = ") + std::to_string(FuncInfo.FunctionHash) + + std::string(" up to ") + std::to_string(MismatchedFuncSum) + + std::string(" count discarded"); Ctx.diagnose( DiagnosticInfoPGOProfile(M->getName().data(), Msg, DS_Warning)); Index: llvm/test/Transforms/PGOProfile/Inputs/diag.proftext =================================================================== --- llvm/test/Transforms/PGOProfile/Inputs/diag.proftext +++ llvm/test/Transforms/PGOProfile/Inputs/diag.proftext @@ -5,3 +5,9 @@ 1 1 +foo +12885999999 +2 +6000 +4000 + Index: llvm/test/Transforms/PGOProfile/diag_mismatch.ll =================================================================== --- llvm/test/Transforms/PGOProfile/diag_mismatch.ll +++ llvm/test/Transforms/PGOProfile/diag_mismatch.ll @@ -1,7 +1,7 @@ ; RUN: llvm-profdata merge %S/Inputs/diag.proftext -o %t.profdata ; RUN: opt < %s -passes=pgo-instr-use -pgo-test-profile-file=%t.profdata -S 2>&1 | FileCheck %s -; CHECK: warning: {{.+}}: function control flow change detected (hash mismatch) foo +; CHECK: warning: {{.+}}: function control flow change detected (hash mismatch) foo Hash = 742261418966908927 up to 10000 count discarded target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu"