| 1 | ///===- MachineOptimizationRemarkEmitter.cpp - Opt 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-exception |
| 6 | /// |
| 7 | ///===---------------------------------------------------------------------===// |
| 8 | /// \file |
| 9 | /// Optimization diagnostic interfaces for machine passes. It's packaged as an |
| 10 | /// analysis pass so that by using this service passes become dependent on MBFI |
| 11 | /// as well. MBFI is used to compute the "hotness" of the diagnostic message. |
| 12 | /// |
| 13 | ///===---------------------------------------------------------------------===// |
| 14 | |
| 15 | #include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h" |
| 16 | #include "llvm/CodeGen/LazyMachineBlockFrequencyInfo.h" |
| 17 | #include "llvm/CodeGen/MachineInstr.h" |
| 18 | #include "llvm/IR/DiagnosticInfo.h" |
| 19 | #include "llvm/IR/LLVMContext.h" |
| 20 | #include "llvm/InitializePasses.h" |
| 21 | #include <optional> |
| 22 | |
| 23 | using namespace llvm; |
| 24 | |
| 25 | DiagnosticInfoMIROptimization::MachineArgument::MachineArgument( |
| 26 | StringRef MKey, const MachineInstr &MI) { |
| 27 | Key = std::string(MKey); |
| 28 | |
| 29 | raw_string_ostream OS(Val); |
| 30 | MI.print(OS, /*IsStandalone=*/true, /*SkipOpers=*/false, |
| 31 | /*SkipDebugLoc=*/true); |
| 32 | } |
| 33 | |
| 34 | bool MachineOptimizationRemarkEmitter::( |
| 35 | MachineFunction &MF, const PreservedAnalyses &PA, |
| 36 | MachineFunctionAnalysisManager::Invalidator &Inv) { |
| 37 | // This analysis has no state and so can be trivially preserved but it needs |
| 38 | // a fresh view of BFI if it was constructed with one. |
| 39 | return MBFI && Inv.invalidate<MachineBlockFrequencyAnalysis>(IR&: MF, PA); |
| 40 | } |
| 41 | |
| 42 | std::optional<uint64_t> |
| 43 | MachineOptimizationRemarkEmitter::(const MachineBasicBlock &MBB) { |
| 44 | if (!MBFI) |
| 45 | return std::nullopt; |
| 46 | |
| 47 | return MBFI->getBlockProfileCount(MBB: &MBB); |
| 48 | } |
| 49 | |
| 50 | void MachineOptimizationRemarkEmitter::( |
| 51 | DiagnosticInfoMIROptimization &) { |
| 52 | const MachineBasicBlock *MBB = Remark.getBlock(); |
| 53 | if (MBB) |
| 54 | Remark.setHotness(computeHotness(MBB: *MBB)); |
| 55 | } |
| 56 | |
| 57 | void MachineOptimizationRemarkEmitter::( |
| 58 | DiagnosticInfoOptimizationBase &OptDiagCommon) { |
| 59 | auto &OptDiag = cast<DiagnosticInfoMIROptimization>(Val&: OptDiagCommon); |
| 60 | computeHotness(Remark&: OptDiag); |
| 61 | |
| 62 | LLVMContext &Ctx = MF.getFunction().getContext(); |
| 63 | |
| 64 | // Only emit it if its hotness meets the threshold. |
| 65 | if (OptDiag.getHotness().value_or(u: 0) < Ctx.getDiagnosticsHotnessThreshold()) |
| 66 | return; |
| 67 | |
| 68 | Ctx.diagnose(DI: OptDiag); |
| 69 | } |
| 70 | |
| 71 | MachineOptimizationRemarkEmitterPass::() |
| 72 | : MachineFunctionPass(ID) { |
| 73 | initializeMachineOptimizationRemarkEmitterPassPass( |
| 74 | *PassRegistry::getPassRegistry()); |
| 75 | } |
| 76 | |
| 77 | bool MachineOptimizationRemarkEmitterPass::( |
| 78 | MachineFunction &MF) { |
| 79 | MachineBlockFrequencyInfo *MBFI; |
| 80 | |
| 81 | if (MF.getFunction().getContext().getDiagnosticsHotnessRequested()) |
| 82 | MBFI = &getAnalysis<LazyMachineBlockFrequencyInfoPass>().getBFI(); |
| 83 | else |
| 84 | MBFI = nullptr; |
| 85 | |
| 86 | ORE = std::make_unique<MachineOptimizationRemarkEmitter>(args&: MF, args&: MBFI); |
| 87 | return false; |
| 88 | } |
| 89 | |
| 90 | void MachineOptimizationRemarkEmitterPass::( |
| 91 | AnalysisUsage &AU) const { |
| 92 | AU.addRequired<LazyMachineBlockFrequencyInfoPass>(); |
| 93 | AU.setPreservesAll(); |
| 94 | MachineFunctionPass::getAnalysisUsage(AU); |
| 95 | } |
| 96 | |
| 97 | AnalysisKey MachineOptimizationRemarkEmitterAnalysis::; |
| 98 | |
| 99 | MachineOptimizationRemarkEmitterAnalysis::Result |
| 100 | MachineOptimizationRemarkEmitterAnalysis::( |
| 101 | MachineFunction &MF, MachineFunctionAnalysisManager &MFAM) { |
| 102 | MachineBlockFrequencyInfo *MBFI = |
| 103 | MF.getFunction().getContext().getDiagnosticsHotnessRequested() |
| 104 | ? &MFAM.getResult<MachineBlockFrequencyAnalysis>(IR&: MF) |
| 105 | : nullptr; |
| 106 | return Result(MF, MBFI); |
| 107 | } |
| 108 | |
| 109 | char MachineOptimizationRemarkEmitterPass:: = 0; |
| 110 | static const char ore_name[] = "Machine Optimization Remark Emitter" ; |
| 111 | #define ORE_NAME "machine-opt-remark-emitter" |
| 112 | |
| 113 | INITIALIZE_PASS_BEGIN(MachineOptimizationRemarkEmitterPass, ORE_NAME, ore_name, |
| 114 | true, true) |
| 115 | INITIALIZE_PASS_DEPENDENCY(LazyMachineBlockFrequencyInfoPass) |
| 116 | INITIALIZE_PASS_END(MachineOptimizationRemarkEmitterPass, ORE_NAME, ore_name, |
| 117 | true, true) |
| 118 | |