diff --git a/llvm/lib/Analysis/CtxProfAnalysis.cpp b/llvm/lib/Analysis/CtxProfAnalysis.cpp index 457a4dcc79684..560d9c742d5e7 100644 --- a/llvm/lib/Analysis/CtxProfAnalysis.cpp +++ b/llvm/lib/Analysis/CtxProfAnalysis.cpp @@ -132,6 +132,23 @@ PGOContextualProfile CtxProfAnalysis::run(Module &M, return {}; } + DenseSet ProfileRootsInModule; + for (const auto &F : M) + if (!F.isDeclaration()) + if (auto GUID = AssignGUIDPass::getGUID(F); + MaybeCtx->find(GUID) != MaybeCtx->end()) + ProfileRootsInModule.insert(GUID); + + // Trim first the roots that aren't in this module. + for (auto &[RootGuid, _] : llvm::make_early_inc_range(*MaybeCtx)) + if (!ProfileRootsInModule.contains(RootGuid)) + MaybeCtx->erase(RootGuid); + // If none of the roots are in the module, we have no profile (for this + // module) + if (MaybeCtx->empty()) + return {}; + + // OK, so we have a valid profile and it's applicable to roots in this module. PGOContextualProfile Result; for (const auto &F : M) { @@ -166,10 +183,6 @@ PGOContextualProfile CtxProfAnalysis::run(Module &M, } // If we made it this far, the Result is valid - which we mark by setting // .Profiles. - // Trim first the roots that aren't in this module. - for (auto &[RootGuid, _] : llvm::make_early_inc_range(*MaybeCtx)) - if (!Result.FuncInfo.contains(RootGuid)) - MaybeCtx->erase(RootGuid); Result.Profiles = std::move(*MaybeCtx); return Result; } diff --git a/llvm/test/Analysis/CtxProfAnalysis/load-unapplicable.ll b/llvm/test/Analysis/CtxProfAnalysis/load-unapplicable.ll new file mode 100644 index 0000000000000..ac5e7930d3f53 --- /dev/null +++ b/llvm/test/Analysis/CtxProfAnalysis/load-unapplicable.ll @@ -0,0 +1,63 @@ +; REQUIRES: x86_64-linux +; +; Check that, if none of the roots in the profile are defined in the module, the +; profile is treated as empty (i.e. "none provided") +; +; RUN: rm -rf %t +; RUN: split-file %s %t +; RUN: llvm-ctxprof-util fromJSON --input=%t/profile.json --output=%t/profile.ctxprofdata +; RUN: opt -passes='require,print' -ctx-profile-printer-level=everything \ +; RUN: %t/example.ll -S 2>&1 | FileCheck %s + +; CHECK: No contextual profile was provided +; +; This is the reference profile, laid out in the format the json formatter will +; output it from opt. +;--- profile.json +[ + { + "Counters": [ + 9 + ], + "Guid": 12341 + }, + { + "Counters": [ + 5 + ], + "Guid": 12074870348631550642 + }, + { + "Callsites": [ + [ + { + "Counters": [ + 6, + 7 + ], + "Guid": 728453322856651412 + } + ] + ], + "Counters": [ + 1 + ], + "Guid": 11872291593386833696 + } +] +;--- example.ll +declare void @bar() + +define void @an_entrypoint(i32 %a) !guid !0 { + %t = icmp eq i32 %a, 0 + br i1 %t, label %yes, label %no + +yes: + call void @bar() + ret void +no: + ret void +} + +attributes #0 = { noinline } +!0 = !{ i64 1000 } \ No newline at end of file