Home | History | Annotate | Download | only in AMDGPU
      1 //===--- SIDebuggerInsertNops.cpp - Inserts nops for debugger usage -------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 /// \file
     11 /// \brief Inserts one nop instruction for each high level source statement for
     12 /// debugger usage.
     13 ///
     14 /// Tools, such as a debugger, need to pause execution based on user input (i.e.
     15 /// breakpoint). In order to do this, one nop instruction is inserted before the
     16 /// first isa instruction of each high level source statement. Further, the
     17 /// debugger may replace nop instructions with trap instructions based on user
     18 /// input.
     19 //
     20 //===----------------------------------------------------------------------===//
     21 
     22 #include "SIInstrInfo.h"
     23 #include "AMDGPUSubtarget.h"
     24 #include "llvm/ADT/DenseSet.h"
     25 #include "llvm/CodeGen/MachineFunction.h"
     26 #include "llvm/CodeGen/MachineFunctionPass.h"
     27 #include "llvm/CodeGen/MachineInstrBuilder.h"
     28 #include "llvm/CodeGen/MachineModuleInfo.h"
     29 using namespace llvm;
     30 
     31 #define DEBUG_TYPE "si-debugger-insert-nops"
     32 #define PASS_NAME "SI Debugger Insert Nops"
     33 
     34 namespace {
     35 
     36 class SIDebuggerInsertNops : public MachineFunctionPass {
     37 public:
     38   static char ID;
     39 
     40   SIDebuggerInsertNops() : MachineFunctionPass(ID) { }
     41   const char *getPassName() const override { return PASS_NAME; }
     42 
     43   void getAnalysisUsage(AnalysisUsage &AU) const override {
     44     AU.setPreservesCFG();
     45     MachineFunctionPass::getAnalysisUsage(AU);
     46   }
     47 
     48   bool runOnMachineFunction(MachineFunction &MF) override;
     49 };
     50 
     51 } // anonymous namespace
     52 
     53 INITIALIZE_PASS(SIDebuggerInsertNops, DEBUG_TYPE, PASS_NAME, false, false)
     54 
     55 char SIDebuggerInsertNops::ID = 0;
     56 char &llvm::SIDebuggerInsertNopsID = SIDebuggerInsertNops::ID;
     57 
     58 FunctionPass *llvm::createSIDebuggerInsertNopsPass() {
     59   return new SIDebuggerInsertNops();
     60 }
     61 
     62 bool SIDebuggerInsertNops::runOnMachineFunction(MachineFunction &MF) {
     63   // Skip this pass if "amdgpu-debugger-insert-nops" attribute was not
     64   // specified.
     65   const SISubtarget &ST = MF.getSubtarget<SISubtarget>();
     66   if (!ST.debuggerInsertNops())
     67     return false;
     68 
     69   // Skip machine functions without debug info.
     70   if (!MF.getMMI().hasDebugInfo())
     71     return false;
     72 
     73   // Target instruction info.
     74   const SIInstrInfo *TII = ST.getInstrInfo();
     75 
     76   // Set containing line numbers that have nop inserted.
     77   DenseSet<unsigned> NopInserted;
     78 
     79   for (auto &MBB : MF) {
     80     for (auto MI = MBB.begin(); MI != MBB.end(); ++MI) {
     81       // Skip DBG_VALUE instructions and instructions without location.
     82       if (MI->isDebugValue() || !MI->getDebugLoc())
     83         continue;
     84 
     85       // Insert nop instruction if line number does not have nop inserted.
     86       auto DL = MI->getDebugLoc();
     87       if (NopInserted.find(DL.getLine()) == NopInserted.end()) {
     88         BuildMI(MBB, *MI, DL, TII->get(AMDGPU::S_NOP))
     89           .addImm(0);
     90         NopInserted.insert(DL.getLine());
     91       }
     92     }
     93   }
     94 
     95   return true;
     96 }
     97