xref: /src/contrib/llvm-project/llvm/lib/CodeGen/MachineOptimizationRemarkEmitter.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
171d5a254SDimitry Andric ///===- MachineOptimizationRemarkEmitter.cpp - Opt Diagnostic -*- C++ -*---===//
271d5a254SDimitry Andric ///
3e6d15924SDimitry Andric /// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e6d15924SDimitry Andric /// See https://llvm.org/LICENSE.txt for license information.
5e6d15924SDimitry Andric /// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
671d5a254SDimitry Andric ///
771d5a254SDimitry Andric ///===---------------------------------------------------------------------===//
871d5a254SDimitry Andric /// \file
971d5a254SDimitry Andric /// Optimization diagnostic interfaces for machine passes.  It's packaged as an
1071d5a254SDimitry Andric /// analysis pass so that by using this service passes become dependent on MBFI
1171d5a254SDimitry Andric /// as well.  MBFI is used to compute the "hotness" of the diagnostic message.
1271d5a254SDimitry Andric ///
1371d5a254SDimitry Andric ///===---------------------------------------------------------------------===//
1471d5a254SDimitry Andric 
1571d5a254SDimitry Andric #include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h"
1671d5a254SDimitry Andric #include "llvm/CodeGen/LazyMachineBlockFrequencyInfo.h"
1771d5a254SDimitry Andric #include "llvm/CodeGen/MachineInstr.h"
1871d5a254SDimitry Andric #include "llvm/IR/DiagnosticInfo.h"
1971d5a254SDimitry Andric #include "llvm/IR/LLVMContext.h"
20706b4fc4SDimitry Andric #include "llvm/InitializePasses.h"
21e3b55780SDimitry Andric #include <optional>
2271d5a254SDimitry Andric 
2371d5a254SDimitry Andric using namespace llvm;
2471d5a254SDimitry Andric 
MachineArgument(StringRef MKey,const MachineInstr & MI)2571d5a254SDimitry Andric DiagnosticInfoMIROptimization::MachineArgument::MachineArgument(
266f8fc217SDimitry Andric     StringRef MKey, const MachineInstr &MI) {
27cfca06d7SDimitry Andric   Key = std::string(MKey);
2871d5a254SDimitry Andric 
2971d5a254SDimitry Andric   raw_string_ostream OS(Val);
30eb11fae6SDimitry Andric   MI.print(OS, /*IsStandalone=*/true, /*SkipOpers=*/false,
31eb11fae6SDimitry Andric            /*SkipDebugLoc=*/true);
3271d5a254SDimitry Andric }
3371d5a254SDimitry Andric 
invalidate(MachineFunction & MF,const PreservedAnalyses & PA,MachineFunctionAnalysisManager::Invalidator & Inv)34ac9a064cSDimitry Andric bool MachineOptimizationRemarkEmitter::invalidate(
35ac9a064cSDimitry Andric     MachineFunction &MF, const PreservedAnalyses &PA,
36ac9a064cSDimitry Andric     MachineFunctionAnalysisManager::Invalidator &Inv) {
37ac9a064cSDimitry Andric   // This analysis has no state and so can be trivially preserved but it needs
38ac9a064cSDimitry Andric   // a fresh view of BFI if it was constructed with one.
39ac9a064cSDimitry Andric   return MBFI && Inv.invalidate<MachineBlockFrequencyAnalysis>(MF, PA);
40ac9a064cSDimitry Andric }
41ac9a064cSDimitry Andric 
42e3b55780SDimitry Andric std::optional<uint64_t>
computeHotness(const MachineBasicBlock & MBB)4371d5a254SDimitry Andric MachineOptimizationRemarkEmitter::computeHotness(const MachineBasicBlock &MBB) {
4471d5a254SDimitry Andric   if (!MBFI)
45e3b55780SDimitry Andric     return std::nullopt;
4671d5a254SDimitry Andric 
4771d5a254SDimitry Andric   return MBFI->getBlockProfileCount(&MBB);
4871d5a254SDimitry Andric }
4971d5a254SDimitry Andric 
computeHotness(DiagnosticInfoMIROptimization & Remark)5071d5a254SDimitry Andric void MachineOptimizationRemarkEmitter::computeHotness(
5171d5a254SDimitry Andric     DiagnosticInfoMIROptimization &Remark) {
5271d5a254SDimitry Andric   const MachineBasicBlock *MBB = Remark.getBlock();
5371d5a254SDimitry Andric   if (MBB)
5471d5a254SDimitry Andric     Remark.setHotness(computeHotness(*MBB));
5571d5a254SDimitry Andric }
5671d5a254SDimitry Andric 
emit(DiagnosticInfoOptimizationBase & OptDiagCommon)5771d5a254SDimitry Andric void MachineOptimizationRemarkEmitter::emit(
5871d5a254SDimitry Andric     DiagnosticInfoOptimizationBase &OptDiagCommon) {
5971d5a254SDimitry Andric   auto &OptDiag = cast<DiagnosticInfoMIROptimization>(OptDiagCommon);
6071d5a254SDimitry Andric   computeHotness(OptDiag);
6171d5a254SDimitry Andric 
62044eb2f6SDimitry Andric   LLVMContext &Ctx = MF.getFunction().getContext();
639df3605dSDimitry Andric 
64044eb2f6SDimitry Andric   // Only emit it if its hotness meets the threshold.
65145449b1SDimitry Andric   if (OptDiag.getHotness().value_or(0) < Ctx.getDiagnosticsHotnessThreshold())
669df3605dSDimitry Andric     return;
679df3605dSDimitry Andric 
6871d5a254SDimitry Andric   Ctx.diagnose(OptDiag);
6971d5a254SDimitry Andric }
7071d5a254SDimitry Andric 
MachineOptimizationRemarkEmitterPass()7171d5a254SDimitry Andric MachineOptimizationRemarkEmitterPass::MachineOptimizationRemarkEmitterPass()
7271d5a254SDimitry Andric     : MachineFunctionPass(ID) {
7371d5a254SDimitry Andric   initializeMachineOptimizationRemarkEmitterPassPass(
7471d5a254SDimitry Andric       *PassRegistry::getPassRegistry());
7571d5a254SDimitry Andric }
7671d5a254SDimitry Andric 
runOnMachineFunction(MachineFunction & MF)7771d5a254SDimitry Andric bool MachineOptimizationRemarkEmitterPass::runOnMachineFunction(
7871d5a254SDimitry Andric     MachineFunction &MF) {
7971d5a254SDimitry Andric   MachineBlockFrequencyInfo *MBFI;
8071d5a254SDimitry Andric 
81044eb2f6SDimitry Andric   if (MF.getFunction().getContext().getDiagnosticsHotnessRequested())
8271d5a254SDimitry Andric     MBFI = &getAnalysis<LazyMachineBlockFrequencyInfoPass>().getBFI();
8371d5a254SDimitry Andric   else
8471d5a254SDimitry Andric     MBFI = nullptr;
8571d5a254SDimitry Andric 
861d5ae102SDimitry Andric   ORE = std::make_unique<MachineOptimizationRemarkEmitter>(MF, MBFI);
8771d5a254SDimitry Andric   return false;
8871d5a254SDimitry Andric }
8971d5a254SDimitry Andric 
getAnalysisUsage(AnalysisUsage & AU) const9071d5a254SDimitry Andric void MachineOptimizationRemarkEmitterPass::getAnalysisUsage(
9171d5a254SDimitry Andric     AnalysisUsage &AU) const {
9271d5a254SDimitry Andric   AU.addRequired<LazyMachineBlockFrequencyInfoPass>();
9371d5a254SDimitry Andric   AU.setPreservesAll();
9471d5a254SDimitry Andric   MachineFunctionPass::getAnalysisUsage(AU);
9571d5a254SDimitry Andric }
9671d5a254SDimitry Andric 
97ac9a064cSDimitry Andric AnalysisKey MachineOptimizationRemarkEmitterAnalysis::Key;
98ac9a064cSDimitry Andric 
99ac9a064cSDimitry Andric MachineOptimizationRemarkEmitterAnalysis::Result
run(MachineFunction & MF,MachineFunctionAnalysisManager & MFAM)100ac9a064cSDimitry Andric MachineOptimizationRemarkEmitterAnalysis::run(
101ac9a064cSDimitry Andric     MachineFunction &MF, MachineFunctionAnalysisManager &MFAM) {
102ac9a064cSDimitry Andric   MachineBlockFrequencyInfo *MBFI =
103ac9a064cSDimitry Andric       MF.getFunction().getContext().getDiagnosticsHotnessRequested()
104ac9a064cSDimitry Andric           ? &MFAM.getResult<MachineBlockFrequencyAnalysis>(MF)
105ac9a064cSDimitry Andric           : nullptr;
106ac9a064cSDimitry Andric   return Result(MF, MBFI);
107ac9a064cSDimitry Andric }
108ac9a064cSDimitry Andric 
10971d5a254SDimitry Andric char MachineOptimizationRemarkEmitterPass::ID = 0;
11071d5a254SDimitry Andric static const char ore_name[] = "Machine Optimization Remark Emitter";
11171d5a254SDimitry Andric #define ORE_NAME "machine-opt-remark-emitter"
11271d5a254SDimitry Andric 
11371d5a254SDimitry Andric INITIALIZE_PASS_BEGIN(MachineOptimizationRemarkEmitterPass, ORE_NAME, ore_name,
114344a3780SDimitry Andric                       true, true)
11571d5a254SDimitry Andric INITIALIZE_PASS_DEPENDENCY(LazyMachineBlockFrequencyInfoPass)
11671d5a254SDimitry Andric INITIALIZE_PASS_END(MachineOptimizationRemarkEmitterPass, ORE_NAME, ore_name,
117344a3780SDimitry Andric                     true, true)
118