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 @@ -121,9 +121,10 @@ public: DefaultInlineAdvice(InlineAdvisor *Advisor, CallBase &CB, Optional OIC, OptimizationRemarkEmitter &ORE, - bool EmitRemarks = true) + bool EmitRemarks = true, + Optional LTOPhase = NoneType::None) : InlineAdvice(Advisor, CB, ORE, OIC.hasValue()), OriginalCB(&CB), - OIC(OIC), EmitRemarks(EmitRemarks) {} + OIC(OIC), EmitRemarks(EmitRemarks), LTOPhase(LTOPhase) {} private: void recordUnsuccessfulInliningImpl(const InlineResult &Result) override; @@ -134,6 +135,10 @@ CallBase *const OriginalCB; Optional OIC; bool EmitRemarks; + + // Optional tells the difference between unspecified lto + // phase and explicit no-lto. + Optional LTOPhase; }; /// Interface for deciding whether to inline a call site or not. @@ -198,13 +203,15 @@ class DefaultInlineAdvisor : public InlineAdvisor { public: DefaultInlineAdvisor(Module &M, FunctionAnalysisManager &FAM, - InlineParams Params) - : InlineAdvisor(M, FAM), Params(Params) {} + InlineParams Params, + Optional LTOPhase) + : InlineAdvisor(M, FAM), Params(Params), LTOPhase(LTOPhase) {} private: std::unique_ptr getAdviceImpl(CallBase &CB) override; InlineParams Params; + Optional LTOPhase; }; /// The InlineAdvisorAnalysis is a module pass because the InlineAdvisor @@ -223,7 +230,8 @@ return !PAC.preservedWhenStateless(); } bool tryCreate(InlineParams Params, InliningAdvisorMode Mode, - const ReplayInlinerSettings &ReplaySettings); + const ReplayInlinerSettings &ReplaySettings, + Optional LTOPhase); InlineAdvisor *getAdvisor() const { return Advisor.get(); } private: 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 @@ -121,6 +121,7 @@ public: ModuleInlinerWrapperPass( InlineParams Params = getInlineParams(), bool MandatoryFirst = true, + Optional LTOPhase = NoneType::None, InliningAdvisorMode Mode = InliningAdvisorMode::Default, unsigned MaxDevirtIterations = 0); ModuleInlinerWrapperPass(ModuleInlinerWrapperPass &&Arg) = default; @@ -146,6 +147,7 @@ private: const InlineParams Params; + const Optional LTOPhase; 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, + Optional LTOPhase = NoneType::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 Optional 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,12 @@ cl::desc("Scale to limit the cost of inline deferral"), cl::init(2), cl::Hidden); +static cl::opt + AnnotateInlineLTOPhase("annotate-inline-lto-phase", cl::Hidden, + cl::init(false), + cl::desc("If true, annotate inline advisor remarks " + "with LTO phase information.")); + extern cl::opt InlinerFunctionImportStats; namespace { @@ -94,6 +100,25 @@ }; } // namespace +static const char *getAnnotatedPassName(Optional LTOPhase) { + if (!AnnotateInlineLTOPhase || !LTOPhase.hasValue()) + return DEBUG_TYPE; + + switch (LTOPhase.getValue()) { + case llvm::ThinOrFullLTOPhase::ThinLTOPreLink: + return "thin-lto-prelink-default-inline"; + case llvm::ThinOrFullLTOPhase::FullLTOPreLink: + return "full-lto-prelink-default-inline"; + case llvm::ThinOrFullLTOPhase::ThinLTOPostLink: + return "thin-lto-postlink-default-inline"; + case llvm::ThinOrFullLTOPhase::FullLTOPostLink: + return "full-lto-postlink-default-inline"; + default: + return DEBUG_TYPE; + } + llvm_unreachable("unreachble path"); +} + void DefaultInlineAdvice::recordUnsuccessfulInliningImpl( const InlineResult &Result) { using namespace ore; @@ -109,12 +134,16 @@ void DefaultInlineAdvice::recordInliningWithCalleeDeletedImpl() { if (EmitRemarks) - emitInlinedIntoBasedOnCost(ORE, DLoc, Block, *Callee, *Caller, *OIC); + emitInlinedIntoBasedOnCost(ORE, DLoc, Block, *Callee, *Caller, *OIC, + /* ForProfileContext= */ false, + getAnnotatedPassName(LTOPhase)); } void DefaultInlineAdvice::recordInliningImpl() { if (EmitRemarks) - emitInlinedIntoBasedOnCost(ORE, DLoc, Block, *Callee, *Caller, *OIC); + emitInlinedIntoBasedOnCost(ORE, DLoc, Block, *Callee, *Caller, *OIC, + /* ForProfileContext= */ false, + getAnnotatedPassName(LTOPhase)); } llvm::Optional static getDefaultInlineAdvice( @@ -155,7 +184,8 @@ auto OIC = getDefaultInlineAdvice(CB, FAM, Params); return std::make_unique( this, CB, OIC, - FAM.getResult(*CB.getCaller())); + FAM.getResult(*CB.getCaller()), + /* EmitRemarks */ true, LTOPhase); } InlineAdvice::InlineAdvice(InlineAdvisor *Advisor, CallBase &CB, @@ -186,12 +216,13 @@ bool InlineAdvisorAnalysis::Result::tryCreate( InlineParams Params, InliningAdvisorMode Mode, - const ReplayInlinerSettings &ReplaySettings) { + const ReplayInlinerSettings &ReplaySettings, + Optional LTOPhase) { 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, LTOPhase)); // Restrict replay to default advisor, ML advisors are stateful so // replay will need augmentations to interleave with them correctly. if (!ReplaySettings.ReplayFile.empty()) { 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 @@ -616,7 +616,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; @@ -628,7 +629,7 @@ // 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, LTOPhase); CGSCCPassManager &CGPipeline = MIWP.getPM(); FunctionPassManager FPM; @@ -726,7 +727,7 @@ if (PGOOpt) IP.EnableDeferral = EnablePGOInlineDeferral; - ModuleInlinerWrapperPass MIWP(IP, PerformMandatoryInliningsFirst, + ModuleInlinerWrapperPass MIWP(IP, PerformMandatoryInliningsFirst, Phase, UseInlineAdvisor, MaxDevirtIterations); // Require the GlobalsAA analysis for the module so we can query it within @@ -813,7 +814,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), @@ -973,7 +974,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 && @@ -1127,7 +1128,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. @@ -1167,11 +1170,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 @@ -1312,13 +1315,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) @@ -1437,7 +1441,8 @@ Level, ThinOrFullLTOPhase::ThinLTOPostLink)); // Now add the optimization pipeline. - MPM.addPass(buildModuleOptimizationPipeline(Level)); + MPM.addPass(buildModuleOptimizationPipeline( + Level, ThinOrFullLTOPhase::ThinLTOPostLink)); // Emit annotation remarks. addAnnotationRemarksPass(MPM); @@ -1600,7 +1605,9 @@ // 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, + ThinOrFullLTOPhase::FullLTOPostLink)); // Optimize globals again after we ran the inliner. MPM.addPass(GlobalOptPass()); @@ -1625,11 +1632,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/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 @@ -712,8 +712,8 @@ // 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(), NoneType::None); if (!CGSCCInlineReplayFile.empty()) OwnedAdvisor = getReplayInlineAdvisor( @@ -1104,11 +1104,12 @@ return PA; } -ModuleInlinerWrapperPass::ModuleInlinerWrapperPass(InlineParams Params, - bool MandatoryFirst, - InliningAdvisorMode Mode, - unsigned MaxDevirtIterations) - : Params(Params), Mode(Mode), MaxDevirtIterations(MaxDevirtIterations) { +ModuleInlinerWrapperPass::ModuleInlinerWrapperPass( + InlineParams Params, bool MandatoryFirst, + Optional LTOPhase, InliningAdvisorMode Mode, + unsigned MaxDevirtIterations) + : Params(Params), LTOPhase(LTOPhase), 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. @@ -1126,7 +1127,8 @@ {CGSCCInlineReplayFile, CGSCCInlineReplayScope, CGSCCInlineReplayFallback, - {CGSCCInlineReplayFormat}})) { + {CGSCCInlineReplayFormat}}, + LTOPhase)) { 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,8 @@ // 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, NoneType::None); return *OwnedAdvisor; } @@ -109,7 +110,7 @@ LLVM_DEBUG(dbgs() << "---- Module Inliner is Running ---- \n"); auto &IAA = MAM.getResult(M); - if (!IAA.tryCreate(Params, Mode, {})) { + if (!IAA.tryCreate(Params, Mode, {}, LTOPhase)) { 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 @@ -95,6 +95,14 @@ using ProfileCount = Function::ProfileCount; #define DEBUG_TYPE "sample-profile" #define CSINLINE_DEBUG DEBUG_TYPE "-inline" +#define THIN_LTO "thin-lto-" +#define FULL_LTO "full-lto-" +#define PRELINK "prelink-" +#define POSTLINK "postlink-" +#define THIN_LTO_PRELINK_CSLINE_DEBUG_TYPE THIN_LTO PRELINK CSINLINE_DEBUG +#define THIN_LTO_POSTLINK_CSLINE_DEBUG_TYPE THIN_LTO POSTLINK CSINLINE_DEBUG +#define FULL_LTO_PRELINK_CSLINE_DEBUG_TYPE FULL_LTO PRELINK CSINLINE_DEBUG +#define FULL_LTO_POSTLINK_CSLINE_DEBUG_TYPE FULL_LTO POSTLINK CSINLINE_DEBUG STATISTIC(NumCSInlined, "Number of functions inlined with context sensitive profile"); @@ -293,6 +301,11 @@ "overwrite-existing-weights", cl::Hidden, cl::init(false), cl::desc("Ignore existing branch weights on IR and always overwrite.")); +static cl::opt AnnotateSampleProfileInlineLTOPhase( + "annotate-sample-profile-inline-lto-phase", cl::Hidden, cl::init(false), + cl::desc("Annotate LTO phase (pre-link or post-link) in remark pass name " + "for analysis.")); + extern cl::opt EnableExtTspBlockPlacement; namespace { @@ -580,6 +593,25 @@ TargetLibraryInfoWrapperPass *TLIWP = nullptr; }; +static inline const char *getAnnotatedRemarkPassName(ThinOrFullLTOPhase phase) { + if (!AnnotateSampleProfileInlineLTOPhase) + return CSINLINE_DEBUG; + + switch (phase) { + case llvm::ThinOrFullLTOPhase::ThinLTOPreLink: + return THIN_LTO_PRELINK_CSLINE_DEBUG_TYPE; + case llvm::ThinOrFullLTOPhase::FullLTOPreLink: + return FULL_LTO_PRELINK_CSLINE_DEBUG_TYPE; + case llvm::ThinOrFullLTOPhase::ThinLTOPostLink: + return THIN_LTO_POSTLINK_CSLINE_DEBUG_TYPE; + case llvm::ThinOrFullLTOPhase::FullLTOPostLink: + return FULL_LTO_POSTLINK_CSLINE_DEBUG_TYPE; + default: + return CSINLINE_DEBUG; + } + llvm_unreachable("unreachable path") +} + } // end anonymous namespace ErrorOr SampleProfileLoader::getInstWeight(const Instruction &Inst) { @@ -1021,8 +1053,9 @@ for (auto I : Candidates) { Function *CalledFunction = I->getCalledFunction(); if (CalledFunction) { - ORE->emit(OptimizationRemarkAnalysis(CSINLINE_DEBUG, "InlineAttempt", - I->getDebugLoc(), I->getParent()) + ORE->emit(OptimizationRemarkAnalysis(getAnnotatedRemarkPassName(LTOPhase), + "InlineAttempt", I->getDebugLoc(), + I->getParent()) << "previous inlining reattempted for " << (Hot ? "hotness: '" : "size: '") << ore::NV("Callee", CalledFunction) << "' into '" @@ -1241,7 +1274,8 @@ InlineCost Cost = shouldInlineCandidate(Candidate); if (Cost.isNever()) { - ORE->emit(OptimizationRemarkAnalysis(CSINLINE_DEBUG, "InlineFail", DLoc, BB) + ORE->emit(OptimizationRemarkAnalysis(getAnnotatedRemarkPassName(LTOPhase), + "InlineFail", DLoc, BB) << "incompatible inlining"); return false; } @@ -1259,8 +1293,8 @@ *CalledFunction); // The call to InlineFunction erases I, so we can't pass it here. - emitInlinedIntoBasedOnCost(*ORE, DLoc, BB, *CalledFunction, - *BB->getParent(), Cost, true, CSINLINE_DEBUG); + emitInlinedIntoBasedOnCost(*ORE, DLoc, BB, *CalledFunction, *BB->getParent(), + Cost, true, getAnnotatedRemarkPassName(LTOPhase)); // Now populate the list of newly exposed call sites. if (InlinedCallSites) { @@ -1546,8 +1580,9 @@ if (!Callee || Callee->isDeclaration()) continue; - ORE->emit(OptimizationRemarkAnalysis(CSINLINE_DEBUG, "NotInline", - I->getDebugLoc(), I->getParent()) + ORE->emit(OptimizationRemarkAnalysis(getAnnotatedRemarkPassName(LTOPhase), + "NotInline", I->getDebugLoc(), + I->getParent()) << "previous inlining not repeated: '" << ore::NV("Callee", Callee) << "' into '" << ore::NV("Caller", &F) << "'"); 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-lto-phase`. +; RUN: rm -f %t.yaml +; RUN: llvm-lto2 run -pass-remarks-output=%t.yaml \ +; RUN: -pass-remarks-with-hotness \ +; RUN: -annotate-inline-lto-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-lto-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-lto-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: full-lto-postlink-default-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,35 @@ ; 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-lto-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-lto-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-FULL-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-lto-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-THIN-LTO ; YAML: --- !Passed -; YAML-NEXT: Pass: inline +; YAML-NO-ANNOTATE: Pass: inline +; YAML-FULL-LTO-NEXT: Pass: full-lto-postlink-default-inline +; YAML-THIN-LTO-NEXT: Pass: thin-lto-postlink-default-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-lto-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-lto-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-lto-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: full-lto-postlink-default-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-lto-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: full-lto-postlink-default-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-lto-phase + +; RUN: llvm-lto -thinlto-action=run \ +; RUN: -lto-pass-remarks-output=%t.yaml \ +; RUN: -annotate-inline-lto-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: thin-lto-postlink-default-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: thin-lto-postlink-default-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-lto-phase +; RUN: rm -f %t.yaml.thin.0.yaml %t.yaml.thin.1.yaml +; RUN: llvm-lto -thinlto-action=run \ +; RUN: -annotate-inline-lto-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: thin-lto-postlink-default-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: thin-lto-postlink-default-inline ; YAML2-NEXT: Name: Inlined ; YAML2-NEXT: Function: foo ; YAML2-NEXT: Args: