Progress towards shepherding debug info through SelectionDAG.

No functional effect yet.  This is still evolving and should
not be viewed as final.

llvm-svn: 98195
This commit is contained in:
Dale Johannesen 2010-03-10 22:13:47 +00:00
parent 1f6689a8ba
commit 49de0607a8
10 changed files with 276 additions and 40 deletions

View File

@ -227,6 +227,7 @@ namespace llvm {
private:
SDNode *Node; // Representative node.
MachineInstr *Instr; // Alternatively, a MachineInstr.
MachineInstr *DbgInstr; // A dbg_value referencing this.
public:
SUnit *OrigNode; // If not this, the node from which
// this node was cloned.
@ -269,10 +270,10 @@ namespace llvm {
/// SUnit - Construct an SUnit for pre-regalloc scheduling to represent
/// an SDNode and any nodes flagged to it.
SUnit(SDNode *node, unsigned nodenum)
: Node(node), Instr(0), OrigNode(0), NodeNum(nodenum), NodeQueueId(0),
Latency(0), NumPreds(0), NumSuccs(0), NumPredsLeft(0), NumSuccsLeft(0),
isTwoAddress(false), isCommutable(false), hasPhysRegDefs(false),
hasPhysRegClobbers(false),
: Node(node), Instr(0), DbgInstr(0), OrigNode(0), NodeNum(nodenum),
NodeQueueId(0), Latency(0), NumPreds(0), NumSuccs(0), NumPredsLeft(0),
NumSuccsLeft(0), isTwoAddress(false), isCommutable(false),
hasPhysRegDefs(false), hasPhysRegClobbers(false),
isPending(false), isAvailable(false), isScheduled(false),
isScheduleHigh(false), isCloned(false),
isDepthCurrent(false), isHeightCurrent(false), Depth(0), Height(0),
@ -281,10 +282,10 @@ namespace llvm {
/// SUnit - Construct an SUnit for post-regalloc scheduling to represent
/// a MachineInstr.
SUnit(MachineInstr *instr, unsigned nodenum)
: Node(0), Instr(instr), OrigNode(0), NodeNum(nodenum), NodeQueueId(0),
Latency(0), NumPreds(0), NumSuccs(0), NumPredsLeft(0), NumSuccsLeft(0),
isTwoAddress(false), isCommutable(false), hasPhysRegDefs(false),
hasPhysRegClobbers(false),
: Node(0), Instr(instr), DbgInstr(0), OrigNode(0), NodeNum(nodenum),
NodeQueueId(0), Latency(0), NumPreds(0), NumSuccs(0), NumPredsLeft(0),
NumSuccsLeft(0), isTwoAddress(false), isCommutable(false),
hasPhysRegDefs(false), hasPhysRegClobbers(false),
isPending(false), isAvailable(false), isScheduled(false),
isScheduleHigh(false), isCloned(false),
isDepthCurrent(false), isHeightCurrent(false), Depth(0), Height(0),
@ -292,10 +293,10 @@ namespace llvm {
/// SUnit - Construct a placeholder SUnit.
SUnit()
: Node(0), Instr(0), OrigNode(0), NodeNum(~0u), NodeQueueId(0),
Latency(0), NumPreds(0), NumSuccs(0), NumPredsLeft(0), NumSuccsLeft(0),
isTwoAddress(false), isCommutable(false), hasPhysRegDefs(false),
hasPhysRegClobbers(false),
: Node(0), Instr(0), DbgInstr(0), OrigNode(0), NodeNum(~0u),
NodeQueueId(0), Latency(0), NumPreds(0), NumSuccs(0), NumPredsLeft(0),
NumSuccsLeft(0), isTwoAddress(false), isCommutable(false),
hasPhysRegDefs(false), hasPhysRegClobbers(false),
isPending(false), isAvailable(false), isScheduled(false),
isScheduleHigh(false), isCloned(false),
isDepthCurrent(false), isHeightCurrent(false), Depth(0), Height(0),
@ -329,6 +330,20 @@ namespace llvm {
return Instr;
}
/// setDbgInstr - Assign the debug instruction for the SUnit.
/// This may be used during post-regalloc scheduling.
void setDbgInstr(MachineInstr *MI) {
assert(!Node && "Setting debug MachineInstr of SUnit with SDNode!");
DbgInstr = MI;
}
/// getDbgInstr - Return the debug MachineInstr for this SUnit.
/// This may be used during post-regalloc scheduling.
MachineInstr *getDbgInstr() const {
assert(!Node && "Reading debug MachineInstr of SUnit with SDNode!");
return DbgInstr;
}
/// addPred - This adds the specified edge as a pred of the current node if
/// not already. It also adds the current node as a successor of the
/// specified node.

View File

@ -35,6 +35,7 @@ class MachineConstantPoolValue;
class MachineFunction;
class MachineModuleInfo;
class SDNodeOrdering;
class SDDbgValue;
class TargetLowering;
template<> struct ilist_traits<SDNode> : public ilist_default_traits<SDNode> {
@ -57,6 +58,46 @@ private:
static void createNode(const SDNode &);
};
/// SDDbgInfo - Keeps track of dbg_value information through SDISel. We do
/// not build SDNodes for these so as not to perturb the generated code;
/// instead the info is kept off to the side in this structure. SDNodes may
/// have an associated dbg_value entry in DbgValMap. Debug info that is not
/// associated with any SDNode is held in DbgConstMap. It is possible for
/// optimizations to change a variable to a constant, in which case the
/// corresponding debug info is moved from the variable to the constant table
/// (NYI).
class SDDbgInfo {
DenseMap<const SDNode*, SDDbgValue*> DbgVblMap;
SmallVector<SDDbgValue*, 4> DbgConstMap;
void operator=(const SDDbgInfo&); // Do not implement.
SDDbgInfo(const SDDbgInfo&); // Do not implement.
public:
SDDbgInfo() {}
void add(const SDNode *Node, SDDbgValue *V) {
DbgVblMap[Node] = V;
}
void add(SDDbgValue *V) { DbgConstMap.push_back(V); }
void remove(const SDNode *Node) {
DenseMap<const SDNode*, SDDbgValue*>::iterator Itr =
DbgVblMap.find(Node);
if (Itr != DbgVblMap.end())
DbgVblMap.erase(Itr);
}
// No need to remove a constant.
void clear() {
DbgVblMap.clear();
DbgConstMap.clear();
}
SDDbgValue *getSDDbgValue(const SDNode *Node) {
return DbgVblMap[Node];
}
typedef SmallVector<SDDbgValue*, 4>::iterator ConstDbgIterator;
ConstDbgIterator DbgConstBegin() { return DbgConstMap.begin(); }
ConstDbgIterator DbgConstEnd() { return DbgConstMap.end(); }
};
enum CombineLevel {
Unrestricted, // Combine may create illegal operations and illegal types.
NoIllegalTypes, // Combine may create illegal operations but no illegal types.
@ -119,6 +160,9 @@ class SelectionDAG {
/// the ordering of the original LLVM instructions.
SDNodeOrdering *Ordering;
/// DbgInfo - Tracks dbg_value information through SDISel.
SDDbgInfo *DbgInfo;
/// VerifyNode - Sanity check the given node. Aborts if it is invalid.
void VerifyNode(SDNode *N);
@ -828,6 +872,20 @@ public:
/// GetOrdering - Get the order for the SDNode.
unsigned GetOrdering(const SDNode *SD) const;
/// AssignDbgInfo - Assign debug info to the SDNode.
void AssignDbgInfo(SDNode *SD, SDDbgValue *db);
/// RememberDbgInfo - Remember debug info with no associated SDNode.
void RememberDbgInfo(SDDbgValue *db);
/// GetDbgInfo - Get the debug info for the SDNode.
SDDbgValue *GetDbgInfo(const SDNode* SD);
SDDbgInfo::ConstDbgIterator DbgConstBegin() {
return DbgInfo->DbgConstBegin();
}
SDDbgInfo::ConstDbgIterator DbgConstEnd() { return DbgInfo->DbgConstEnd(); }
void dump() const;
/// CreateStackTemporary - Create a stack temporary, suitable for holding the

View File

@ -34,6 +34,7 @@ ScheduleDAGInstrs::ScheduleDAGInstrs(MachineFunction &mf,
const MachineDominatorTree &mdt)
: ScheduleDAG(mf), MLI(mli), MDT(mdt), LoopRegs(MLI, MDT) {
MFI = mf.getFrameInfo();
DbgValueVec.clear();
}
/// Run - perform scheduling.
@ -157,6 +158,10 @@ void ScheduleDAGInstrs::BuildSchedGraph(AliasAnalysis *AA) {
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 @@ void ScheduleDAGInstrs::BuildSchedGraph(AliasAnalysis *AA) {
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 @@ void ScheduleDAGInstrs::BuildSchedGraph(AliasAnalysis *AA) {
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 @@ EmitSchedule(DenseMap<MachineBasicBlock*, MachineBasicBlock*> *EM) {
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 @@ EmitSchedule(DenseMap<MachineBasicBlock*, MachineBasicBlock*> *EM) {
}
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;
}

View File

@ -106,6 +106,10 @@ namespace llvm {
/// 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

View File

@ -508,6 +508,7 @@ InstrEmitter::EmitDbgValue(SDNode *Node,
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 @@ InstrEmitter::EmitDbgValue(SDNode *Node,
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);
}

View File

@ -106,7 +106,8 @@ public:
/// 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.
///

View File

@ -28,9 +28,22 @@ class Value;
/// 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 @@ class SDDbgValue {
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; }

View File

@ -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 @@ EmitSchedule(DenseMap<MachineBasicBlock*, MachineBasicBlock*> *EM) {
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 @@ EmitSchedule(DenseMap<MachineBasicBlock*, MachineBasicBlock*> *EM) {
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();

View File

@ -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 @@ void SelectionDAG::DeallocateNode(SDNode *N) {
// 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 @@ SelectionDAG::SelectionDAG(TargetLowering &tli, FunctionLoweringInfo &fli)
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 @@ void SelectionDAG::init(MachineFunction &mf, MachineModuleInfo *mmi,
SelectionDAG::~SelectionDAG() {
allnodes_clear();
delete Ordering;
delete DbgInfo;
}
void SelectionDAG::allnodes_clear() {
@ -833,6 +839,8 @@ void SelectionDAG::clear() {
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 @@ unsigned SelectionDAG::GetOrdering(const SDNode *SD) const {
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 @@ void SDNode::print_details(raw_ostream &OS, const SelectionDAG *G) const {
if (G)
if (unsigned Order = G->GetOrdering(this))
OS << " [ORD=" << Order << ']';
if (getNodeId() != -1)
OS << " [ID=" << getNodeId() << ']';
}

View File

@ -8521,6 +8521,21 @@ X86TargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
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 */);