123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157 |
- //===- OptimizationRemarkEmitter.cpp - Optimization Diagnostic --*- C++ -*-===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- //
- // Optimization diagnostic interfaces. It's packaged as an analysis pass so
- // that by using this service passes become dependent on BFI as well. BFI is
- // used to compute the "hotness" of the diagnostic message.
- //===----------------------------------------------------------------------===//
- #include "llvm/Analysis/OptimizationRemarkEmitter.h"
- #include "llvm/Analysis/BranchProbabilityInfo.h"
- #include "llvm/Analysis/LazyBlockFrequencyInfo.h"
- #include "llvm/Analysis/LoopInfo.h"
- #include "llvm/Analysis/ProfileSummaryInfo.h"
- #include "llvm/IR/DiagnosticInfo.h"
- #include "llvm/IR/Dominators.h"
- #include "llvm/IR/LLVMContext.h"
- #include "llvm/InitializePasses.h"
- using namespace llvm;
- OptimizationRemarkEmitter::OptimizationRemarkEmitter(const Function *F)
- : F(F), BFI(nullptr) {
- if (!F->getContext().getDiagnosticsHotnessRequested())
- return;
- // First create a dominator tree.
- DominatorTree DT;
- DT.recalculate(*const_cast<Function *>(F));
- // Generate LoopInfo from it.
- LoopInfo LI;
- LI.analyze(DT);
- // Then compute BranchProbabilityInfo.
- BranchProbabilityInfo BPI(*F, LI, nullptr, &DT, nullptr);
- // Finally compute BFI.
- OwnedBFI = std::make_unique<BlockFrequencyInfo>(*F, BPI, LI);
- BFI = OwnedBFI.get();
- }
- bool OptimizationRemarkEmitter::invalidate(
- Function &F, const PreservedAnalyses &PA,
- FunctionAnalysisManager::Invalidator &Inv) {
- if (OwnedBFI.get()) {
- OwnedBFI.reset();
- BFI = nullptr;
- }
- // This analysis has no state and so can be trivially preserved but it needs
- // a fresh view of BFI if it was constructed with one.
- if (BFI && Inv.invalidate<BlockFrequencyAnalysis>(F, PA))
- return true;
- // Otherwise this analysis result remains valid.
- return false;
- }
- Optional<uint64_t> OptimizationRemarkEmitter::computeHotness(const Value *V) {
- if (!BFI)
- return None;
- return BFI->getBlockProfileCount(cast<BasicBlock>(V));
- }
- void OptimizationRemarkEmitter::computeHotness(
- DiagnosticInfoIROptimization &OptDiag) {
- const Value *V = OptDiag.getCodeRegion();
- if (V)
- OptDiag.setHotness(computeHotness(V));
- }
- void OptimizationRemarkEmitter::emit(
- DiagnosticInfoOptimizationBase &OptDiagBase) {
- auto &OptDiag = cast<DiagnosticInfoIROptimization>(OptDiagBase);
- computeHotness(OptDiag);
- // Only emit it if its hotness meets the threshold.
- if (OptDiag.getHotness().getValueOr(0) <
- F->getContext().getDiagnosticsHotnessThreshold()) {
- return;
- }
- F->getContext().diagnose(OptDiag);
- }
- OptimizationRemarkEmitterWrapperPass::OptimizationRemarkEmitterWrapperPass()
- : FunctionPass(ID) {
- initializeOptimizationRemarkEmitterWrapperPassPass(
- *PassRegistry::getPassRegistry());
- }
- bool OptimizationRemarkEmitterWrapperPass::runOnFunction(Function &Fn) {
- BlockFrequencyInfo *BFI;
- auto &Context = Fn.getContext();
- if (Context.getDiagnosticsHotnessRequested()) {
- BFI = &getAnalysis<LazyBlockFrequencyInfoPass>().getBFI();
- // Get hotness threshold from PSI. This should only happen once.
- if (Context.isDiagnosticsHotnessThresholdSetFromPSI()) {
- if (ProfileSummaryInfo *PSI =
- &getAnalysis<ProfileSummaryInfoWrapperPass>().getPSI())
- Context.setDiagnosticsHotnessThreshold(
- PSI->getOrCompHotCountThreshold());
- }
- } else
- BFI = nullptr;
- ORE = std::make_unique<OptimizationRemarkEmitter>(&Fn, BFI);
- return false;
- }
- void OptimizationRemarkEmitterWrapperPass::getAnalysisUsage(
- AnalysisUsage &AU) const {
- LazyBlockFrequencyInfoPass::getLazyBFIAnalysisUsage(AU);
- AU.addRequired<ProfileSummaryInfoWrapperPass>();
- AU.setPreservesAll();
- }
- AnalysisKey OptimizationRemarkEmitterAnalysis::Key;
- OptimizationRemarkEmitter
- OptimizationRemarkEmitterAnalysis::run(Function &F,
- FunctionAnalysisManager &AM) {
- BlockFrequencyInfo *BFI;
- auto &Context = F.getContext();
- if (Context.getDiagnosticsHotnessRequested()) {
- BFI = &AM.getResult<BlockFrequencyAnalysis>(F);
- // Get hotness threshold from PSI. This should only happen once.
- if (Context.isDiagnosticsHotnessThresholdSetFromPSI()) {
- auto &MAMProxy = AM.getResult<ModuleAnalysisManagerFunctionProxy>(F);
- if (ProfileSummaryInfo *PSI =
- MAMProxy.getCachedResult<ProfileSummaryAnalysis>(*F.getParent()))
- Context.setDiagnosticsHotnessThreshold(
- PSI->getOrCompHotCountThreshold());
- }
- } else
- BFI = nullptr;
- return OptimizationRemarkEmitter(&F, BFI);
- }
- char OptimizationRemarkEmitterWrapperPass::ID = 0;
- static const char ore_name[] = "Optimization Remark Emitter";
- #define ORE_NAME "opt-remark-emitter"
- INITIALIZE_PASS_BEGIN(OptimizationRemarkEmitterWrapperPass, ORE_NAME, ore_name,
- false, true)
- INITIALIZE_PASS_DEPENDENCY(LazyBFIPass)
- INITIALIZE_PASS_DEPENDENCY(ProfileSummaryInfoWrapperPass)
- INITIALIZE_PASS_END(OptimizationRemarkEmitterWrapperPass, ORE_NAME, ore_name,
- false, true)
|