diff --git a/llvm/include/llvm/Transforms/Utils/SampleProfileLoaderBaseImpl.h b/llvm/include/llvm/Transforms/Utils/SampleProfileLoaderBaseImpl.h --- a/llvm/include/llvm/Transforms/Utils/SampleProfileLoaderBaseImpl.h +++ b/llvm/include/llvm/Transforms/Utils/SampleProfileLoaderBaseImpl.h @@ -87,12 +87,6 @@ class PseudoProbeManager { DenseMap GUIDToProbeDescMap; - const PseudoProbeDescriptor *getDesc(const Function &F) const { - auto I = GUIDToProbeDescMap.find( - Function::getGUID(FunctionSamples::getCanonicalFnName(F))); - return I == GUIDToProbeDescMap.end() ? nullptr : &I->second; - } - public: PseudoProbeManager(const Module &M) { if (NamedMDNode *FuncInfo = @@ -108,6 +102,24 @@ } } + const PseudoProbeDescriptor *getDesc(uint64_t GUID) const { + auto I = GUIDToProbeDescMap.find(GUID); + return I == GUIDToProbeDescMap.end() ? nullptr : &I->second; + } + + const PseudoProbeDescriptor *getDesc(StringRef FProfileName) const { + return getDesc(Function::getGUID(FProfileName)); + } + + const PseudoProbeDescriptor *getDesc(const Function &F) const { + return getDesc(Function::getGUID(FunctionSamples::getCanonicalFnName(F))); + } + + bool profileIsHashMismatched(const PseudoProbeDescriptor &FuncDesc, + const FunctionSamples &Samples) const { + return FuncDesc.getFunctionHash() != Samples.getFunctionHash(); + } + bool moduleIsProbed(const Module &M) const { return M.getNamedMetadata(PseudoProbeDescMetadataName); } diff --git a/llvm/lib/Transforms/IPO/SampleProfile.cpp b/llvm/lib/Transforms/IPO/SampleProfile.cpp --- a/llvm/lib/Transforms/IPO/SampleProfile.cpp +++ b/llvm/lib/Transforms/IPO/SampleProfile.cpp @@ -477,6 +477,7 @@ std::map &IRAnchors); void findProfileAnchors(const FunctionSamples &FS, std::map> &ProfileAnchors); + void countMismatchedSamples(const FunctionSamples &FS); void countProfileMismatches( const Function &F, const FunctionSamples &FS, const std::map &IRAnchors, @@ -2166,19 +2167,36 @@ } } +void SampleProfileMatcher::countMismatchedSamples(const FunctionSamples &FS) { + const auto *FuncDesc = ProbeManager->getDesc(FS.getName()); + // Skip the function that is external or renamed. + if (!FuncDesc) + return; + + if (ProbeManager->profileIsHashMismatched(*FuncDesc, FS)) { + MismatchedFuncHashSamples += FS.getTotalSamples(); + return; + } + for (const auto &I : FS.getCallsiteSamples()) + for (const auto &CS : I.second) + countMismatchedSamples(CS.second); +} + void SampleProfileMatcher::countProfileMismatches( const Function &F, const FunctionSamples &FS, const std::map &IRAnchors, const std::map> &ProfileAnchors) { bool IsFuncHashMismatch = false; if (FunctionSamples::ProfileIsProbeBased) { - uint64_t Count = FS.getTotalSamples(); - TotalFuncHashSamples += Count; + TotalFuncHashSamples += FS.getTotalSamples(); TotalProfiledFunc++; - if (!ProbeManager->profileIsValid(F, FS)) { - MismatchedFuncHashSamples += Count; - NumMismatchedFuncHash++; - IsFuncHashMismatch = true; + const auto *FuncDesc = ProbeManager->getDesc(F); + if (FuncDesc) { + if (ProbeManager->profileIsHashMismatched(*FuncDesc, FS)) { + NumMismatchedFuncHash++; + IsFuncHashMismatch = true; + } + countMismatchedSamples(FS); } } diff --git a/llvm/test/Transforms/SampleProfile/Inputs/pseudo-probe-profile-mismatch-nested.prof b/llvm/test/Transforms/SampleProfile/Inputs/pseudo-probe-profile-mismatch-nested.prof new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/SampleProfile/Inputs/pseudo-probe-profile-mismatch-nested.prof @@ -0,0 +1,12 @@ +main:300:0 + 1: 0 + 12: 10 matched:10 + 20: 10 bar:10 + 13: bar:200 + 1: 100 + !CFGChecksum: 123 + !CFGChecksum: 844635331715433 +bar:11:11 + 1: 11 +# Original CFGChecksum is 4294967295 + !CFGChecksum: 123 diff --git a/llvm/test/Transforms/SampleProfile/pseudo-probe-profile-mismatch.ll b/llvm/test/Transforms/SampleProfile/pseudo-probe-profile-mismatch.ll --- a/llvm/test/Transforms/SampleProfile/pseudo-probe-profile-mismatch.ll +++ b/llvm/test/Transforms/SampleProfile/pseudo-probe-profile-mismatch.ll @@ -6,6 +6,9 @@ ; RUN: llvm-objdump --section-headers %t.obj | FileCheck %s --check-prefix=CHECK-OBJ ; RUN: llc < %t.ll -filetype=asm -o - | FileCheck %s --check-prefix=CHECK-ASM +; RUN: opt < %s -passes=sample-profile -sample-profile-file=%S/Inputs/pseudo-probe-profile-mismatch-nested.prof -report-profile-staleness -persist-profile-staleness -S 2>&1 | FileCheck %s --check-prefix=CHECK-NESTED + + ; CHECK: (1/3) of functions' profile are invalid and (10/50) of samples are discarded due to function hash mismatch. ; CHECK: (2/3) of callsites' profile are invalid and (20/30) of samples are discarded due to callsite location mismatch. @@ -47,6 +50,9 @@ ; CHECK-ASM: .byte 4 ; CHECK-ASM: .ascii "MzA=" +; CHECK-NESTED: (1/2) of functions' profile are invalid and (211/311) of samples are discarded due to function hash mismatch. + + 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"