Line data Source code
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 : /// 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 "AMDGPUSubtarget.h"
23 : #include "SIInstrInfo.h"
24 : #include "MCTargetDesc/AMDGPUMCTargetDesc.h"
25 : #include "llvm/ADT/DenseSet.h"
26 : #include "llvm/CodeGen/MachineFunction.h"
27 : #include "llvm/CodeGen/MachineFunctionPass.h"
28 : #include "llvm/CodeGen/MachineInstrBuilder.h"
29 : #include "llvm/CodeGen/MachineModuleInfo.h"
30 : using namespace llvm;
31 :
32 : #define DEBUG_TYPE "si-debugger-insert-nops"
33 : #define PASS_NAME "SI Debugger Insert Nops"
34 :
35 : namespace {
36 :
37 : class SIDebuggerInsertNops : public MachineFunctionPass {
38 : public:
39 : static char ID;
40 :
41 1964 : SIDebuggerInsertNops() : MachineFunctionPass(ID) { }
42 1950 : StringRef getPassName() const override { return PASS_NAME; }
43 :
44 1950 : void getAnalysisUsage(AnalysisUsage &AU) const override {
45 1950 : AU.setPreservesCFG();
46 1950 : MachineFunctionPass::getAnalysisUsage(AU);
47 1950 : }
48 :
49 : bool runOnMachineFunction(MachineFunction &MF) override;
50 : };
51 :
52 : } // anonymous namespace
53 :
54 199024 : INITIALIZE_PASS(SIDebuggerInsertNops, DEBUG_TYPE, PASS_NAME, false, false)
55 :
56 : char SIDebuggerInsertNops::ID = 0;
57 : char &llvm::SIDebuggerInsertNopsID = SIDebuggerInsertNops::ID;
58 :
59 1964 : FunctionPass *llvm::createSIDebuggerInsertNopsPass() {
60 1964 : return new SIDebuggerInsertNops();
61 : }
62 :
63 19723 : bool SIDebuggerInsertNops::runOnMachineFunction(MachineFunction &MF) {
64 : // Skip this pass if "amdgpu-debugger-insert-nops" attribute was not
65 : // specified.
66 19723 : const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
67 19723 : if (!ST.debuggerInsertNops())
68 : return false;
69 :
70 : // Skip machine functions without debug info.
71 5 : if (!MF.getMMI().hasDebugInfo())
72 : return false;
73 :
74 : // Target instruction info.
75 5 : const SIInstrInfo *TII = ST.getInstrInfo();
76 :
77 : // Set containing line numbers that have nop inserted.
78 : DenseSet<unsigned> NopInserted;
79 :
80 10 : for (auto &MBB : MF) {
81 238 : for (auto MI = MBB.begin(); MI != MBB.end(); ++MI) {
82 : // Skip debug instructions and instructions without location.
83 227 : if (MI->isDebugInstr() || !MI->getDebugLoc())
84 121 : continue;
85 :
86 : // Insert nop instruction if line number does not have nop inserted.
87 : auto DL = MI->getDebugLoc();
88 112 : if (NopInserted.find(DL.getLine()) == NopInserted.end()) {
89 40 : BuildMI(MBB, *MI, DL, TII->get(AMDGPU::S_NOP))
90 : .addImm(0);
91 20 : NopInserted.insert(DL.getLine());
92 : }
93 : }
94 : }
95 :
96 : return true;
97 : }
|