33#define DEBUG_TYPE "dwarfdebug"
56 unsigned Position = 0;
59 InstNumberMap[&
MI] =
MI.isMetaInstruction() ? Position : ++Position;
64 assert(
A->getParent() &&
B->getParent() &&
"Operands must have a parent");
66 "Operands must be in the same MachineFunction");
67 return InstNumberMap.lookup(
A) < InstNumberMap.lookup(
B);
75 assert(
MI.isDebugValue() &&
"not a DBG_VALUE");
76 auto &
Entries = VarEntries[Var];
92 auto &
Entries = VarEntries[Var];
113static std::optional<ArrayRef<InsnRange>::iterator>
117 for (
auto RangesI = Ranges.begin(), RangesE = Ranges.end();
118 RangesI != RangesE; ++RangesI) {
119 if (EndMI && Ordering.isBefore(EndMI, RangesI->first))
121 if (EndMI && !Ordering.isBefore(RangesI->second, EndMI))
123 if (Ordering.isBefore(StartMI, RangesI->second))
144 for (
auto &
Record : VarEntries) {
145 auto &HistoryMapEntries =
Record.second;
146 if (HistoryMapEntries.empty())
153 if (
const DILocation *InlinedAt = Entity.second) {
165 (Scope->getScopeNode() == Scope->getScopeNode()->getSubprogram()) &&
166 (Scope->getScopeNode() == LocalVar->getScope()))
177 ReferenceCount.
assign(HistoryMapEntries.size(), 0);
182 for (
auto EI = HistoryMapEntries.begin(), EE = HistoryMapEntries.end();
183 EI != EE; ++EI, ++StartIndex) {
185 if (!EI->isDbgValue())
192 ReferenceCount[EndIndex] += 1;
197 if (ReferenceCount[StartIndex] > 0)
202 ? HistoryMapEntries[EndIndex].getInstr()
206 if (
auto R =
intersects(StartMI, EndMI, ScopeRanges, Ordering)) {
218 ReferenceCount[EndIndex] -= 1;
219 LLVM_DEBUG(
dbgs() <<
"Dropping value outside scope range of variable: ";
229 for (
size_t i = 0; i < HistoryMapEntries.size(); ++i)
230 if (ReferenceCount[i] <= 0 && HistoryMapEntries[i].isClobber())
238 Offsets.assign(HistoryMapEntries.size(), 0);
239 size_t CurOffset = 0;
240 auto ToRemoveItr =
ToRemove.begin();
241 for (
size_t EntryIdx = *ToRemoveItr; EntryIdx < HistoryMapEntries.size();
244 if (ToRemoveItr !=
ToRemove.end() && *ToRemoveItr == EntryIdx) {
248 Offsets[EntryIdx] = CurOffset;
253 for (
auto &
Entry : HistoryMapEntries)
260 HistoryMapEntries.erase(HistoryMapEntries.begin() +
Idx);
262 <<
"') size: " << HistoryMapEntries.size() <<
"\n");
274 if (
MI->isUndefDebugValue())
284 assert(
MI.isDebugLabel() &&
"not a DBG_LABEL");
285 LabelInstr[Label] = &
MI;
292using RegDescribedVarsMap = std::map<unsigned, SmallVector<InlinedEntity, 1>>;
298using DbgValueEntriesMap = std::map<InlinedEntity, SmallSet<EntryIndex, 1>>;
305 const auto &
I = RegVars.find(RegNo);
306 assert(RegNo != 0U &&
I != RegVars.end());
307 auto &VarSet =
I->second;
309 assert(VarPos != VarSet.end());
310 VarSet.erase(VarPos);
320 auto &VarSet = RegVars[RegNo];
322 VarSet.push_back(Var);
331 DbgValueEntriesMap &LiveEntries,
342 for (
auto Index : LiveEntries[Var]) {
344 assert(Entry.isDbgValue() &&
"Not a DBG_VALUE in LiveEntries");
345 if (Entry.getInstr()->isDebugEntryValue())
347 if (Entry.getInstr()->hasDebugOperandForReg(RegNo)) {
349 Entry.endEntry(ClobberIndex);
350 for (
const auto &MO : Entry.getInstr()->debug_operands())
351 if (MO.isReg() && MO.getReg() && MO.getReg() != RegNo)
352 MaybeRemovedRegisters.
insert(MO.getReg());
354 for (
const auto &MO : Entry.getInstr()->debug_operands())
355 if (MO.isReg() && MO.getReg())
356 KeepRegisters.
insert(MO.getReg());
360 for (
Register Reg : MaybeRemovedRegisters)
365 for (
auto Index : IndicesToErase)
366 LiveEntries[Var].erase(
Index);
371 RegDescribedVarsMap &RegVars,
372 DbgValueEntriesMap &LiveEntries,
382 for (
auto Index : LiveEntries[Var]) {
384 assert(Entry.isDbgValue() &&
"Not a DBG_VALUE in LiveEntries");
389 Entry.endEntry(NewIndex);
393 if (
Op.isReg() &&
Op.getReg())
394 TrackedRegs[
Op.getReg()] |= !Overlaps;
401 if (
Op.isReg() &&
Op.getReg()) {
403 if (!TrackedRegs.
count(NewReg))
405 LiveEntries[Var].insert(NewIndex);
406 TrackedRegs[NewReg] =
true;
412 for (
auto I : TrackedRegs)
417 for (
auto Index : IndicesToErase)
418 LiveEntries[Var].erase(
Index);
419 LiveEntries[Var].insert(NewIndex);
426 RegDescribedVarsMap::iterator
I,
428 DbgValueEntriesMap &LiveEntries,
434 for (
const auto &Var :
I->second) {
438 for (
Register RegNo : FellowRegisters)
448 DbgValueEntriesMap &LiveEntries,
450 const auto &
I = RegVars.find(RegNo);
451 if (
I == RegVars.end())
463 RegDescribedVarsMap RegVars;
464 DbgValueEntriesMap LiveEntries;
465 for (
const auto &
MBB : *MF) {
466 for (
const auto &
MI :
MBB) {
467 if (
MI.isDebugValue()) {
468 assert(
MI.getNumOperands() > 1 &&
"Invalid DBG_VALUE instruction!");
474 "Expected inlined-at fields to agree");
478 }
else if (
MI.isDebugLabel()) {
479 assert(
MI.getNumOperands() == 1 &&
"Invalid DBG_LABEL instruction!");
480 const DILabel *RawLabel =
MI.getDebugLabel();
482 "Expected inlined-at fields to agree");
492 if (
MI.isMetaInstruction())
498 if (MO.isReg() && MO.isDef() && MO.getReg()) {
501 if (
MI.isCall() && MO.getReg() == SP)
505 if (MO.getReg().isVirtual())
512 else if (MO.getReg() != FrameReg ||
519 }
else if (MO.isRegMask()) {
524 for (
auto It : RegVars) {
525 unsigned int Reg = It.first;
527 MO.clobbersPhysReg(Reg))
531 for (
unsigned Reg : RegsToClobber) {
543 for (
auto &Pair : LiveEntries) {
544 if (Pair.second.empty())
564#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
566 dbgs() <<
"DbgValueHistoryMap('" << FuncName <<
"'):\n";
567 for (
const auto &VarRangePair : *
this) {
574 dbgs() <<
" - " << LocalVar->getName() <<
" at ";
577 dbgs() << Location->getFilename() <<
":" << Location->getLine() <<
":"
578 << Location->getColumn();
580 dbgs() <<
"<unknown location>";
585 const auto &
Entry = E.value();
586 dbgs() <<
" Entry[" << E.index() <<
"]: ";
588 dbgs() <<
"Debug value\n";
590 dbgs() <<
"Clobber\n";
594 dbgs() <<
" - Valid until end of function\n";
ReachingDefAnalysis InstSet & ToRemove
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
static std::optional< ArrayRef< InsnRange >::iterator > intersects(const MachineInstr *StartMI, const MachineInstr *EndMI, const ArrayRef< InsnRange > &Ranges, const InstructionOrdering &Ordering)
Check if the instruction range [StartMI, EndMI] intersects any instruction range in Ranges.
static void addRegDescribedVar(RegDescribedVarsMap &RegVars, unsigned RegNo, InlinedEntity Var)
static void clobberRegEntries(InlinedEntity Var, unsigned RegNo, const MachineInstr &ClobberingInstr, DbgValueEntriesMap &LiveEntries, DbgValueHistoryMap &HistMap, SmallVectorImpl< Register > &FellowRegisters)
Create a clobbering entry and end all open debug value entries for Var that are described by RegNo us...
static void handleNewDebugValue(InlinedEntity Var, const MachineInstr &DV, RegDescribedVarsMap &RegVars, DbgValueEntriesMap &LiveEntries, DbgValueHistoryMap &HistMap)
Add a new debug value for Var. Closes all overlapping debug values.
static void dropRegDescribedVar(RegDescribedVarsMap &RegVars, unsigned RegNo, InlinedEntity Var)
static void clobberRegisterUses(RegDescribedVarsMap &RegVars, RegDescribedVarsMap::iterator I, DbgValueHistoryMap &HistMap, DbgValueEntriesMap &LiveEntries, const MachineInstr &ClobberingInstr)
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
unsigned const TargetRegisterInfo * TRI
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallSet class.
This file defines the SmallVector class.
This file describes how to lower LLVM code to machine code.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
static bool fragmentsOverlap(const FragmentInfo &A, const FragmentInfo &B)
Check if fragments overlap between a pair of FragmentInfos.
bool isValidLocationForIntrinsic(const DILocation *DL) const
Check that a location is valid for this label.
bool isValidLocationForIntrinsic(const DILocation *DL) const
Check that a location is valid for this variable.
This class represents an Operation in the Expression.
For each inlined instance of a source-level label, keep the corresponding DBG_LABEL instruction.
std::pair< const DINode *, const DILocation * > InlinedEntity
void addInstr(InlinedEntity Label, const MachineInstr &MI)
Specifies a change in a variable's debug value history.
const MachineInstr * getInstr() const
EntryIndex getEndIndex() const
void endEntry(EntryIndex EndIndex)
For each user variable, keep a list of instruction ranges where this variable is accessible.
bool startDbgValue(InlinedEntity Var, const MachineInstr &MI, EntryIndex &NewIndex)
void trimLocationRanges(const MachineFunction &MF, LexicalScopes &LScopes, const InstructionOrdering &Ordering)
Drop location ranges which exist entirely outside each variable's scope.
size_t EntryIndex
Index in the entry vector.
EntryIndex startClobber(InlinedEntity Var, const MachineInstr &MI)
Entry & getEntry(InlinedEntity Var, EntryIndex Index)
LLVM_DUMP_METHOD void dump(StringRef FuncName) const
static const EntryIndex NoEntry
Special value to indicate that an entry is valid until the end of the function.
bool hasNonEmptyLocation(const Entries &Entries) const
Test whether a vector of entries features any non-empty locations.
std::pair< const DINode *, const DILocation * > InlinedEntity
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
Record instruction ordering so we can query their relative positions within a function.
void initialize(const MachineFunction &MF)
bool isBefore(const MachineInstr *A, const MachineInstr *B) const
Check if instruction A comes before B, where A and B both belong to the MachineFunction passed to ini...
LexicalScope - This class is used to track scope information.
LexicalScopes - This class provides interface to collect and use lexical scoping information from mac...
LexicalScope * findLexicalScope(const DILocation *DL)
findLexicalScope - Find lexical scope, either regular or inlined, for the given DebugLoc.
LexicalScope * findInlinedScope(const DILocalScope *N, const DILocation *IA)
findInlinedScope - Find an inlined scope for the given scope/inlined-at.
MCRegAliasIterator enumerates all registers aliasing Reg.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
const MachineBasicBlock & back() const
Representation of each machine instruction.
iterator_range< mop_iterator > debug_operands()
Returns a range over all operands that are used to determine the variable location for this DBG_VALUE...
const DIExpression * getDebugExpression() const
Return the complex address expression referenced by this DBG_VALUE instruction.
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.
bool isDebugEntryValue() const
A DBG_VALUE is an entry value iff its debug expression contains the DW_OP_LLVM_entry_value operation.
MachineOperand class - Representation of each machine instruction operand.
Wrapper class representing virtual and physical registers.
static constexpr bool isPhysicalRegister(unsigned Reg)
Return true if the specified register number is in the physical register namespace.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
bool contains(const T &V) const
Check if the SmallSet contains the given element.
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void assign(size_type NumElts, ValueParamT Elt)
reference emplace_back(ArgTypes &&... Args)
void push_back(const T &Elt)
StringRef - Represent a constant reference to a string, i.e.
Register getStackPointerRegisterToSaveRestore() const
If a physical register, this specifies the register that llvm.savestack/llvm.restorestack should save...
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual const TargetLowering * getTargetLowering() const
This is an optimization pass for GlobalISel generic memory operations.
auto find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
void calculateDbgEntityHistory(const MachineFunction *MF, const TargetRegisterInfo *TRI, DbgValueHistoryMap &DbgValues, DbgLabelInstrMap &DbgLabels)
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
auto reverse(ContainerTy &&C)
void sort(IteratorTy Start, IteratorTy End)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.