1*0b57cec5SDimitry Andric ///===- MachineOptimizationRemarkEmitter.cpp - Opt Diagnostic -*- C++ -*---===//
2*0b57cec5SDimitry Andric ///
3*0b57cec5SDimitry Andric /// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0b57cec5SDimitry Andric /// See https://llvm.org/LICENSE.txt for license information.
5*0b57cec5SDimitry Andric /// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0b57cec5SDimitry Andric ///
7*0b57cec5SDimitry Andric ///===---------------------------------------------------------------------===//
8*0b57cec5SDimitry Andric /// \file
9*0b57cec5SDimitry Andric /// Optimization diagnostic interfaces for machine passes.  It's packaged as an
10*0b57cec5SDimitry Andric /// analysis pass so that by using this service passes become dependent on MBFI
11*0b57cec5SDimitry Andric /// as well.  MBFI is used to compute the "hotness" of the diagnostic message.
12*0b57cec5SDimitry Andric ///
13*0b57cec5SDimitry Andric ///===---------------------------------------------------------------------===//
14*0b57cec5SDimitry Andric 
15*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h"
16*0b57cec5SDimitry Andric #include "llvm/CodeGen/LazyMachineBlockFrequencyInfo.h"
17*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstr.h"
18*0b57cec5SDimitry Andric #include "llvm/IR/DiagnosticInfo.h"
19*0b57cec5SDimitry Andric #include "llvm/IR/LLVMContext.h"
20*0b57cec5SDimitry Andric #include "llvm/InitializePasses.h"
21*0b57cec5SDimitry Andric #include <optional>
22*0b57cec5SDimitry Andric 
23*0b57cec5SDimitry Andric using namespace llvm;
24*0b57cec5SDimitry Andric 
MachineArgument(StringRef MKey,const MachineInstr & MI)25*0b57cec5SDimitry Andric DiagnosticInfoMIROptimization::MachineArgument::MachineArgument(
26*0b57cec5SDimitry Andric     StringRef MKey, const MachineInstr &MI) {
27*0b57cec5SDimitry Andric   Key = std::string(MKey);
28*0b57cec5SDimitry Andric 
29*0b57cec5SDimitry Andric   raw_string_ostream OS(Val);
30*0b57cec5SDimitry Andric   MI.print(OS, /*IsStandalone=*/true, /*SkipOpers=*/false,
31*0b57cec5SDimitry Andric            /*SkipDebugLoc=*/true);
32*0b57cec5SDimitry Andric }
33*0b57cec5SDimitry Andric 
34*0b57cec5SDimitry Andric std::optional<uint64_t>
computeHotness(const MachineBasicBlock & MBB)35*0b57cec5SDimitry Andric MachineOptimizationRemarkEmitter::computeHotness(const MachineBasicBlock &MBB) {
36*0b57cec5SDimitry Andric   if (!MBFI)
37*0b57cec5SDimitry Andric     return std::nullopt;
38*0b57cec5SDimitry Andric 
39*0b57cec5SDimitry Andric   return MBFI->getBlockProfileCount(&MBB);
40*0b57cec5SDimitry Andric }
41*0b57cec5SDimitry Andric 
computeHotness(DiagnosticInfoMIROptimization & Remark)42*0b57cec5SDimitry Andric void MachineOptimizationRemarkEmitter::computeHotness(
43*0b57cec5SDimitry Andric     DiagnosticInfoMIROptimization &Remark) {
44*0b57cec5SDimitry Andric   const MachineBasicBlock *MBB = Remark.getBlock();
45*0b57cec5SDimitry Andric   if (MBB)
46*0b57cec5SDimitry Andric     Remark.setHotness(computeHotness(*MBB));
47*0b57cec5SDimitry Andric }
48*0b57cec5SDimitry Andric 
emit(DiagnosticInfoOptimizationBase & OptDiagCommon)49*0b57cec5SDimitry Andric void MachineOptimizationRemarkEmitter::emit(
50*0b57cec5SDimitry Andric     DiagnosticInfoOptimizationBase &OptDiagCommon) {
51*0b57cec5SDimitry Andric   auto &OptDiag = cast<DiagnosticInfoMIROptimization>(OptDiagCommon);
52*0b57cec5SDimitry Andric   computeHotness(OptDiag);
53*0b57cec5SDimitry Andric 
54*0b57cec5SDimitry Andric   LLVMContext &Ctx = MF.getFunction().getContext();
55*0b57cec5SDimitry Andric 
56*0b57cec5SDimitry Andric   // Only emit it if its hotness meets the threshold.
57*0b57cec5SDimitry Andric   if (OptDiag.getHotness().value_or(0) < Ctx.getDiagnosticsHotnessThreshold())
58*0b57cec5SDimitry Andric     return;
59*0b57cec5SDimitry Andric 
60*0b57cec5SDimitry Andric   Ctx.diagnose(OptDiag);
61*0b57cec5SDimitry Andric }
62*0b57cec5SDimitry Andric 
MachineOptimizationRemarkEmitterPass()63*0b57cec5SDimitry Andric MachineOptimizationRemarkEmitterPass::MachineOptimizationRemarkEmitterPass()
64*0b57cec5SDimitry Andric     : MachineFunctionPass(ID) {
65*0b57cec5SDimitry Andric   initializeMachineOptimizationRemarkEmitterPassPass(
66*0b57cec5SDimitry Andric       *PassRegistry::getPassRegistry());
67*0b57cec5SDimitry Andric }
68*0b57cec5SDimitry Andric 
runOnMachineFunction(MachineFunction & MF)69*0b57cec5SDimitry Andric bool MachineOptimizationRemarkEmitterPass::runOnMachineFunction(
70*0b57cec5SDimitry Andric     MachineFunction &MF) {
71*0b57cec5SDimitry Andric   MachineBlockFrequencyInfo *MBFI;
72*0b57cec5SDimitry Andric 
73*0b57cec5SDimitry Andric   if (MF.getFunction().getContext().getDiagnosticsHotnessRequested())
74*0b57cec5SDimitry Andric     MBFI = &getAnalysis<LazyMachineBlockFrequencyInfoPass>().getBFI();
75*0b57cec5SDimitry Andric   else
76*0b57cec5SDimitry Andric     MBFI = nullptr;
77*0b57cec5SDimitry Andric 
78*0b57cec5SDimitry Andric   ORE = std::make_unique<MachineOptimizationRemarkEmitter>(MF, MBFI);
79*0b57cec5SDimitry Andric   return false;
80*0b57cec5SDimitry Andric }
81*0b57cec5SDimitry Andric 
getAnalysisUsage(AnalysisUsage & AU) const82*0b57cec5SDimitry Andric void MachineOptimizationRemarkEmitterPass::getAnalysisUsage(
83*0b57cec5SDimitry Andric     AnalysisUsage &AU) const {
84*0b57cec5SDimitry Andric   AU.addRequired<LazyMachineBlockFrequencyInfoPass>();
85*0b57cec5SDimitry Andric   AU.setPreservesAll();
86*0b57cec5SDimitry Andric   MachineFunctionPass::getAnalysisUsage(AU);
87*0b57cec5SDimitry Andric }
88*0b57cec5SDimitry Andric 
89*0b57cec5SDimitry Andric char MachineOptimizationRemarkEmitterPass::ID = 0;
90*0b57cec5SDimitry Andric static const char ore_name[] = "Machine Optimization Remark Emitter";
91*0b57cec5SDimitry Andric #define ORE_NAME "machine-opt-remark-emitter"
92*0b57cec5SDimitry Andric 
93*0b57cec5SDimitry Andric INITIALIZE_PASS_BEGIN(MachineOptimizationRemarkEmitterPass, ORE_NAME, ore_name,
94*0b57cec5SDimitry Andric                       true, true)
95*0b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(LazyMachineBlockFrequencyInfoPass)
96*0b57cec5SDimitry Andric INITIALIZE_PASS_END(MachineOptimizationRemarkEmitterPass, ORE_NAME, ore_name,
97*0b57cec5SDimitry Andric                     true, true)
98*0b57cec5SDimitry Andric