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 @@ -229,8 +229,8 @@ class DefaultInlineAdvisor : public InlineAdvisor { public: DefaultInlineAdvisor(Module &M, FunctionAnalysisManager &FAM, - InlineParams Params) - : InlineAdvisor(M, FAM), Params(Params) {} + InlineParams Params, InlineContext IC) + : InlineAdvisor(M, FAM, IC), Params(Params) {} private: std::unique_ptr getAdviceImpl(CallBase &CB) override; @@ -254,7 +254,8 @@ return !PAC.preservedWhenStateless(); } bool tryCreate(InlineParams Params, InliningAdvisorMode Mode, - const ReplayInlinerSettings &ReplaySettings); + const ReplayInlinerSettings &ReplaySettings, + InlineContext IC); InlineAdvisor *getAdvisor() const { return Advisor.get(); } private: diff --git a/llvm/include/llvm/Analysis/ReplayInlineAdvisor.h b/llvm/include/llvm/Analysis/ReplayInlineAdvisor.h --- a/llvm/include/llvm/Analysis/ReplayInlineAdvisor.h +++ b/llvm/include/llvm/Analysis/ReplayInlineAdvisor.h @@ -53,10 +53,12 @@ /// Get call site location as a string with the given format std::string formatCallSiteLocation(DebugLoc DLoc, const CallSiteFormat &Format); -std::unique_ptr getReplayInlineAdvisor( - Module &M, FunctionAnalysisManager &FAM, LLVMContext &Context, - std::unique_ptr OriginalAdvisor, - const ReplayInlinerSettings &ReplaySettings, bool EmitRemarks); +std::unique_ptr +getReplayInlineAdvisor(Module &M, FunctionAnalysisManager &FAM, + LLVMContext &Context, + std::unique_ptr OriginalAdvisor, + const ReplayInlinerSettings &ReplaySettings, + bool EmitRemarks, InlineContext IC); /// Replay inline advisor that uses optimization remarks from inlining of /// previous build to guide current inlining. This is useful for inliner tuning. @@ -66,7 +68,7 @@ LLVMContext &Context, std::unique_ptr OriginalAdvisor, const ReplayInlinerSettings &ReplaySettings, - bool EmitRemarks); + bool EmitRemarks, InlineContext IC); std::unique_ptr getAdviceImpl(CallBase &CB) override; bool areReplayRemarksLoaded() const { return HasReplayRemarks; } diff --git a/llvm/include/llvm/Passes/PassBuilder.h b/llvm/include/llvm/Passes/PassBuilder.h --- a/llvm/include/llvm/Passes/PassBuilder.h +++ b/llvm/include/llvm/Passes/PassBuilder.h @@ -215,8 +215,9 @@ /// only intended for use when attempting to optimize code. If frontends /// require some transformations for semantic reasons, they should explicitly /// build them. - ModulePassManager buildModuleOptimizationPipeline(OptimizationLevel Level, - bool LTOPreLink = false); + ModulePassManager + buildModuleOptimizationPipeline(OptimizationLevel Level, + ThinOrFullLTOPhase LTOPhase); /// Build a per-module default optimization pipeline. /// @@ -609,7 +610,8 @@ void addPGOInstrPasses(ModulePassManager &MPM, OptimizationLevel Level, bool RunProfileGen, bool IsCS, std::string ProfileFile, - std::string ProfileRemappingFile); + std::string ProfileRemappingFile, + ThinOrFullLTOPhase LTOPhase); void invokePeepholeEPCallbacks(FunctionPassManager &, OptimizationLevel); // Extension Point callbacks diff --git a/llvm/include/llvm/Transforms/IPO/Inliner.h b/llvm/include/llvm/Transforms/IPO/Inliner.h --- a/llvm/include/llvm/Transforms/IPO/Inliner.h +++ b/llvm/include/llvm/Transforms/IPO/Inliner.h @@ -95,7 +95,9 @@ /// passes be composed to achieve the same end result. class InlinerPass : public PassInfoMixin { public: - InlinerPass(bool OnlyMandatory = false) : OnlyMandatory(OnlyMandatory) {} + InlinerPass(bool OnlyMandatory = false, + ThinOrFullLTOPhase LTOPhase = ThinOrFullLTOPhase::None) + : OnlyMandatory(OnlyMandatory), LTOPhase(LTOPhase) {} InlinerPass(InlinerPass &&Arg) = default; PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, @@ -109,6 +111,7 @@ FunctionAnalysisManager &FAM, Module &M); std::unique_ptr OwnedAdvisor; const bool OnlyMandatory; + const ThinOrFullLTOPhase LTOPhase; }; /// Module pass, wrapping the inliner pass. This works in conjunction with the @@ -121,6 +124,7 @@ public: ModuleInlinerWrapperPass( InlineParams Params = getInlineParams(), bool MandatoryFirst = true, + InlineContext IC = {}, InliningAdvisorMode Mode = InliningAdvisorMode::Default, unsigned MaxDevirtIterations = 0); ModuleInlinerWrapperPass(ModuleInlinerWrapperPass &&Arg) = default; @@ -146,6 +150,7 @@ private: const InlineParams Params; + const InlineContext IC; const InliningAdvisorMode Mode; const unsigned MaxDevirtIterations; // TODO: Clean this up so we only have one ModulePassManager. diff --git a/llvm/include/llvm/Transforms/IPO/ModuleInliner.h b/llvm/include/llvm/Transforms/IPO/ModuleInliner.h --- a/llvm/include/llvm/Transforms/IPO/ModuleInliner.h +++ b/llvm/include/llvm/Transforms/IPO/ModuleInliner.h @@ -27,8 +27,9 @@ class ModuleInlinerPass : public PassInfoMixin { public: ModuleInlinerPass(InlineParams Params = getInlineParams(), - InliningAdvisorMode Mode = InliningAdvisorMode::Default) - : Params(Params), Mode(Mode){}; + InliningAdvisorMode Mode = InliningAdvisorMode::Default, + ThinOrFullLTOPhase LTOPhase = ThinOrFullLTOPhase::None) + : Params(Params), Mode(Mode), LTOPhase(LTOPhase){}; ModuleInlinerPass(ModuleInlinerPass &&Arg) = default; PreservedAnalyses run(Module &, ModuleAnalysisManager &); @@ -39,6 +40,7 @@ std::unique_ptr OwnedAdvisor; const InlineParams Params; const InliningAdvisorMode Mode; + const ThinOrFullLTOPhase LTOPhase; }; } // end namespace llvm 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 @@ -56,6 +56,11 @@ cl::desc("Scale to limit the cost of inline deferral"), cl::init(2), cl::Hidden); +static cl::opt AnnotateInlinePhase( + "annotate-inline-phase", cl::Hidden, cl::init(false), + cl::desc("If true, annotate inline advisor remarks " + "with LTO and pass information.")); + extern cl::opt InlinerFunctionImportStats; namespace { @@ -192,18 +197,18 @@ bool InlineAdvisorAnalysis::Result::tryCreate( InlineParams Params, InliningAdvisorMode Mode, - const ReplayInlinerSettings &ReplaySettings) { + const ReplayInlinerSettings &ReplaySettings, InlineContext IC) { auto &FAM = MAM.getResult(M).getManager(); switch (Mode) { case InliningAdvisorMode::Default: LLVM_DEBUG(dbgs() << "Using default inliner heuristic.\n"); - Advisor.reset(new DefaultInlineAdvisor(M, FAM, Params)); + Advisor.reset(new DefaultInlineAdvisor(M, FAM, Params, IC)); // Restrict replay to default advisor, ML advisors are stateful so // replay will need augmentations to interleave with them correctly. if (!ReplaySettings.ReplayFile.empty()) { Advisor = llvm::getReplayInlineAdvisor(M, FAM, M.getContext(), std::move(Advisor), ReplaySettings, - /* EmitRemarks =*/true); + /* EmitRemarks =*/true, IC); } break; case InliningAdvisorMode::Development: @@ -509,7 +514,7 @@ InlineAdvisor::InlineAdvisor(Module &M, FunctionAnalysisManager &FAM, Optional IC) : M(M), FAM(FAM), IC(IC), - AnnotatedInlinePassName(IC ? llvm::AnnotateInlinePassName(*IC) + AnnotatedInlinePassName((IC && AnnotateInlinePhase) ? llvm::AnnotateInlinePassName(*IC) : DEBUG_TYPE) { if (InlinerFunctionImportStats != InlinerFunctionImportStatsOpts::No) { ImportedFunctionsStats = diff --git a/llvm/lib/Analysis/ReplayInlineAdvisor.cpp b/llvm/lib/Analysis/ReplayInlineAdvisor.cpp --- a/llvm/lib/Analysis/ReplayInlineAdvisor.cpp +++ b/llvm/lib/Analysis/ReplayInlineAdvisor.cpp @@ -26,8 +26,9 @@ ReplayInlineAdvisor::ReplayInlineAdvisor( Module &M, FunctionAnalysisManager &FAM, LLVMContext &Context, std::unique_ptr OriginalAdvisor, - const ReplayInlinerSettings &ReplaySettings, bool EmitRemarks) - : InlineAdvisor(M, FAM), OriginalAdvisor(std::move(OriginalAdvisor)), + const ReplayInlinerSettings &ReplaySettings, bool EmitRemarks, + InlineContext IC) + : InlineAdvisor(M, FAM, IC), OriginalAdvisor(std::move(OriginalAdvisor)), ReplaySettings(ReplaySettings), EmitRemarks(EmitRemarks) { auto BufferOrErr = MemoryBuffer::getFileOrSTDIN(ReplaySettings.ReplayFile); @@ -75,12 +76,15 @@ HasReplayRemarks = true; } -std::unique_ptr llvm::getReplayInlineAdvisor( - Module &M, FunctionAnalysisManager &FAM, LLVMContext &Context, - std::unique_ptr OriginalAdvisor, - const ReplayInlinerSettings &ReplaySettings, bool EmitRemarks) { +std::unique_ptr +llvm::getReplayInlineAdvisor(Module &M, FunctionAnalysisManager &FAM, + LLVMContext &Context, + std::unique_ptr OriginalAdvisor, + const ReplayInlinerSettings &ReplaySettings, + bool EmitRemarks, InlineContext IC) { auto Advisor = std::make_unique( - M, FAM, Context, std::move(OriginalAdvisor), ReplaySettings, EmitRemarks); + M, FAM, Context, std::move(OriginalAdvisor), ReplaySettings, EmitRemarks, + IC); if (!Advisor->areReplayRemarksLoaded()) Advisor.reset(); return Advisor; diff --git a/llvm/lib/Passes/PassBuilderPipelines.cpp b/llvm/lib/Passes/PassBuilderPipelines.cpp --- a/llvm/lib/Passes/PassBuilderPipelines.cpp +++ b/llvm/lib/Passes/PassBuilderPipelines.cpp @@ -615,7 +615,8 @@ void PassBuilder::addPGOInstrPasses(ModulePassManager &MPM, OptimizationLevel Level, bool RunProfileGen, bool IsCS, std::string ProfileFile, - std::string ProfileRemappingFile) { + std::string ProfileRemappingFile, + ThinOrFullLTOPhase LTOPhase) { assert(Level != OptimizationLevel::O0 && "Not expecting O0 here!"); if (!IsCS && !DisablePreInliner) { InlineParams IP; @@ -627,7 +628,9 @@ // performance testing. // FIXME: this comment is cargo culted from the old pass manager, revisit). IP.HintThreshold = Level.isOptimizingForSize() ? PreInlineThreshold : 325; - ModuleInlinerWrapperPass MIWP(IP); + ModuleInlinerWrapperPass MIWP( + IP, /* MandatoryFirst */ true, + InlineContext{LTOPhase, InlinePass::EarlyInliner}); CGSCCPassManager &CGPipeline = MIWP.getPM(); FunctionPassManager FPM; @@ -725,8 +728,10 @@ if (PGOOpt) IP.EnableDeferral = EnablePGOInlineDeferral; - ModuleInlinerWrapperPass MIWP(IP, PerformMandatoryInliningsFirst, - UseInlineAdvisor, MaxDevirtIterations); + ModuleInlinerWrapperPass MIWP( + IP, PerformMandatoryInliningsFirst, + InlineContext{Phase, InlinePass::CGSCCInliner}, + UseInlineAdvisor, MaxDevirtIterations); // Require the GlobalsAA analysis for the module so we can query it within // the CGSCC pipeline. @@ -812,7 +817,7 @@ // inline deferral logic in module inliner. IP.EnableDeferral = false; - MPM.addPass(ModuleInlinerPass(IP, UseInlineAdvisor)); + MPM.addPass(ModuleInlinerPass(IP, UseInlineAdvisor, Phase)); MPM.addPass(createModuleToFunctionPassAdaptor( buildFunctionSimplificationPipeline(Level, Phase), @@ -972,7 +977,7 @@ addPGOInstrPasses(MPM, Level, /* RunProfileGen */ PGOOpt->Action == PGOOptions::IRInstr, /* IsCS */ false, PGOOpt->ProfileFile, - PGOOpt->ProfileRemappingFile); + PGOOpt->ProfileRemappingFile, Phase); MPM.addPass(PGOIndirectCallPromotion(false, false)); } if (PGOOpt && Phase != ThinOrFullLTOPhase::ThinLTOPostLink && @@ -1126,7 +1131,9 @@ ModulePassManager PassBuilder::buildModuleOptimizationPipeline(OptimizationLevel Level, - bool LTOPreLink) { + ThinOrFullLTOPhase LTOPhase) { + const bool LTOPreLink = (LTOPhase == ThinOrFullLTOPhase::ThinLTOPreLink || + LTOPhase == ThinOrFullLTOPhase::FullLTOPreLink); ModulePassManager MPM; // Optimize globals now that the module is fully simplified. @@ -1166,11 +1173,11 @@ if (PGOOpt->CSAction == PGOOptions::CSIRInstr) addPGOInstrPasses(MPM, Level, /* RunProfileGen */ true, /* IsCS */ true, PGOOpt->CSProfileGenFile, - PGOOpt->ProfileRemappingFile); + PGOOpt->ProfileRemappingFile, LTOPhase); else if (PGOOpt->CSAction == PGOOptions::CSIRUse) addPGOInstrPasses(MPM, Level, /* RunProfileGen */ false, /* IsCS */ true, PGOOpt->ProfileFile, - PGOOpt->ProfileRemappingFile); + PGOOpt->ProfileRemappingFile, LTOPhase); } // Re-compute GlobalsAA here prior to function passes. This is particularly @@ -1311,13 +1318,14 @@ if (PGOOpt && PGOOpt->DebugInfoForProfiling) MPM.addPass(createModuleToFunctionPassAdaptor(AddDiscriminatorsPass())); + const ThinOrFullLTOPhase LTOPhase = LTOPreLink + ? ThinOrFullLTOPhase::FullLTOPreLink + : ThinOrFullLTOPhase::None; // Add the core simplification pipeline. - MPM.addPass(buildModuleSimplificationPipeline( - Level, LTOPreLink ? ThinOrFullLTOPhase::FullLTOPreLink - : ThinOrFullLTOPhase::None)); + MPM.addPass(buildModuleSimplificationPipeline(Level, LTOPhase)); // Now add the optimization pipeline. - MPM.addPass(buildModuleOptimizationPipeline(Level, LTOPreLink)); + MPM.addPass(buildModuleOptimizationPipeline(Level, LTOPhase)); if (PGOOpt && PGOOpt->PseudoProbeForProfiling && PGOOpt->Action == PGOOptions::SampleUse) @@ -1436,7 +1444,8 @@ Level, ThinOrFullLTOPhase::ThinLTOPostLink)); // Now add the optimization pipeline. - MPM.addPass(buildModuleOptimizationPipeline(Level)); + MPM.addPass(buildModuleOptimizationPipeline( + Level, ThinOrFullLTOPhase::ThinLTOPostLink)); // Emit annotation remarks. addAnnotationRemarksPass(MPM); @@ -1599,7 +1608,11 @@ // valuable as the inliner doesn't currently care whether it is inlining an // invoke or a call. // Run the inliner now. - MPM.addPass(ModuleInlinerWrapperPass(getInlineParamsFromOptLevel(Level))); + MPM.addPass(ModuleInlinerWrapperPass( + getInlineParamsFromOptLevel(Level), + /* MandatoryFirst */ true, + InlineContext{ThinOrFullLTOPhase::FullLTOPostLink, + InlinePass::CGSCCInliner})); // Optimize globals again after we ran the inliner. MPM.addPass(GlobalOptPass()); @@ -1624,11 +1637,13 @@ if (PGOOpt->CSAction == PGOOptions::CSIRInstr) addPGOInstrPasses(MPM, Level, /* RunProfileGen */ true, /* IsCS */ true, PGOOpt->CSProfileGenFile, - PGOOpt->ProfileRemappingFile); + PGOOpt->ProfileRemappingFile, + ThinOrFullLTOPhase::FullLTOPostLink); else if (PGOOpt->CSAction == PGOOptions::CSIRUse) addPGOInstrPasses(MPM, Level, /* RunProfileGen */ false, /* IsCS */ true, PGOOpt->ProfileFile, - PGOOpt->ProfileRemappingFile); + PGOOpt->ProfileRemappingFile, + ThinOrFullLTOPhase::FullLTOPostLink); } // Break up allocas diff --git a/llvm/lib/Passes/PassRegistry.def b/llvm/lib/Passes/PassRegistry.def --- a/llvm/lib/Passes/PassRegistry.def +++ b/llvm/lib/Passes/PassRegistry.def @@ -67,7 +67,7 @@ MODULE_PASS("hotcoldsplit", HotColdSplittingPass()) MODULE_PASS("inferattrs", InferFunctionAttrsPass()) MODULE_PASS("inliner-wrapper", ModuleInlinerWrapperPass()) -MODULE_PASS("inliner-ml-advisor-release", ModuleInlinerWrapperPass(getInlineParams(), true, InliningAdvisorMode::Release, 0)) +MODULE_PASS("inliner-ml-advisor-release", ModuleInlinerWrapperPass(getInlineParams(), true, {}, InliningAdvisorMode::Release, 0)) MODULE_PASS("print", InlineAdvisorAnalysisPrinterPass(dbgs())) MODULE_PASS("inliner-wrapper-no-mandatory-first", ModuleInlinerWrapperPass( getInlineParams(), diff --git a/llvm/lib/Transforms/IPO/Inliner.cpp b/llvm/lib/Transforms/IPO/Inliner.cpp --- a/llvm/lib/Transforms/IPO/Inliner.cpp +++ b/llvm/lib/Transforms/IPO/Inliner.cpp @@ -717,8 +717,9 @@ // duration of the inliner pass, and thus the lifetime of the owned advisor. // The one we would get from the MAM can be invalidated as a result of the // inliner's activity. - OwnedAdvisor = - std::make_unique(M, FAM, getInlineParams()); + OwnedAdvisor = std::make_unique( + M, FAM, getInlineParams(), + InlineContext{LTOPhase, InlinePass::CGSCCInliner}); if (!CGSCCInlineReplayFile.empty()) OwnedAdvisor = getReplayInlineAdvisor( @@ -727,7 +728,9 @@ CGSCCInlineReplayScope, CGSCCInlineReplayFallback, {CGSCCInlineReplayFormat}}, - /*EmitRemarks=*/true); + /*EmitRemarks=*/true, + InlineContext{LTOPhase, + InlinePass::ReplayCGSCCInliner}); return *OwnedAdvisor; } @@ -1111,9 +1114,11 @@ ModuleInlinerWrapperPass::ModuleInlinerWrapperPass(InlineParams Params, bool MandatoryFirst, + InlineContext IC, InliningAdvisorMode Mode, unsigned MaxDevirtIterations) - : Params(Params), Mode(Mode), MaxDevirtIterations(MaxDevirtIterations) { + : Params(Params), IC(IC), Mode(Mode), + MaxDevirtIterations(MaxDevirtIterations) { // Run the inliner first. The theory is that we are walking bottom-up and so // the callees have already been fully optimized, and we want to inline them // into the callers so that our optimizations can reflect that. @@ -1136,7 +1141,8 @@ {CGSCCInlineReplayFile, CGSCCInlineReplayScope, CGSCCInlineReplayFallback, - {CGSCCInlineReplayFormat}})) { + {CGSCCInlineReplayFormat}}, + IC)) { M.getContext().emitError( "Could not setup Inlining Advisor for the requested " "mode and/or options"); diff --git a/llvm/lib/Transforms/IPO/ModuleInliner.cpp b/llvm/lib/Transforms/IPO/ModuleInliner.cpp --- a/llvm/lib/Transforms/IPO/ModuleInliner.cpp +++ b/llvm/lib/Transforms/IPO/ModuleInliner.cpp @@ -84,7 +84,9 @@ // inliner pass, and thus the lifetime of the owned advisor. The one we // would get from the MAM can be invalidated as a result of the inliner's // activity. - OwnedAdvisor = std::make_unique(M, FAM, Params); + OwnedAdvisor = std::make_unique( + M, FAM, Params, + InlineContext{LTOPhase, InlinePass::ModuleInliner}); return *OwnedAdvisor; } @@ -109,7 +111,9 @@ LLVM_DEBUG(dbgs() << "---- Module Inliner is Running ---- \n"); auto &IAA = MAM.getResult(M); - if (!IAA.tryCreate(Params, Mode, {})) { + if (!IAA.tryCreate( + Params, Mode, {}, + InlineContext{LTOPhase, InlinePass::ModuleInliner})) { M.getContext().emitError( "Could not setup Inlining Advisor for the requested " "mode and/or options"); 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 @@ -2015,7 +2015,7 @@ ProfileInlineReplayScope, ProfileInlineReplayFallback, {ProfileInlineReplayFormat}}, - /*EmitRemarks=*/false); + /*EmitRemarks=*/false, InlineContext{LTOPhase, InlinePass::ReplaySampleProfileInliner}); } // Apply tweaks if context-sensitive or probe-based profile is available. diff --git a/llvm/test/LTO/Resolution/X86/diagnostic-handler-remarks-with-hotness.ll b/llvm/test/LTO/Resolution/X86/diagnostic-handler-remarks-with-hotness.ll --- a/llvm/test/LTO/Resolution/X86/diagnostic-handler-remarks-with-hotness.ll +++ b/llvm/test/LTO/Resolution/X86/diagnostic-handler-remarks-with-hotness.ll @@ -7,7 +7,7 @@ ; RUN: -r %t.bc,tinkywinky,p \ ; RUN: -r %t.bc,patatino,px \ ; RUN: -r %t.bc,main,px -o %t.o %t.bc -; RUN: cat %t.yaml | FileCheck %s -check-prefix=YAML +; RUN: cat %t.yaml | FileCheck %s -check-prefixes=YAML,YAML-NO-ANNOTATE ; Check low threshold allows remarks to emit. ; RUN: rm -f %t.t300.yaml @@ -17,7 +17,7 @@ ; RUN: -r %t.bc,tinkywinky,p \ ; RUN: -r %t.bc,patatino,px \ ; RUN: -r %t.bc,main,px -o %t.o %t.bc -; RUN: FileCheck %s -check-prefix=YAML < %t.t300.yaml +; RUN: FileCheck %s -check-prefixes=YAML,YAML-NO-ANNOTATE < %t.t300.yaml ; Check high threshold disallows remarks to emit. ; RUN: rm -f %t.t301.yaml @@ -52,8 +52,31 @@ ; RUN: -r %t.bc,patatino,px \ ; RUN: -r %t.bc,main,px -o %t.o %t.bc 2>&1 | count 0 +; Check that remarks are annotated with LTO phase information with `-annotate-inline-phase`. +; RUN: rm -f %t.yaml +; RUN: llvm-lto2 run -pass-remarks-output=%t.yaml \ +; RUN: -pass-remarks-with-hotness \ +; RUN: -annotate-inline-phase \ +; RUN: -r %t.bc,tinkywinky,p \ +; RUN: -r %t.bc,patatino,px \ +; RUN: -r %t.bc,main,px -o %t.o %t.bc +; RUN: cat %t.yaml | FileCheck %s -check-prefixes=YAML,YAML-ANNOTATE + +; Run again with `-annotate-inline-phase`. +; RUN: rm -f %t.t300.yaml +; RUN: llvm-lto2 run -pass-remarks-output=%t.t300.yaml \ +; RUN: -pass-remarks-with-hotness \ +; RUN: -pass-remarks-hotness-threshold=300 \ +; RUN: -annotate-inline-phase \ +; RUN: -r %t.bc,tinkywinky,p \ +; RUN: -r %t.bc,patatino,px \ +; RUN: -r %t.bc,main,px -o %t.o %t.bc +; RUN: FileCheck %s -check-prefixes=YAML,YAML-ANNOTATE < %t.t300.yaml + ; YAML: --- !Passed -; YAML-NEXT: Pass: inline +; YAML-NO-ANNOTATE-NEXT: Pass: inline +; YAML-ANNOTATE-NEXT: Pass: postlink-cgscc-inline + ; YAML-NEXT: Name: Inlined ; YAML-NEXT: Function: main ; YAML-NEXT: Hotness: 300 diff --git a/llvm/test/LTO/Resolution/X86/diagnostic-handler-remarks.ll b/llvm/test/LTO/Resolution/X86/diagnostic-handler-remarks.ll --- a/llvm/test/LTO/Resolution/X86/diagnostic-handler-remarks.ll +++ b/llvm/test/LTO/Resolution/X86/diagnostic-handler-remarks.ll @@ -8,7 +8,7 @@ ; RUN: -r %t.bc,tinkywinky,p \ ; RUN: -r %t.bc,patatino,px \ ; RUN: -r %t.bc,main,px -o %t.o %t.bc -; RUN: cat %t.yaml | FileCheck %s -check-prefix=YAML +; RUN: cat %t.yaml | FileCheck %s -check-prefixes=YAML,YAML-NO-ANNOTATE ; Try again with ThinLTO ; RUN: opt -module-summary %s -o %t.bc @@ -18,10 +18,34 @@ ; RUN: -r %t.bc,tinkywinky,p \ ; RUN: -r %t.bc,patatino,px \ ; RUN: -r %t.bc,main,px -o %t.o %t.bc -; RUN: cat %t.thin.1.yaml | FileCheck %s -check-prefix=YAML +; RUN: cat %t.thin.1.yaml | FileCheck %s -check-prefixes=YAML,YAML-NO-ANNOTATE + +; Check that remarks are annotated with LTO phase information with `-annotate-inline-phase`. +; First try with Regular LTO +; RUN: llvm-as < %s >%t.bc +; RUN: rm -f %t.yaml +; RUN: llvm-lto2 run -pass-remarks-output=%t.yaml \ +; RUN: -pass-remarks-filter=inline \ +; RUN: -annotate-inline-phase \ +; RUN: -r %t.bc,tinkywinky,p \ +; RUN: -r %t.bc,patatino,px \ +; RUN: -r %t.bc,main,px -o %t.o %t.bc +; RUN: cat %t.yaml | FileCheck %s -check-prefixes=YAML,YAML-POSTLINK-LTO + +; Try again with ThinLTO +; RUN: opt -module-summary %s -o %t.bc +; RUN: rm -f %t.thin.1.yaml +; RUN: llvm-lto2 run -pass-remarks-output=%t \ +; RUN: -pass-remarks-filter=inline \ +; RUN: -annotate-inline-phase \ +; RUN: -r %t.bc,tinkywinky,p \ +; RUN: -r %t.bc,patatino,px \ +; RUN: -r %t.bc,main,px -o %t.o %t.bc +; RUN: cat %t.thin.1.yaml | FileCheck %s -check-prefixes=YAML,YAML-POSTLINK-LTO ; YAML: --- !Passed -; YAML-NEXT: Pass: inline +; YAML-NO-ANNOTATE: Pass: inline +; YAML-POSTLINK-LTO-NEXT: Pass: postlink-cgscc-inline ; YAML-NEXT: Name: Inlined ; YAML-NEXT: Function: main ; YAML-NEXT: Args: diff --git a/llvm/test/LTO/X86/diagnostic-handler-remarks-with-hotness.ll b/llvm/test/LTO/X86/diagnostic-handler-remarks-with-hotness.ll --- a/llvm/test/LTO/X86/diagnostic-handler-remarks-with-hotness.ll +++ b/llvm/test/LTO/X86/diagnostic-handler-remarks-with-hotness.ll @@ -6,22 +6,46 @@ ; RUN: llvm-lto -lto-pass-remarks-output=%t.yaml \ ; RUN: -lto-pass-remarks-with-hotness \ ; RUN: -exported-symbol _main -o %t.o %t.bc -; RUN: cat %t.yaml | FileCheck -check-prefix=YAML %s +; RUN: cat %t.yaml | FileCheck -check-prefixes=YAML,YAML-NO-ANNOTATE %s ; RUN: llvm-lto -lto-pass-remarks-output=%t.t300.yaml \ ; RUN: -lto-pass-remarks-with-hotness \ ; RUN: -lto-pass-remarks-hotness-threshold=300 \ ; RUN: -exported-symbol _main -o %t.o %t.bc -; RUN: FileCheck -check-prefix=YAML %s < %t.t300.yaml +; RUN: FileCheck -check-prefixes=YAML,YAML-NO-ANNOTATE %s < %t.t300.yaml ; RUN: llvm-lto -lto-pass-remarks-output=%t.t301.yaml \ ; RUN: -lto-pass-remarks-with-hotness \ ; RUN: -lto-pass-remarks-hotness-threshold=301 \ ; RUN: -exported-symbol _main -o %t.o %t.bc -; RUN: not FileCheck -check-prefix=YAML %s < %t.t301.yaml +; RUN: not FileCheck -check-prefixes=YAML,YAML-NO-ANNOTATE %s < %t.t301.yaml + +; Check that remarks are annotated with LTO phase information with `-annotate-inline-lto-phase`. +; RUN: llvm-as < %s >%t.bc +; RUN: rm -f %t.yaml %t.t300.yaml %t.t301.yaml +; RUN: llvm-lto -lto-pass-remarks-output=%t.yaml \ +; RUN: -lto-pass-remarks-with-hotness \ +; RUN: -annotate-inline-phase \ +; RUN: -exported-symbol _main -o %t.o %t.bc +; RUN: cat %t.yaml | FileCheck -check-prefixes=YAML,YAML-ANNOTATE %s + +; RUN: llvm-lto -lto-pass-remarks-output=%t.t300.yaml \ +; RUN: -lto-pass-remarks-with-hotness \ +; RUN: -lto-pass-remarks-hotness-threshold=300 \ +; RUN: -annotate-inline-phase \ +; RUN: -exported-symbol _main -o %t.o %t.bc +; RUN: FileCheck -check-prefixes=YAML,YAML-ANNOTATE %s < %t.t300.yaml + +; RUN: llvm-lto -lto-pass-remarks-output=%t.t301.yaml \ +; RUN: -lto-pass-remarks-with-hotness \ +; RUN: -lto-pass-remarks-hotness-threshold=301 \ +; RUN: -annotate-inline-phase \ +; RUN: -exported-symbol _main -o %t.o %t.bc +; RUN: not FileCheck -check-prefixes=YAML,YAML-ANNOTATE %s < %t.t301.yaml ; YAML: --- !Passed -; YAML-NEXT: Pass: inline +; YAML-NO-ANNOTATE-NEXT: Pass: inline +; YAML-ANNOTATE-NEXT: Pass: postlink-cgscc-inline ; YAML-NEXT: Name: Inlined ; YAML-NEXT: Function: main ; YAML-NEXT: Hotness: 300 diff --git a/llvm/test/LTO/X86/diagnostic-handler-remarks.ll b/llvm/test/LTO/X86/diagnostic-handler-remarks.ll --- a/llvm/test/LTO/X86/diagnostic-handler-remarks.ll +++ b/llvm/test/LTO/X86/diagnostic-handler-remarks.ll @@ -37,7 +37,17 @@ ; RUN: -exported-symbol _func2 \ ; RUN: -exported-symbol _main -o %t.o %t.bc 2>&1 | \ ; RUN: FileCheck %s -allow-empty -; RUN: cat %t.yaml | FileCheck %s -check-prefix=YAML +; RUN: cat %t.yaml | FileCheck %s -check-prefixes=YAML,YAML-NO-ANNOTATE + +; Try again with `-annotate-inline-lto-phase`. +; RUN: rm -f %t.yaml +; RUN: llvm-lto \ +; RUN: -annotate-inline-phase \ +; RUN: -lto-pass-remarks-output=%t.yaml \ +; RUN: -exported-symbol _func2 \ +; RUN: -exported-symbol _main -o %t.o %t.bc 2>&1 | \ +; RUN: FileCheck %s -allow-empty +; RUN: cat %t.yaml | FileCheck %s -check-prefixes=YAML,YAML-ANNOTATE ; REMARKS: remark: {{.*}} 'foo' inlined into 'main' ; REMARKS: remark: {{.*}} loop not vectorized: cannot prove it is safe to reorder memory operations @@ -50,7 +60,8 @@ ; NM: main ; YAML: --- !Passed -; YAML-NEXT: Pass: inline +; YAML-NO-ANNOTATE-NEXT: Pass: inline +; YAML-ANNOTATE-NEXT: Pass: postlink-cgscc-inline ; YAML-NEXT: Name: Inlined ; YAML-NEXT: Function: main ; YAML-NEXT: Args: diff --git a/llvm/test/ThinLTO/X86/diagnostic-handler-remarks-with-hotness.ll b/llvm/test/ThinLTO/X86/diagnostic-handler-remarks-with-hotness.ll --- a/llvm/test/ThinLTO/X86/diagnostic-handler-remarks-with-hotness.ll +++ b/llvm/test/ThinLTO/X86/diagnostic-handler-remarks-with-hotness.ll @@ -13,12 +13,31 @@ ; CHECK-NOT: remark: ; CHECK-NOT: llvm-lto: +; Verify that bar is imported 'and' inlined into 'foo' +; RUN: cat %t.yaml.thin.0.yaml | FileCheck %s -check-prefixes=YAML1,YAML1-NO-ANNOTATE ; Verify that bar is imported 'and' inlined into 'foo' -; RUN: cat %t.yaml.thin.0.yaml | FileCheck %s -check-prefix=YAML1 +; RUN: cat %t.yaml.thin.1.yaml | FileCheck %s -check-prefixes=YAML2,YAML2-NO-ANNOTATE + +; Run again with -annotate-inline-phase + +; RUN: llvm-lto -thinlto-action=run \ +; RUN: -lto-pass-remarks-output=%t.yaml \ +; RUN: -annotate-inline-phase \ +; RUN: -lto-pass-remarks-with-hotness \ +; RUN: -exported-symbol _func2 \ +; RUN: -exported-symbol _main %t1.bc %t2.bc 2>&1 | \ +; RUN: FileCheck %s -allow-empty +; CHECK-NOT: remark: +; CHECK-NOT: llvm-lto: + +; Verify that pass name is annotated with LTO phase information. +; RUN: cat %t.yaml.thin.0.yaml | FileCheck %s -check-prefixes=YAML1,YAML1-ANNOTATE + ; YAML1: --- !Passed ; YAML1: --- !Passed -; YAML1-NEXT: Pass: inline +; YAML1-NO-ANNOTATE-NEXT: Pass: inline +; YAML1-ANNOTATE-NEXT: Pass: postlink-cgscc-inline ; YAML1-NEXT: Name: Inlined ; YAML1-NEXT: Function: main ; YAML1-NEXT: Hotness: 50 @@ -38,9 +57,10 @@ ; Verify that bar is imported 'and' inlined into 'foo' -; RUN: cat %t.yaml.thin.1.yaml | FileCheck %s -check-prefix=YAML2 +; RUN: cat %t.yaml.thin.1.yaml | FileCheck %s -check-prefixes=YAML2,YAML2-ANNOTATE ; YAML2: --- !Passed -; YAML2-NEXT: Pass: inline +; YAML2-NO-ANNOTATE-NEXT: Pass: inline +; YAML2-ANNOTATE-NEXT: Pass: postlink-cgscc-inline ; YAML2-NEXT: Name: Inlined ; YAML2-NEXT: Function: foo ; YAML2-NEXT: Args: diff --git a/llvm/test/ThinLTO/X86/diagnostic-handler-remarks.ll b/llvm/test/ThinLTO/X86/diagnostic-handler-remarks.ll --- a/llvm/test/ThinLTO/X86/diagnostic-handler-remarks.ll +++ b/llvm/test/ThinLTO/X86/diagnostic-handler-remarks.ll @@ -15,10 +15,34 @@ ; Verify that bar is imported 'and' inlined into 'foo' -; RUN: cat %t.yaml.thin.0.yaml | FileCheck %s -check-prefix=YAML1 +; RUN: cat %t.yaml.thin.0.yaml | FileCheck %s -check-prefixes=YAML1,YAML1-NO-ANNOTATE + +; Verify that bar is imported 'and' inlined into 'foo' +; RUN: cat %t.yaml.thin.1.yaml | FileCheck %s -check-prefixes=YAML2,YAML2-NO-ANNOTATE + +; Try again with -annotate-inline-phase +; RUN: rm -f %t.yaml.thin.0.yaml %t.yaml.thin.1.yaml +; RUN: llvm-lto -thinlto-action=run \ +; RUN: -annotate-inline-phase \ +; RUN: -lto-pass-remarks-output=%t.yaml \ +; RUN: -lto-pass-remarks-filter=inline \ +; RUN: -lto-pass-remarks-format=yaml \ +; RUN: -exported-symbol _func2 \ +; RUN: -exported-symbol _main %t1.bc %t2.bc 2>&1 | \ +; RUN: FileCheck %s -allow-empty +; CHECK-NOT: remark: +; CHECK-NOT: llvm-lto: + +; Verify thati inline happens the same way and pass name are annotated with LTO phase information. +; RUN: cat %t.yaml.thin.0.yaml | FileCheck %s -check-prefixes=YAML1,YAML1-ANNOTATE + +; Verify that bar is imported 'and' inlined into 'foo' +; RUN: cat %t.yaml.thin.1.yaml | FileCheck %s -check-prefixes=YAML2,YAML2-ANNOTATE + ; YAML1: --- !Passed ; YAML1: --- !Passed -; YAML1-NEXT: Pass: inline +; YAML1-NO-ANNOTATE: Pass: inline +; YAML1-ANNOTATE-NEXT: Pass: postlink-cgscc-inline ; YAML1-NEXT: Name: Inlined ; YAML1-NEXT: Function: main ; YAML1-NEXT: Args: @@ -35,11 +59,9 @@ ; YAML1-NEXT: - String: ')' ; YAML1-NEXT: ... - -; Verify that bar is imported 'and' inlined into 'foo' -; RUN: cat %t.yaml.thin.1.yaml | FileCheck %s -check-prefix=YAML2 ; YAML2: --- !Passed -; YAML2-NEXT: Pass: inline +; YAML2-NO-ANNOTATE: Pass: inline +; YAML2-ANNOTATE-NEXT: Pass: postlink-cgscc-inline ; YAML2-NEXT: Name: Inlined ; YAML2-NEXT: Function: foo ; YAML2-NEXT: Args: diff --git a/llvm/test/Transforms/Inline/optimization-remarks-passed-yaml.ll b/llvm/test/Transforms/Inline/optimization-remarks-passed-yaml.ll --- a/llvm/test/Transforms/Inline/optimization-remarks-passed-yaml.ll +++ b/llvm/test/Transforms/Inline/optimization-remarks-passed-yaml.ll @@ -1,17 +1,24 @@ ; RUN: opt < %s -S -inline -pass-remarks-output=%t -pass-remarks=inline \ ; RUN: -pass-remarks-missed=inline -pass-remarks-analysis=inline \ ; RUN: -pass-remarks-with-hotness 2>&1 | FileCheck %s -; RUN: cat %t | FileCheck -check-prefix=YAML %s +; RUN: cat %t | FileCheck -check-prefixes=YAML,YAML-NO-ANNOTATE %s ; RUN: opt < %s -S -passes=inline -pass-remarks-output=%t -pass-remarks=inline \ ; RUN: -pass-remarks-missed=inline -pass-remarks-analysis=inline \ ; RUN: -pass-remarks-with-hotness 2>&1 | FileCheck %s -; RUN: cat %t | FileCheck -check-prefix=YAML %s +; RUN: cat %t | FileCheck -check-prefixes=YAML,YAML-NO-ANNOTATE %s ; RUN: opt < %s -S -passes=inliner-wrapper -pass-remarks-output=%t -pass-remarks=inline \ ; RUN: -pass-remarks-missed=inline -pass-remarks-analysis=inline \ +; RUN: -annotate-inline-phase=false \ ; RUN: -pass-remarks-with-hotness 2>&1 | FileCheck %s -; RUN: cat %t | FileCheck -check-prefix=YAML %s +; RUN: cat %t | FileCheck -check-prefixes=YAML,YAML-NO-ANNOTATE %s + +; RUN: opt < %s -S -passes=inliner-wrapper -pass-remarks-output=%t -pass-remarks=inline \ +; RUN: -pass-remarks-missed=inline -pass-remarks-analysis=inline \ +; RUN: -annotate-inline-phase \ +; RUN: -pass-remarks-with-hotness 2>&1 | FileCheck %s +; RUN: cat %t | FileCheck -check-prefixes=YAML,YAML-ANNOTATE %s ; Check the YAML file for inliner-generated passed and analysis remarks. This ; is the input: @@ -25,7 +32,8 @@ ; CHECK: remark: /tmp/s.c:4:10: 'foo' inlined into 'bar' with (cost={{[0-9\-]+}}, threshold={{[0-9]+}}) at callsite bar:1:10; (hotness: 30) ; YAML: --- !Passed -; YAML-NEXT: Pass: inline +; YAML-NO-ANNOTATE-NEXT: Pass: inline +; YAML-ANNOTATE-NEXT: Pass: main-always-inline ; YAML-NEXT: Name: Inlined ; YAML-NEXT: DebugLoc: { File: '/tmp/s.c', Line: 4, Column: 10 } ; YAML-NEXT: Function: bar