forked from OSchip/llvm-project
111 lines
3.7 KiB
C++
111 lines
3.7 KiB
C++
//===--- SIInsertNopsPass.cpp - Use predicates for control flow -----------===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
/// \file
|
|
/// \brief Insert two nop instructions for each high level source statement.
|
|
///
|
|
/// Tools, such as debugger, need to pause execution based on user input (i.e.
|
|
/// breakpoint). In order to do this, two nop instructions are inserted for each
|
|
/// high level source statement: one before first isa instruction of high level
|
|
/// source statement, and one after last isa instruction of high level source
|
|
/// statement. Further, debugger may replace nop instructions with trap
|
|
/// instructions based on user input.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "SIInstrInfo.h"
|
|
#include "llvm/ADT/DenseMap.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-insert-nops"
|
|
#define PASS_NAME "SI Insert Nops"
|
|
|
|
namespace {
|
|
|
|
class SIInsertNops : public MachineFunctionPass {
|
|
public:
|
|
static char ID;
|
|
|
|
SIInsertNops() : MachineFunctionPass(ID) { }
|
|
const char *getPassName() const override { return PASS_NAME; }
|
|
|
|
bool runOnMachineFunction(MachineFunction &MF) override;
|
|
};
|
|
|
|
} // anonymous namespace
|
|
|
|
INITIALIZE_PASS(SIInsertNops, DEBUG_TYPE, PASS_NAME, false, false)
|
|
|
|
char SIInsertNops::ID = 0;
|
|
char &llvm::SIInsertNopsID = SIInsertNops::ID;
|
|
|
|
FunctionPass *llvm::createSIInsertNopsPass() {
|
|
return new SIInsertNops();
|
|
}
|
|
|
|
bool SIInsertNops::runOnMachineFunction(MachineFunction &MF) {
|
|
// Skip this pass if debugger-insert-nops feature is not enabled.
|
|
const AMDGPUSubtarget &ST = MF.getSubtarget<AMDGPUSubtarget>();
|
|
if (!ST.debuggerInsertNops())
|
|
return false;
|
|
|
|
// Skip machine functions without debug info.
|
|
if (!MF.getMMI().hasDebugInfo())
|
|
return false;
|
|
|
|
// Target instruction info.
|
|
const SIInstrInfo *TII =
|
|
static_cast<const SIInstrInfo*>(MF.getSubtarget().getInstrInfo());
|
|
|
|
// Mapping from high level source statement line number to last corresponding
|
|
// isa instruction.
|
|
DenseMap<unsigned, MachineBasicBlock::iterator> LineToInst;
|
|
// Insert nop instruction before first isa instruction of each high level
|
|
// source statement and collect last isa instruction for each high level
|
|
// source statement.
|
|
for (auto &MBB : MF) {
|
|
for (auto MI = MBB.begin(); MI != MBB.end(); ++MI) {
|
|
if (MI->isDebugValue() || !MI->getDebugLoc())
|
|
continue;
|
|
|
|
auto DL = MI->getDebugLoc();
|
|
auto CL = DL.getLine();
|
|
auto LineToInstEntry = LineToInst.find(CL);
|
|
if (LineToInstEntry == LineToInst.end()) {
|
|
BuildMI(MBB, *MI, DL, TII->get(AMDGPU::S_NOP))
|
|
.addImm(0);
|
|
LineToInst.insert(std::make_pair(CL, MI));
|
|
} else {
|
|
LineToInstEntry->second = MI;
|
|
}
|
|
}
|
|
}
|
|
// Insert nop instruction after last isa instruction of each high level source
|
|
// statement.
|
|
for (auto const &LineToInstEntry : LineToInst) {
|
|
auto MBB = LineToInstEntry.second->getParent();
|
|
auto DL = LineToInstEntry.second->getDebugLoc();
|
|
MachineBasicBlock::iterator MI = LineToInstEntry.second;
|
|
if (MI->getOpcode() != AMDGPU::S_ENDPGM)
|
|
BuildMI(*MBB, *(++MI), DL, TII->get(AMDGPU::S_NOP))
|
|
.addImm(0);
|
|
}
|
|
// Insert nop instruction before prologue.
|
|
MachineBasicBlock &MBB = MF.front();
|
|
MachineInstr &MI = MBB.front();
|
|
BuildMI(MBB, MI, DebugLoc(), TII->get(AMDGPU::S_NOP))
|
|
.addImm(0);
|
|
|
|
return true;
|
|
}
|