10965da20SAdam Nemet //===- OptimizationRemarkEmitter.cpp - Optimization Diagnostic --*- C++ -*-===//
20965da20SAdam Nemet //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60965da20SAdam Nemet //
70965da20SAdam Nemet //===----------------------------------------------------------------------===//
80965da20SAdam Nemet //
90965da20SAdam Nemet // Optimization diagnostic interfaces. It's packaged as an analysis pass so
100965da20SAdam Nemet // that by using this service passes become dependent on BFI as well. BFI is
110965da20SAdam Nemet // used to compute the "hotness" of the diagnostic message.
120965da20SAdam Nemet //===----------------------------------------------------------------------===//
130965da20SAdam Nemet
140965da20SAdam Nemet #include "llvm/Analysis/OptimizationRemarkEmitter.h"
150965da20SAdam Nemet #include "llvm/Analysis/BranchProbabilityInfo.h"
160965da20SAdam Nemet #include "llvm/Analysis/LazyBlockFrequencyInfo.h"
170965da20SAdam Nemet #include "llvm/Analysis/LoopInfo.h"
1893dc1b5bSWei Wang #include "llvm/Analysis/ProfileSummaryInfo.h"
190965da20SAdam Nemet #include "llvm/IR/DiagnosticInfo.h"
200965da20SAdam Nemet #include "llvm/IR/Dominators.h"
210965da20SAdam Nemet #include "llvm/IR/LLVMContext.h"
2205da2fe5SReid Kleckner #include "llvm/InitializePasses.h"
230965da20SAdam Nemet
240965da20SAdam Nemet using namespace llvm;
250965da20SAdam Nemet
OptimizationRemarkEmitter(const Function * F)260965da20SAdam Nemet OptimizationRemarkEmitter::OptimizationRemarkEmitter(const Function *F)
270965da20SAdam Nemet : F(F), BFI(nullptr) {
280965da20SAdam Nemet if (!F->getContext().getDiagnosticsHotnessRequested())
290965da20SAdam Nemet return;
300965da20SAdam Nemet
310965da20SAdam Nemet // First create a dominator tree.
320965da20SAdam Nemet DominatorTree DT;
330965da20SAdam Nemet DT.recalculate(*const_cast<Function *>(F));
340965da20SAdam Nemet
350965da20SAdam Nemet // Generate LoopInfo from it.
360965da20SAdam Nemet LoopInfo LI;
370965da20SAdam Nemet LI.analyze(DT);
380965da20SAdam Nemet
390965da20SAdam Nemet // Then compute BranchProbabilityInfo.
409fb074e7SEvgeniy Brevnov BranchProbabilityInfo BPI(*F, LI, nullptr, &DT, nullptr);
410965da20SAdam Nemet
420965da20SAdam Nemet // Finally compute BFI.
430eaee545SJonas Devlieghere OwnedBFI = std::make_unique<BlockFrequencyInfo>(*F, BPI, LI);
440965da20SAdam Nemet BFI = OwnedBFI.get();
450965da20SAdam Nemet }
460965da20SAdam Nemet
invalidate(Function & F,const PreservedAnalyses & PA,FunctionAnalysisManager::Invalidator & Inv)470965da20SAdam Nemet bool OptimizationRemarkEmitter::invalidate(
480965da20SAdam Nemet Function &F, const PreservedAnalyses &PA,
490965da20SAdam Nemet FunctionAnalysisManager::Invalidator &Inv) {
509aa52ba5SKazu Hirata if (OwnedBFI) {
514f33a689SAlina Sbirlea OwnedBFI.reset();
524f33a689SAlina Sbirlea BFI = nullptr;
534f33a689SAlina Sbirlea }
540965da20SAdam Nemet // This analysis has no state and so can be trivially preserved but it needs
550965da20SAdam Nemet // a fresh view of BFI if it was constructed with one.
560965da20SAdam Nemet if (BFI && Inv.invalidate<BlockFrequencyAnalysis>(F, PA))
570965da20SAdam Nemet return true;
580965da20SAdam Nemet
590965da20SAdam Nemet // Otherwise this analysis result remains valid.
600965da20SAdam Nemet return false;
610965da20SAdam Nemet }
620965da20SAdam Nemet
computeHotness(const Value * V)630965da20SAdam Nemet Optional<uint64_t> OptimizationRemarkEmitter::computeHotness(const Value *V) {
640965da20SAdam Nemet if (!BFI)
650965da20SAdam Nemet return None;
660965da20SAdam Nemet
670965da20SAdam Nemet return BFI->getBlockProfileCount(cast<BasicBlock>(V));
680965da20SAdam Nemet }
690965da20SAdam Nemet
computeHotness(DiagnosticInfoIROptimization & OptDiag)700965da20SAdam Nemet void OptimizationRemarkEmitter::computeHotness(
710965da20SAdam Nemet DiagnosticInfoIROptimization &OptDiag) {
720965da20SAdam Nemet const Value *V = OptDiag.getCodeRegion();
730965da20SAdam Nemet if (V)
740965da20SAdam Nemet OptDiag.setHotness(computeHotness(V));
750965da20SAdam Nemet }
760965da20SAdam Nemet
emit(DiagnosticInfoOptimizationBase & OptDiagBase)770965da20SAdam Nemet void OptimizationRemarkEmitter::emit(
780965da20SAdam Nemet DiagnosticInfoOptimizationBase &OptDiagBase) {
790965da20SAdam Nemet auto &OptDiag = cast<DiagnosticInfoIROptimization>(OptDiagBase);
800965da20SAdam Nemet computeHotness(OptDiag);
819303f622SAdam Nemet
829303f622SAdam Nemet // Only emit it if its hotness meets the threshold.
83*129b531cSKazu Hirata if (OptDiag.getHotness().value_or(0) <
840965da20SAdam Nemet F->getContext().getDiagnosticsHotnessThreshold()) {
850965da20SAdam Nemet return;
860965da20SAdam Nemet }
870965da20SAdam Nemet
880965da20SAdam Nemet F->getContext().diagnose(OptDiag);
890965da20SAdam Nemet }
900965da20SAdam Nemet
OptimizationRemarkEmitterWrapperPass()910965da20SAdam Nemet OptimizationRemarkEmitterWrapperPass::OptimizationRemarkEmitterWrapperPass()
920965da20SAdam Nemet : FunctionPass(ID) {
930965da20SAdam Nemet initializeOptimizationRemarkEmitterWrapperPassPass(
940965da20SAdam Nemet *PassRegistry::getPassRegistry());
950965da20SAdam Nemet }
960965da20SAdam Nemet
runOnFunction(Function & Fn)970965da20SAdam Nemet bool OptimizationRemarkEmitterWrapperPass::runOnFunction(Function &Fn) {
980965da20SAdam Nemet BlockFrequencyInfo *BFI;
990965da20SAdam Nemet
10093dc1b5bSWei Wang auto &Context = Fn.getContext();
10193dc1b5bSWei Wang if (Context.getDiagnosticsHotnessRequested()) {
1020965da20SAdam Nemet BFI = &getAnalysis<LazyBlockFrequencyInfoPass>().getBFI();
10393dc1b5bSWei Wang // Get hotness threshold from PSI. This should only happen once.
10493dc1b5bSWei Wang if (Context.isDiagnosticsHotnessThresholdSetFromPSI()) {
10593dc1b5bSWei Wang if (ProfileSummaryInfo *PSI =
10693dc1b5bSWei Wang &getAnalysis<ProfileSummaryInfoWrapperPass>().getPSI())
10793dc1b5bSWei Wang Context.setDiagnosticsHotnessThreshold(
10893dc1b5bSWei Wang PSI->getOrCompHotCountThreshold());
10993dc1b5bSWei Wang }
11093dc1b5bSWei Wang } else
1110965da20SAdam Nemet BFI = nullptr;
1120965da20SAdam Nemet
1130eaee545SJonas Devlieghere ORE = std::make_unique<OptimizationRemarkEmitter>(&Fn, BFI);
1140965da20SAdam Nemet return false;
1150965da20SAdam Nemet }
1160965da20SAdam Nemet
getAnalysisUsage(AnalysisUsage & AU) const1170965da20SAdam Nemet void OptimizationRemarkEmitterWrapperPass::getAnalysisUsage(
1180965da20SAdam Nemet AnalysisUsage &AU) const {
1190965da20SAdam Nemet LazyBlockFrequencyInfoPass::getLazyBFIAnalysisUsage(AU);
12093dc1b5bSWei Wang AU.addRequired<ProfileSummaryInfoWrapperPass>();
1210965da20SAdam Nemet AU.setPreservesAll();
1220965da20SAdam Nemet }
1230965da20SAdam Nemet
1240965da20SAdam Nemet AnalysisKey OptimizationRemarkEmitterAnalysis::Key;
1250965da20SAdam Nemet
1260965da20SAdam Nemet OptimizationRemarkEmitter
run(Function & F,FunctionAnalysisManager & AM)1270965da20SAdam Nemet OptimizationRemarkEmitterAnalysis::run(Function &F,
1280965da20SAdam Nemet FunctionAnalysisManager &AM) {
1290965da20SAdam Nemet BlockFrequencyInfo *BFI;
13093dc1b5bSWei Wang auto &Context = F.getContext();
1310965da20SAdam Nemet
13293dc1b5bSWei Wang if (Context.getDiagnosticsHotnessRequested()) {
1330965da20SAdam Nemet BFI = &AM.getResult<BlockFrequencyAnalysis>(F);
13493dc1b5bSWei Wang // Get hotness threshold from PSI. This should only happen once.
13593dc1b5bSWei Wang if (Context.isDiagnosticsHotnessThresholdSetFromPSI()) {
13693dc1b5bSWei Wang auto &MAMProxy = AM.getResult<ModuleAnalysisManagerFunctionProxy>(F);
13793dc1b5bSWei Wang if (ProfileSummaryInfo *PSI =
13893dc1b5bSWei Wang MAMProxy.getCachedResult<ProfileSummaryAnalysis>(*F.getParent()))
13993dc1b5bSWei Wang Context.setDiagnosticsHotnessThreshold(
14093dc1b5bSWei Wang PSI->getOrCompHotCountThreshold());
14193dc1b5bSWei Wang }
14293dc1b5bSWei Wang } else
1430965da20SAdam Nemet BFI = nullptr;
1440965da20SAdam Nemet
1450965da20SAdam Nemet return OptimizationRemarkEmitter(&F, BFI);
1460965da20SAdam Nemet }
1470965da20SAdam Nemet
1480965da20SAdam Nemet char OptimizationRemarkEmitterWrapperPass::ID = 0;
1490965da20SAdam Nemet static const char ore_name[] = "Optimization Remark Emitter";
1500965da20SAdam Nemet #define ORE_NAME "opt-remark-emitter"
1510965da20SAdam Nemet
1520965da20SAdam Nemet INITIALIZE_PASS_BEGIN(OptimizationRemarkEmitterWrapperPass, ORE_NAME, ore_name,
1530965da20SAdam Nemet false, true)
1540965da20SAdam Nemet INITIALIZE_PASS_DEPENDENCY(LazyBFIPass)
15593dc1b5bSWei Wang INITIALIZE_PASS_DEPENDENCY(ProfileSummaryInfoWrapperPass)
1560965da20SAdam Nemet INITIALIZE_PASS_END(OptimizationRemarkEmitterWrapperPass, ORE_NAME, ore_name,
1570965da20SAdam Nemet false, true)
158