diff --git a/llvm/include/llvm/Analysis/InlineAdvisor.h b/llvm/include/llvm/Analysis/InlineAdvisor.h --- a/llvm/include/llvm/Analysis/InlineAdvisor.h +++ b/llvm/include/llvm/Analysis/InlineAdvisor.h @@ -40,6 +40,28 @@ /// training. enum class InliningAdvisorMode : int { Default, Release, Development }; +// Each entry represents an inline driver. +enum class InlinePass : int { + AlwaysInliner, + CGSCCInliner, + EarlyInliner, + ModuleInliner, + MLInliner, + ReplayCGSCCInliner, + ReplaySampleProfileInliner, + SampleProfileInliner, +}; + +/// Provides context on when an inline advisor is constructed in the pipeline +/// (e.g., link phase, inline driver). +struct InlineContext { + ThinOrFullLTOPhase LTOPhase; + + InlinePass Pass; +}; + +std::string AnnotateInlinePassName(InlineContext IC); + class InlineAdvisor; /// Capture state between an inlining decision having had been made, and /// its impact being observable. When collecting model training data, this @@ -170,14 +192,20 @@ OS << "Unimplemented InlineAdvisor print\n"; } + /// NOTE pass name is annotated only when `--annotate-inline-phase` is true + /// and inline advisor constructor provides InlineContext. + const char *getAnnotatedInlinePassName(); + protected: - InlineAdvisor(Module &M, FunctionAnalysisManager &FAM); + InlineAdvisor(Module &M, FunctionAnalysisManager &FAM, + Optional IC = NoneType::None); virtual std::unique_ptr getAdviceImpl(CallBase &CB) = 0; virtual std::unique_ptr getMandatoryAdvice(CallBase &CB, bool Advice); Module &M; FunctionAnalysisManager &FAM; + const Optional IC; std::unique_ptr ImportedFunctionsStats; enum class MandatoryInliningKind { NotMandatory, Always, Never }; diff --git a/llvm/lib/Analysis/InlineAdvisor.cpp b/llvm/lib/Analysis/InlineAdvisor.cpp --- a/llvm/lib/Analysis/InlineAdvisor.cpp +++ b/llvm/lib/Analysis/InlineAdvisor.cpp @@ -81,7 +81,8 @@ void recordUnsuccessfulInliningImpl(const InlineResult &Result) override { if (IsInliningRecommended) ORE.emit([&]() { - return OptimizationRemarkMissed(DEBUG_TYPE, "NotInlined", DLoc, Block) + return OptimizationRemarkMissed(Advisor->getAnnotatedInlinePassName(), + "NotInlined", DLoc, Block) << "'" << NV("Callee", Callee) << "' is not AlwaysInline into '" << NV("Caller", Caller) << "': " << NV("Reason", Result.getFailureReason()); @@ -100,7 +101,8 @@ llvm::setInlineRemark(*OriginalCB, std::string(Result.getFailureReason()) + "; " + inlineCostStr(*OIC)); ORE.emit([&]() { - return OptimizationRemarkMissed(DEBUG_TYPE, "NotInlined", DLoc, Block) + return OptimizationRemarkMissed(Advisor->getAnnotatedInlinePassName(), + "NotInlined", DLoc, Block) << "'" << NV("Callee", Callee) << "' is not inlined into '" << NV("Caller", Caller) << "': " << NV("Reason", Result.getFailureReason()); @@ -109,12 +111,16 @@ void DefaultInlineAdvice::recordInliningWithCalleeDeletedImpl() { if (EmitRemarks) - emitInlinedIntoBasedOnCost(ORE, DLoc, Block, *Callee, *Caller, *OIC); + emitInlinedIntoBasedOnCost(ORE, DLoc, Block, *Callee, *Caller, *OIC, + /* ForProfileContext= */ false, + Advisor->getAnnotatedInlinePassName()); } void DefaultInlineAdvice::recordInliningImpl() { if (EmitRemarks) - emitInlinedIntoBasedOnCost(ORE, DLoc, Block, *Callee, *Caller, *OIC); + emitInlinedIntoBasedOnCost(ORE, DLoc, Block, *Callee, *Caller, *OIC, + /* ForProfileContext= */ false, + Advisor->getAnnotatedInlinePassName()); } llvm::Optional static getDefaultInlineAdvice( @@ -500,8 +506,9 @@ PassName); } -InlineAdvisor::InlineAdvisor(Module &M, FunctionAnalysisManager &FAM) - : M(M), FAM(FAM) { +InlineAdvisor::InlineAdvisor(Module &M, FunctionAnalysisManager &FAM, + Optional IC) + : M(M), FAM(FAM), IC(IC) { if (InlinerFunctionImportStats != InlinerFunctionImportStatsOpts::No) { ImportedFunctionsStats = std::make_unique(); @@ -523,6 +530,60 @@ Advice); } +static inline const char *getLTOPhase(ThinOrFullLTOPhase LTOPhase) { + switch (LTOPhase) { + case (ThinOrFullLTOPhase::None): + return "main"; + case (ThinOrFullLTOPhase::ThinLTOPreLink): + case (ThinOrFullLTOPhase::FullLTOPreLink): + return "prelink"; + case (ThinOrFullLTOPhase::ThinLTOPostLink): + case (ThinOrFullLTOPhase::FullLTOPostLink): + return "postlink"; + } + llvm_unreachable("unreachable"); +} + +static inline const char *getInlineAdvisorContext(InlinePass IP) { + switch (IP) { + case (InlinePass::AlwaysInliner): + return "always-inline"; + case (InlinePass::CGSCCInliner): + return "cgscc-inline"; + case (InlinePass::EarlyInliner): + return "early-inline"; + case (InlinePass::MLInliner): + return "ml-inline"; + case (InlinePass::ModuleInliner): + return "module-inline"; + case (InlinePass::ReplayCGSCCInliner): + return "replay-cgscc-inline"; + case (InlinePass::ReplaySampleProfileInliner): + return "replay-sample-profile-inline"; + case (InlinePass::SampleProfileInliner): + return "sample-profile-inline"; + } + + llvm_unreachable("unreachable"); +} + +std::string llvm::AnnotateInlinePassName(InlineContext IC) { + return std::string(getLTOPhase(IC.LTOPhase)) + "-" + + std::string(getInlineAdvisorContext(IC.Pass)); +} + +const char *InlineAdvisor::getAnnotatedInlinePassName() { + if (!IC.hasValue()) + return DEBUG_TYPE; + + // IC is constant and initialized in constructor, so compute the annotated + // name only once. + static const std::string PassName = + llvm::AnnotateInlinePassName(IC.getValue()); + + return PassName.c_str(); +} + InlineAdvisor::MandatoryInliningKind InlineAdvisor::getMandatoryKind(CallBase &CB, FunctionAnalysisManager &FAM, OptimizationRemarkEmitter &ORE) {