brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.1 KiB · fbb5971 Raw
157 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8//9// Optimization diagnostic interfaces.  It's packaged as an analysis pass so10// that by using this service passes become dependent on BFI as well.  BFI is11// used to compute the "hotness" of the diagnostic message.12//===----------------------------------------------------------------------===//13 14#include "llvm/Analysis/OptimizationRemarkEmitter.h"15#include "llvm/Analysis/BranchProbabilityInfo.h"16#include "llvm/Analysis/LazyBlockFrequencyInfo.h"17#include "llvm/Analysis/LoopInfo.h"18#include "llvm/Analysis/ProfileSummaryInfo.h"19#include "llvm/IR/DiagnosticInfo.h"20#include "llvm/IR/Dominators.h"21#include "llvm/IR/LLVMContext.h"22#include "llvm/InitializePasses.h"23#include <optional>24 25using namespace llvm;26 27OptimizationRemarkEmitter::OptimizationRemarkEmitter(const Function *F)28    : F(F), BFI(nullptr) {29  if (!F->getContext().getDiagnosticsHotnessRequested())30    return;31 32  // First create a dominator tree.33  DominatorTree DT;34  DT.recalculate(*const_cast<Function *>(F));35 36  // Generate LoopInfo from it.37  LoopInfo LI;38  LI.analyze(DT);39 40  // Then compute BranchProbabilityInfo.41  BranchProbabilityInfo BPI(*F, LI, nullptr, &DT, nullptr);42 43  // Finally compute BFI.44  OwnedBFI = std::make_unique<BlockFrequencyInfo>(*F, BPI, LI);45  BFI = OwnedBFI.get();46}47 48bool OptimizationRemarkEmitter::invalidate(49    Function &F, const PreservedAnalyses &PA,50    FunctionAnalysisManager::Invalidator &Inv) {51  if (OwnedBFI) {52    OwnedBFI.reset();53    BFI = nullptr;54  }55  // This analysis has no state and so can be trivially preserved but it needs56  // a fresh view of BFI if it was constructed with one.57  if (BFI && Inv.invalidate<BlockFrequencyAnalysis>(F, PA))58    return true;59 60  // Otherwise this analysis result remains valid.61  return false;62}63 64std::optional<uint64_t>65OptimizationRemarkEmitter::computeHotness(const Value *V) {66  if (!BFI)67    return std::nullopt;68 69  return BFI->getBlockProfileCount(cast<BasicBlock>(V));70}71 72void OptimizationRemarkEmitter::computeHotness(73    DiagnosticInfoIROptimization &OptDiag) {74  const Value *V = OptDiag.getCodeRegion();75  if (V)76    OptDiag.setHotness(computeHotness(V));77}78 79void OptimizationRemarkEmitter::emit(80    DiagnosticInfoOptimizationBase &OptDiagBase) {81  auto &OptDiag = cast<DiagnosticInfoIROptimization>(OptDiagBase);82  computeHotness(OptDiag);83 84  // Only emit it if its hotness meets the threshold.85  if (OptDiag.getHotness().value_or(0) <86      F->getContext().getDiagnosticsHotnessThreshold()) {87    return;88  }89 90  F->getContext().diagnose(OptDiag);91}92 93OptimizationRemarkEmitterWrapperPass::OptimizationRemarkEmitterWrapperPass()94    : FunctionPass(ID) {}95 96bool OptimizationRemarkEmitterWrapperPass::runOnFunction(Function &Fn) {97  BlockFrequencyInfo *BFI;98 99  auto &Context = Fn.getContext();100  if (Context.getDiagnosticsHotnessRequested()) {101    BFI = &getAnalysis<LazyBlockFrequencyInfoPass>().getBFI();102    // Get hotness threshold from PSI. This should only happen once.103    if (Context.isDiagnosticsHotnessThresholdSetFromPSI()) {104      if (ProfileSummaryInfo *PSI =105              &getAnalysis<ProfileSummaryInfoWrapperPass>().getPSI())106        Context.setDiagnosticsHotnessThreshold(107            PSI->getOrCompHotCountThreshold());108    }109  } else110    BFI = nullptr;111 112  ORE = std::make_unique<OptimizationRemarkEmitter>(&Fn, BFI);113  return false;114}115 116void OptimizationRemarkEmitterWrapperPass::getAnalysisUsage(117    AnalysisUsage &AU) const {118  LazyBlockFrequencyInfoPass::getLazyBFIAnalysisUsage(AU);119  AU.addRequired<ProfileSummaryInfoWrapperPass>();120  AU.setPreservesAll();121}122 123AnalysisKey OptimizationRemarkEmitterAnalysis::Key;124 125OptimizationRemarkEmitter126OptimizationRemarkEmitterAnalysis::run(Function &F,127                                       FunctionAnalysisManager &AM) {128  BlockFrequencyInfo *BFI;129  auto &Context = F.getContext();130 131  if (Context.getDiagnosticsHotnessRequested()) {132    BFI = &AM.getResult<BlockFrequencyAnalysis>(F);133    // Get hotness threshold from PSI. This should only happen once.134    if (Context.isDiagnosticsHotnessThresholdSetFromPSI()) {135      auto &MAMProxy = AM.getResult<ModuleAnalysisManagerFunctionProxy>(F);136      if (ProfileSummaryInfo *PSI =137              MAMProxy.getCachedResult<ProfileSummaryAnalysis>(*F.getParent()))138        Context.setDiagnosticsHotnessThreshold(139            PSI->getOrCompHotCountThreshold());140    }141  } else142    BFI = nullptr;143 144  return OptimizationRemarkEmitter(&F, BFI);145}146 147char OptimizationRemarkEmitterWrapperPass::ID = 0;148static const char ore_name[] = "Optimization Remark Emitter";149#define ORE_NAME "opt-remark-emitter"150 151INITIALIZE_PASS_BEGIN(OptimizationRemarkEmitterWrapperPass, ORE_NAME, ore_name,152                      false, true)153INITIALIZE_PASS_DEPENDENCY(LazyBFIPass)154INITIALIZE_PASS_DEPENDENCY(ProfileSummaryInfoWrapperPass)155INITIALIZE_PASS_END(OptimizationRemarkEmitterWrapperPass, ORE_NAME, ore_name,156                    false, true)157