| //===--- SIDebuggerInsertNops.cpp - Inserts nops for debugger usage -------===// | |
| // | |
| // The LLVM Compiler Infrastructure | |
| // | |
| // This file is distributed under the University of Illinois Open Source | |
| // License. See LICENSE.TXT for details. | |
| // | |
| //===----------------------------------------------------------------------===// | |
| // | |
| /// \file | |
| /// Inserts one nop instruction for each high level source statement for | |
| /// debugger usage. | |
| /// | |
| /// Tools, such as a debugger, need to pause execution based on user input (i.e. | |
| /// breakpoint). In order to do this, one nop instruction is inserted before the | |
| /// first isa instruction of each high level source statement. Further, the | |
| /// debugger may replace nop instructions with trap instructions based on user | |
| /// input. | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #include "AMDGPUSubtarget.h" | |
| #include "SIInstrInfo.h" | |
| #include "MCTargetDesc/AMDGPUMCTargetDesc.h" | |
| #include "llvm/ADT/DenseSet.h" | |
| #include "llvm/CodeGen/MachineFunction.h" | |
| #include "llvm/CodeGen/MachineFunctionPass.h" | |
| #include "llvm/CodeGen/MachineInstrBuilder.h" | |
| #include "llvm/CodeGen/MachineModuleInfo.h" | |
| using namespace llvm; | |
| #define DEBUG_TYPE "si-debugger-insert-nops" | |
| #define PASS_NAME "SI Debugger Insert Nops" | |
| namespace { | |
| class SIDebuggerInsertNops : public MachineFunctionPass { | |
| public: | |
| static char ID; | |
| SIDebuggerInsertNops() : MachineFunctionPass(ID) { } | |
| StringRef getPassName() const override { return PASS_NAME; } | |
| void getAnalysisUsage(AnalysisUsage &AU) const override { | |
| AU.setPreservesCFG(); | |
| MachineFunctionPass::getAnalysisUsage(AU); | |
| } | |
| bool runOnMachineFunction(MachineFunction &MF) override; | |
| }; | |
| } // anonymous namespace | |
| INITIALIZE_PASS(SIDebuggerInsertNops, DEBUG_TYPE, PASS_NAME, false, false) | |
| char SIDebuggerInsertNops::ID = 0; | |
| char &llvm::SIDebuggerInsertNopsID = SIDebuggerInsertNops::ID; | |
| FunctionPass *llvm::createSIDebuggerInsertNopsPass() { | |
| return new SIDebuggerInsertNops(); | |
| } | |
| bool SIDebuggerInsertNops::runOnMachineFunction(MachineFunction &MF) { | |
| // Skip this pass if "amdgpu-debugger-insert-nops" attribute was not | |
| // specified. | |
| const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>(); | |
| if (!ST.debuggerInsertNops()) | |
| return false; | |
| // Skip machine functions without debug info. | |
| if (!MF.getMMI().hasDebugInfo()) | |
| return false; | |
| // Target instruction info. | |
| const SIInstrInfo *TII = ST.getInstrInfo(); | |
| // Set containing line numbers that have nop inserted. | |
| DenseSet<unsigned> NopInserted; | |
| for (auto &MBB : MF) { | |
| for (auto MI = MBB.begin(); MI != MBB.end(); ++MI) { | |
| // Skip debug instructions and instructions without location. | |
| if (MI->isDebugInstr() || !MI->getDebugLoc()) | |
| continue; | |
| // Insert nop instruction if line number does not have nop inserted. | |
| auto DL = MI->getDebugLoc(); | |
| if (NopInserted.find(DL.getLine()) == NopInserted.end()) { | |
| BuildMI(MBB, *MI, DL, TII->get(AMDGPU::S_NOP)) | |
| .addImm(0); | |
| NopInserted.insert(DL.getLine()); | |
| } | |
| } | |
| } | |
| return true; | |
| } |