OptimizationRemarkEmitter.cpp revision 341825
1//===- OptimizationRemarkEmitter.cpp - Optimization Diagnostic --*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// Optimization diagnostic interfaces.  It's packaged as an analysis pass so
11// that by using this service passes become dependent on BFI as well.  BFI is
12// used to compute the "hotness" of the diagnostic message.
13//===----------------------------------------------------------------------===//
14
15#include "llvm/Analysis/OptimizationRemarkEmitter.h"
16#include "llvm/Analysis/BranchProbabilityInfo.h"
17#include "llvm/Analysis/LazyBlockFrequencyInfo.h"
18#include "llvm/Analysis/LoopInfo.h"
19#include "llvm/IR/DiagnosticInfo.h"
20#include "llvm/IR/Dominators.h"
21#include "llvm/IR/LLVMContext.h"
22
23using namespace llvm;
24
25OptimizationRemarkEmitter::OptimizationRemarkEmitter(const Function *F)
26    : F(F), BFI(nullptr) {
27  if (!F->getContext().getDiagnosticsHotnessRequested())
28    return;
29
30  // First create a dominator tree.
31  DominatorTree DT;
32  DT.recalculate(*const_cast<Function *>(F));
33
34  // Generate LoopInfo from it.
35  LoopInfo LI;
36  LI.analyze(DT);
37
38  // Then compute BranchProbabilityInfo.
39  BranchProbabilityInfo BPI;
40  BPI.calculate(*F, LI);
41
42  // Finally compute BFI.
43  OwnedBFI = llvm::make_unique<BlockFrequencyInfo>(*F, BPI, LI);
44  BFI = OwnedBFI.get();
45}
46
47bool OptimizationRemarkEmitter::invalidate(
48    Function &F, const PreservedAnalyses &PA,
49    FunctionAnalysisManager::Invalidator &Inv) {
50  // This analysis has no state and so can be trivially preserved but it needs
51  // a fresh view of BFI if it was constructed with one.
52  if (BFI && Inv.invalidate<BlockFrequencyAnalysis>(F, PA))
53    return true;
54
55  // Otherwise this analysis result remains valid.
56  return false;
57}
58
59Optional<uint64_t> OptimizationRemarkEmitter::computeHotness(const Value *V) {
60  if (!BFI)
61    return None;
62
63  return BFI->getBlockProfileCount(cast<BasicBlock>(V));
64}
65
66void OptimizationRemarkEmitter::computeHotness(
67    DiagnosticInfoIROptimization &OptDiag) {
68  const Value *V = OptDiag.getCodeRegion();
69  if (V)
70    OptDiag.setHotness(computeHotness(V));
71}
72
73void OptimizationRemarkEmitter::emit(
74    DiagnosticInfoOptimizationBase &OptDiagBase) {
75  auto &OptDiag = cast<DiagnosticInfoIROptimization>(OptDiagBase);
76  computeHotness(OptDiag);
77
78  // Only emit it if its hotness meets the threshold.
79  if (OptDiag.getHotness().getValueOr(0) <
80      F->getContext().getDiagnosticsHotnessThreshold()) {
81    return;
82  }
83
84  F->getContext().diagnose(OptDiag);
85}
86
87OptimizationRemarkEmitterWrapperPass::OptimizationRemarkEmitterWrapperPass()
88    : FunctionPass(ID) {
89  initializeOptimizationRemarkEmitterWrapperPassPass(
90      *PassRegistry::getPassRegistry());
91}
92
93bool OptimizationRemarkEmitterWrapperPass::runOnFunction(Function &Fn) {
94  BlockFrequencyInfo *BFI;
95
96  if (Fn.getContext().getDiagnosticsHotnessRequested())
97    BFI = &getAnalysis<LazyBlockFrequencyInfoPass>().getBFI();
98  else
99    BFI = nullptr;
100
101  ORE = llvm::make_unique<OptimizationRemarkEmitter>(&Fn, BFI);
102  return false;
103}
104
105void OptimizationRemarkEmitterWrapperPass::getAnalysisUsage(
106    AnalysisUsage &AU) const {
107  LazyBlockFrequencyInfoPass::getLazyBFIAnalysisUsage(AU);
108  AU.setPreservesAll();
109}
110
111AnalysisKey OptimizationRemarkEmitterAnalysis::Key;
112
113OptimizationRemarkEmitter
114OptimizationRemarkEmitterAnalysis::run(Function &F,
115                                       FunctionAnalysisManager &AM) {
116  BlockFrequencyInfo *BFI;
117
118  if (F.getContext().getDiagnosticsHotnessRequested())
119    BFI = &AM.getResult<BlockFrequencyAnalysis>(F);
120  else
121    BFI = nullptr;
122
123  return OptimizationRemarkEmitter(&F, BFI);
124}
125
126char OptimizationRemarkEmitterWrapperPass::ID = 0;
127static const char ore_name[] = "Optimization Remark Emitter";
128#define ORE_NAME "opt-remark-emitter"
129
130INITIALIZE_PASS_BEGIN(OptimizationRemarkEmitterWrapperPass, ORE_NAME, ore_name,
131                      false, true)
132INITIALIZE_PASS_DEPENDENCY(LazyBFIPass)
133INITIALIZE_PASS_END(OptimizationRemarkEmitterWrapperPass, ORE_NAME, ore_name,
134                    false, true)
135