1 //===- OptimizationRemarkEmitter.cpp - Optimization Diagnostic --*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // Optimization diagnostic interfaces. It's packaged as an analysis pass so
10 // that by using this service passes become dependent on BFI as well. BFI is
11 // used to compute the "hotness" of the diagnostic message.
12 //===----------------------------------------------------------------------===//
14 #include "llvm/Analysis/OptimizationRemarkEmitter.h"
15 #include "llvm/Analysis/BranchProbabilityInfo.h"
16 #include "llvm/Analysis/LazyBlockFrequencyInfo.h"
17 #include "llvm/Analysis/LoopInfo.h"
18 #include "llvm/IR/DiagnosticInfo.h"
19 #include "llvm/IR/Dominators.h"
20 #include "llvm/IR/LLVMContext.h"
21 #include "llvm/InitializePasses.h"
25 OptimizationRemarkEmitter::OptimizationRemarkEmitter(const Function *F)
26 : F(F), BFI(nullptr) {
27 if (!F->getContext().getDiagnosticsHotnessRequested())
30 // First create a dominator tree.
32 DT.recalculate(*const_cast<Function *>(F));
34 // Generate LoopInfo from it.
38 // Then compute BranchProbabilityInfo.
39 BranchProbabilityInfo BPI(*F, LI);
41 // Finally compute BFI.
42 OwnedBFI = std::make_unique<BlockFrequencyInfo>(*F, BPI, LI);
46 bool OptimizationRemarkEmitter::invalidate(
47 Function &F, const PreservedAnalyses &PA,
48 FunctionAnalysisManager::Invalidator &Inv) {
53 // This analysis has no state and so can be trivially preserved but it needs
54 // a fresh view of BFI if it was constructed with one.
55 if (BFI && Inv.invalidate<BlockFrequencyAnalysis>(F, PA))
58 // Otherwise this analysis result remains valid.
62 Optional<uint64_t> OptimizationRemarkEmitter::computeHotness(const Value *V) {
66 return BFI->getBlockProfileCount(cast<BasicBlock>(V));
69 void OptimizationRemarkEmitter::computeHotness(
70 DiagnosticInfoIROptimization &OptDiag) {
71 const Value *V = OptDiag.getCodeRegion();
73 OptDiag.setHotness(computeHotness(V));
76 void OptimizationRemarkEmitter::emit(
77 DiagnosticInfoOptimizationBase &OptDiagBase) {
78 auto &OptDiag = cast<DiagnosticInfoIROptimization>(OptDiagBase);
79 computeHotness(OptDiag);
81 // Only emit it if its hotness meets the threshold.
82 if (OptDiag.getHotness().getValueOr(0) <
83 F->getContext().getDiagnosticsHotnessThreshold()) {
87 F->getContext().diagnose(OptDiag);
90 OptimizationRemarkEmitterWrapperPass::OptimizationRemarkEmitterWrapperPass()
92 initializeOptimizationRemarkEmitterWrapperPassPass(
93 *PassRegistry::getPassRegistry());
96 bool OptimizationRemarkEmitterWrapperPass::runOnFunction(Function &Fn) {
97 BlockFrequencyInfo *BFI;
99 if (Fn.getContext().getDiagnosticsHotnessRequested())
100 BFI = &getAnalysis<LazyBlockFrequencyInfoPass>().getBFI();
104 ORE = std::make_unique<OptimizationRemarkEmitter>(&Fn, BFI);
108 void OptimizationRemarkEmitterWrapperPass::getAnalysisUsage(
109 AnalysisUsage &AU) const {
110 LazyBlockFrequencyInfoPass::getLazyBFIAnalysisUsage(AU);
111 AU.setPreservesAll();
114 AnalysisKey OptimizationRemarkEmitterAnalysis::Key;
116 OptimizationRemarkEmitter
117 OptimizationRemarkEmitterAnalysis::run(Function &F,
118 FunctionAnalysisManager &AM) {
119 BlockFrequencyInfo *BFI;
121 if (F.getContext().getDiagnosticsHotnessRequested())
122 BFI = &AM.getResult<BlockFrequencyAnalysis>(F);
126 return OptimizationRemarkEmitter(&F, BFI);
129 char OptimizationRemarkEmitterWrapperPass::ID = 0;
130 static const char ore_name[] = "Optimization Remark Emitter";
131 #define ORE_NAME "opt-remark-emitter"
133 INITIALIZE_PASS_BEGIN(OptimizationRemarkEmitterWrapperPass, ORE_NAME, ore_name,
135 INITIALIZE_PASS_DEPENDENCY(LazyBFIPass)
136 INITIALIZE_PASS_END(OptimizationRemarkEmitterWrapperPass, ORE_NAME, ore_name,