//
//===----------------------------------------------------------------------===//
-#define DEBUG_TYPE "livedebug"
#include "LiveDebugVariables.h"
#include "llvm/ADT/IntervalMap.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/VirtRegMap.h"
-#include "llvm/DebugInfo.h"
#include "llvm/IR/Constants.h"
+#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/Metadata.h"
#include "llvm/IR/Value.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetRegisterInfo.h"
+#include "llvm/Target/TargetSubtargetInfo.h"
+
+#include <memory>
using namespace llvm;
+#define DEBUG_TYPE "livedebug"
+
static cl::opt<bool>
EnableLDV("live-debug-variables", cl::init(true),
cl::desc("Enable the live debug variables pass"), cl::Hidden);
MachineFunctionPass::getAnalysisUsage(AU);
}
-LiveDebugVariables::LiveDebugVariables() : MachineFunctionPass(ID), pImpl(0) {
+LiveDebugVariables::LiveDebugVariables() : MachineFunctionPass(ID), pImpl(nullptr) {
initializeLiveDebugVariablesPass(*PassRegistry::getPassRegistry());
}
typedef IntervalMap<SlotIndex, unsigned, 4> LocMap;
namespace {
-/// UserValueScopes - Keeps track of lexical scopes associated with an
+/// UserValueScopes - Keeps track of lexical scopes associated with a
/// user value's source location.
class UserValueScopes {
DebugLoc DL;
UserValue(const MDNode *var, unsigned o, bool i, DebugLoc L,
LocMap::Allocator &alloc)
: variable(var), offset(o), IsIndirect(i), dl(L), leader(this),
- next(0), locInts(alloc)
+ next(nullptr), locInts(alloc)
{}
/// getLeader - Get the leader of this value's equivalence class.
UserValue *getNext() const { return next; }
/// match - Does this UserValue match the parameters?
- bool match(const MDNode *Var, unsigned Offset) const {
- return Var == variable && Offset == offset;
+ bool match(const MDNode *Var, unsigned Offset, bool indirect) const {
+ return Var == variable && Offset == offset && indirect == IsIndirect;
}
/// merge - Merge equivalence classes.
/// End points where VNI is no longer live are added to Kills.
/// @param Idx Starting point for the definition.
/// @param LocNo Location number to propagate.
- /// @param LI Restrict liveness to where LI has the value VNI. May be null.
- /// @param VNI When LI is not null, this is the value to restrict to.
+ /// @param LR Restrict liveness to where LR has the value VNI. May be null.
+ /// @param VNI When LR is not null, this is the value to restrict to.
/// @param Kills Append end points of VNI's live range to Kills.
/// @param LIS Live intervals analysis.
/// @param MDT Dominator tree.
void extendDef(SlotIndex Idx, unsigned LocNo,
- LiveInterval *LI, const VNInfo *VNI,
+ LiveRange *LR, const VNInfo *VNI,
SmallVectorImpl<SlotIndex> *Kills,
LiveIntervals &LIS, MachineDominatorTree &MDT,
UserValueScopes &UVS);
LiveIntervals &LIS, const TargetInstrInfo &TRI);
/// findDebugLoc - Return DebugLoc used for this DBG_VALUE instruction. A
- /// variable may have more than one corresponding DBG_VALUE instructions.
+ /// variable may have more than one corresponding DBG_VALUE instructions.
/// Only first one needs DebugLoc to identify variable's lexical scope
/// in source file.
DebugLoc findDebugLoc();
bool ModifiedMF;
/// userValues - All allocated UserValue instances.
- SmallVector<UserValue*, 8> userValues;
+ SmallVector<std::unique_ptr<UserValue>, 8> userValues;
/// Map virtual register to eq class leader.
typedef DenseMap<unsigned, UserValue*> VRMap;
void computeIntervals();
public:
- LDVImpl(LiveDebugVariables *ps) : pass(*ps), EmitDone(false),
- ModifiedMF(false) {}
+ LDVImpl(LiveDebugVariables *ps)
+ : pass(*ps), MF(nullptr), EmitDone(false), ModifiedMF(false) {}
bool runOnMachineFunction(MachineFunction &mf);
/// clear - Release all memory.
void clear() {
- DeleteContainerPointers(userValues);
+ MF = nullptr;
userValues.clear();
virtRegToEqClass.clear();
userVarMap.clear();
void UserValue::print(raw_ostream &OS, const TargetMachine *TM) {
DIVariable DV(variable);
- OS << "!\"";
+ OS << "!\"";
DV.printExtendedName(OS);
OS << "\"\t";
if (offset)
UserValue *UV = Leader->getLeader();
Leader = UV;
for (; UV; UV = UV->getNext())
- if (UV->match(Var, Offset))
+ if (UV->match(Var, Offset, IsIndirect))
return UV;
}
- UserValue *UV = new UserValue(Var, Offset, IsIndirect, DL, allocator);
- userValues.push_back(UV);
+ userValues.push_back(
+ make_unique<UserValue>(Var, Offset, IsIndirect, DL, allocator));
+ UserValue *UV = userValues.back().get();
Leader = UserValue::merge(Leader, UV);
return UV;
}
UserValue *LDVImpl::lookupVirtReg(unsigned VirtReg) {
if (UserValue *UV = virtRegToEqClass.lookup(VirtReg))
return UV->getLeader();
- return 0;
+ return nullptr;
}
bool LDVImpl::handleDebugValue(MachineInstr *MI, SlotIndex Idx) {
// DBG_VALUE has no slot index, use the previous instruction instead.
SlotIndex Idx = MBBI == MBB->begin() ?
LIS->getMBBStartIdx(MBB) :
- LIS->getInstructionIndex(llvm::prior(MBBI)).getRegSlot();
+ LIS->getInstructionIndex(std::prev(MBBI)).getRegSlot();
// Handle consecutive DBG_VALUE instructions with the same slot index.
do {
if (handleDebugValue(MBBI, Idx)) {
}
void UserValue::extendDef(SlotIndex Idx, unsigned LocNo,
- LiveInterval *LI, const VNInfo *VNI,
+ LiveRange *LR, const VNInfo *VNI,
SmallVectorImpl<SlotIndex> *Kills,
LiveIntervals &LIS, MachineDominatorTree &MDT,
UserValueScopes &UVS) {
// Limit to VNI's live range.
bool ToEnd = true;
- if (LI && VNI) {
- LiveInterval::Segment *Segment = LI->getSegmentContaining(Start);
+ if (LR && VNI) {
+ LiveInterval::Segment *Segment = LR->getSegmentContaining(Start);
if (!Segment || Segment->valno != VNI) {
if (Kills)
Kills->push_back(Start);
// Collect all the (vreg, valno) pairs that are copies of LI.
SmallVector<std::pair<LiveInterval*, const VNInfo*>, 8> CopyValues;
- for (MachineRegisterInfo::use_nodbg_iterator
- UI = MRI.use_nodbg_begin(LI->reg),
- UE = MRI.use_nodbg_end(); UI != UE; ++UI) {
+ for (MachineOperand &MO : MRI.use_nodbg_operands(LI->reg)) {
+ MachineInstr *MI = MO.getParent();
// Copies of the full value.
- if (UI.getOperand().getSubReg() || !UI->isCopy())
+ if (MO.getSubReg() || !MI->isCopy())
continue;
- MachineInstr *MI = &*UI;
unsigned DstReg = MI->getOperand(0).getReg();
// Don't follow copies to physregs. These are usually setting up call
const MachineOperand &Loc = locations[LocNo];
if (!Loc.isReg()) {
- extendDef(Idx, LocNo, 0, 0, 0, LIS, MDT, UVS);
+ extendDef(Idx, LocNo, nullptr, nullptr, nullptr, LIS, MDT, UVS);
continue;
}
// Register locations are constrained to where the register value is live.
if (TargetRegisterInfo::isVirtualRegister(Loc.getReg())) {
- LiveInterval *LI = 0;
- const VNInfo *VNI = 0;
+ LiveInterval *LI = nullptr;
+ const VNInfo *VNI = nullptr;
if (LIS.hasInterval(Loc.getReg())) {
LI = &LIS.getInterval(Loc.getReg());
VNI = LI->getVNInfoAt(Idx);
// For physregs, use the live range of the first regunit as a guide.
unsigned Unit = *MCRegUnitIterator(Loc.getReg(), &TRI);
- LiveInterval *LI = &LIS.getRegUnit(Unit);
- const VNInfo *VNI = LI->getVNInfoAt(Idx);
+ LiveRange *LR = &LIS.getRegUnit(Unit);
+ const VNInfo *VNI = LR->getVNInfoAt(Idx);
// Don't track copies from physregs, it is too expensive.
- extendDef(Idx, LocNo, LI, VNI, 0, LIS, MDT, UVS);
+ extendDef(Idx, LocNo, LR, VNI, nullptr, LIS, MDT, UVS);
}
// Finally, erase all the undefs.
}
bool LDVImpl::runOnMachineFunction(MachineFunction &mf) {
+ clear();
MF = &mf;
LIS = &pass.getAnalysis<LiveIntervals>();
MDT = &pass.getAnalysis<MachineDominatorTree>();
- TRI = mf.getTarget().getRegisterInfo();
- clear();
+ TRI = mf.getSubtarget().getRegisterInfo();
LS.initialize(mf);
DEBUG(dbgs() << "********** COMPUTING LIVE DEBUG VARIABLES: "
<< mf.getName() << " **********\n");
bool Changed = collectDebugValues(mf);
computeIntervals();
DEBUG(print(dbgs()));
- LS.releaseMemory();
ModifiedMF = Changed;
return Changed;
}
+static void removeDebugValues(MachineFunction &mf) {
+ for (MachineBasicBlock &MBB : mf) {
+ for (auto MBBI = MBB.begin(), MBBE = MBB.end(); MBBI != MBBE; ) {
+ if (!MBBI->isDebugValue()) {
+ ++MBBI;
+ continue;
+ }
+ MBBI = MBB.erase(MBBI);
+ }
+ }
+}
+
bool LiveDebugVariables::runOnMachineFunction(MachineFunction &mf) {
if (!EnableLDV)
return false;
+ if (!FunctionDIs.count(mf.getFunction())) {
+ removeDebugValues(mf);
+ return false;
+ }
if (!pImpl)
pImpl = new LDVImpl(this);
return static_cast<LDVImpl*>(pImpl)->runOnMachineFunction(mf);
LiveIntervals& LIS) {
DEBUG({
dbgs() << "Splitting Loc" << OldLocNo << '\t';
- print(dbgs(), 0);
+ print(dbgs(), nullptr);
});
bool DidChange = false;
LocMap::iterator LocMapI;
}
}
- DEBUG({dbgs() << "Split result: \t"; print(dbgs(), 0);});
+ DEBUG({dbgs() << "Split result: \t"; print(dbgs(), nullptr);});
return DidChange;
}
// Don't insert anything after the first terminator, though.
return MI->isTerminator() ? MBB->getFirstTerminator() :
- llvm::next(MachineBasicBlock::iterator(MI));
+ std::next(MachineBasicBlock::iterator(MI));
}
DebugLoc UserValue::findDebugLoc() {
void LDVImpl::emitDebugValues(VirtRegMap *VRM) {
DEBUG(dbgs() << "********** EMITTING LIVE DEBUG VARIABLES **********\n");
- const TargetInstrInfo *TII = MF->getTarget().getInstrInfo();
+ if (!MF)
+ return;
+ const TargetInstrInfo *TII = MF->getSubtarget().getInstrInfo();
for (unsigned i = 0, e = userValues.size(); i != e; ++i) {
DEBUG(userValues[i]->print(dbgs(), &MF->getTarget()));
userValues[i]->rewriteLocations(*VRM, *TRI);
static_cast<LDVImpl*>(pImpl)->emitDebugValues(VRM);
}
+bool LiveDebugVariables::doInitialization(Module &M) {
+ FunctionDIs = makeSubprogramMap(M);
+ return Pass::doInitialization(M);
+}
#ifndef NDEBUG
void LiveDebugVariables::dump() {