17a7e6055SDimitry Andric ///===- MachineOptimizationRemarkEmitter.cpp - Opt Diagnostic -*- C++ -*---===//
27a7e6055SDimitry Andric ///
37a7e6055SDimitry Andric ///                     The LLVM Compiler Infrastructure
47a7e6055SDimitry Andric ///
57a7e6055SDimitry Andric /// This file is distributed under the University of Illinois Open Source
67a7e6055SDimitry Andric /// License. See LICENSE.TXT for details.
77a7e6055SDimitry Andric ///
87a7e6055SDimitry Andric ///===---------------------------------------------------------------------===//
97a7e6055SDimitry Andric /// \file
107a7e6055SDimitry Andric /// Optimization diagnostic interfaces for machine passes.  It's packaged as an
117a7e6055SDimitry Andric /// analysis pass so that by using this service passes become dependent on MBFI
127a7e6055SDimitry Andric /// as well.  MBFI is used to compute the "hotness" of the diagnostic message.
137a7e6055SDimitry Andric ///
147a7e6055SDimitry Andric ///===---------------------------------------------------------------------===//
157a7e6055SDimitry Andric 
167a7e6055SDimitry Andric #include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h"
177a7e6055SDimitry Andric #include "llvm/CodeGen/LazyMachineBlockFrequencyInfo.h"
187a7e6055SDimitry Andric #include "llvm/CodeGen/MachineInstr.h"
197a7e6055SDimitry Andric #include "llvm/IR/DiagnosticInfo.h"
207a7e6055SDimitry Andric #include "llvm/IR/LLVMContext.h"
217a7e6055SDimitry Andric 
227a7e6055SDimitry Andric using namespace llvm;
237a7e6055SDimitry Andric 
MachineArgument(StringRef MKey,const MachineInstr & MI)247a7e6055SDimitry Andric DiagnosticInfoMIROptimization::MachineArgument::MachineArgument(
257a7e6055SDimitry Andric     StringRef MKey, const MachineInstr &MI)
267a7e6055SDimitry Andric     : Argument() {
277a7e6055SDimitry Andric   Key = MKey;
287a7e6055SDimitry Andric 
297a7e6055SDimitry Andric   raw_string_ostream OS(Val);
30*4ba319b5SDimitry Andric   MI.print(OS, /*IsStandalone=*/true, /*SkipOpers=*/false,
31*4ba319b5SDimitry Andric            /*SkipDebugLoc=*/true);
327a7e6055SDimitry Andric }
337a7e6055SDimitry Andric 
347a7e6055SDimitry Andric Optional<uint64_t>
computeHotness(const MachineBasicBlock & MBB)357a7e6055SDimitry Andric MachineOptimizationRemarkEmitter::computeHotness(const MachineBasicBlock &MBB) {
367a7e6055SDimitry Andric   if (!MBFI)
377a7e6055SDimitry Andric     return None;
387a7e6055SDimitry Andric 
397a7e6055SDimitry Andric   return MBFI->getBlockProfileCount(&MBB);
407a7e6055SDimitry Andric }
417a7e6055SDimitry Andric 
computeHotness(DiagnosticInfoMIROptimization & Remark)427a7e6055SDimitry Andric void MachineOptimizationRemarkEmitter::computeHotness(
437a7e6055SDimitry Andric     DiagnosticInfoMIROptimization &Remark) {
447a7e6055SDimitry Andric   const MachineBasicBlock *MBB = Remark.getBlock();
457a7e6055SDimitry Andric   if (MBB)
467a7e6055SDimitry Andric     Remark.setHotness(computeHotness(*MBB));
477a7e6055SDimitry Andric }
487a7e6055SDimitry Andric 
emit(DiagnosticInfoOptimizationBase & OptDiagCommon)497a7e6055SDimitry Andric void MachineOptimizationRemarkEmitter::emit(
507a7e6055SDimitry Andric     DiagnosticInfoOptimizationBase &OptDiagCommon) {
517a7e6055SDimitry Andric   auto &OptDiag = cast<DiagnosticInfoMIROptimization>(OptDiagCommon);
527a7e6055SDimitry Andric   computeHotness(OptDiag);
537a7e6055SDimitry Andric 
542cab237bSDimitry Andric   LLVMContext &Ctx = MF.getFunction().getContext();
55a580b014SDimitry Andric 
562cab237bSDimitry Andric   // Only emit it if its hotness meets the threshold.
572cab237bSDimitry Andric   if (OptDiag.getHotness().getValueOr(0) <
582cab237bSDimitry Andric       Ctx.getDiagnosticsHotnessThreshold()) {
59a580b014SDimitry Andric     return;
60a580b014SDimitry Andric   }
61a580b014SDimitry Andric 
627a7e6055SDimitry Andric   Ctx.diagnose(OptDiag);
637a7e6055SDimitry Andric }
647a7e6055SDimitry Andric 
MachineOptimizationRemarkEmitterPass()657a7e6055SDimitry Andric MachineOptimizationRemarkEmitterPass::MachineOptimizationRemarkEmitterPass()
667a7e6055SDimitry Andric     : MachineFunctionPass(ID) {
677a7e6055SDimitry Andric   initializeMachineOptimizationRemarkEmitterPassPass(
687a7e6055SDimitry Andric       *PassRegistry::getPassRegistry());
697a7e6055SDimitry Andric }
707a7e6055SDimitry Andric 
runOnMachineFunction(MachineFunction & MF)717a7e6055SDimitry Andric bool MachineOptimizationRemarkEmitterPass::runOnMachineFunction(
727a7e6055SDimitry Andric     MachineFunction &MF) {
737a7e6055SDimitry Andric   MachineBlockFrequencyInfo *MBFI;
747a7e6055SDimitry Andric 
752cab237bSDimitry Andric   if (MF.getFunction().getContext().getDiagnosticsHotnessRequested())
767a7e6055SDimitry Andric     MBFI = &getAnalysis<LazyMachineBlockFrequencyInfoPass>().getBFI();
777a7e6055SDimitry Andric   else
787a7e6055SDimitry Andric     MBFI = nullptr;
797a7e6055SDimitry Andric 
807a7e6055SDimitry Andric   ORE = llvm::make_unique<MachineOptimizationRemarkEmitter>(MF, MBFI);
817a7e6055SDimitry Andric   return false;
827a7e6055SDimitry Andric }
837a7e6055SDimitry Andric 
getAnalysisUsage(AnalysisUsage & AU) const847a7e6055SDimitry Andric void MachineOptimizationRemarkEmitterPass::getAnalysisUsage(
857a7e6055SDimitry Andric     AnalysisUsage &AU) const {
867a7e6055SDimitry Andric   AU.addRequired<LazyMachineBlockFrequencyInfoPass>();
877a7e6055SDimitry Andric   AU.setPreservesAll();
887a7e6055SDimitry Andric   MachineFunctionPass::getAnalysisUsage(AU);
897a7e6055SDimitry Andric }
907a7e6055SDimitry Andric 
917a7e6055SDimitry Andric char MachineOptimizationRemarkEmitterPass::ID = 0;
927a7e6055SDimitry Andric static const char ore_name[] = "Machine Optimization Remark Emitter";
937a7e6055SDimitry Andric #define ORE_NAME "machine-opt-remark-emitter"
947a7e6055SDimitry Andric 
957a7e6055SDimitry Andric INITIALIZE_PASS_BEGIN(MachineOptimizationRemarkEmitterPass, ORE_NAME, ore_name,
967a7e6055SDimitry Andric                       false, true)
977a7e6055SDimitry Andric INITIALIZE_PASS_DEPENDENCY(LazyMachineBlockFrequencyInfoPass)
987a7e6055SDimitry Andric INITIALIZE_PASS_END(MachineOptimizationRemarkEmitterPass, ORE_NAME, ore_name,
997a7e6055SDimitry Andric                     false, true)
100