Progress towards shepherding debug info through SelectionDAG.
No functional effect yet. This is still evolving and should
not be viewed as final.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@98195 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/ScheduleDAGInstrs.cpp b/lib/CodeGen/ScheduleDAGInstrs.cpp
index badf34e..e532ade 100644
--- a/lib/CodeGen/ScheduleDAGInstrs.cpp
+++ b/lib/CodeGen/ScheduleDAGInstrs.cpp
@@ -34,6 +34,7 @@
const MachineDominatorTree &mdt)
: ScheduleDAG(mf), MLI(mli), MDT(mdt), LoopRegs(MLI, MDT) {
MFI = mf.getFrameInfo();
+ DbgValueVec.clear();
}
/// Run - perform scheduling.
@@ -157,6 +158,10 @@
std::map<const Value *, SUnit *> AliasMemDefs, NonAliasMemDefs;
std::map<const Value *, std::vector<SUnit *> > AliasMemUses, NonAliasMemUses;
+ // Keep track of dangling debug references to registers.
+ std::pair<MachineInstr*, unsigned>
+ DanglingDebugValue[TargetRegisterInfo::FirstVirtualRegister];
+
// Check to see if the scheduler cares about latencies.
bool UnitLatencies = ForceUnitLatencies();
@@ -164,10 +169,25 @@
const TargetSubtarget &ST = TM.getSubtarget<TargetSubtarget>();
unsigned SpecialAddressLatency = ST.getSpecialAddressLatency();
+ // Remove any stale debug info; sometimes BuildSchedGraph is called again
+ // without emitting the info from the previous call.
+ DbgValueVec.clear();
+ std::memset(DanglingDebugValue, 0, sizeof(DanglingDebugValue));
+
// Walk the list of instructions, from bottom moving up.
for (MachineBasicBlock::iterator MII = InsertPos, MIE = Begin;
MII != MIE; --MII) {
MachineInstr *MI = prior(MII);
+ // DBG_VALUE does not have SUnit's built, so just remember these for later
+ // reinsertion.
+ if (MI->isDebugValue()) {
+ if (MI->getNumOperands()==3 && MI->getOperand(0).isReg() &&
+ MI->getOperand(0).getReg())
+ DanglingDebugValue[MI->getOperand(0).getReg()] =
+ std::make_pair(MI, DbgValueVec.size());
+ DbgValueVec.push_back(MI);
+ continue;
+ }
const TargetInstrDesc &TID = MI->getDesc();
assert(!TID.isTerminator() && !MI->isLabel() &&
"Cannot schedule terminators or labels!");
@@ -188,6 +208,13 @@
if (Reg == 0) continue;
assert(TRI->isPhysicalRegister(Reg) && "Virtual register encountered!");
+
+ if (MO.isDef() && DanglingDebugValue[Reg].first!=0) {
+ SU->setDbgInstr(DanglingDebugValue[Reg].first);
+ DbgValueVec[DanglingDebugValue[Reg].second] = 0;
+ DanglingDebugValue[Reg] = std::make_pair((MachineInstr*)0, 0);
+ }
+
std::vector<SUnit *> &UseList = Uses[Reg];
std::vector<SUnit *> &DefList = Defs[Reg];
// Optionally add output and anti dependencies. For anti
@@ -555,6 +582,14 @@
BB->remove(I);
}
+ // First reinsert any remaining debug_values; these are either constants,
+ // or refer to live-in registers. The beginning of the block is the right
+ // place for the latter. The former might reasonably be placed elsewhere
+ // using some kind of ordering algorithm, but right now it doesn't matter.
+ for (int i = DbgValueVec.size()-1; i>=0; --i)
+ if (DbgValueVec[i])
+ BB->insert(InsertPos, DbgValueVec[i]);
+
// Then re-insert them according to the given schedule.
for (unsigned i = 0, e = Sequence.size(); i != e; i++) {
SUnit *SU = Sequence[i];
@@ -565,12 +600,21 @@
}
BB->insert(InsertPos, SU->getInstr());
+ if (SU->getDbgInstr())
+ BB->insert(InsertPos, SU->getDbgInstr());
}
// Update the Begin iterator, as the first instruction in the block
// may have been scheduled later.
- if (!Sequence.empty())
+ if (!DbgValueVec.empty()) {
+ for (int i = DbgValueVec.size()-1; i>=0; --i)
+ if (DbgValueVec[i]!=0) {
+ Begin = DbgValueVec[DbgValueVec.size()-1];
+ break;
+ }
+ } else if (!Sequence.empty())
Begin = Sequence[0]->getInstr();
+ DbgValueVec.clear();
return BB;
}
diff --git a/lib/CodeGen/ScheduleDAGInstrs.h b/lib/CodeGen/ScheduleDAGInstrs.h
index 366c3a8..c9b44de 100644
--- a/lib/CodeGen/ScheduleDAGInstrs.h
+++ b/lib/CodeGen/ScheduleDAGInstrs.h
@@ -106,6 +106,10 @@
/// initialized and destructed for each block.
std::vector<SUnit *> Defs[TargetRegisterInfo::FirstVirtualRegister];
std::vector<SUnit *> Uses[TargetRegisterInfo::FirstVirtualRegister];
+
+ /// DbgValueVec - Remember DBG_VALUEs that refer to a particular
+ /// register.
+ std::vector<MachineInstr *>DbgValueVec;
/// PendingLoads - Remember where unknown loads are after the most recent
/// unknown store, as we iterate. As with Defs and Uses, this is here
diff --git a/lib/CodeGen/SelectionDAG/InstrEmitter.cpp b/lib/CodeGen/SelectionDAG/InstrEmitter.cpp
index 625de11..e6ad363 100644
--- a/lib/CodeGen/SelectionDAG/InstrEmitter.cpp
+++ b/lib/CodeGen/SelectionDAG/InstrEmitter.cpp
@@ -508,6 +508,7 @@
return;
if (!sd)
return;
+ assert(sd->getKind() == SDDbgValue::SD);
unsigned VReg = getVR(SDValue(sd->getSDNode(), sd->getResNo()), VRBaseMap);
const TargetInstrDesc &II = TII->get(TargetOpcode::DBG_VALUE);
DebugLoc DL = sd->getDebugLoc();
@@ -524,26 +525,46 @@
MBB->insert(InsertPos, MI);
}
-/// EmitDbgValue - Generate constant debug info. No SDNode is involved.
+/// EmitDbgValue - Generate debug info that does not refer to a SDNode.
void
-InstrEmitter::EmitDbgValue(SDDbgValue *sd) {
+InstrEmitter::EmitDbgValue(SDDbgValue *sd,
+ DenseMap<MachineBasicBlock*, MachineBasicBlock*> *EM) {
if (!sd)
return;
const TargetInstrDesc &II = TII->get(TargetOpcode::DBG_VALUE);
+ uint64_t Offset = sd->getOffset();
+ MDNode* mdPtr = sd->getMDPtr();
+ SDDbgValue::DbgValueKind kind = sd->getKind();
DebugLoc DL = sd->getDebugLoc();
- MachineInstr *MI;
- Value *V = sd->getConst();
- if (ConstantInt *CI = dyn_cast<ConstantInt>(V)) {
- MI = BuildMI(*MF, DL, II).addImm(CI->getZExtValue()).
- addImm(sd->getOffset()).
- addMetadata(sd->getMDPtr());
- } else if (ConstantFP *CF = dyn_cast<ConstantFP>(V)) {
- MI = BuildMI(*MF, DL, II).addFPImm(CF).addImm(sd->getOffset()).
- addMetadata(sd->getMDPtr());
+ MachineInstr* MI;
+ if (kind == SDDbgValue::CNST) {
+ Value *V = sd->getConst();
+ if (ConstantInt *CI = dyn_cast<ConstantInt>(V)) {
+ MI = BuildMI(*MF, DL, II).addImm(CI->getZExtValue()).
+ addImm(Offset).addMetadata(mdPtr);
+ } else if (ConstantFP *CF = dyn_cast<ConstantFP>(V)) {
+ MI = BuildMI(*MF, DL, II).addFPImm(CF).
+ addImm(Offset).addMetadata(mdPtr);
+ } else {
+ // Could be an Undef. In any case insert an Undef so we can see what we
+ // dropped.
+ MI = BuildMI(*MF, DL, II).addReg(0U).
+ addImm(Offset).addMetadata(mdPtr);
+ }
+ } else if (kind == SDDbgValue::FX) {
+ unsigned FrameIx = sd->getFrameIx();
+ // Stack address; this needs to be lowered in target-dependent fashion.
+ // FIXME test that the target supports this somehow; if not emit Undef.
+ // Create a pseudo for EmitInstrWithCustomInserter's consumption.
+ MI = BuildMI(*MF, DL, II).addImm(FrameIx).
+ addImm(Offset).addMetadata(mdPtr);
+ MBB = TLI->EmitInstrWithCustomInserter(MI, MBB, EM);
+ InsertPos = MBB->end();
+ return;
} else {
// Insert an Undef so we can see what we dropped.
- MI = BuildMI(*MF, DL, II).addReg(0U).addImm(sd->getOffset()).
- addMetadata(sd->getMDPtr());
+ MI = BuildMI(*MF, DL, II).addReg(0U).
+ addImm(Offset).addMetadata(mdPtr);
}
MBB->insert(InsertPos, MI);
}
diff --git a/lib/CodeGen/SelectionDAG/InstrEmitter.h b/lib/CodeGen/SelectionDAG/InstrEmitter.h
index 4fe9f19..eefcd73 100644
--- a/lib/CodeGen/SelectionDAG/InstrEmitter.h
+++ b/lib/CodeGen/SelectionDAG/InstrEmitter.h
@@ -106,7 +106,8 @@
/// EmitDbgValue - Generate a constant DBG_VALUE. No node is involved.
- void EmitDbgValue(SDDbgValue* sd);
+ void EmitDbgValue(SDDbgValue* sd,
+ DenseMap<MachineBasicBlock*, MachineBasicBlock*> *EM);
/// EmitNode - Generate machine code for a node and needed dependencies.
///
diff --git a/lib/CodeGen/SelectionDAG/SDDbgValue.h b/lib/CodeGen/SelectionDAG/SDDbgValue.h
index d43a044..1b7ba18 100644
--- a/lib/CodeGen/SelectionDAG/SDDbgValue.h
+++ b/lib/CodeGen/SelectionDAG/SDDbgValue.h
@@ -28,9 +28,22 @@
/// We do not use SDValue here to avoid including its header.
class SDDbgValue {
- SDNode *Node; // valid for non-constants
- unsigned ResNo; // valid for non-constants
- Value *Const; // valid for constants
+public:
+ enum DbgValueKind {
+ SD = 0,
+ CNST = 1,
+ FX = 2
+ };
+private:
+ enum DbgValueKind kind;
+ union {
+ struct {
+ SDNode *Node; // valid for non-constants
+ unsigned ResNo; // valid for non-constants
+ } s;
+ Value *Const; // valid for constants
+ unsigned FrameIx; // valid for stack objects
+ } u;
MDNode *mdPtr;
uint64_t Offset;
DebugLoc DL;
@@ -38,24 +51,43 @@
public:
// Constructor for non-constants.
SDDbgValue(MDNode *mdP, SDNode *N, unsigned R, uint64_t off, DebugLoc dl,
- unsigned O) :
- Node(N), ResNo(R), Const(0), mdPtr(mdP), Offset(off), DL(dl), Order(O) {}
+ unsigned O) : mdPtr(mdP), Offset(off), DL(dl), Order(O) {
+ kind = SD;
+ u.s.Node = N;
+ u.s.ResNo = R;
+ }
// Constructor for constants.
SDDbgValue(MDNode *mdP, Value *C, uint64_t off, DebugLoc dl, unsigned O) :
- Node(0), ResNo(0), Const(C), mdPtr(mdP), Offset(off), DL(dl), Order(O) {}
+ mdPtr(mdP), Offset(off), DL(dl), Order(O) {
+ kind = CNST;
+ u.Const = C;
+ }
+
+ // Constructor for frame indices.
+ SDDbgValue(MDNode *mdP, unsigned FI, uint64_t off, DebugLoc dl, unsigned O) :
+ mdPtr(mdP), Offset(off), DL(dl), Order(O) {
+ kind = FX;
+ u.FrameIx = FI;
+ }
+
+ // Returns the kind.
+ DbgValueKind getKind() { return kind; }
// Returns the MDNode pointer.
MDNode *getMDPtr() { return mdPtr; }
- // Returns the SDNode* (valid for non-constants only).
- SDNode *getSDNode() { assert (!Const); return Node; }
+ // Returns the SDNode* for a register ref
+ SDNode *getSDNode() { assert (kind==SD); return u.s.Node; }
- // Returns the ResNo (valid for non-constants only).
- unsigned getResNo() { assert (!Const); return ResNo; }
+ // Returns the ResNo for a register ref
+ unsigned getResNo() { assert (kind==SD); return u.s.ResNo; }
- // Returns the Value* for a constant (invalid for non-constants).
- Value *getConst() { assert (!Node); return Const; }
+ // Returns the Value* for a constant
+ Value *getConst() { assert (kind==CNST); return u.Const; }
+
+ // Returns the FrameIx for a stack object
+ unsigned getFrameIx() { assert (kind==FX); return u.FrameIx; }
// Returns the offset.
uint64_t getOffset() { return Offset; }
diff --git a/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp b/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp
index 06e7b8c..4ace1b7 100644
--- a/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp
+++ b/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp
@@ -13,6 +13,7 @@
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "pre-RA-sched"
+#include "SDDbgValue.h"
#include "ScheduleDAGSDNodes.h"
#include "InstrEmitter.h"
#include "llvm/CodeGen/SelectionDAG.h"
@@ -412,6 +413,14 @@
InstrEmitter Emitter(BB, InsertPos);
DenseMap<SDValue, unsigned> VRBaseMap;
DenseMap<SUnit*, unsigned> CopyVRBaseMap;
+
+ // For now, any constant debug info nodes go at the beginning.
+ for (SDDbgInfo::ConstDbgIterator I = DAG->DbgConstBegin(),
+ E = DAG->DbgConstEnd(); I!=E; I++) {
+ Emitter.EmitDbgValue(*I, EM);
+ delete *I;
+ }
+
for (unsigned i = 0, e = Sequence.size(); i != e; i++) {
SUnit *SU = Sequence[i];
if (!SU) {
@@ -435,10 +444,20 @@
while (!FlaggedNodes.empty()) {
Emitter.EmitNode(FlaggedNodes.back(), SU->OrigNode != SU, SU->isCloned,
VRBaseMap, EM);
+ if (FlaggedNodes.back()->getHasDebugValue())
+ if (SDDbgValue *sd = DAG->GetDbgInfo(FlaggedNodes.back())) {
+ Emitter.EmitDbgValue(FlaggedNodes.back(), VRBaseMap, sd);
+ delete sd;
+ }
FlaggedNodes.pop_back();
}
Emitter.EmitNode(SU->getNode(), SU->OrigNode != SU, SU->isCloned,
VRBaseMap, EM);
+ if (SU->getNode()->getHasDebugValue())
+ if (SDDbgValue *sd = DAG->GetDbgInfo(SU->getNode())) {
+ Emitter.EmitDbgValue(SU->getNode(), VRBaseMap, sd);
+ delete sd;
+ }
}
BB = Emitter.getBlock();
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index 746d4e2..58a475c 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -13,6 +13,7 @@
#include "llvm/CodeGen/SelectionDAG.h"
#include "SDNodeOrdering.h"
+#include "SDDbgValue.h"
#include "llvm/Constants.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/Function.h"
@@ -596,6 +597,9 @@
// Remove the ordering of this node.
Ordering->remove(N);
+
+ // And its entry in the debug info table, if any.
+ DbgInfo->remove(N);
}
/// RemoveNodeFromCSEMaps - Take the specified node out of the CSE map that
@@ -793,6 +797,7 @@
Root(getEntryNode()), Ordering(0) {
AllNodes.push_back(&EntryNode);
Ordering = new SDNodeOrdering();
+ DbgInfo = new SDDbgInfo();
}
void SelectionDAG::init(MachineFunction &mf, MachineModuleInfo *mmi,
@@ -806,6 +811,7 @@
SelectionDAG::~SelectionDAG() {
allnodes_clear();
delete Ordering;
+ delete DbgInfo;
}
void SelectionDAG::allnodes_clear() {
@@ -833,6 +839,8 @@
Root = getEntryNode();
delete Ordering;
Ordering = new SDNodeOrdering();
+ delete DbgInfo;
+ DbgInfo = new SDDbgInfo();
}
SDValue SelectionDAG::getSExtOrTrunc(SDValue Op, DebugLoc DL, EVT VT) {
@@ -5264,6 +5272,25 @@
return Ordering->getOrder(SD);
}
+/// AssignDbgInfo - Assign debug info to the SDNode.
+void SelectionDAG::AssignDbgInfo(SDNode* SD, SDDbgValue* db) {
+ assert(SD && "Trying to assign dbg info to a null node!");
+ DbgInfo->add(SD, db);
+ SD->setHasDebugValue(true);
+}
+
+/// RememberDbgInfo - Remember debug info which is not assigned to an SDNode.
+void SelectionDAG::RememberDbgInfo(SDDbgValue* db) {
+ DbgInfo->add(db);
+}
+
+/// GetDbgInfo - Get the debug info, if any, for the SDNode.
+SDDbgValue* SelectionDAG::GetDbgInfo(const SDNode *SD) {
+ assert(SD && "Trying to get the order of a null node!");
+ if (SD->getHasDebugValue())
+ return DbgInfo->getSDDbgValue(SD);
+ return 0;
+}
//===----------------------------------------------------------------------===//
// SDNode Class
@@ -5911,7 +5938,7 @@
if (G)
if (unsigned Order = G->GetOrdering(this))
OS << " [ORD=" << Order << ']';
-
+
if (getNodeId() != -1)
OS << " [ID=" << getNodeId() << ']';
}
diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp
index 0cfcbb6..1416a6d 100644
--- a/lib/Target/X86/X86ISelLowering.cpp
+++ b/lib/Target/X86/X86ISelLowering.cpp
@@ -8521,6 +8521,21 @@
F->DeleteMachineInstr(MI); // The pseudo instruction is gone now.
return BB;
}
+ // DBG_VALUE. Only the frame index case is done here.
+ case X86::DBG_VALUE: {
+ const TargetInstrInfo *TII = getTargetMachine().getInstrInfo();
+ DebugLoc DL = MI->getDebugLoc();
+ X86AddressMode AM;
+ MachineFunction *F = BB->getParent();
+ AM.BaseType = X86AddressMode::FrameIndexBase;
+ AM.Base.FrameIndex = MI->getOperand(0).getImm();
+ addFullAddress(BuildMI(BB, DL, TII->get(X86::DBG_VALUE)), AM).
+ addImm(MI->getOperand(1).getImm()).
+ addMetadata(MI->getOperand(2).getMetadata());
+ F->DeleteMachineInstr(MI); // Remove pseudo.
+ return BB;
+ }
+
// String/text processing lowering.
case X86::PCMPISTRM128REG:
return EmitPCMP(MI, BB, 3, false /* in-mem */);