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 79 // Only emit it if its hotness meets the threshold. 80 if (OptDiag.getHotness().getValueOr(0) < 81 F->getContext().getDiagnosticsHotnessThreshold()) { 82 return; 83 } 84 85 F->getContext().diagnose(OptDiag); 86 } 87 88 OptimizationRemarkEmitterWrapperPass::OptimizationRemarkEmitterWrapperPass() 89 : FunctionPass(ID) { 90 initializeOptimizationRemarkEmitterWrapperPassPass( 91 *PassRegistry::getPassRegistry()); 92 } 93 94 bool OptimizationRemarkEmitterWrapperPass::runOnFunction(Function &Fn) { 95 BlockFrequencyInfo *BFI; 96 97 if (Fn.getContext().getDiagnosticsHotnessRequested()) 98 BFI = &getAnalysis<LazyBlockFrequencyInfoPass>().getBFI(); 99 else 100 BFI = nullptr; 101 102 ORE = llvm::make_unique<OptimizationRemarkEmitter>(&Fn, BFI); 103 return false; 104 } 105 106 void OptimizationRemarkEmitterWrapperPass::getAnalysisUsage( 107 AnalysisUsage &AU) const { 108 LazyBlockFrequencyInfoPass::getLazyBFIAnalysisUsage(AU); 109 AU.setPreservesAll(); 110 } 111 112 AnalysisKey OptimizationRemarkEmitterAnalysis::Key; 113 114 OptimizationRemarkEmitter 115 OptimizationRemarkEmitterAnalysis::run(Function &F, 116 FunctionAnalysisManager &AM) { 117 BlockFrequencyInfo *BFI; 118 119 if (F.getContext().getDiagnosticsHotnessRequested()) 120 BFI = &AM.getResult<BlockFrequencyAnalysis>(F); 121 else 122 BFI = nullptr; 123 124 return OptimizationRemarkEmitter(&F, BFI); 125 } 126 127 char OptimizationRemarkEmitterWrapperPass::ID = 0; 128 static const char ore_name[] = "Optimization Remark Emitter"; 129 #define ORE_NAME "opt-remark-emitter" 130 131 INITIALIZE_PASS_BEGIN(OptimizationRemarkEmitterWrapperPass, ORE_NAME, ore_name, 132 false, true) 133 INITIALIZE_PASS_DEPENDENCY(LazyBFIPass) 134 INITIALIZE_PASS_END(OptimizationRemarkEmitterWrapperPass, ORE_NAME, ore_name, 135 false, true) 136