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/DebugInfo.h" 20 #include "llvm/IR/DiagnosticInfo.h" 21 #include "llvm/IR/Dominators.h" 22 #include "llvm/IR/LLVMContext.h" 23 24 using namespace llvm; 25 26 OptimizationRemarkEmitter::OptimizationRemarkEmitter(const Function *F) 27 : F(F), BFI(nullptr) { 28 if (!F->getContext().getDiagnosticsHotnessRequested()) 29 return; 30 31 // First create a dominator tree. 32 DominatorTree DT; 33 DT.recalculate(*const_cast<Function *>(F)); 34 35 // Generate LoopInfo from it. 36 LoopInfo LI; 37 LI.analyze(DT); 38 39 // Then compute BranchProbabilityInfo. 40 BranchProbabilityInfo BPI; 41 BPI.calculate(*F, LI); 42 43 // Finally compute BFI. 44 OwnedBFI = llvm::make_unique<BlockFrequencyInfo>(*F, BPI, LI); 45 BFI = OwnedBFI.get(); 46 } 47 48 bool OptimizationRemarkEmitter::invalidate( 49 Function &F, const PreservedAnalyses &PA, 50 FunctionAnalysisManager::Invalidator &Inv) { 51 // This analysis has no state and so can be trivially preserved but it needs 52 // a fresh view of BFI if it was constructed with one. 53 if (BFI && Inv.invalidate<BlockFrequencyAnalysis>(F, PA)) 54 return true; 55 56 // Otherwise this analysis result remains valid. 57 return false; 58 } 59 60 Optional<uint64_t> OptimizationRemarkEmitter::computeHotness(const Value *V) { 61 if (!BFI) 62 return None; 63 64 return BFI->getBlockProfileCount(cast<BasicBlock>(V)); 65 } 66 67 void OptimizationRemarkEmitter::computeHotness( 68 DiagnosticInfoIROptimization &OptDiag) { 69 const Value *V = OptDiag.getCodeRegion(); 70 if (V) 71 OptDiag.setHotness(computeHotness(V)); 72 } 73 74 void OptimizationRemarkEmitter::emit( 75 DiagnosticInfoOptimizationBase &OptDiagBase) { 76 auto &OptDiag = cast<DiagnosticInfoIROptimization>(OptDiagBase); 77 computeHotness(OptDiag); 78 // If a diagnostic has a hotness value, then only emit it if its hotness 79 // meets the threshold. 80 if (OptDiag.getHotness() && 81 *OptDiag.getHotness() < 82 F->getContext().getDiagnosticsHotnessThreshold()) { 83 return; 84 } 85 86 F->getContext().diagnose(OptDiag); 87 } 88 89 OptimizationRemarkEmitterWrapperPass::OptimizationRemarkEmitterWrapperPass() 90 : FunctionPass(ID) { 91 initializeOptimizationRemarkEmitterWrapperPassPass( 92 *PassRegistry::getPassRegistry()); 93 } 94 95 bool OptimizationRemarkEmitterWrapperPass::runOnFunction(Function &Fn) { 96 BlockFrequencyInfo *BFI; 97 98 if (Fn.getContext().getDiagnosticsHotnessRequested()) 99 BFI = &getAnalysis<LazyBlockFrequencyInfoPass>().getBFI(); 100 else 101 BFI = nullptr; 102 103 ORE = llvm::make_unique<OptimizationRemarkEmitter>(&Fn, BFI); 104 return false; 105 } 106 107 void OptimizationRemarkEmitterWrapperPass::getAnalysisUsage( 108 AnalysisUsage &AU) const { 109 LazyBlockFrequencyInfoPass::getLazyBFIAnalysisUsage(AU); 110 AU.setPreservesAll(); 111 } 112 113 AnalysisKey OptimizationRemarkEmitterAnalysis::Key; 114 115 OptimizationRemarkEmitter 116 OptimizationRemarkEmitterAnalysis::run(Function &F, 117 FunctionAnalysisManager &AM) { 118 BlockFrequencyInfo *BFI; 119 120 if (F.getContext().getDiagnosticsHotnessRequested()) 121 BFI = &AM.getResult<BlockFrequencyAnalysis>(F); 122 else 123 BFI = nullptr; 124 125 return OptimizationRemarkEmitter(&F, BFI); 126 } 127 128 char OptimizationRemarkEmitterWrapperPass::ID = 0; 129 static const char ore_name[] = "Optimization Remark Emitter"; 130 #define ORE_NAME "opt-remark-emitter" 131 132 INITIALIZE_PASS_BEGIN(OptimizationRemarkEmitterWrapperPass, ORE_NAME, ore_name, 133 false, true) 134 INITIALIZE_PASS_DEPENDENCY(LazyBFIPass) 135 INITIALIZE_PASS_END(OptimizationRemarkEmitterWrapperPass, ORE_NAME, ore_name, 136 false, true) 137