44 #include "llvm/Config/llvm-config.h" 65 #define DEBUG_TYPE "livedebugvalues" 67 STATISTIC(NumInserted,
"Number of DBG_VALUE instructions inserted");
91 class UserValueScopes {
109 using DebugVariableBase =
110 std::pair<const DILocalVariable *, const DILocation *>;
112 struct DebugVariable :
public DebugVariableBase {
114 : DebugVariableBase(Var, InlinedAt) {}
119 bool operator<(
const DebugVariable &DV)
const {
120 if (getVar() == DV.getVar())
121 return getInlinedAt() < DV.getInlinedAt();
122 return getVar() < DV.getVar();
128 const DebugVariable Var;
130 mutable UserValueScopes UVS;
143 static_assert((
sizeof(Loc) ==
sizeof(uint64_t)),
144 "hash does not cover all members of Loc");
165 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 170 return Var == Other.Var && Loc.Hash == Other.Loc.Hash;
174 bool operator<(
const VarLoc &Other)
const {
175 if (Var == Other.Var)
176 return Loc.Hash < Other.Loc.Hash;
177 return Var < Other.Var;
184 struct TransferDebugPair {
194 class OpenRangesSet {
199 const VarLocSet &getVarLocs()
const {
return VarLocs; }
202 void erase(DebugVariable Var) {
203 auto It = Vars.
find(Var);
204 if (It != Vars.
end()) {
205 unsigned ID = It->second;
213 void erase(
const VarLocSet &KillSet,
const VarLocMap &VarLocIDs) {
214 VarLocs.intersectWithComplement(KillSet);
215 for (
unsigned ID : KillSet)
220 void insert(
unsigned VarLocID, DebugVariableBase Var) {
221 VarLocs.set(VarLocID);
222 Vars.
insert({Var, VarLocID});
233 assert(Vars.
empty() == VarLocs.empty() &&
"open ranges are inconsistent");
234 return VarLocs.empty();
240 int extractSpillBaseRegAndOffset(
const MachineInstr &MI,
unsigned &Reg);
241 void insertTransferDebugPair(
MachineInstr &MI, OpenRangesSet &OpenRanges,
242 TransferMap &Transfers, VarLocMap &VarLocIDs,
243 unsigned OldVarID,
unsigned NewReg = 0);
245 void transferDebugValue(
const MachineInstr &MI, OpenRangesSet &OpenRanges,
246 VarLocMap &VarLocIDs);
247 void transferSpillInst(
MachineInstr &MI, OpenRangesSet &OpenRanges,
248 VarLocMap &VarLocIDs, TransferMap &Transfers);
249 void transferRegisterCopy(
MachineInstr &MI, OpenRangesSet &OpenRanges,
250 VarLocMap &VarLocIDs, TransferMap &Transfers);
251 void transferRegisterDef(
MachineInstr &MI, OpenRangesSet &OpenRanges,
252 const VarLocMap &VarLocIDs);
253 bool transferTerminatorInst(
MachineInstr &MI, OpenRangesSet &OpenRanges,
254 VarLocInMBB &OutLocs,
const VarLocMap &VarLocIDs);
255 bool process(
MachineInstr &MI, OpenRangesSet &OpenRanges,
256 VarLocInMBB &OutLocs, VarLocMap &VarLocIDs,
257 TransferMap &Transfers,
bool transferChanges);
260 const VarLocMap &VarLocIDs,
283 const VarLocMap &VarLocIDs,
const char *msg,
310 void LiveDebugValues::getAnalysisUsage(
AnalysisUsage &AU)
const {
321 const VarLocInMBB &V,
322 const VarLocMap &VarLocIDs,
325 Out <<
'\n' << msg <<
'\n';
327 const VarLocSet &L = V.lookup(&BB);
330 Out <<
"MBB: " << BB.getNumber() <<
":\n";
331 for (
unsigned VLL : L) {
332 const VarLoc &VL = VarLocIDs[VLL];
333 Out <<
" Var: " << VL.Var.getVar()->getName();
344 int LiveDebugValues::extractSpillBaseRegAndOffset(
const MachineInstr &
MI,
347 "Spill instruction does not have exactly one memory operand?");
351 "Inconsistent memory operand in spill instruction");
352 int FI = cast<FixedStackPseudoSourceValue>(PVal)->getFrameIndex();
354 return TFI->getFrameIndexReference(*MBB->
getParent(), FI,
Reg);
359 void LiveDebugValues::transferDebugValue(
const MachineInstr &MI,
360 OpenRangesSet &OpenRanges,
361 VarLocMap &VarLocIDs) {
366 const DILocation *InlinedAt = DebugLoc->getInlinedAt();
368 "Expected inlined-at fields to agree");
371 DebugVariable V(Var, InlinedAt);
378 unsigned ID = VarLocIDs.insert(VL);
379 OpenRanges.insert(ID, VL.Var);
388 void LiveDebugValues::insertTransferDebugPair(
389 MachineInstr &MI, OpenRangesSet &OpenRanges, TransferMap &Transfers,
390 VarLocMap &VarLocIDs,
unsigned OldVarID,
unsigned NewReg) {
402 LLVM_DEBUG(
dbgs() <<
"Creating DBG_VALUE inst for register copy: ";
408 int SpillOffset = extractSpillBaseRegAndOffset(MI, SpillBase);
414 NewDMI->print(
dbgs(),
false,
false,
false,
TII));
419 TransferDebugPair MIP = {&
MI, NewDMI};
420 Transfers.push_back(MIP);
423 OpenRanges.erase(VarLocIDs[OldVarID].Var);
426 VarLoc VL(*NewDMI,
LS);
427 unsigned LocID = VarLocIDs.insert(VL);
428 OpenRanges.insert(LocID, VL.Var);
432 void LiveDebugValues::transferRegisterDef(
MachineInstr &MI,
433 OpenRangesSet &OpenRanges,
434 const VarLocMap &VarLocIDs) {
443 if (MO.isReg() && MO.isDef() && MO.getReg() &&
444 TRI->isPhysicalRegister(MO.getReg()) &&
445 !(MI.
isCall() && MO.getReg() == SP)) {
448 for (
unsigned ID : OpenRanges.getVarLocs())
451 }
else if (MO.isRegMask()) {
456 for (
unsigned ID : OpenRanges.getVarLocs()) {
457 unsigned Reg = VarLocIDs[
ID].isDescribedByReg();
458 if (Reg && Reg != SP && MO.clobbersPhysReg(Reg))
463 OpenRanges.erase(KillSet, VarLocIDs);
472 bool LiveDebugValues::isSpillInstruction(
const MachineInstr &MI,
483 if (!((
TII->isStoreToStackSlotPostFE(MI, FI) &&
505 if (isKilledReg(MO, Reg))
519 if (isKilledReg(MONext, RegNext) && RegNext ==
Reg)
534 void LiveDebugValues::transferSpillInst(
MachineInstr &MI,
535 OpenRangesSet &OpenRanges,
536 VarLocMap &VarLocIDs,
537 TransferMap &Transfers) {
540 if (!isSpillInstruction(MI, MF, Reg))
544 for (
unsigned ID : OpenRanges.getVarLocs()) {
547 << VarLocIDs[
ID].Var.getVar()->getName() <<
")\n");
548 insertTransferDebugPair(MI, OpenRanges, Transfers, VarLocIDs,
ID);
557 void LiveDebugValues::transferRegisterCopy(
MachineInstr &MI,
558 OpenRangesSet &OpenRanges,
559 VarLocMap &VarLocIDs,
560 TransferMap &Transfers) {
563 if (!
TII->isCopyInstr(MI, SrcRegOp, DestRegOp) || !SrcRegOp->
isKill() ||
567 auto isCalleSavedReg = [&](
unsigned Reg) {
569 if (CalleeSavedRegs.test(*RAI))
574 unsigned SrcReg = SrcRegOp->
getReg();
575 unsigned DestReg = DestRegOp->
getReg();
582 if (!isCalleSavedReg(DestReg))
585 for (
unsigned ID : OpenRanges.getVarLocs()) {
587 insertTransferDebugPair(MI, OpenRanges, Transfers, VarLocIDs,
ID,
595 bool LiveDebugValues::transferTerminatorInst(
MachineInstr &MI,
596 OpenRangesSet &OpenRanges,
597 VarLocInMBB &OutLocs,
598 const VarLocMap &VarLocIDs) {
599 bool Changed =
false;
604 if (OpenRanges.empty())
608 : OpenRanges.getVarLocs()) {
610 dbgs() <<
"Add to OutLocs in MBB #" << CurMBB->
getNumber() <<
": ";
611 VarLocIDs[
ID].dump();
613 VarLocSet &VLS = OutLocs[CurMBB];
614 Changed = VLS |= OpenRanges.getVarLocs();
620 bool LiveDebugValues::process(
MachineInstr &MI, OpenRangesSet &OpenRanges,
621 VarLocInMBB &OutLocs, VarLocMap &VarLocIDs,
622 TransferMap &Transfers,
bool transferChanges) {
623 bool Changed =
false;
624 transferDebugValue(MI, OpenRanges, VarLocIDs);
625 transferRegisterDef(MI, OpenRanges, VarLocIDs);
626 if (transferChanges) {
627 transferRegisterCopy(MI, OpenRanges, VarLocIDs, Transfers);
628 transferSpillInst(MI, OpenRanges, VarLocIDs, Transfers);
630 Changed = transferTerminatorInst(MI, OpenRanges, OutLocs, VarLocIDs);
639 const VarLocMap &VarLocIDs,
643 bool Changed =
false;
654 if (!Visited.
count(p)) {
655 LLVM_DEBUG(
dbgs() <<
" ignoring unvisited pred MBB: " << p->getNumber()
659 auto OL = OutLocs.find(p);
661 if (OL == OutLocs.end())
667 InLocsT = OL->second;
669 InLocsT &= OL->second;
672 if (!InLocsT.empty()) {
673 for (
auto ID : InLocsT)
674 dbgs() <<
" gathered candidate incoming var: " 675 << VarLocIDs[
ID].Var.getVar()->getName() <<
"\n";
684 bool IsArtificial = ArtificialBlocks.
count(&MBB);
686 for (
auto ID : InLocsT) {
687 if (!VarLocIDs[
ID].dominates(MBB)) {
691 dbgs() <<
" killing " <<
Name <<
", it doesn't dominate MBB\n";
696 InLocsT.intersectWithComplement(KillSet);
702 "Should have processed at least one predecessor");
706 VarLocSet &ILS = InLocs[&MBB];
709 VarLocSet Diff = InLocsT;
710 Diff.intersectWithComplement(ILS);
711 for (
auto ID : Diff) {
715 const VarLoc &DiffIt = VarLocIDs[
ID];
736 bool Changed =
false;
737 bool OLChanged =
false;
738 bool MBBJoined =
false;
741 OpenRangesSet OpenRanges;
744 TransferMap Transfers;
752 std::priority_queue<unsigned int, std::vector<unsigned int>,
753 std::greater<unsigned int>>
755 std::priority_queue<unsigned int, std::vector<unsigned int>,
756 std::greater<unsigned int>>
759 enum :
bool { dontTransferChanges =
false, transferChanges =
true };
768 process(MI, OpenRanges, OutLocs, VarLocIDs, Transfers,
769 dontTransferChanges);
771 auto hasNonArtificialLocation = [](
const MachineInstr &
MI) ->
bool {
773 return DL.getLine() != 0;
777 if (
none_of(MBB.instrs(), hasNonArtificialLocation))
778 ArtificialBlocks.
insert(&MBB);
780 LLVM_DEBUG(printVarLocInMBB(MF, OutLocs, VarLocIDs,
781 "OutLocs after initialization",
dbgs()));
784 unsigned int RPONumber = 0;
785 for (
auto RI = RPOT.
begin(), RE = RPOT.
end(); RI != RE; ++RI) {
786 OrderToBB[RPONumber] = *RI;
787 BBToOrder[*RI] = RPONumber;
788 Worklist.push(RPONumber);
796 while (!Worklist.empty() || !Pending.empty()) {
802 while (!Worklist.empty()) {
806 join(*MBB, OutLocs, InLocs, VarLocIDs, Visited, ArtificialBlocks);
814 for (
auto &MI : *MBB)
815 OLChanged |= process(MI, OpenRanges, OutLocs, VarLocIDs, Transfers,
819 for (
auto &TR : Transfers)
824 LLVM_DEBUG(printVarLocInMBB(MF, OutLocs, VarLocIDs,
825 "OutLocs after propagating",
dbgs()));
826 LLVM_DEBUG(printVarLocInMBB(MF, InLocs, VarLocIDs,
827 "InLocs after propagating",
dbgs()));
831 for (
auto s : MBB->successors())
832 if (OnPending.
insert(s).second) {
833 Pending.push(BBToOrder[s]);
838 Worklist.swap(Pending);
841 assert(Pending.empty() &&
"Pending should be empty");
844 LLVM_DEBUG(printVarLocInMBB(MF, OutLocs, VarLocIDs,
"Final OutLocs",
dbgs()));
845 LLVM_DEBUG(printVarLocInMBB(MF, InLocs, VarLocIDs,
"Final InLocs",
dbgs()));
863 make_unique<RegScavenger>().
get());
866 bool Changed = ExtendRanges(MF);
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
instr_iterator instr_begin()
bool isCall(QueryType Type=AnyInBundle) const
const MachineFunction * getMF() const
Return the function that contains the basic block that this instruction belongs to.
This class represents lattice values for constants.
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
bool dominates(const DILocation *DL, MachineBasicBlock *MBB)
dominates - Return true if DebugLoc's lexical scope dominates at least one machine instruction's lexi...
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
unsigned getReg() const
getReg - Returns the register number.
virtual const TargetLowering * getTargetLowering() const
STATISTIC(NumFunctions, "Total number of functions")
unsigned const TargetRegisterInfo * TRI
iterator_range< mop_iterator > operands()
static DIExpression * prepend(const DIExpression *Expr, bool DerefBefore, int64_t Offset=0, bool DerefAfter=false, bool StackValue=false)
Prepend DIExpr with a deref and offset operation and optionally turn it into a stack value...
virtual void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs, RegScavenger *RS=nullptr) const
This method determines which of the registers reported by TargetRegisterInfo::getCalleeSavedRegs() sh...
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
A description of a memory reference used in the backend.
amdgpu Simplify well known AMD library false Value Value const Twine & Name
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
const HexagonInstrInfo * TII
unsigned getNumOperands() const
Retuns the total number of operands.
Printable printReg(unsigned Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)
Prints virtual and physical registers with or without a TRI instance.
bool none_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly...
bool isTerminator(QueryType Type=AnyInBundle) const
Returns true if this instruction part of the terminator for a basic block.
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted...
std::string join(IteratorT Begin, IteratorT End, StringRef Separator)
Joins the strings in the range [Begin, End), adding Separator between the elements.
bool hasStoreToStackSlot(const MachineInstr &MI, SmallVectorImpl< const MachineMemOperand *> &Accesses) const override
Check if the instruction or the bundle of instructions has store to stack slots.
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
const MCInstrDesc & getDesc() const
Returns the target instruction descriptor of this MachineInstr.
INITIALIZE_PASS(LiveDebugValues, DEBUG_TYPE, "Live DEBUG_VALUE analysis", false, false) LiveDebugValues
Default construct and initialize the pass.
int getNumber() const
MachineBasicBlocks are uniquely numbered at the function level, unless they're not in a MachineFuncti...
virtual const TargetInstrInfo * getInstrInfo() const
void initializeLiveDebugValuesPass(PassRegistry &)
TargetInstrInfo - Interface to description of machine instruction set.
iterator find(const_arg_type_t< KeyT > Val)
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
bool erase(const KeyT &Val)
This file declares the machine register scavenger class.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
DISubprogram * getSubprogram() const
Get the attached subprogram.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
LLVM_NODISCARD bool empty() const
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
bool isValidLocationForIntrinsic(const DILocation *DL) const
Check that a location is valid for this variable.
MCRegAliasIterator enumerates all registers aliasing Reg.
Represent the analysis usage information of a pass.
bool hasOneMemOperand() const
Return true if this instruction has exactly one MachineMemOperand.
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly...
const PseudoSourceValue * getPseudoValue() const
char & LiveDebugValuesID
LiveDebugValues pass.
void setImm(int64_t immVal)
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
self_iterator getIterator()
iterator_range< pred_iterator > predecessors()
void print(raw_ostream &OS, bool IsStandalone=true, bool SkipOpers=false, bool SkipDebugLoc=false, bool AddNewLine=true, const TargetInstrInfo *TII=nullptr) const
Print this MI to OS.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
static unsigned isDescribedByReg(const MachineInstr &MI)
void getMachineBasicBlocks(const DILocation *DL, SmallPtrSetImpl< const MachineBasicBlock *> &MBBs)
getMachineBasicBlocks - Populate given set using machine basic blocks which have machine instructions...
const DIExpression * getDebugExpression() const
Return the complex address expression referenced by this DBG_VALUE instruction.
constexpr bool empty(const T &RangeOrContainer)
Test whether RangeOrContainer is empty. Similar to C++17 std::empty.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements...
mmo_iterator memoperands_begin() const
Access to memory operands of the instruction.
bool isDebugValue() const
MachineOperand class - Representation of each machine instruction operand.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
Module.h This file contains the declarations for the Module class.
Information about stack frame layout on the target.
static unsigned isDbgValueDescribedByReg(const MachineInstr &MI)
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
void setPreservesCFG()
This function should be called by the pass, iff they do not:
const Function & getFunction() const
Return the LLVM function that this machine code represents.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Special value supplied for machine level alias analysis.
static void clear(coro::Shape &Shape)
const MachineBasicBlock * getParent() const
MachineFunctionProperties & set(Property P)
Representation of each machine instruction.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
LexicalScopes - This class provides interface to collect and use lexical scoping information from mac...
StringRef getName() const
Return a constant reference to the value's name.
virtual const TargetFrameLowering * getFrameLowering() const
LLVM_NODISCARD bool empty() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
bool operator<(int64_t V1, const APSInt &V2)
unsigned getStackPointerRegisterToSaveRestore() const
If a physical register, this specifies the register that llvm.savestack/llvm.restorestack should save...
const DILocalVariable * getDebugVariable() const
Return the debug variable referenced by this DBG_VALUE instruction.
This class implements an extremely fast bulk output stream that can only output to a stream...
bool operator==(uint64_t V1, const APInt &V2)
const MachineOperand & getOperand(unsigned i) const
bool isIndirectDebugValue() const
A DBG_VALUE is indirect iff the first operand is a register and the second operand is an immediate...
UniqueVector - This class produces a sequential ID number (base 1) for each unique entry that is adde...
bool isSpillSlotObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to a spill slot.
Properties which a MachineFunction may have at a given point in time.
This file describes how to lower LLVM code to machine code.