diff options
Diffstat (limited to 'lib/Target/AMDGPU/SIDebuggerInsertNops.cpp')
-rw-r--r-- | lib/Target/AMDGPU/SIDebuggerInsertNops.cpp | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/lib/Target/AMDGPU/SIDebuggerInsertNops.cpp b/lib/Target/AMDGPU/SIDebuggerInsertNops.cpp new file mode 100644 index 0000000000000..65ceff3930ace --- /dev/null +++ b/lib/Target/AMDGPU/SIDebuggerInsertNops.cpp @@ -0,0 +1,96 @@ +//===--- 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 +/// \brief 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 "SIInstrInfo.h" +#include "AMDGPUSubtarget.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) { } + const char *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 SISubtarget &ST = MF.getSubtarget<SISubtarget>(); + 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 DBG_VALUE instructions and instructions without location. + if (MI->isDebugValue() || !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; +} |