[ORC] Add std::tuple support to SimplePackedSerialization.
[llvm-project.git] / llvm / lib / Analysis / OptimizationRemarkEmitter.cpp
blob6f3d4d536c40144a8f5519346ee3f4669a55925f
1 //===- OptimizationRemarkEmitter.cpp - Optimization Diagnostic --*- C++ -*-===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8 //
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/Analysis/ProfileSummaryInfo.h"
19 #include "llvm/IR/DiagnosticInfo.h"
20 #include "llvm/IR/Dominators.h"
21 #include "llvm/IR/LLVMContext.h"
22 #include "llvm/InitializePasses.h"
24 using namespace llvm;
26 OptimizationRemarkEmitter::OptimizationRemarkEmitter(const Function *F)
27 : F(F), BFI(nullptr) {
28 if (!F->getContext().getDiagnosticsHotnessRequested())
29 return;
31 // First create a dominator tree.
32 DominatorTree DT;
33 DT.recalculate(*const_cast<Function *>(F));
35 // Generate LoopInfo from it.
36 LoopInfo LI;
37 LI.analyze(DT);
39 // Then compute BranchProbabilityInfo.
40 BranchProbabilityInfo BPI(*F, LI, nullptr, &DT, nullptr);
42 // Finally compute BFI.
43 OwnedBFI = std::make_unique<BlockFrequencyInfo>(*F, BPI, LI);
44 BFI = OwnedBFI.get();
47 bool OptimizationRemarkEmitter::invalidate(
48 Function &F, const PreservedAnalyses &PA,
49 FunctionAnalysisManager::Invalidator &Inv) {
50 if (OwnedBFI.get()) {
51 OwnedBFI.reset();
52 BFI = nullptr;
54 // This analysis has no state and so can be trivially preserved but it needs
55 // a fresh view of BFI if it was constructed with one.
56 if (BFI && Inv.invalidate<BlockFrequencyAnalysis>(F, PA))
57 return true;
59 // Otherwise this analysis result remains valid.
60 return false;
63 Optional<uint64_t> OptimizationRemarkEmitter::computeHotness(const Value *V) {
64 if (!BFI)
65 return None;
67 return BFI->getBlockProfileCount(cast<BasicBlock>(V));
70 void OptimizationRemarkEmitter::computeHotness(
71 DiagnosticInfoIROptimization &OptDiag) {
72 const Value *V = OptDiag.getCodeRegion();
73 if (V)
74 OptDiag.setHotness(computeHotness(V));
77 void OptimizationRemarkEmitter::emit(
78 DiagnosticInfoOptimizationBase &OptDiagBase) {
79 auto &OptDiag = cast<DiagnosticInfoIROptimization>(OptDiagBase);
80 computeHotness(OptDiag);
82 // Only emit it if its hotness meets the threshold.
83 if (OptDiag.getHotness().getValueOr(0) <
84 F->getContext().getDiagnosticsHotnessThreshold()) {
85 return;
88 F->getContext().diagnose(OptDiag);
91 OptimizationRemarkEmitterWrapperPass::OptimizationRemarkEmitterWrapperPass()
92 : FunctionPass(ID) {
93 initializeOptimizationRemarkEmitterWrapperPassPass(
94 *PassRegistry::getPassRegistry());
97 bool OptimizationRemarkEmitterWrapperPass::runOnFunction(Function &Fn) {
98 BlockFrequencyInfo *BFI;
100 auto &Context = Fn.getContext();
101 if (Context.getDiagnosticsHotnessRequested()) {
102 BFI = &getAnalysis<LazyBlockFrequencyInfoPass>().getBFI();
103 // Get hotness threshold from PSI. This should only happen once.
104 if (Context.isDiagnosticsHotnessThresholdSetFromPSI()) {
105 if (ProfileSummaryInfo *PSI =
106 &getAnalysis<ProfileSummaryInfoWrapperPass>().getPSI())
107 Context.setDiagnosticsHotnessThreshold(
108 PSI->getOrCompHotCountThreshold());
110 } else
111 BFI = nullptr;
113 ORE = std::make_unique<OptimizationRemarkEmitter>(&Fn, BFI);
114 return false;
117 void OptimizationRemarkEmitterWrapperPass::getAnalysisUsage(
118 AnalysisUsage &AU) const {
119 LazyBlockFrequencyInfoPass::getLazyBFIAnalysisUsage(AU);
120 AU.addRequired<ProfileSummaryInfoWrapperPass>();
121 AU.setPreservesAll();
124 AnalysisKey OptimizationRemarkEmitterAnalysis::Key;
126 OptimizationRemarkEmitter
127 OptimizationRemarkEmitterAnalysis::run(Function &F,
128 FunctionAnalysisManager &AM) {
129 BlockFrequencyInfo *BFI;
130 auto &Context = F.getContext();
132 if (Context.getDiagnosticsHotnessRequested()) {
133 BFI = &AM.getResult<BlockFrequencyAnalysis>(F);
134 // Get hotness threshold from PSI. This should only happen once.
135 if (Context.isDiagnosticsHotnessThresholdSetFromPSI()) {
136 auto &MAMProxy = AM.getResult<ModuleAnalysisManagerFunctionProxy>(F);
137 if (ProfileSummaryInfo *PSI =
138 MAMProxy.getCachedResult<ProfileSummaryAnalysis>(*F.getParent()))
139 Context.setDiagnosticsHotnessThreshold(
140 PSI->getOrCompHotCountThreshold());
142 } else
143 BFI = nullptr;
145 return OptimizationRemarkEmitter(&F, BFI);
148 char OptimizationRemarkEmitterWrapperPass::ID = 0;
149 static const char ore_name[] = "Optimization Remark Emitter";
150 #define ORE_NAME "opt-remark-emitter"
152 INITIALIZE_PASS_BEGIN(OptimizationRemarkEmitterWrapperPass, ORE_NAME, ore_name,
153 false, true)
154 INITIALIZE_PASS_DEPENDENCY(LazyBFIPass)
155 INITIALIZE_PASS_DEPENDENCY(ProfileSummaryInfoWrapperPass)
156 INITIALIZE_PASS_END(OptimizationRemarkEmitterWrapperPass, ORE_NAME, ore_name,
157 false, true)