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