10b57cec5SDimitry Andric ///===- MachineOptimizationRemarkEmitter.cpp - Opt Diagnostic -*- C++ -*---===// 20b57cec5SDimitry Andric /// 30b57cec5SDimitry Andric /// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric /// See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric /// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric /// 70b57cec5SDimitry Andric ///===---------------------------------------------------------------------===// 80b57cec5SDimitry Andric /// \file 90b57cec5SDimitry Andric /// Optimization diagnostic interfaces for machine passes. It's packaged as an 100b57cec5SDimitry Andric /// analysis pass so that by using this service passes become dependent on MBFI 110b57cec5SDimitry Andric /// as well. MBFI is used to compute the "hotness" of the diagnostic message. 120b57cec5SDimitry Andric /// 130b57cec5SDimitry Andric ///===---------------------------------------------------------------------===// 140b57cec5SDimitry Andric 150b57cec5SDimitry Andric #include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h" 160b57cec5SDimitry Andric #include "llvm/CodeGen/LazyMachineBlockFrequencyInfo.h" 170b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstr.h" 180b57cec5SDimitry Andric #include "llvm/IR/DiagnosticInfo.h" 190b57cec5SDimitry Andric #include "llvm/IR/LLVMContext.h" 20480093f4SDimitry Andric #include "llvm/InitializePasses.h" 21bdd1243dSDimitry Andric #include <optional> 220b57cec5SDimitry Andric 230b57cec5SDimitry Andric using namespace llvm; 240b57cec5SDimitry Andric 250b57cec5SDimitry Andric DiagnosticInfoMIROptimization::MachineArgument::MachineArgument( 2604eeddc0SDimitry Andric StringRef MKey, const MachineInstr &MI) { 275ffd83dbSDimitry Andric Key = std::string(MKey); 280b57cec5SDimitry Andric 290b57cec5SDimitry Andric raw_string_ostream OS(Val); 300b57cec5SDimitry Andric MI.print(OS, /*IsStandalone=*/true, /*SkipOpers=*/false, 310b57cec5SDimitry Andric /*SkipDebugLoc=*/true); 320b57cec5SDimitry Andric } 330b57cec5SDimitry Andric 34*0fca6ea1SDimitry Andric bool MachineOptimizationRemarkEmitter::invalidate( 35*0fca6ea1SDimitry Andric MachineFunction &MF, const PreservedAnalyses &PA, 36*0fca6ea1SDimitry Andric MachineFunctionAnalysisManager::Invalidator &Inv) { 37*0fca6ea1SDimitry Andric // This analysis has no state and so can be trivially preserved but it needs 38*0fca6ea1SDimitry Andric // a fresh view of BFI if it was constructed with one. 39*0fca6ea1SDimitry Andric return MBFI && Inv.invalidate<MachineBlockFrequencyAnalysis>(MF, PA); 40*0fca6ea1SDimitry Andric } 41*0fca6ea1SDimitry Andric 42bdd1243dSDimitry Andric std::optional<uint64_t> 430b57cec5SDimitry Andric MachineOptimizationRemarkEmitter::computeHotness(const MachineBasicBlock &MBB) { 440b57cec5SDimitry Andric if (!MBFI) 45bdd1243dSDimitry Andric return std::nullopt; 460b57cec5SDimitry Andric 470b57cec5SDimitry Andric return MBFI->getBlockProfileCount(&MBB); 480b57cec5SDimitry Andric } 490b57cec5SDimitry Andric 500b57cec5SDimitry Andric void MachineOptimizationRemarkEmitter::computeHotness( 510b57cec5SDimitry Andric DiagnosticInfoMIROptimization &Remark) { 520b57cec5SDimitry Andric const MachineBasicBlock *MBB = Remark.getBlock(); 530b57cec5SDimitry Andric if (MBB) 540b57cec5SDimitry Andric Remark.setHotness(computeHotness(*MBB)); 550b57cec5SDimitry Andric } 560b57cec5SDimitry Andric 570b57cec5SDimitry Andric void MachineOptimizationRemarkEmitter::emit( 580b57cec5SDimitry Andric DiagnosticInfoOptimizationBase &OptDiagCommon) { 590b57cec5SDimitry Andric auto &OptDiag = cast<DiagnosticInfoMIROptimization>(OptDiagCommon); 600b57cec5SDimitry Andric computeHotness(OptDiag); 610b57cec5SDimitry Andric 620b57cec5SDimitry Andric LLVMContext &Ctx = MF.getFunction().getContext(); 630b57cec5SDimitry Andric 640b57cec5SDimitry Andric // Only emit it if its hotness meets the threshold. 6581ad6265SDimitry Andric if (OptDiag.getHotness().value_or(0) < Ctx.getDiagnosticsHotnessThreshold()) 660b57cec5SDimitry Andric return; 670b57cec5SDimitry Andric 680b57cec5SDimitry Andric Ctx.diagnose(OptDiag); 690b57cec5SDimitry Andric } 700b57cec5SDimitry Andric 710b57cec5SDimitry Andric MachineOptimizationRemarkEmitterPass::MachineOptimizationRemarkEmitterPass() 720b57cec5SDimitry Andric : MachineFunctionPass(ID) { 730b57cec5SDimitry Andric initializeMachineOptimizationRemarkEmitterPassPass( 740b57cec5SDimitry Andric *PassRegistry::getPassRegistry()); 750b57cec5SDimitry Andric } 760b57cec5SDimitry Andric 770b57cec5SDimitry Andric bool MachineOptimizationRemarkEmitterPass::runOnMachineFunction( 780b57cec5SDimitry Andric MachineFunction &MF) { 790b57cec5SDimitry Andric MachineBlockFrequencyInfo *MBFI; 800b57cec5SDimitry Andric 810b57cec5SDimitry Andric if (MF.getFunction().getContext().getDiagnosticsHotnessRequested()) 820b57cec5SDimitry Andric MBFI = &getAnalysis<LazyMachineBlockFrequencyInfoPass>().getBFI(); 830b57cec5SDimitry Andric else 840b57cec5SDimitry Andric MBFI = nullptr; 850b57cec5SDimitry Andric 868bcb0991SDimitry Andric ORE = std::make_unique<MachineOptimizationRemarkEmitter>(MF, MBFI); 870b57cec5SDimitry Andric return false; 880b57cec5SDimitry Andric } 890b57cec5SDimitry Andric 900b57cec5SDimitry Andric void MachineOptimizationRemarkEmitterPass::getAnalysisUsage( 910b57cec5SDimitry Andric AnalysisUsage &AU) const { 920b57cec5SDimitry Andric AU.addRequired<LazyMachineBlockFrequencyInfoPass>(); 930b57cec5SDimitry Andric AU.setPreservesAll(); 940b57cec5SDimitry Andric MachineFunctionPass::getAnalysisUsage(AU); 950b57cec5SDimitry Andric } 960b57cec5SDimitry Andric 97*0fca6ea1SDimitry Andric AnalysisKey MachineOptimizationRemarkEmitterAnalysis::Key; 98*0fca6ea1SDimitry Andric 99*0fca6ea1SDimitry Andric MachineOptimizationRemarkEmitterAnalysis::Result 100*0fca6ea1SDimitry Andric MachineOptimizationRemarkEmitterAnalysis::run( 101*0fca6ea1SDimitry Andric MachineFunction &MF, MachineFunctionAnalysisManager &MFAM) { 102*0fca6ea1SDimitry Andric MachineBlockFrequencyInfo *MBFI = 103*0fca6ea1SDimitry Andric MF.getFunction().getContext().getDiagnosticsHotnessRequested() 104*0fca6ea1SDimitry Andric ? &MFAM.getResult<MachineBlockFrequencyAnalysis>(MF) 105*0fca6ea1SDimitry Andric : nullptr; 106*0fca6ea1SDimitry Andric return Result(MF, MBFI); 107*0fca6ea1SDimitry Andric } 108*0fca6ea1SDimitry Andric 1090b57cec5SDimitry Andric char MachineOptimizationRemarkEmitterPass::ID = 0; 1100b57cec5SDimitry Andric static const char ore_name[] = "Machine Optimization Remark Emitter"; 1110b57cec5SDimitry Andric #define ORE_NAME "machine-opt-remark-emitter" 1120b57cec5SDimitry Andric 1130b57cec5SDimitry Andric INITIALIZE_PASS_BEGIN(MachineOptimizationRemarkEmitterPass, ORE_NAME, ore_name, 114fe6060f1SDimitry Andric true, true) 1150b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(LazyMachineBlockFrequencyInfoPass) 1160b57cec5SDimitry Andric INITIALIZE_PASS_END(MachineOptimizationRemarkEmitterPass, ORE_NAME, ore_name, 117fe6060f1SDimitry Andric true, true) 118