43 #define DEBUG_TYPE "live-debug-values"
45 STATISTIC(NumInserted,
"Number of DBG_VALUE instructions inserted");
68 class UserValueScopes {
80 LS.getMachineBasicBlocks(DL, LBlocks);
81 return LBlocks.count(MBB) != 0 ||
LS.dominates(DL, MBB);
86 typedef std::pair<const DILocalVariable *, const DILocation *>
89 struct DebugVariable :
public DebugVariableBase {
91 : DebugVariableBase(Var, InlinedAt) {}
94 const DILocation *getInlinedAt()
const {
return this->second; };
96 bool operator<(
const DebugVariable &DV)
const {
97 if (getVar() == DV.getVar())
98 return getInlinedAt() < DV.getInlinedAt();
99 return getVar() < DV.getVar();
105 const DebugVariable Var;
107 mutable UserValueScopes UVS;
121 : Var(MI.getDebugVariable(), MI.getDebugLoc()->getInlinedAt()), MI(MI),
122 UVS(MI.getDebugLoc(), LS),
Kind(InvalidKind) {
123 static_assert((
sizeof(Loc) ==
sizeof(uint64_t)),
124 "hash does not cover all members of Loc");
127 if (
int RegNo = isDbgValueDescribedByReg(MI)) {
129 Loc.RegisterLoc.RegNo = RegNo;
134 if (Offset >= (1ULL << 32))
137 Loc.RegisterLoc.Offset =
Offset;
145 return Loc.RegisterLoc.RegNo;
156 return Var == Other.Var && Loc.Hash == Other.Loc.Hash;
160 bool operator<(
const VarLoc &Other)
const {
161 if (Var == Other.Var)
162 return Loc.Hash < Other.Loc.Hash;
163 return Var < Other.Var;
175 class OpenRangesSet {
180 const VarLocSet &getVarLocs()
const {
return VarLocs; }
183 void erase(DebugVariable Var) {
184 auto It = Vars.
find(Var);
185 if (It != Vars.end()) {
186 unsigned ID = It->second;
194 void erase(
const VarLocSet &KillSet,
const VarLocMap &VarLocIDs) {
195 VarLocs.intersectWithComplement(KillSet);
196 for (
unsigned ID : KillSet)
197 Vars.erase(VarLocIDs[ID].Var);
201 void insert(
unsigned VarLocID, DebugVariableBase Var) {
202 VarLocs.set(VarLocID);
203 Vars.insert({Var, VarLocID});
214 assert(Vars.empty() == VarLocs.empty() &&
"open ranges are inconsistent");
215 return VarLocs.empty();
219 void transferDebugValue(
const MachineInstr &MI, OpenRangesSet &OpenRanges,
220 VarLocMap &VarLocIDs);
221 void transferRegisterDef(
MachineInstr &MI, OpenRangesSet &OpenRanges,
222 const VarLocMap &VarLocIDs);
223 bool transferTerminatorInst(
MachineInstr &MI, OpenRangesSet &OpenRanges,
224 VarLocInMBB &OutLocs,
const VarLocMap &VarLocIDs);
225 bool transfer(
MachineInstr &MI, OpenRangesSet &OpenRanges,
226 VarLocInMBB &OutLocs, VarLocMap &VarLocIDs);
229 const VarLocMap &VarLocIDs,
251 const VarLocMap &VarLocIDs,
const char *msg,
276 void LiveDebugValues::getAnalysisUsage(
AnalysisUsage &AU)
const {
286 const VarLocInMBB &V,
287 const VarLocMap &VarLocIDs,
290 Out <<
'\n' << msg <<
'\n';
292 const auto &
L = V.lookup(&BB);
293 Out <<
"MBB: " << BB.getName() <<
":\n";
294 for (
unsigned VLL :
L) {
295 const VarLoc &VL = VarLocIDs[VLL];
296 Out <<
" Var: " << VL.Var.getVar()->getName();
306 void LiveDebugValues::transferDebugValue(
const MachineInstr &MI,
307 OpenRangesSet &OpenRanges,
308 VarLocMap &VarLocIDs) {
313 const DILocation *InlinedAt = DebugLoc->getInlinedAt();
315 "Expected inlined-at fields to agree");
318 DebugVariable V(Var, InlinedAt);
323 if (isDbgValueDescribedByReg(MI)) {
325 unsigned ID = VarLocIDs.insert(VL);
326 OpenRanges.insert(ID, VL.Var);
331 void LiveDebugValues::transferRegisterDef(
MachineInstr &MI,
332 OpenRangesSet &OpenRanges,
333 const VarLocMap &VarLocIDs) {
339 if (MO.isReg() && MO.isDef() && MO.getReg() &&
340 TRI->isPhysicalRegister(MO.getReg())) {
343 for (
unsigned ID : OpenRanges.getVarLocs())
346 }
else if (MO.isRegMask()) {
351 for (
unsigned ID : OpenRanges.getVarLocs()) {
352 unsigned Reg = VarLocIDs[
ID].isDescribedByReg();
353 if (Reg && Reg != SP && MO.clobbersPhysReg(Reg))
358 OpenRanges.erase(KillSet, VarLocIDs);
362 bool LiveDebugValues::transferTerminatorInst(
MachineInstr &MI,
363 OpenRangesSet &OpenRanges,
364 VarLocInMBB &OutLocs,
365 const VarLocMap &VarLocIDs) {
366 bool Changed =
false;
371 if (OpenRanges.empty())
374 DEBUG(
for (
unsigned ID : OpenRanges.getVarLocs()) {
376 dbgs() <<
"Add to OutLocs: "; VarLocIDs[
ID].dump();
378 VarLocSet &VLS = OutLocs[CurMBB];
379 Changed = VLS |= OpenRanges.getVarLocs();
385 bool LiveDebugValues::transfer(
MachineInstr &MI, OpenRangesSet &OpenRanges,
386 VarLocInMBB &OutLocs, VarLocMap &VarLocIDs) {
387 bool Changed =
false;
388 transferDebugValue(MI, OpenRanges, VarLocIDs);
389 transferRegisterDef(MI, OpenRanges, VarLocIDs);
390 Changed = transferTerminatorInst(MI, OpenRanges, OutLocs, VarLocIDs);
398 VarLocInMBB &InLocs,
const VarLocMap &VarLocIDs,
401 bool Changed =
false;
412 if (!Visited.
count(p))
414 auto OL = OutLocs.find(p);
416 if (OL == OutLocs.end())
422 InLocsT = OL->second;
424 InLocsT &= OL->second;
430 for (
auto ID : InLocsT)
431 if (!VarLocIDs[ID].dominates(MBB))
433 InLocsT.intersectWithComplement(KillSet);
439 "Should have processed at least one predecessor");
443 VarLocSet &ILS = InLocs[&
MBB];
446 VarLocSet Diff = InLocsT;
447 Diff.intersectWithComplement(ILS);
448 for (
auto ID : Diff) {
452 const VarLoc &DiffIt = VarLocIDs[
ID];
472 DEBUG(
dbgs() <<
"\nDebug Range Extension\n");
474 bool Changed =
false;
475 bool OLChanged =
false;
476 bool MBBJoined =
false;
479 OpenRangesSet OpenRanges;
485 std::priority_queue<unsigned int, std::vector<unsigned int>,
486 std::greater<unsigned int>>
488 std::priority_queue<unsigned int, std::vector<unsigned int>,
489 std::greater<unsigned int>>
495 transfer(MI, OpenRanges, OutLocs, VarLocIDs);
497 DEBUG(printVarLocInMBB(MF, OutLocs, VarLocIDs,
"OutLocs after initialization",
501 unsigned int RPONumber = 0;
502 for (
auto RI = RPOT.begin(), RE = RPOT.end(); RI != RE; ++RI) {
503 OrderToBB[RPONumber] = *RI;
504 BBToOrder[*RI] = RPONumber;
505 Worklist.push(RPONumber);
513 while (!Worklist.empty() || !Pending.empty()) {
518 DEBUG(
dbgs() <<
"Processing Worklist\n");
519 while (!Worklist.empty()) {
522 MBBJoined =
join(*MBB, OutLocs, InLocs, VarLocIDs, Visited);
527 for (
auto &MI : *MBB)
528 OLChanged |= transfer(MI, OpenRanges, OutLocs, VarLocIDs);
530 DEBUG(printVarLocInMBB(MF, OutLocs, VarLocIDs,
531 "OutLocs after propagating",
dbgs()));
532 DEBUG(printVarLocInMBB(MF, InLocs, VarLocIDs,
533 "InLocs after propagating",
dbgs()));
537 for (
auto s : MBB->successors())
538 if (OnPending.
insert(s).second) {
539 Pending.push(BBToOrder[s]);
544 Worklist.swap(Pending);
547 assert(Pending.empty() &&
"Pending should be empty");
550 DEBUG(printVarLocInMBB(MF, OutLocs, VarLocIDs,
"Final OutLocs",
dbgs()));
551 DEBUG(printVarLocInMBB(MF, InLocs, VarLocIDs,
"Final InLocs",
dbgs()));
564 bool Changed = ExtendRanges(MF);
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
instr_iterator instr_begin()
STATISTIC(NumFunctions,"Total number of functions")
MachineInstr & instr_back()
size_type count(PtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
const MCInstrDesc & getDesc() const
Returns the target instruction descriptor of this MachineInstr.
const Function * getFunction() const
getFunction - Return the LLVM function that this machine code represents
iterator_range< mop_iterator > operands()
bool isTerminator(QueryType Type=AnyInBundle) const
Returns true if this instruction part of the terminator for a basic block.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
const HexagonInstrInfo * TII
bool isReg() const
isReg - Tests if this is a MO_Register operand.
static GCRegistry::Add< StatepointGC > D("statepoint-example","an example strategy for statepoint")
Reg
All possible values of the reg field in the ModR/M byte.
INITIALIZE_PASS(LiveDebugValues,"livedebugvalues","Live DEBUG_VALUE analysis", false, false) LiveDebugValues
Default construct and initialize the pass.
std::string join(IteratorT Begin, IteratorT End, StringRef Separator)
Joins the strings in the range [Begin, End), adding Separator between the elements.
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
unsigned getNumOperands() const
Access to explicit operands of the instruction.
void initialize(const MachineFunction &)
initialize - Scan machine function and constuct lexical scope nest, resets the instance if necessary...
void initializeLiveDebugValuesPass(PassRegistry &)
const MachineBasicBlock * getParent() const
TargetInstrInfo - Interface to description of machine instruction set.
bool isDebugValue() const
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
bool isIndirectDebugValue() const
A DBG_VALUE is indirect iff the first operand is a register and the second operand is an immediate...
const MachineOperand & getOperand(unsigned i) const
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
MCRegAliasIterator enumerates all registers aliasing Reg.
Represent the analysis usage information of a pass.
char & LiveDebugValuesID
LiveDebugValues pass.
void setImm(int64_t immVal)
iterator_range< pred_iterator > predecessors()
const DIExpression * getDebugExpression() const
Return the complex address expression referenced by this DBG_VALUE instruction.
unsigned getStackPointerRegisterToSaveRestore() const
If a physical register, this specifies the register that llvm.savestack/llvm.restorestack should save...
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
static unsigned isDescribedByReg(const MachineInstr &MI)
void dump() const
Support for debugging, callable in GDB: V->dump()
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements...
MachineOperand class - Representation of each machine instruction operand.
virtual const TargetLowering * getTargetLowering() const
void dump(const TargetInstrInfo *TII=nullptr) const
void setPreservesCFG()
This function should be called by the pass, iff they do not:
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
StringRef getName() const
Return the name of the corresponding LLVM basic block, or "(null)".
DISubprogram * getSubprogram() const
Get the attached subprogram.
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
static void clear(coro::Shape &Shape)
MachineFunctionProperties & set(Property P)
Representation of each machine instruction.
LexicalScopes - This class provides interface to collect and use lexical scoping information from mac...
iterator find(const KeyT &Val)
const DILocalVariable * getDebugVariable() const
Return the debug variable referenced by this DBG_VALUE instruction.
unsigned getReg() const
getReg - Returns the register number.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
bool operator<(int64_t V1, const APSInt &V2)
virtual const TargetInstrInfo * getInstrInfo() const
This class implements an extremely fast bulk output stream that can only output to a stream...
std::string Hash(const Unit &U)
bool isValidLocationForIntrinsic(const DILocation *DL) const
Check that a location is valid for this variable.
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
bool operator==(uint64_t V1, const APInt &V2)
UniqueVector - This class produces a sequential ID number (base 1) for each unique entry that is adde...
Properties which a MachineFunction may have at a given point in time.
This file describes how to lower LLVM code to machine code.