OptimizationRemarkEmitter.cpp 5.2 KB

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