104#include "llvm/Config/llvm-config.h"
136#define DEBUG_TYPE "livedebugvalues"
141 cl::desc(
"Act like old LiveDebugValues did"),
155 cl::desc(
"livedebugvalues-stack-ws-limit"),
276 TLI =
MF.getSubtarget().getTargetLowering();
281 unsigned Reg =
MTracker->LocIdxToLocID[L];
304 unsigned Location : 24;
305 unsigned Quality : 8;
310 : Location(L.asU64()), Quality(static_cast<
unsigned>(Q)) {}
325 return A.first <
B.first;
330 std::optional<LocationQuality>
360 bool IsValueValid =
true;
361 unsigned LastUseBeforeDef = 0;
362 bool DbgLocAvailableAndIsEntryVal =
false;
378 IsValueValid =
false;
390 auto ValuesPreferredLoc =
394 assert(ValuesPreferredLoc != ValueToLoc.
end() &&
395 ValuesPreferredLoc->first == Num);
397 if (ValuesPreferredLoc->second.isIllegal()) {
403 LastUseBeforeDef = std::max(LastUseBeforeDef,
404 static_cast<unsigned>(Num.
getInst()));
408 IsValueValid =
false;
414 LocIdx M = ValuesPreferredLoc->second.getLoc();
416 if (
Value.Properties.DIExpr->isEntryValue())
417 DbgLocAvailableAndIsEntryVal =
true;
426 if (LastUseBeforeDef) {
433 std::make_pair(
VarID, &*
MTracker->emitLoc(ResolvedDbgOps, Var, DILoc,
438 if (DbgLocAvailableAndIsEntryVal)
473 for (
const auto &VLoc : VLocs)
475 for (
DbgOpID OpID : VLoc.second.getDbgOpIDs())
476 if (!OpID.ID.IsConst)
487 for (
auto Location :
MTracker->locations()) {
488 LocIdx Idx = Location.Idx;
497 if (VIt == ValueToLoc.
end() || VIt->first != VNum)
500 auto &Previous = VIt->second;
503 std::optional<LocationQuality> ReplacementQuality =
505 if (ReplacementQuality)
510 for (
const auto &Var : VLocs) {
540 for (
auto &
Use : MIt->second) {
545 assert(!
Op.isUndef() &&
"UseBeforeDef erroneously created for a "
546 "DbgValue with undef values.");
555 if (ValueToLoc.
empty())
559 for (
auto Location :
MTracker->locations()) {
560 LocIdx Idx = Location.Idx;
564 auto VIt = ValueToLoc.
find(LocValueID);
565 if (VIt == ValueToLoc.
end())
568 auto &Previous = VIt->second;
571 std::optional<LocationQuality> ReplacementQuality =
573 if (ReplacementQuality)
579 for (
auto &
Use : MIt->second) {
590 LocIdx NewLoc = ValueToLoc.
find(
Op.ID)->second.getLoc();
599 if (DbgOps.
size() !=
Use.Values.size())
603 auto &[Var, DILoc] =
DVMap.lookupDVID(
Use.VarID);
605 Use.VarID,
MTracker->emitLoc(DbgOps, Var, DILoc,
Use.Properties)));
617 if (
MBB && Pos ==
MBB->begin())
618 BundleStart =
MBB->instr_begin();
649 Register SP =
TLI->getStackPointerRegisterToSaveRestore();
652 return Reg != SP && Reg !=
FP;
669 auto NonVariadicExpression =
671 if (!NonVariadicExpression)
673 DIExpr = *NonVariadicExpression;
709 MI.getDebugLoc()->getInlinedAt());
714 if (
MI.isUndefDebugValue() ||
MI.getDebugExpression()->isEntryValue() ||
719 for (
LocIdx Loc : It->second.loc_indices())
749 MI.getDebugLoc()->getInlinedAt());
757 for (
LocIdx Loc : It->second.loc_indices())
762 if (NewLocs.
empty()) {
782 for (
LocIdx Loc : LostVLocIt->second.loc_indices()) {
792 for (
const auto &LostMLoc : LostMLocs)
793 ActiveMLocs[LostMLoc.first].erase(LostMLoc.second);
807 It->second.Ops.assign(NewLocs);
808 It->second.Properties = Properties;
817 bool MakeUndef =
true) {
839 std::optional<LocIdx> NewLoc;
841 if (
Loc.Value == OldValue)
846 if (!NewLoc && !MakeUndef) {
876 DbgOps.
insert(DbgOps.
begin(), ActiveVLocIt->second.Ops.size(),
883 VarID, &*
MTracker->emitLoc(DbgOps, Var, DILoc, Properties)));
888 for (
LocIdx Loc : ActiveVLocIt->second.loc_indices()) {
894 ActiveVLocIt->second.Ops = DbgOps;
901 for (
auto &LocVarIt : LostMLocs) {
902 auto LostMLocIt =
ActiveMLocs.find(LocVarIt.first);
904 "Variable was using this MLoc, but ActiveMLocs[MLoc] has no "
906 LostMLocIt->second.erase(LocVarIt.second);
912 VarLocs[NewLoc->asU64()] = OldValue;
917 ActiveMLocIt->second.clear();
918 if (!NewMLocs.
empty())
951 ActiveVLocIt->second.Properties);
976 MIB.addMetadata(Properties.
DIExpr);
1018 for (
unsigned Idx = 0; Idx <
getDbgOpIDs().size(); ++Idx) {
1045 Register SP =
TLI.getStackPointerRegisterToSaveRestore();
1067 for (
unsigned int I = 1;
I <
TRI.getNumSubRegIndices(); ++
I) {
1068 unsigned Size =
TRI.getSubRegIdxSize(
I);
1069 unsigned Offs =
TRI.getSubRegIdxOffset(
I);
1074 if (
Size > 60000 || Offs > 60000)
1082 unsigned Size =
TRI.getRegSizeInBits(*RC);
1110 if (MaskPair.first->clobbersPhysReg(
ID)) {
1112 ValNum = {
CurBB, MaskPair.second, NewIdx};
1133 Masks.push_back(std::make_pair(MO, InstID));
1139 if (SpillID.
id() == 0) {
1143 return std::nullopt;
1148 for (
unsigned StackIdx = 0; StackIdx <
NumSlotIdxes; ++StackIdx) {
1169 return Twine(
"slot ")
1174 return TRI.getRegAsmName(
ID).str();
1186 std::string MLocName =
LocIdxToName(Location.Value.getLoc());
1187 std::string DefName = Location.Value.asString(MLocName);
1195 dbgs() <<
"Idx " << Location.Idx.asU64() <<
" " << foo <<
"\n";
1207 ?
TII.get(TargetOpcode::DBG_VALUE_LIST)
1208 :
TII.get(TargetOpcode::DBG_VALUE);
1210#ifdef EXPENSIVE_CHECKS
1213 return Op.IsConst || !
Op.Loc.isIllegal();
1215 "Did not expect illegal ops in DbgOps.");
1218 "Expected to have either one DbgOp per MI LocationOp, or none.");
1231 auto EmitUndef = [&]() {
1243 bool Indirect = Properties.
Indirect;
1265 unsigned short Offset = StackIdx.second;
1276 unsigned Base = Spill.SpillBase;
1292 bool UseDerefSize =
false;
1294 unsigned DerefSizeInBytes = ValueSizeInBits / 8;
1296 unsigned VariableSizeInBits = Fragment->SizeInBits;
1297 if (VariableSizeInBits != ValueSizeInBits || Expr->
isComplex())
1298 UseDerefSize =
true;
1300 if (*
Size != ValueSizeInBits) {
1301 UseDerefSize =
true;
1323 if (ValueSizeInBits >
MF.getTarget().getPointerSizeInBits(0))
1324 UseDerefSize =
false;
1327 TRI.getOffsetOpcodes(Spill.SpillOffset, OffsetOps);
1328 bool StackValue =
false;
1335 OffsetOps.
push_back(dwarf::DW_OP_deref);
1342 OffsetOps.
push_back(dwarf::DW_OP_deref_size);
1348 OffsetOps.
push_back(dwarf::DW_OP_deref);
1376 unsigned Reg = MTracker->LocIdxToLocID[L];
1381 if (CalleeSavedRegs.test((*RAI).id()))
1395std::optional<SpillLocationNo>
1396InstrRefBasedLDV::extractSpillBaseRegAndOffset(
const MachineInstr &
MI) {
1398 "Spill instruction does not have exactly one memory operand?");
1399 auto MMOI =
MI.memoperands_begin();
1402 "Inconsistent memory operand in spill instruction");
1410std::optional<LocIdx>
1412 std::optional<SpillLocationNo>
SpillLoc = extractSpillBaseRegAndOffset(
MI);
1414 return std::nullopt;
1420 auto *MemOperand = *
MI.memoperands_begin();
1422 assert(SizeInBits.
hasValue() &&
"Expected to find a valid size!");
1425 auto IdxIt = MTracker->StackSlotIdxes.find({SizeInBits.
getValue(), 0});
1426 if (IdxIt == MTracker->StackSlotIdxes.end())
1429 return std::nullopt;
1431 unsigned SpillID = MTracker->getSpillIDWithIdx(*
SpillLoc, IdxIt->second);
1432 return MTracker->getSpillMLoc(SpillID);
1437bool InstrRefBasedLDV::transferDebugValue(
const MachineInstr &
MI) {
1438 if (!
MI.isDebugValue())
1441 assert(
MI.getDebugVariable()->isValidLocationForIntrinsic(
MI.getDebugLoc()) &&
1442 "Expected inlined-at fields to agree");
1447 if (Scope ==
nullptr)
1453 if (MO.isReg() && MO.getReg() != 0)
1454 (void)MTracker->
readReg(MO.getReg());
1463 if (!
MI.isUndefDebugValue()) {
1469 }
else if (MO.isImm() || MO.isFPImm() || MO.isCImm()) {
1476 VTracker->defVar(
MI, DbgValueProperties(
MI), DebugOps);
1482 TTracker->redefVar(
MI);
1486std::optional<ValueIDNum> InstrRefBasedLDV::getValueForInstrRef(
1493 const MachineFunction &MF = *
MI.getParent()->getParent();
1497 MachineFunction::DebugSubstitution({InstNo, OpNo}, {0, 0}, 0);
1499 SmallVector<unsigned, 4> SeenSubregs;
1502 LowerBoundIt->Src == SoughtSub.Src) {
1503 std::tie(InstNo, OpNo) = LowerBoundIt->Dest;
1504 SoughtSub.Src = LowerBoundIt->Dest;
1505 if (
unsigned Subreg = LowerBoundIt->Subreg)
1506 SeenSubregs.push_back(Subreg);
1512 std::optional<ValueIDNum> NewID;
1516 auto InstrIt = DebugInstrNumToInstr.find(InstNo);
1518 if (InstrIt != DebugInstrNumToInstr.end()) {
1519 const MachineInstr &TargetInstr = *InstrIt->second.first;
1528 NewID = ValueIDNum(BlockNo, InstrIt->second.second, *L);
1536 const MachineOperand &MO = TargetInstr.
getOperand(OpNo);
1539 unsigned LocID = MTracker->getLocID(MO.
getReg());
1540 LocIdx
L = MTracker->LocIDToLocIdx[LocID];
1541 NewID = ValueIDNum(BlockNo, InstrIt->second.second, L);
1547 {
dbgs() <<
"Seen instruction reference to illegal operand\n"; });
1551 }
else if (PHIIt != DebugPHINumToValue.end() && PHIIt->InstrNum == InstNo) {
1554 assert(MLiveOuts && MLiveIns);
1555 NewID = resolveDbgPHIs(*
MI.getParent()->getParent(), *MLiveOuts, *MLiveIns,
1568 if (NewID && !SeenSubregs.empty()) {
1576 for (
unsigned Subreg :
reverse(SeenSubregs)) {
1577 unsigned ThisSize = TRI->getSubRegIdxSize(Subreg);
1578 unsigned ThisOffset = TRI->getSubRegIdxOffset(Subreg);
1587 LocIdx
L = NewID->getLoc();
1588 if (NewID && !MTracker->isSpill(L)) {
1592 const TargetRegisterClass *TRC =
nullptr;
1593 for (
const auto *TRCI : TRI->regclasses())
1594 if (TRCI->contains(
Reg))
1596 assert(TRC &&
"Couldn't find target register class?");
1600 unsigned MainRegSize = TRI->getRegSizeInBits(*TRC);
1604 for (MCRegister SR : TRI->subregs(
Reg)) {
1605 unsigned Subreg = TRI->getSubRegIndex(
Reg, SR);
1606 unsigned SubregSize = TRI->getSubRegIdxSize(Subreg);
1607 unsigned SubregOffset = TRI->getSubRegIdxOffset(Subreg);
1608 if (SubregSize ==
Size && SubregOffset ==
Offset) {
1616 NewID = std::nullopt;
1621 MTracker->lookupOrTrackRegister(MTracker->getLocID(NewReg));
1622 NewID = ValueIDNum(NewID->getBlock(), NewID->getInst(), NewLoc);
1627 NewID = std::nullopt;
1637 if (!
MI.isDebugRef())
1642 if (!VTracker && !TTracker)
1645 const DILocalVariable *Var =
MI.getDebugVariable();
1646 const DIExpression *Expr =
MI.getDebugExpression();
1647 const DILocation *
DebugLoc =
MI.getDebugLoc();
1648 const DILocation *InlinedAt =
DebugLoc->getInlinedAt();
1650 "Expected inlined-at fields to agree");
1652 DebugVariable
V(Var, Expr, InlinedAt);
1654 auto *
Scope = LS.findLexicalScope(
MI.getDebugLoc().get());
1655 if (Scope ==
nullptr)
1659 for (
const MachineOperand &MO :
MI.debug_operands()) {
1661 assert(!MO.
isReg() &&
"DBG_INSTR_REF should not contain registers");
1662 DbgOpID ConstOpID = DbgOpStore.insert(DbgOp(MO));
1672 std::optional<ValueIDNum> NewID =
1673 getValueForInstrRef(InstNo, OpNo,
MI, MLiveOuts, MLiveIns);
1677 DbgOpIDs.
push_back(DbgOpStore.insert(*NewID));
1688 DbgValueProperties Properties(Expr,
false,
true);
1690 VTracker->defVar(
MI, Properties, DbgOpIDs);
1699 for (DbgOpID OpID : DbgOpIDs) {
1700 DbgOps.
push_back(DbgOpStore.find(OpID));
1705 SmallDenseMap<ValueIDNum, TransferTracker::LocationAndQuality> FoundLocs;
1709 for (
const DbgOp &
Op : DbgOps) {
1715 for (
auto Location : MTracker->locations()) {
1717 ValueIDNum
ID = MTracker->readMLoc(CurL);
1718 auto ValueToFindIt =
find(ValuesToFind,
ID);
1719 if (ValueToFindIt == ValuesToFind.
end())
1721 auto &Previous = FoundLocs.
find(
ID)->second;
1724 std::optional<TransferTracker::LocationQuality> ReplacementQuality =
1725 TTracker->getLocQualityIfBetter(CurL, Previous.getQuality());
1726 if (ReplacementQuality) {
1727 Previous = TransferTracker::LocationAndQuality(CurL, *ReplacementQuality);
1728 if (Previous.isBest()) {
1729 ValuesToFind.
erase(ValueToFindIt);
1730 if (ValuesToFind.
empty())
1737 for (
const DbgOp &DbgOp : DbgOps) {
1738 if (DbgOp.IsConst) {
1742 LocIdx FoundLoc = FoundLocs.
find(DbgOp.ID)->second.getLoc();
1750 TTracker->redefVar(
MI, Properties, NewLocs);
1754 if (!DbgOps.empty() && NewLocs.
empty()) {
1755 bool IsValidUseBeforeDef =
true;
1756 uint64_t LastUseBeforeDef = 0;
1757 for (
auto ValueLoc : FoundLocs) {
1758 ValueIDNum NewID = ValueLoc.first;
1759 LocIdx FoundLoc = ValueLoc.second.getLoc();
1765 IsValidUseBeforeDef =
false;
1768 LastUseBeforeDef = std::max(LastUseBeforeDef, NewID.
getInst());
1770 if (IsValidUseBeforeDef) {
1772 TTracker->addUseBeforeDef(VID, {
MI.getDebugExpression(),
false,
true},
1773 DbgOps, LastUseBeforeDef);
1781 MachineInstr *DbgMI =
1782 MTracker->emitLoc(NewLocs, V,
MI.getDebugLoc().get(), Properties);
1785 TTracker->PendingDbgValues.push_back(std::make_pair(
ID, DbgMI));
1786 TTracker->flushDbgValues(
MI.getIterator(),
nullptr);
1791 if (!
MI.isDebugPHI())
1795 if (VTracker || TTracker)
1800 const MachineOperand &MO =
MI.getOperand(0);
1801 unsigned InstrNum =
MI.getOperand(1).getImm();
1803 auto EmitBadPHI = [
this, &
MI, InstrNum]() ->
bool {
1808 DebugPHINumToValue.push_back(
1809 {InstrNum,
MI.getParent(), std::nullopt, std::nullopt});
1817 ValueIDNum Num = MTracker->readReg(
Reg);
1818 auto PHIRec = DebugPHIRecord(
1819 {InstrNum,
MI.getParent(), Num,
1820 MTracker->lookupOrTrackRegister(MTracker->getLocID(
Reg))});
1821 DebugPHINumToValue.push_back(PHIRec);
1824 for (MCRegAliasIterator RAI(MO.
getReg(), TRI,
true); RAI.isValid(); ++RAI)
1825 MTracker->lookupOrTrackRegister(MTracker->getLocID(*RAI));
1826 }
else if (MO.
isFI()) {
1832 if (MFI->isDeadObjectIndex(FI))
1833 return EmitBadPHI();
1837 StackOffset Offs = TFI->getFrameIndexReference(*
MI.getMF(), FI,
Base);
1838 SpillLoc SL = {
Base, Offs};
1839 std::optional<SpillLocationNo> SpillNo = MTracker->getOrTrackSpillLoc(SL);
1844 return EmitBadPHI();
1847 assert(
MI.getNumOperands() == 3 &&
"Stack DBG_PHI with no size?");
1848 unsigned slotBitSize =
MI.getOperand(2).getImm();
1850 unsigned SpillID = MTracker->getLocID(*SpillNo, {slotBitSize, 0});
1851 LocIdx SpillLoc = MTracker->getSpillMLoc(SpillID);
1852 ValueIDNum
Result = MTracker->readMLoc(SpillLoc);
1855 auto DbgPHI = DebugPHIRecord({InstrNum,
MI.getParent(),
Result, SpillLoc});
1856 DebugPHINumToValue.push_back(DbgPHI);
1863 {
dbgs() <<
"Seen DBG_PHI with unrecognised operand format\n"; });
1864 return EmitBadPHI();
1873 if (
MI.isImplicitDef()) {
1878 ValueIDNum Num = MTracker->readReg(
MI.getOperand(0).getReg());
1883 }
else if (
MI.isMetaInstruction())
1891 bool CallChangesSP =
false;
1892 if (AdjustsStackInCalls &&
MI.isCall() &&
MI.getOperand(0).isSymbol() &&
1893 !strcmp(
MI.getOperand(0).getSymbolName(), StackProbeSymbolName.data()))
1894 CallChangesSP =
true;
1898 auto IgnoreSPAlias = [
this, &
MI, CallChangesSP](
Register R) ->
bool {
1901 return MI.isCall() && MTracker->SPAliases.count(R);
1907 SmallSet<uint32_t, 32> DeadRegs;
1908 SmallVector<const uint32_t *, 4> RegMasks;
1910 for (
const MachineOperand &MO :
MI.operands()) {
1913 !IgnoreSPAlias(MO.
getReg())) {
1915 for (MCRegAliasIterator RAI(MO.
getReg(), TRI,
true); RAI.isValid(); ++RAI)
1917 DeadRegs.
insert((*RAI).id());
1925 for (uint32_t DeadReg : DeadRegs)
1926 MTracker->defReg(DeadReg, CurBB, CurInst);
1928 for (
const auto *MO : RegMaskPtrs)
1929 MTracker->writeRegMask(MO, CurBB, CurInst);
1933 if (std::optional<SpillLocationNo> SpillNo =
1934 extractSpillBaseRegAndOffset(
MI)) {
1935 for (
unsigned int I = 0;
I < MTracker->NumSlotIdxes; ++
I) {
1936 unsigned SpillID = MTracker->getSpillIDWithIdx(*SpillNo,
I);
1937 LocIdx
L = MTracker->getSpillMLoc(SpillID);
1938 MTracker->setMLoc(L, ValueIDNum(CurBB, CurInst, L));
1951 for (MCRegister DeadReg : DeadRegs) {
1952 LocIdx Loc = MTracker->lookupOrTrackRegister(MTracker->getLocID(DeadReg));
1953 TTracker->clobberMloc(Loc,
MI.getIterator(),
false);
1958 if (!RegMaskPtrs.empty()) {
1959 for (
auto L : MTracker->locations()) {
1961 if (MTracker->isSpill(
L.Idx))
1965 if (IgnoreSPAlias(
Reg))
1968 for (
const auto *MO : RegMaskPtrs)
1970 TTracker->clobberMloc(
L.Idx,
MI.getIterator(),
false);
1976 if (std::optional<SpillLocationNo> SpillNo =
1977 extractSpillBaseRegAndOffset(
MI)) {
1978 for (
unsigned int I = 0;
I < MTracker->NumSlotIdxes; ++
I) {
1979 unsigned SpillID = MTracker->getSpillIDWithIdx(*SpillNo,
I);
1980 LocIdx
L = MTracker->getSpillMLoc(SpillID);
1981 TTracker->clobberMloc(L,
MI.getIterator(),
true);
1987void InstrRefBasedLDV::performCopy(
Register SrcRegNum,
Register DstRegNum) {
1989 for (MCRegAliasIterator RAI(DstRegNum, TRI,
true); RAI.isValid(); ++RAI)
1990 MTracker->defReg(*RAI, CurBB, CurInst);
1992 ValueIDNum SrcValue = MTracker->readReg(SrcRegNum);
1993 MTracker->setReg(DstRegNum, SrcValue);
1996 for (MCSubRegIndexIterator SRI(SrcRegNum, TRI); SRI.isValid(); ++SRI) {
1997 MCRegister SrcSubReg = SRI.getSubReg();
1998 unsigned SubRegIdx = SRI.getSubRegIndex();
1999 MCRegister DstSubReg = TRI->getSubReg(DstRegNum, SubRegIdx);
2009 MTracker->lookupOrTrackRegister(MTracker->getLocID(SrcSubReg));
2011 MTracker->lookupOrTrackRegister(MTracker->getLocID(DstSubReg));
2014 ValueIDNum CpyValue = MTracker->readReg(SrcSubReg);
2016 MTracker->setReg(DstSubReg, CpyValue);
2020std::optional<SpillLocationNo>
2024 if (!
MI.hasOneMemOperand())
2025 return std::nullopt;
2028 auto MMOI =
MI.memoperands_begin();
2029 const PseudoSourceValue *PVal = (*MMOI)->getPseudoValue();
2031 return std::nullopt;
2033 if (!
MI.getSpillSize(TII) && !
MI.getFoldedSpillSize(TII))
2034 return std::nullopt;
2037 return extractSpillBaseRegAndOffset(
MI);
2042 if (!isSpillInstruction(
MI, MF))
2046 Reg = TII->isStoreToStackSlotPostFE(
MI, FI);
2050std::optional<SpillLocationNo>
2053 if (!
MI.hasOneMemOperand())
2054 return std::nullopt;
2058 if (
MI.getRestoreSize(TII)) {
2059 Reg =
MI.getOperand(0).getReg();
2060 return extractSpillBaseRegAndOffset(
MI);
2062 return std::nullopt;
2065bool InstrRefBasedLDV::transferSpillOrRestoreInst(
MachineInstr &
MI) {
2075 if (!TII->isStoreToStackSlotPostFE(
MI, DummyFI) &&
2076 !TII->isLoadFromStackSlotPostFE(
MI, DummyFI))
2079 MachineFunction *MF =
MI.getMF();
2087 if (!TII->isStoreToStackSlotPostFE(
MI, FIDummy) &&
2088 !TII->isLoadFromStackSlotPostFE(
MI, FIDummy))
2094 if (std::optional<SpillLocationNo> Loc = isSpillInstruction(
MI, MF)) {
2097 for (
unsigned SlotIdx = 0; SlotIdx < MTracker->NumSlotIdxes; ++SlotIdx) {
2098 unsigned SpillID = MTracker->getSpillIDWithIdx(*Loc, SlotIdx);
2099 std::optional<LocIdx> MLoc = MTracker->getSpillMLoc(SpillID);
2107 ValueIDNum
Def(CurBB, CurInst, *MLoc);
2108 MTracker->setMLoc(*MLoc, Def);
2110 TTracker->clobberMloc(*MLoc,
MI.getIterator());
2115 if (isLocationSpill(
MI, MF,
Reg)) {
2118 SpillLocationNo Loc = *extractSpillBaseRegAndOffset(
MI);
2120 auto DoTransfer = [&](
Register SrcReg,
unsigned SpillID) {
2121 auto ReadValue = MTracker->readReg(SrcReg);
2122 LocIdx DstLoc = MTracker->getSpillMLoc(SpillID);
2123 MTracker->setMLoc(DstLoc, ReadValue);
2126 LocIdx SrcLoc = MTracker->getRegMLoc(SrcReg);
2127 TTracker->transferMlocs(SrcLoc, DstLoc,
MI.getIterator());
2134 (void)MTracker->lookupOrTrackRegister(MTracker->getLocID(SR));
2135 unsigned SubregIdx = TRI->getSubRegIndex(
Reg, SR);
2136 unsigned SpillID = MTracker->getLocID(Loc, SubregIdx);
2137 DoTransfer(SR, SpillID);
2141 unsigned Size = TRI->getRegSizeInBits(
Reg, *MRI);
2142 unsigned SpillID = MTracker->getLocID(Loc, {
Size, 0});
2143 DoTransfer(
Reg, SpillID);
2145 std::optional<SpillLocationNo> Loc = isRestoreInstruction(
MI, MF,
Reg);
2156 for (MCRegAliasIterator RAI(
Reg, TRI,
true); RAI.isValid(); ++RAI)
2157 MTracker->defReg(*RAI, CurBB, CurInst);
2161 auto DoTransfer = [&](
Register DestReg,
unsigned SpillID) {
2162 LocIdx SrcIdx = MTracker->getSpillMLoc(SpillID);
2163 auto ReadValue = MTracker->readMLoc(SrcIdx);
2164 MTracker->setReg(DestReg, ReadValue);
2168 unsigned Subreg = TRI->getSubRegIndex(
Reg, SR);
2169 unsigned SpillID = MTracker->getLocID(*Loc, Subreg);
2170 DoTransfer(SR, SpillID);
2174 unsigned Size = TRI->getRegSizeInBits(
Reg, *MRI);
2175 unsigned SpillID = MTracker->getLocID(*Loc, {
Size, 0});
2176 DoTransfer(
Reg, SpillID);
2182 auto DestSrc = TII->isCopyLikeInstr(
MI);
2186 const MachineOperand *DestRegOp = DestSrc->Destination;
2187 const MachineOperand *SrcRegOp = DestSrc->Source;
2193 if (SrcReg == DestReg)
2215 DenseMap<LocIdx, ValueIDNum> ClobberedLocs;
2217 for (MCRegAliasIterator RAI(DestReg, TRI,
true); RAI.isValid(); ++RAI) {
2218 LocIdx ClobberedLoc = MTracker->getRegMLoc(*RAI);
2219 auto MLocIt = TTracker->ActiveMLocs.find(ClobberedLoc);
2222 if (MLocIt == TTracker->ActiveMLocs.end() || MLocIt->second.empty())
2224 ValueIDNum
Value = MTracker->readReg(*RAI);
2225 ClobberedLocs[ClobberedLoc] =
Value;
2230 InstrRefBasedLDV::performCopy(SrcReg, DestReg);
2236 for (
auto LocVal : ClobberedLocs) {
2237 TTracker->clobberMloc(LocVal.first, LocVal.second,
MI.getIterator(),
false);
2245 TTracker->transferMlocs(MTracker->getRegMLoc(SrcReg),
2246 MTracker->getRegMLoc(DestReg),
MI.getIterator());
2250 MTracker->defReg(SrcReg, CurBB, CurInst);
2263 DebugVariable MIVar(
MI.getDebugVariable(),
MI.getDebugExpression(),
2264 MI.getDebugLoc()->getInlinedAt());
2265 FragmentInfo ThisFragment = MIVar.getFragmentOrDefault();
2270 auto [SeenIt,
Inserted] = SeenFragments.try_emplace(MIVar.getVariable());
2272 SeenIt->second.insert(ThisFragment);
2274 OverlapFragments.insert({{MIVar.getVariable(), ThisFragment}, {}});
2281 OverlapFragments.insert({{MIVar.getVariable(), ThisFragment}, {}});
2282 if (!IsInOLapMap.second)
2285 auto &ThisFragmentsOverlaps = IsInOLapMap.first->second;
2286 auto &AllSeenFragments = SeenIt->second;
2291 for (
const auto &ASeenFragment : AllSeenFragments) {
2295 ThisFragmentsOverlaps.push_back(ASeenFragment);
2298 auto ASeenFragmentsOverlaps =
2299 OverlapFragments.find({MIVar.getVariable(), ASeenFragment});
2300 assert(ASeenFragmentsOverlaps != OverlapFragments.end() &&
2301 "Previously seen var fragment has no vector of overlaps");
2302 ASeenFragmentsOverlaps->second.push_back(ThisFragment);
2306 AllSeenFragments.insert(ThisFragment);
2315 if (transferDebugValue(
MI))
2317 if (transferDebugInstrRef(
MI, MLiveOuts, MLiveIns))
2319 if (transferDebugPHI(
MI))
2321 if (transferRegisterCopy(
MI))
2323 if (transferSpillOrRestoreInst(
MI))
2325 transferRegisterDef(
MI);
2328void InstrRefBasedLDV::produceMLocTransferFunction(
2344 for (
auto &BV : BlockMasks)
2345 BV.resize(TRI->getNumRegs(),
true);
2348 for (
auto &
MBB : MF) {
2357 MTracker->setMPhis(CurBB);
2360 for (
auto &
MI :
MBB) {
2363 process(
MI,
nullptr,
nullptr);
2366 if (
MI.isDebugValueLike())
2367 accumulateFragmentMap(
MI);
2371 if (uint64_t InstrNo =
MI.peekDebugInstrNum()) {
2372 auto InstrAndPos = std::make_pair(&
MI, CurInst);
2374 DebugInstrNumToInstr.insert(std::make_pair(InstrNo, InstrAndPos));
2377 assert(InsertResult.second);
2388 for (
auto Location : MTracker->locations()) {
2391 if (
P.isPHI() &&
P.getLoc() == Idx.
asU64())
2395 auto &TransferMap = MLocTransfer[CurBB];
2396 auto Result = TransferMap.insert(std::make_pair(Idx.
asU64(),
P));
2403 for (
auto &
P : MTracker->Masks) {
2404 BlockMasks[CurBB].clearBitsNotInMask(
P.first->getRegMask(), BVWords);
2409 BitVector UsedRegs(TRI->getNumRegs());
2410 for (
auto Location : MTracker->locations()) {
2411 unsigned ID = MTracker->LocIdxToLocID[
Location.Idx];
2413 if (
ID >= TRI->getNumRegs() || MTracker->SPAliases.count(
ID))
2422 BitVector &BV = BlockMasks[
I];
2428 for (
unsigned Bit : BV.
set_bits()) {
2429 unsigned ID = MTracker->getLocID(Bit);
2430 LocIdx Idx = MTracker->LocIDToLocIdx[
ID];
2431 auto &TransferMap = MLocTransfer[
I];
2438 ValueIDNum NotGeneratedNum = ValueIDNum(
I, 1, Idx);
2440 TransferMap.insert(std::make_pair(Idx.
asU64(), NotGeneratedNum));
2442 ValueIDNum &ValueID =
Result.first->second;
2445 ValueID = NotGeneratedNum;
2451bool InstrRefBasedLDV::mlocJoin(
2465 auto Cmp = [&](
const MachineBasicBlock *
A,
const MachineBasicBlock *
B) {
2466 return BBToOrder.find(
A)->second < BBToOrder.find(
B)->second;
2471 if (BlockOrders.size() == 0) {
2476 <<
" from entry which may lead out of "
2477 "bound access to VarLocs\n");
2483 for (
auto Location : MTracker->locations()) {
2488 ValueIDNum FirstVal = OutLocs[*BlockOrders[0]][Idx.
asU64()];
2493 if (InLocs[Idx.
asU64()] != FirstVal) {
2494 InLocs[Idx.
asU64()] = FirstVal;
2502 bool Disagree =
false;
2503 for (
unsigned int I = 1;
I < BlockOrders.size(); ++
I) {
2504 const MachineBasicBlock *PredMBB = BlockOrders[
I];
2505 const ValueIDNum &PredLiveOut = OutLocs[*PredMBB][Idx.
asU64()];
2508 if (FirstVal == PredLiveOut)
2512 if (PredLiveOut == ValueIDNum(
MBB.
getNumber(), 0, Idx))
2521 InLocs[Idx.
asU64()] = FirstVal;
2530void InstrRefBasedLDV::findStackIndexInterference(
2543 auto It = MTracker->StackSlotIdxes.find({8, 0});
2544 assert(It != MTracker->StackSlotIdxes.end());
2548 for (
auto &Pair : MTracker->StackSlotIdxes) {
2550 if (!Pair.first.second)
2556void InstrRefBasedLDV::placeMLocPHIs(
2559 SmallVector<unsigned, 4> StackUnits;
2560 findStackIndexInterference(StackUnits);
2569 SmallSet<Register, 32> RegUnitsToPHIUp;
2570 SmallSet<LocIdx, 32> NormalLocsToPHI;
2571 SmallSet<SpillLocationNo, 32> StackSlots;
2572 for (
auto Location : MTracker->locations()) {
2574 if (MTracker->isSpill(L)) {
2575 StackSlots.
insert(MTracker->locIDToSpill(MTracker->LocIdxToLocID[L]));
2580 SmallSet<Register, 8> FoundRegUnits;
2581 bool AnyIllegal =
false;
2582 for (MCRegUnit Unit : TRI->regunits(
R.asMCReg())) {
2583 for (MCRegUnitRootIterator URoot(Unit, TRI); URoot.isValid(); ++URoot) {
2584 if (!MTracker->isRegisterTracked(*URoot)) {
2590 FoundRegUnits.
insert(*URoot);
2596 NormalLocsToPHI.
insert(L);
2605 SmallVector<MachineBasicBlock *, 32> PHIBlocks;
2606 auto CollectPHIsForLoc = [&](LocIdx
L) {
2608 SmallPtrSet<MachineBasicBlock *, 32> DefBlocks;
2609 for (MachineBasicBlock *
MBB : OrderToBB) {
2610 const auto &TransferFunc = MLocTransfer[
MBB->
getNumber()];
2611 if (TransferFunc.contains(L))
2618 if (!DefBlocks.
empty())
2624 BlockPHIPlacement(AllBlocks, DefBlocks, PHIBlocks);
2627 auto InstallPHIsAtLoc = [&PHIBlocks, &MInLocs](LocIdx
L) {
2628 for (
const MachineBasicBlock *
MBB : PHIBlocks)
2633 for (LocIdx L : NormalLocsToPHI) {
2634 CollectPHIsForLoc(L);
2636 InstallPHIsAtLoc(L);
2641 for (SpillLocationNo Slot : StackSlots) {
2642 for (
unsigned Idx : StackUnits) {
2643 unsigned SpillID = MTracker->getSpillIDWithIdx(Slot, Idx);
2644 LocIdx
L = MTracker->getSpillMLoc(SpillID);
2645 CollectPHIsForLoc(L);
2646 InstallPHIsAtLoc(L);
2650 std::tie(
Size,
Offset) = MTracker->StackIdxesToPos[Idx];
2651 for (
auto &Pair : MTracker->StackSlotIdxes) {
2652 unsigned ThisSize, ThisOffset;
2653 std::tie(ThisSize, ThisOffset) = Pair.first;
2657 unsigned ThisID = MTracker->getSpillIDWithIdx(Slot, Pair.second);
2658 LocIdx ThisL = MTracker->getSpillMLoc(ThisID);
2659 InstallPHIsAtLoc(ThisL);
2665 for (
Register R : RegUnitsToPHIUp) {
2666 LocIdx
L = MTracker->lookupOrTrackRegister(MTracker->getLocID(R));
2667 CollectPHIsForLoc(L);
2670 InstallPHIsAtLoc(L);
2673 for (MCRegAliasIterator RAI(R, TRI,
true); RAI.isValid(); ++RAI) {
2676 if (!MTracker->isRegisterTracked(*RAI))
2680 MTracker->lookupOrTrackRegister(MTracker->getLocID(*RAI));
2681 InstallPHIsAtLoc(AliasLoc);
2686void InstrRefBasedLDV::buildMLocValueMap(
2689 std::priority_queue<unsigned int, std::vector<unsigned int>,
2690 std::greater<unsigned int>>
2696 SmallPtrSet<MachineBasicBlock *, 16> OnPending, OnWorklist;
2700 SmallPtrSet<MachineBasicBlock *, 32> AllBlocks;
2701 for (
unsigned int I = 0;
I < BBToOrder.size(); ++
I) {
2703 OnWorklist.
insert(OrderToBB[
I]);
2704 AllBlocks.
insert(OrderToBB[
I]);
2708 for (
auto Location : MTracker->locations())
2717 placeMLocPHIs(MF, AllBlocks, MInLocs, MLocTransfer);
2727 SmallPtrSet<const MachineBasicBlock *, 16> Visited;
2728 while (!Worklist.empty() || !Pending.empty()) {
2732 while (!Worklist.empty()) {
2733 MachineBasicBlock *
MBB = OrderToBB[Worklist.top()];
2739 InLocsChanged = mlocJoin(*
MBB, Visited, MOutLocs, MInLocs[*
MBB]);
2740 InLocsChanged |= Visited.
insert(
MBB).second;
2748 MTracker->loadFromArray(MInLocs[*
MBB], CurBB);
2753 for (
auto &
P : MLocTransfer[CurBB]) {
2754 if (
P.second.getBlock() == CurBB &&
P.second.isPHI()) {
2756 ValueIDNum NewID = MTracker->readMLoc(
P.second.getLoc());
2757 ToRemap.
push_back(std::make_pair(
P.first, NewID));
2760 assert(
P.second.getBlock() == CurBB);
2761 ToRemap.
push_back(std::make_pair(
P.first,
P.second));
2767 for (
auto &
P : ToRemap)
2768 MTracker->setMLoc(
P.first,
P.second);
2773 bool OLChanged =
false;
2774 for (
auto Location : MTracker->locations()) {
2790 unsigned Order = BBToOrder[s];
2791 if (Order > BBToOrder[
MBB]) {
2793 if (OnWorklist.
insert(s).second)
2794 Worklist.push(Order);
2797 if (OnPending.
insert(s).second)
2798 Pending.push(Order);
2803 Worklist.swap(Pending);
2808 assert(Pending.empty() &&
"Pending should be empty");
2815void InstrRefBasedLDV::BlockPHIPlacement(
2822 IDFCalculatorBase<MachineBasicBlock, false> IDF(*DomTree);
2824 IDF.setLiveInBlocks(AllBlocks);
2825 IDF.setDefiningBlocks(DefBlocks);
2826 IDF.calculate(PHIBlocks);
2829bool InstrRefBasedLDV::pickVPHILoc(
2835 if (BlockOrders.
empty())
2840 SmallDenseSet<unsigned> LocOpsToJoin;
2842 auto FirstValueIt = LiveOuts.find(BlockOrders[0]);
2843 if (FirstValueIt == LiveOuts.end())
2845 const DbgValue &FirstValue = *FirstValueIt->second;
2847 for (
const auto p : BlockOrders) {
2848 auto OutValIt = LiveOuts.find(p);
2849 if (OutValIt == LiveOuts.end())
2852 const DbgValue &OutVal = *OutValIt->second;
2870 LocOpsToJoin.
insert(Idx);
2873 DbgOpID FirstValOp = FirstValue.
getDbgOpID(Idx);
2875 if (FirstValOp != OutValOp) {
2881 LocOpsToJoin.
insert(Idx);
2896 std::optional<ValueIDNum> JoinedOpLoc =
2897 pickOperandPHILoc(Idx,
MBB, LiveOuts, MOutLocs, BlockOrders);
2902 NewDbgOps.
push_back(DbgOpStore.insert(*JoinedOpLoc));
2905 OutValues.
append(NewDbgOps);
2909std::optional<ValueIDNum> InstrRefBasedLDV::pickOperandPHILoc(
2917 unsigned NumLocs = MTracker->getNumLocs();
2919 for (
const auto p : BlockOrders) {
2920 auto OutValIt = LiveOuts.find(p);
2921 assert(OutValIt != LiveOuts.end());
2922 const DbgValue &OutVal = *OutValIt->second;
2923 DbgOpID OutValOpID = OutVal.
getDbgOpID(DbgOpIdx);
2924 DbgOp OutValOp = DbgOpStore.find(OutValOpID);
2935 ValueIDNum ValToLookFor = OutValOp.
ID;
2937 for (
unsigned int I = 0;
I < NumLocs; ++
I) {
2938 if (MOutLocs[*p][
I] == ValToLookFor)
2939 Locs.
back().push_back(LocIdx(
I));
2949 for (
unsigned int I = 0;
I < NumLocs; ++
I) {
2951 if (MOutLocs[*p][
I] == MPHI)
2952 Locs.
back().push_back(LocIdx(
I));
2962 for (
unsigned int I = 1;
I < Locs.
size(); ++
I) {
2963 auto &LocVec = Locs[
I];
2965 std::set_intersection(CandidateLocs.
begin(), CandidateLocs.
end(),
2966 LocVec.begin(), LocVec.end(), std::inserter(NewCandidates, NewCandidates.
begin()));
2967 CandidateLocs = std::move(NewCandidates);
2969 if (CandidateLocs.
empty())
2970 return std::nullopt;
2975 LocIdx
L = *CandidateLocs.
begin();
2982bool InstrRefBasedLDV::vlocJoin(
2992 auto Cmp = [&](MachineBasicBlock *
A, MachineBasicBlock *
B) {
2993 return BBToOrder[
A] < BBToOrder[
B];
2998 unsigned CurBlockRPONum = BBToOrder[&
MBB];
3004 int BackEdgesStart = 0;
3005 for (
auto *p : BlockOrders) {
3008 if (!BlocksToExplore.
contains(p)) {
3014 DbgValue &OutLoc = *VLOCOutLocs.find(p)->second;
3018 unsigned ThisBBRPONum = BBToOrder[
p];
3019 if (ThisBBRPONum < CurBlockRPONum)
3022 Values.
push_back(std::make_pair(p, &OutLoc));
3028 if (Bail || Values.
size() == 0)
3034 const DbgValue &FirstVal = *Values[0].second;
3049 for (
const auto &V : Values) {
3050 if (!
V.second->Properties.isJoinable(FirstVal.
Properties))
3054 if (!
V.second->hasJoinableLocOps(FirstVal))
3059 bool Disagree =
false;
3060 for (
auto &V : Values) {
3061 if (*
V.second == FirstVal)
3067 if (
V.second->hasIdenticalValidLocOps(FirstVal))
3074 std::distance(Values.begin(), &V) >= BackEdgesStart)
3096void InstrRefBasedLDV::getBlocksForScope(
3101 LS.getMachineBasicBlocks(DILoc, BlocksToExplore);
3109 DenseSet<const MachineBasicBlock *> ToAdd;
3116 for (
const auto *
MBB : BlocksToExplore) {
3126 if (BlocksToExplore.count(succ))
3128 if (!ArtificialBlocks.count(succ))
3131 DFS.push_back({succ, succ->succ_begin()});
3135 while (!DFS.empty()) {
3136 const MachineBasicBlock *CurBB = DFS.back().first;
3139 if (CurSucc == CurBB->succ_end()) {
3146 if (!ToAdd.
count(*CurSucc) && ArtificialBlocks.count(*CurSucc)) {
3148 DFS.push_back({*CurSucc, (*CurSucc)->succ_begin()});
3156 BlocksToExplore.insert_range(ToAdd);
3159void InstrRefBasedLDV::buildVLocValueMap(
3169 std::priority_queue<unsigned int, std::vector<unsigned int>,
3170 std::greater<unsigned int>>
3172 SmallPtrSet<MachineBasicBlock *, 16> OnWorklist, OnPending;
3175 SmallPtrSet<const MachineBasicBlock *, 8> BlocksToExplore;
3179 SmallVector<unsigned, 32> BlockOrderNums;
3181 getBlocksForScope(DILoc, BlocksToExplore, AssignBlocks);
3187 if (BlocksToExplore.
size() == 1)
3193 SmallPtrSet<MachineBasicBlock *, 8> MutBlocksToExplore;
3194 for (
const auto *
MBB : BlocksToExplore)
3195 MutBlocksToExplore.
insert(
const_cast<MachineBasicBlock *
>(
MBB));
3200 for (
const auto *
MBB : BlocksToExplore)
3204 for (
unsigned int I : BlockOrderNums)
3206 BlockOrderNums.clear();
3207 unsigned NumBlocks = BlockOrders.
size();
3216 DbgValueProperties EmptyProperties(EmptyExpr,
false,
false);
3217 for (
unsigned int I = 0;
I < NumBlocks; ++
I) {
3226 LiveOutIdx.reserve(NumBlocks);
3227 LiveInIdx.reserve(NumBlocks);
3228 for (
unsigned I = 0;
I < NumBlocks; ++
I) {
3229 LiveOutIdx[BlockOrders[
I]] = &LiveOuts[
I];
3230 LiveInIdx[BlockOrders[
I]] = &LiveIns[
I];
3240 for (
unsigned int I = 0;
I < NumBlocks; ++
I) {
3242 LiveIns[
I] = EmptyDbgValue;
3243 LiveOuts[
I] = EmptyDbgValue;
3248 SmallPtrSet<MachineBasicBlock *, 32> DefBlocks;
3249 for (
const MachineBasicBlock *ExpMBB : BlocksToExplore) {
3250 auto &TransferFunc = AllTheVLocs[ExpMBB->getNumber()].Vars;
3251 if (TransferFunc.contains(
VarID))
3252 DefBlocks.
insert(
const_cast<MachineBasicBlock *
>(ExpMBB));
3255 SmallVector<MachineBasicBlock *, 32> PHIBlocks;
3259 if (DefBlocks.
size() == 1) {
3260 placePHIsForSingleVarDefinition(MutBlocksToExplore, *DefBlocks.
begin(),
3261 AllTheVLocs,
VarID, Output);
3266 BlockPHIPlacement(MutBlocksToExplore, DefBlocks, PHIBlocks);
3269 for (MachineBasicBlock *PHIMBB : PHIBlocks) {
3270 unsigned BlockNo = PHIMBB->getNumber();
3271 DbgValue *LiveIn = LiveInIdx[PHIMBB];
3275 for (
auto *
MBB : BlockOrders) {
3276 Worklist.push(BBToOrder[
MBB]);
3287 bool FirstTrip =
true;
3288 while (!Worklist.empty() || !Pending.empty()) {
3289 while (!Worklist.empty()) {
3290 auto *
MBB = OrderToBB[Worklist.top()];
3294 auto LiveInsIt = LiveInIdx.find(
MBB);
3295 assert(LiveInsIt != LiveInIdx.end());
3296 DbgValue *LiveIn = LiveInsIt->second;
3300 bool InLocsChanged =
3301 vlocJoin(*
MBB, LiveOutIdx, BlocksToExplore, *LiveIn);
3316 if (pickVPHILoc(JoinedOps, *
MBB, LiveOutIdx, MOutLocs, Preds)) {
3318 InLocsChanged |= NewLocPicked;
3324 if (!InLocsChanged && !FirstTrip)
3327 DbgValue *LiveOut = LiveOutIdx[
MBB];
3328 bool OLChanged =
false;
3332 auto TransferIt = VTracker.Vars.find(
VarID);
3333 if (TransferIt != VTracker.Vars.end()) {
3337 if (*LiveOut != NewVal) {
3343 if (*LiveOut != TransferIt->second) {
3344 *LiveOut = TransferIt->second;
3350 if (*LiveOut != *LiveIn) {
3365 if (!LiveInIdx.contains(s))
3368 unsigned Order = BBToOrder[s];
3369 if (Order > BBToOrder[
MBB]) {
3370 if (OnWorklist.
insert(s).second)
3371 Worklist.push(Order);
3372 }
else if (OnPending.
insert(s).second && (FirstTrip || OLChanged)) {
3373 Pending.push(Order);
3377 Worklist.swap(Pending);
3387 for (
auto *
MBB : BlockOrders) {
3388 DbgValue *BlockLiveIn = LiveInIdx[
MBB];
3395 [[maybe_unused]]
auto &[Var, DILoc] = DVMap.lookupDVID(
VarID);
3397 Var.getFragment() &&
3398 "Fragment info missing during value prop");
3403 BlockOrders.clear();
3404 BlocksToExplore.clear();
3407void InstrRefBasedLDV::placePHIsForSingleVarDefinition(
3422 VLocTracker &VLocs = AllTheVLocs[AssignMBB->
getNumber()];
3424 const DbgValue &
Value = ValueIt->second;
3434 for (
auto *ScopeBlock : InScopeBlocks) {
3435 if (!DomTree->properlyDominates(AssignMBB, ScopeBlock))
3438 Output[ScopeBlock->getNumber()].push_back({
VarID,
Value});
3445#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
3448 for (
const auto &
P : mloc_transfer) {
3449 std::string foo = MTracker->LocIdxToName(
P.first);
3450 std::string bar = MTracker->IDAsString(
P.second);
3451 dbgs() <<
"Loc " << foo <<
" --> " << bar <<
"\n";
3462 auto hasNonArtificialLocation = [](
const MachineInstr &
MI) ->
bool {
3464 return DL.getLine() != 0;
3470 unsigned int Size = 0;
3471 for (
auto &
MBB : MF) {
3474 ArtificialBlocks.insert(&
MBB);
3478 ReversePostOrderTraversal<MachineFunction *> RPOT(&MF);
3479 unsigned int RPONumber = 0;
3480 OrderToBB.reserve(
Size);
3481 BBToOrder.reserve(
Size);
3482 BBNumToRPO.reserve(
Size);
3483 auto processMBB = [&](MachineBasicBlock *
MBB) {
3484 OrderToBB.push_back(
MBB);
3485 BBToOrder[
MBB] = RPONumber;
3489 for (MachineBasicBlock *
MBB : RPOT)
3491 for (MachineBasicBlock &
MBB : MF)
3492 if (!BBToOrder.contains(&
MBB))
3498#ifdef EXPENSIVE_CHECKS
3501 if (MF.DebugValueSubstitutions.size() > 2) {
3502 for (
auto It = MF.DebugValueSubstitutions.begin();
3503 It != std::prev(MF.DebugValueSubstitutions.end()); ++It) {
3504 assert(It->Src != std::next(It)->Src &&
"Duplicate variable location "
3505 "substitution seen");
3514void InstrRefBasedLDV::makeDepthFirstEjectionMap(
3516 const ScopeToDILocT &ScopeToDILocation,
3517 ScopeToAssignBlocksT &ScopeToAssignBlocks) {
3518 SmallPtrSet<const MachineBasicBlock *, 8> BlocksToExplore;
3520 auto *TopScope = LS.getCurrentFunctionScope();
3524 WorkStack.
push_back({TopScope, TopScope->getChildren().size() - 1});
3526 while (!WorkStack.
empty()) {
3527 auto &ScopePosition = WorkStack.
back();
3528 LexicalScope *WS = ScopePosition.first;
3529 ssize_t ChildNum = ScopePosition.second--;
3532 if (ChildNum >= 0) {
3535 auto &ChildScope =
Children[ChildNum];
3537 std::make_pair(ChildScope, ChildScope->getChildren().size() - 1));
3544 auto DILocationIt = ScopeToDILocation.find(WS);
3545 if (DILocationIt != ScopeToDILocation.end()) {
3546 getBlocksForScope(DILocationIt->second, BlocksToExplore,
3547 ScopeToAssignBlocks.find(WS)->second);
3548 for (
const auto *
MBB : BlocksToExplore) {
3550 if (EjectionMap[BBNum] == 0)
3554 BlocksToExplore.clear();
3560bool InstrRefBasedLDV::depthFirstVLocAndEmit(
3561 unsigned MaxNumBlocks,
const ScopeToDILocT &ScopeToDILocation,
3562 const ScopeToVarsT &ScopeToVars, ScopeToAssignBlocksT &ScopeToAssignBlocks,
3565 bool ShouldEmitDebugEntryValues) {
3566 TTracker =
new TransferTracker(TII, MTracker, MF, DVMap, *TRI,
3567 CalleeSavedRegs, ShouldEmitDebugEntryValues);
3568 unsigned NumLocs = MTracker->getNumLocs();
3572 if (!LS.getCurrentFunctionScope())
3576 SmallVector<unsigned, 16> EjectionMap;
3578 makeDepthFirstEjectionMap(EjectionMap, ScopeToDILocation,
3579 ScopeToAssignBlocks);
3584 auto EjectBlock = [&](MachineBasicBlock &
MBB) ->
void {
3586 AllTheVLocs[BBNum].
clear();
3591 MTracker->loadFromArray(MInLocs[
MBB], BBNum);
3592 TTracker->loadInlocs(
MBB, MInLocs[
MBB], DbgOpStore, Output[BBNum], NumLocs);
3596 for (
auto &
MI :
MBB) {
3597 process(
MI, &MOutLocs, &MInLocs);
3598 TTracker->checkInstForNewValues(CurInst,
MI.getIterator());
3606 Output[BBNum].clear();
3607 AllTheVLocs[BBNum].
clear();
3610 SmallPtrSet<const MachineBasicBlock *, 8> BlocksToExplore;
3612 WorkStack.
push_back({LS.getCurrentFunctionScope(), 0});
3613 unsigned HighestDFSIn = 0;
3616 while (!WorkStack.
empty()) {
3617 auto &ScopePosition = WorkStack.
back();
3618 LexicalScope *WS = ScopePosition.first;
3619 ssize_t ChildNum = ScopePosition.second++;
3626 auto DILocIt = ScopeToDILocation.find(WS);
3627 if (HighestDFSIn <= WS->getDFSIn() && DILocIt != ScopeToDILocation.end()) {
3628 const DILocation *DILoc = DILocIt->second;
3629 auto &VarsWeCareAbout = ScopeToVars.find(WS)->second;
3630 auto &BlocksInScope = ScopeToAssignBlocks.find(WS)->second;
3632 buildVLocValueMap(DILoc, VarsWeCareAbout, BlocksInScope, Output, MOutLocs,
3633 MInLocs, AllTheVLocs);
3636 HighestDFSIn = std::max(HighestDFSIn, WS->
getDFSIn());
3640 if (ChildNum < (ssize_t)
Children.size()) {
3642 auto &ChildScope =
Children[ChildNum];
3643 WorkStack.
push_back(std::make_pair(ChildScope, 0));
3649 auto DILocationIt = ScopeToDILocation.find(WS);
3650 if (DILocationIt == ScopeToDILocation.end())
3653 getBlocksForScope(DILocationIt->second, BlocksToExplore,
3654 ScopeToAssignBlocks.find(WS)->second);
3655 for (
const auto *
MBB : BlocksToExplore)
3657 EjectBlock(
const_cast<MachineBasicBlock &
>(*
MBB));
3659 BlocksToExplore.clear();
3668 for (
auto *
MBB : ArtificialBlocks)
3672 return emitTransfers();
3675bool InstrRefBasedLDV::emitTransfers() {
3679 for (
auto &
P : TTracker->Transfers) {
3688 MachineBasicBlock &
MBB = *
P.MBB;
3689 for (
const auto &Pair :
P.Insts)
3694 if (
P.Pos->isTerminator())
3698 for (
const auto &Pair :
P.Insts)
3703 return TTracker->Transfers.size() != 0;
3710 bool ShouldEmitDebugEntryValues,
3712 unsigned InputDbgValLimit) {
3719 this->DomTree = DomTree;
3726 LS.scanFunction(MF);
3729 AdjustsStackInCalls = MFI->adjustsStack() &&
3731 if (AdjustsStackInCalls)
3732 StackProbeSymbolName = STI.getTargetLowering()->getStackProbeSymbolName(MF);
3744 for (
auto &
MBB : MF)
3755 produceMLocTransferFunction(MF, MLocTransfer,
MaxNumBlocks);
3760 unsigned NumLocs = MTracker->getNumLocs();
3768 buildMLocValueMap(MF, MInLocs, MOutLocs, MLocTransfer);
3772 for (
auto &DBG_PHI : DebugPHINumToValue) {
3774 if (!DBG_PHI.ValueRead)
3777 ValueIDNum &Num = *DBG_PHI.ValueRead;
3782 LocIdx LocNo = Num.
getLoc();
3783 ValueIDNum ResolvedValue = MInLocs[BlockNo][LocNo.
asU64()];
3788 Num = ResolvedValue;
3795 for (MachineBasicBlock *
MBB : OrderToBB) {
3797 VTracker = &vlocs[CurBB];
3798 VTracker->MBB =
MBB;
3799 MTracker->loadFromArray(MInLocs[*
MBB], CurBB);
3801 for (
auto &
MI : *
MBB) {
3802 process(
MI, &MOutLocs, &MInLocs);
3820 unsigned VarAssignCount = 0;
3821 for (MachineBasicBlock *
MBB : OrderToBB) {
3824 for (
auto &idx : VTracker->Vars) {
3826 const DILocation *ScopeLoc = VTracker->Scopes[
VarID];
3827 assert(ScopeLoc !=
nullptr);
3828 auto *
Scope = LS.findLexicalScope(ScopeLoc);
3831 assert(Scope !=
nullptr);
3834 ScopeToAssignBlocks[
Scope].insert(VTracker->MBB);
3835 ScopeToDILocation[
Scope] = ScopeLoc;
3846 VarAssignCount > InputDbgValLimit) {
3847 LLVM_DEBUG(
dbgs() <<
"Disabling InstrRefBasedLDV: " << MF.getName()
3850 <<
" variable assignments, exceeding limits.\n");
3855 Changed = depthFirstVLocAndEmit(
3856 MaxNumBlocks, ScopeToDILocation, ScopeToVars, ScopeToAssignBlocks,
3857 SavedLiveIns, MOutLocs, MInLocs, vlocs, MF, ShouldEmitDebugEntryValues);
3866 ArtificialBlocks.clear();
3870 DebugInstrNumToInstr.clear();
3871 DebugPHINumToValue.clear();
3872 OverlapFragments.clear();
3873 SeenFragments.clear();
3874 SeenDbgPHIs.clear();
3900 LDVSSABlock *ParentBlock;
3901 BlockValueNum PHIValNum;
3902 LDVSSAPhi(BlockValueNum PHIValNum, LDVSSABlock *ParentBlock)
3903 : ParentBlock(ParentBlock), PHIValNum(PHIValNum) {}
3905 LDVSSABlock *
getParent() {
return ParentBlock; }
3910class LDVSSABlockIterator {
3913 LDVSSAUpdater &Updater;
3916 LDVSSAUpdater &Updater)
3917 : PredIt(PredIt), Updater(Updater) {}
3919 bool operator!=(
const LDVSSABlockIterator &OtherIt)
const {
3920 return OtherIt.PredIt != PredIt;
3923 LDVSSABlockIterator &operator++() {
3936 MachineBasicBlock &BB;
3937 LDVSSAUpdater &Updater;
3938 using PHIListT = SmallVector<LDVSSAPhi, 1>;
3942 LDVSSABlock(MachineBasicBlock &BB, LDVSSAUpdater &Updater)
3943 : BB(BB), Updater(Updater) {}
3946 return LDVSSABlockIterator(BB.
succ_begin(), Updater);
3950 return LDVSSABlockIterator(BB.
succ_end(), Updater);
3954 LDVSSAPhi *newPHI(BlockValueNum
Value) {
3955 PHIList.emplace_back(
Value,
this);
3956 return &PHIList.back();
3960 PHIListT &phis() {
return PHIList; }
3966class LDVSSAUpdater {
3969 DenseMap<BlockValueNum, LDVSSAPhi *> PHIs;
3972 DenseMap<MachineBasicBlock *, BlockValueNum> PoisonMap;
3974 DenseMap<MachineBasicBlock *, LDVSSABlock *> BlockMap;
3978 const FuncValueTable &MLiveIns;
3980 LDVSSAUpdater(LocIdx L,
const FuncValueTable &MLiveIns)
3981 : Loc(
L), MLiveIns(MLiveIns) {}
3984 for (
auto &
Block : BlockMap)
3985 delete Block.second;
3992 ~LDVSSAUpdater() { reset(); }
3996 LDVSSABlock *getSSALDVBlock(MachineBasicBlock *BB) {
3997 auto [It,
Inserted] = BlockMap.try_emplace(BB);
3999 It->second =
new LDVSSABlock(*BB, *
this);
4005 BlockValueNum
getValue(LDVSSABlock *LDVBB) {
4006 return MLiveIns[LDVBB->BB][Loc.
asU64()].asU64();
4010LDVSSABlock *LDVSSABlockIterator::operator*() {
4011 return Updater.getSSALDVBlock(*PredIt);
4017 out <<
"SSALDVPHI " <<
PHI.PHIValNum;
4052 : PHI(
P), Idx(PHI->IncomingValues.
size()) {}
4077 Preds->
push_back(BB->Updater.getSSALDVBlock(Pred));
4083 static BlockValueNum
GetPoisonVal(LDVSSABlock *BB, LDVSSAUpdater *Updater) {
4088 Updater->PoisonMap[&BB->BB] = Num;
4098 LDVSSAUpdater *Updater) {
4099 BlockValueNum PHIValNum = Updater->getValue(BB);
4100 LDVSSAPhi *
PHI = BB->newPHI(PHIValNum);
4101 Updater->PHIs[PHIValNum] =
PHI;
4108 PHI->IncomingValues.push_back(std::make_pair(Pred, Val));
4113 static LDVSSAPhi *
ValueIsPHI(BlockValueNum Val, LDVSSAUpdater *Updater) {
4114 return Updater->PHIs.lookup(Val);
4121 if (
PHI &&
PHI->IncomingValues.size() == 0)
4133std::optional<ValueIDNum> InstrRefBasedLDV::resolveDbgPHIs(
4138 auto SeenDbgPHIIt = SeenDbgPHIs.find(std::make_pair(&Here, InstrNum));
4139 if (SeenDbgPHIIt != SeenDbgPHIs.end())
4140 return SeenDbgPHIIt->second;
4142 std::optional<ValueIDNum>
Result =
4143 resolveDbgPHIsImpl(MF, MLiveOuts, MLiveIns, Here, InstrNum);
4144 SeenDbgPHIs.insert({std::make_pair(&Here, InstrNum),
Result});
4148std::optional<ValueIDNum> InstrRefBasedLDV::resolveDbgPHIsImpl(
4153 auto RangePair = std::equal_range(DebugPHINumToValue.begin(),
4154 DebugPHINumToValue.end(), InstrNum);
4155 auto LowerIt = RangePair.first;
4156 auto UpperIt = RangePair.second;
4159 if (LowerIt == UpperIt)
4160 return std::nullopt;
4166 auto DBGPHIRange =
make_range(LowerIt, UpperIt);
4167 for (
const DebugPHIRecord &DBG_PHI : DBGPHIRange)
4168 if (!DBG_PHI.ValueRead)
4169 return std::nullopt;
4172 if (std::distance(LowerIt, UpperIt) == 1)
4173 return *LowerIt->ValueRead;
4179 LocIdx Loc = *LowerIt->ReadLoc;
4188 LDVSSAUpdater Updater(Loc, MLiveIns);
4190 DenseMap<LDVSSABlock *, BlockValueNum> AvailableValues;
4196 for (
const auto &DBG_PHI : DBGPHIRange) {
4197 LDVSSABlock *
Block = Updater.getSSALDVBlock(DBG_PHI.MBB);
4198 const ValueIDNum &Num = *DBG_PHI.ValueRead;
4202 LDVSSABlock *HereBlock = Updater.getSSALDVBlock(Here.
getParent());
4203 const auto &AvailIt = AvailableValues.
find(HereBlock);
4204 if (AvailIt != AvailableValues.
end()) {
4212 SSAUpdaterImpl<LDVSSAUpdater> Impl(&Updater, &AvailableValues, &CreatedPHIs);
4213 BlockValueNum ResultInt = Impl.GetValue(Updater.getSSALDVBlock(Here.
getParent()));
4227 DenseMap<LDVSSABlock *, ValueIDNum> ValidatedValues;
4230 for (
const auto &DBG_PHI : DBGPHIRange) {
4231 LDVSSABlock *
Block = Updater.getSSALDVBlock(DBG_PHI.MBB);
4232 const ValueIDNum &Num = *DBG_PHI.ValueRead;
4233 ValidatedValues.
insert(std::make_pair(
Block, Num));
4239 llvm::sort(SortedPHIs, [&](LDVSSAPhi *
A, LDVSSAPhi *
B) {
4240 return BBToOrder[&
A->getParent()->BB] < BBToOrder[&
B->getParent()->BB];
4243 for (
auto &
PHI : SortedPHIs) {
4244 ValueIDNum ThisBlockValueNum = MLiveIns[
PHI->ParentBlock->BB][Loc.
asU64()];
4247 for (
auto &PHIIt :
PHI->IncomingValues) {
4249 if (Updater.PoisonMap.contains(&PHIIt.first->BB))
4250 return std::nullopt;
4252 ValueIDNum ValueToCheck;
4253 const ValueTable &BlockLiveOuts = MLiveOuts[PHIIt.first->BB];
4255 auto VVal = ValidatedValues.
find(PHIIt.first);
4256 if (VVal == ValidatedValues.
end()) {
4261 ValueToCheck = ThisBlockValueNum;
4265 ValueToCheck = VVal->second;
4268 if (BlockLiveOuts[Loc.
asU64()] != ValueToCheck)
4269 return std::nullopt;
4273 ValidatedValues.
insert({
PHI->ParentBlock, ThisBlockValueNum});
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static cl::opt< unsigned > MaxNumBlocks("debug-ata-max-blocks", cl::init(10000), cl::desc("Maximum num basic blocks before debug info dropped"), cl::Hidden)
static const Function * getParent(const Value *V)
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
This file defines the DenseMap class.
This file contains constants used for implementing Dwarf debug support.
Compute iterated dominance frontiers using a linear time algorithm.
static cl::opt< unsigned > StackWorkingSetLimit("livedebugvalues-max-stack-slots", cl::Hidden, cl::desc("livedebugvalues-stack-ws-limit"), cl::init(250))
static cl::opt< bool > EmulateOldLDV("emulate-old-livedebugvalues", cl::Hidden, cl::desc("Act like old LiveDebugValues did"), cl::init(false))
static constexpr Value * getValue(Ty &ValueOrUse)
static cl::opt< unsigned > InputBBLimit("livedebugvalues-input-bb-limit", cl::desc("Maximum input basic blocks before DBG_VALUE limit applies"), cl::init(10000), cl::Hidden)
Promote Memory to Register
This file builds on the ADT/GraphTraits.h file to build a generic graph post order iterator.
This file defines the SmallPtrSet class.
This file defines the SmallSet class.
This file defines the SmallVector class.
This file describes how to lower LLVM code to machine code.
Class storing the complete set of values that are observed by DbgValues within the current function.
DbgOp find(DbgOpID ID) const
Returns the DbgOp associated with ID.
DbgOpID insert(DbgOp Op)
If Op does not already exist in this map, it is inserted and the corresponding DbgOpID is returned.
Meta qualifiers for a value.
const DIExpression * DIExpr
bool isJoinable(const DbgValueProperties &Other) const
unsigned getLocationOpCount() const
Class recording the (high level) value of a variable.
int BlockNo
For a NoVal or VPHI DbgValue, which block it was generated in.
DbgValueProperties Properties
Qualifiers for the ValueIDNum above.
ArrayRef< DbgOpID > getDbgOpIDs() const
void setDbgOpIDs(ArrayRef< DbgOpID > NewIDs)
void dump(const MLocTracker *MTrack=nullptr, const DbgOpIDMap *OpStore=nullptr) const
bool isUnjoinedPHI() const
DbgOpID getDbgOpID(unsigned Index) const
KindT Kind
Discriminator for whether this is a constant or an in-program value.
unsigned getLocationOpCount() const
Mapping from DebugVariable to/from a unique identifying number.
DenseMap< const LexicalScope *, const DILocation * > ScopeToDILocT
Mapping from lexical scopes to a DILocation in that scope.
std::optional< LocIdx > findLocationForMemOperand(const MachineInstr &MI)
SmallVector< SmallVector< VarAndLoc, 8 >, 8 > LiveInsT
Vector (per block) of a collection (inner smallvector) of live-ins.
LLVM_ABI_FOR_TEST InstrRefBasedLDV()
Default construct and initialize the pass.
DenseMap< const LexicalScope *, SmallPtrSet< MachineBasicBlock *, 4 > > ScopeToAssignBlocksT
Mapping from lexical scopes to blocks where variables in that scope are assigned.
DIExpression::FragmentInfo FragmentInfo
DenseMap< const LexicalScope *, SmallSet< DebugVariableID, 4 > > ScopeToVarsT
Mapping from lexical scopes to variables in that scope.
SmallDenseMap< const MachineBasicBlock *, DbgValue *, 16 > LiveIdxT
Live in/out structure for the variable values: a per-block map of variables to their values.
SmallDenseMap< LocIdx, ValueIDNum > MLocTransferMap
Machine location/value transfer function, a mapping of which locations are assigned which new values.
bool hasFoldedStackStore(const MachineInstr &MI)
bool isCalleeSaved(LocIdx L) const
bool isCalleeSavedReg(Register R) const
LLVM_DUMP_METHOD void dump_mloc_transfer(const MLocTransferMap &mloc_transfer) const
Handle-class for a particular "location".
static LocIdx MakeIllegalLoc()
Tracker for what values are in machine locations.
unsigned getLocSizeInBits(LocIdx L) const
How large is this location (aka, how wide is a value defined there?).
LLVM_ABI_FOR_TEST std::optional< SpillLocationNo > getOrTrackSpillLoc(SpillLoc L)
Find LocIdx for SpillLoc L, creating a new one if it's not tracked.
IndexedMap< unsigned, LocIdxToIndexFunctor > LocIdxToLocID
Inverse map of LocIDToLocIdx.
unsigned getSpillIDWithIdx(SpillLocationNo Spill, unsigned Idx)
Given a spill number, and a slot within the spill, calculate the ID number for that location.
iterator_range< MLocIterator > locations()
Return a range over all locations currently tracked.
SmallSet< Register, 8 > SPAliases
When clobbering register masks, we chose to not believe the machine model and don't clobber SP.
unsigned getLocID(Register Reg)
Produce location ID number for a Register.
const TargetLowering & TLI
const TargetRegisterInfo & TRI
unsigned NumRegs
Cached local copy of the number of registers the target has.
DenseMap< StackSlotPos, unsigned > StackSlotIdxes
Map from a size/offset pair describing a position in a stack slot, to a numeric identifier for that p...
LocIdx lookupOrTrackRegister(unsigned ID)
SpillLocationNo locIDToSpill(unsigned ID) const
Return the spill number that a location ID corresponds to.
void reset()
Wipe any un-necessary location records after traversing a block.
DenseMap< unsigned, StackSlotPos > StackIdxesToPos
Inverse of StackSlotIdxes.
std::string IDAsString(const ValueIDNum &Num) const
void writeRegMask(const MachineOperand *MO, unsigned CurBB, unsigned InstID)
Record a RegMask operand being executed.
std::pair< unsigned short, unsigned short > StackSlotPos
Pair for describing a position within a stack slot – first the size in bits, then the offset.
const TargetInstrInfo & TII
MachineInstrBuilder emitLoc(const SmallVectorImpl< ResolvedDbgOp > &DbgOps, const DebugVariable &Var, const DILocation *DILoc, const DbgValueProperties &Properties)
Create a DBG_VALUE based on debug operands DbgOps.
LocToValueType LocIdxToIDNum
Map of LocIdxes to the ValueIDNums that they store.
std::vector< LocIdx > LocIDToLocIdx
"Map" of machine location IDs (i.e., raw register or spill number) to the LocIdx key / number for tha...
SmallVector< std::pair< const MachineOperand *, unsigned >, 32 > Masks
Collection of register mask operands that have been observed.
unsigned NumSlotIdxes
Number of slot indexes the target has – distinct segments of a stack slot that can take on the value ...
UniqueVector< SpillLoc > SpillLocs
Unique-ification of spill.
ValueIDNum readReg(Register R)
void defReg(Register R, unsigned BB, unsigned Inst)
Record a definition of the specified register at the given block / inst.
LLVM_DUMP_METHOD void dump()
LLVM_ABI_FOR_TEST LocIdx trackRegister(unsigned ID)
Create a LocIdx for an untracked register ID.
LLVM_ABI_FOR_TEST MLocTracker(MachineFunction &MF, const TargetInstrInfo &TII, const TargetRegisterInfo &TRI, const TargetLowering &TLI)
LLVM_DUMP_METHOD void dump_mloc_map()
StackSlotPos locIDToSpillIdx(unsigned ID) const
Returns the spill-slot size/offs that a location ID corresponds to.
std::string LocIdxToName(LocIdx Idx) const
Thin wrapper around an integer – designed to give more type safety to spill location numbers.
SmallMapVector< DebugVariableID, DbgValue, 8 > Vars
Map DebugVariable to the latest Value it's defined to have.
Unique identifier for a value defined by an instruction, as a value type.
static ValueIDNum fromU64(uint64_t v)
std::string asString(const std::string &mlocname) const
static LLVM_ABI_FOR_TEST ValueIDNum EmptyValue
uint64_t getBlock() const
LocationAndQuality(LocIdx L, LocationQuality Q)
LocationQuality getQuality() const
const DebugVariableMap & DVMap
TransferTracker(const TargetInstrInfo *TII, MLocTracker *MTracker, MachineFunction &MF, const DebugVariableMap &DVMap, const TargetRegisterInfo &TRI, const BitVector &CalleeSavedRegs, bool ShouldEmitDebugEntryValues)
DenseSet< DebugVariableID > UseBeforeDefVariables
The set of variables that are in UseBeforeDefs and can become a location once the relevant value is d...
const BitVector & CalleeSavedRegs
void loadInlocs(MachineBasicBlock &MBB, ValueTable &MLocs, DbgOpIDMap &DbgOpStore, const SmallVectorImpl< std::pair< DebugVariableID, DbgValue > > &VLocs, unsigned NumLocs)
Load object with live-in variable values.
const TargetLowering * TLI
void addUseBeforeDef(DebugVariableID VarID, const DbgValueProperties &Properties, const SmallVectorImpl< DbgOp > &DbgOps, unsigned Inst)
Record that Var has value ID, a value that becomes available later in the function.
SmallVector< ValueIDNum, 32 > VarLocs
Local cache of what-value-is-in-what-LocIdx.
MLocTracker * MTracker
This machine location tracker is assumed to always contain the up-to-date value mapping for all machi...
void transferMlocs(LocIdx Src, LocIdx Dst, MachineBasicBlock::iterator Pos)
Transfer variables based on Src to be based on Dst.
std::optional< LocationQuality > getLocQualityIfBetter(LocIdx L, LocationQuality Min) const
SmallVector< std::pair< DebugVariableID, MachineInstr * >, 4 > PendingDbgValues
Temporary cache of DBG_VALUEs to be entered into the Transfers collection.
bool isEntryValueVariable(const DebugVariable &Var, const DIExpression *Expr) const
void checkInstForNewValues(unsigned Inst, MachineBasicBlock::iterator pos)
After the instruction at index Inst and position pos has been processed, check whether it defines a v...
const TargetInstrInfo * TII
DenseMap< LocIdx, SmallSet< DebugVariableID, 4 > > ActiveMLocs
Map from LocIdxes to which DebugVariables are based that location.
MachineInstrBuilder emitMOLoc(const MachineOperand &MO, const DebugVariable &Var, const DbgValueProperties &Properties)
bool isEntryValueValue(const ValueIDNum &Val) const
const TargetRegisterInfo & TRI
void redefVar(const MachineInstr &MI)
Change a variable value after encountering a DBG_VALUE inside a block.
bool recoverAsEntryValue(DebugVariableID VarID, const DbgValueProperties &Prop, const ValueIDNum &Num)
bool isCalleeSaved(LocIdx L) const
void clobberMloc(LocIdx MLoc, MachineBasicBlock::iterator Pos, bool MakeUndef=true)
Account for a location mloc being clobbered.
void flushDbgValues(MachineBasicBlock::iterator Pos, MachineBasicBlock *MBB)
Helper to move created DBG_VALUEs into Transfers collection.
DenseMap< DebugVariableID, ResolvedDbgValue > ActiveVLocs
Map from DebugVariable to it's current location and qualifying meta information.
DenseMap< unsigned, SmallVector< UseBeforeDef, 1 > > UseBeforeDefs
Map from instruction index (within the block) to the set of UseBeforeDefs that become defined at that...
void clobberMloc(LocIdx MLoc, ValueIDNum OldValue, MachineBasicBlock::iterator Pos, bool MakeUndef=true)
Overload that takes an explicit value OldValue for when the value in MLoc has changed and the Transfe...
SmallVector< Transfer, 32 > Transfers
Collection of transfers (DBG_VALUEs) to be inserted.
bool ShouldEmitDebugEntryValues
void redefVar(const MachineInstr &MI, const DbgValueProperties &Properties, SmallVectorImpl< ResolvedDbgOp > &NewLocs)
Handle a change in variable location within a block.
void loadVarInloc(MachineBasicBlock &MBB, DbgOpIDMap &DbgOpStore, const SmallVectorImpl< ValueLocPair > &ValueToLoc, DebugVariableID VarID, DbgValue Value)
For a variable Var with the live-in value Value, attempts to resolve the DbgValue to a concrete DBG_V...
std::pair< ValueIDNum, LocationAndQuality > ValueLocPair
static bool ValueToLocSort(const ValueLocPair &A, const ValueLocPair &B)
Represent a constant reference to an array (0 or more elements consecutively in memory),...
BitVector & flip()
Flip all bits in the bitvector.
iterator_range< const_set_bits_iterator > set_bits() const
LLVM_ABI bool isEntryValue() const
Check if the expression consists of exactly one entry value operand.
unsigned getNumElements() const
LLVM_ABI bool isImplicit() const
Return whether this is an implicit location description.
static bool fragmentsOverlap(const FragmentInfo &A, const FragmentInfo &B)
Check if fragments overlap between a pair of FragmentInfos.
static LLVM_ABI DIExpression * appendOpsToArg(const DIExpression *Expr, ArrayRef< uint64_t > Ops, unsigned ArgNo, bool StackValue=false)
Create a copy of Expr by appending the given list of Ops to each instance of the operand DW_OP_LLVM_a...
LLVM_ABI bool isComplex() const
Return whether the location is computed on the expression stack, meaning it cannot be a simple regist...
static LLVM_ABI std::optional< FragmentInfo > getFragmentInfo(expr_op_iterator Start, expr_op_iterator End)
Retrieve the details of this fragment expression.
static LLVM_ABI std::optional< const DIExpression * > convertToNonVariadicExpression(const DIExpression *Expr)
If Expr is a valid single-location expression, i.e.
LLVM_ABI bool isDeref() const
Return whether there is exactly one operator and it is a DW_OP_deref;.
static LLVM_ABI DIExpression * prepend(const DIExpression *Expr, uint8_t Flags, int64_t Offset=0)
Prepend DIExpr with a deref and offset operation and optionally turn it into a stack value or/and an ...
LLVM_ABI bool isSingleLocationExpression() const
Return whether the evaluated expression makes use of a single location at the start of the expression...
DILocalScope * getScope() const
Get the local scope for this variable.
bool isValidLocationForIntrinsic(const DILocation *DL) const
Check that a location is valid for this variable.
LLVM_ABI std::optional< uint64_t > getSizeInBits() const
Determines the size of the variable's type.
Identifies a unique instance of a variable.
const DILocation * getInlinedAt() const
std::optional< FragmentInfo > getFragment() const
const DILocalVariable * getVariable() const
iterator find(const_arg_type_t< KeyT > Val)
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Implements a dense probed hash-table based set.
DISubprogram * getSubprogram() const
Get the attached subprogram.
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
This is an important class for using LLVM in a threaded context.
unsigned getDFSIn() const
SmallVectorImpl< LexicalScope * > & getChildren()
unsigned getDFSOut() const
LLVM_ABI LexicalScope * findLexicalScope(const DILocation *DL)
Find lexical scope, either regular or inlined, for the given DebugLoc.
TypeSize getValue() const
Describe properties that are true of each instruction in the target description file.
MCRegAliasIterator enumerates all registers aliasing Reg.
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
LLVMContext & getContext() const
LLVM_ABI instr_iterator insert(instr_iterator I, MachineInstr *M)
Insert MI into the instruction list before I, possibly inside a bundle.
int getNumber() const
MachineBasicBlocks are uniquely numbered at the function level, unless they're not in a MachineFuncti...
SmallVectorImpl< MachineBasicBlock * >::const_iterator const_succ_iterator
succ_iterator succ_begin()
LLVM_ABI bool isEntryBlock() const
Returns true if this is the entry block of the function.
SmallVectorImpl< MachineBasicBlock * >::iterator pred_iterator
Instructions::iterator instr_iterator
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
LLVM_ABI std::string getFullName() const
Return a formatted string to identify this block and its parent function.
iterator_range< succ_iterator > successors()
iterator_range< pred_iterator > predecessors()
MachineInstrBundleIterator< MachineInstr > iterator
instr_iterator insertAfterBundle(instr_iterator I, MachineInstr *MI)
If I is bundled then insert MI into the instruction list after the end of the bundle,...
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
SmallVector< DebugSubstitution, 8 > DebugValueSubstitutions
Debug value substitutions: a collection of DebugSubstitution objects, recording changes in where a va...
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
static const unsigned int DebugOperandMemNumber
A reserved operand number representing the instructions memory operand, for instructions that have a ...
Function & getFunction()
Return the LLVM function that this machine code represents.
Representation of each machine instruction.
const MachineBasicBlock * getParent() const
unsigned getNumOperands() const
Retuns the total number of operands.
bool hasOneMemOperand() const
Return true if this instruction has exactly one MachineMemOperand.
const MachineOperand & getOperand(unsigned i) const
MachineOperand class - Representation of each machine instruction operand.
unsigned getInstrRefOpIndex() const
unsigned getInstrRefInstrIndex() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
bool isRegMask() const
isRegMask - Tests if this is a MO_RegisterMask operand.
static unsigned getRegMaskSize(unsigned NumRegs)
Returns number of elements needed for a regmask array.
Register getReg() const
getReg - Returns the register number.
bool isDbgInstrRef() const
bool isFI() const
isFI - Tests if this is a MO_FrameIndex operand.
static bool clobbersPhysReg(const uint32_t *RegMask, MCRegister PhysReg)
clobbersPhysReg - Returns true if this RegMask clobbers PhysReg.
const uint32_t * getRegMask() const
getRegMask - Returns a bit mask of registers preserved by this RegMask operand.
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
Special value supplied for machine level alias analysis.
virtual bool isAliased(const MachineFrameInfo *) const
Test whether the memory pointed to by this PseudoSourceValue may also be pointed to by an LLVM IR Val...
Wrapper class representing virtual and physical registers.
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
Iterator for PHI operands.
BlockValueNum getIncomingValue()
PHI_iterator(LDVSSAPhi *P, bool)
LDVSSABlock * getIncomingBlock()
bool operator!=(const PHI_iterator &X) const
PHI_iterator(LDVSSAPhi *P)
PHI_iterator & operator++()
bool operator==(const PHI_iterator &X) const
LDVSSABlockIterator BlkSucc_iterator
static BlockValueNum CreateEmptyPHI(LDVSSABlock *BB, unsigned NumPreds, LDVSSAUpdater *Updater)
CreateEmptyPHI - Create a (representation of a) PHI in the given block.
static BlockValueNum GetPoisonVal(LDVSSABlock *BB, LDVSSAUpdater *Updater)
GetPoisonVal - Normally creates an IMPLICIT_DEF instruction with a new register.
static BlkSucc_iterator BlkSucc_end(BlkT *BB)
static PHI_iterator PHI_begin(PhiT *PHI)
static void AddPHIOperand(LDVSSAPhi *PHI, BlockValueNum Val, LDVSSABlock *Pred)
AddPHIOperand - Add the specified value as an operand of the PHI for the specified predecessor block.
static void FindPredecessorBlocks(LDVSSABlock *BB, SmallVectorImpl< LDVSSABlock * > *Preds)
FindPredecessorBlocks - Put the predecessors of BB into the Preds vector.
static BlockValueNum GetPHIValue(LDVSSAPhi *PHI)
GetPHIValue - For the specified PHI instruction, return the value that it defines.
static LDVSSAPhi * ValueIsNewPHI(BlockValueNum Val, LDVSSAUpdater *Updater)
ValueIsNewPHI - Like ValueIsPHI but also check if the PHI has no source operands, i....
static PHI_iterator PHI_end(PhiT *PHI)
static LDVSSAPhi * ValueIsPHI(BlockValueNum Val, LDVSSAUpdater *Updater)
ValueIsPHI - Check if the instruction that defines the specified value is a PHI instruction.
static BlkSucc_iterator BlkSucc_begin(BlkT *BB)
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
void insert_range(Range &&R)
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
bool contains(ConstPtrType Ptr) const
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
void insert_range(Range &&R)
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 reserve(size_type N)
iterator erase(const_iterator CI)
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
iterator insert(iterator I, T &&Elt)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StackOffset holds a fixed and a scalable offset in bytes.
virtual bool stackProbeFunctionModifiesSP() const
Does the stack probe function call return with a modified stack pointer?
virtual void getCalleeSaves(const MachineFunction &MF, BitVector &SavedRegs) const
Returns the callee-saved registers as computed by determineCalleeSaves in the BitVector SavedRegs.
virtual StackOffset getFrameIndexReference(const MachineFunction &MF, int FI, Register &FrameReg) const
getFrameIndexReference - This method should return the base register and offset used to reference a f...
TargetInstrInfo - Interface to description of machine instruction set.
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 TargetFrameLowering * getFrameLowering() const
virtual const TargetInstrInfo * getInstrInfo() const
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
virtual const TargetLowering * getTargetLowering() const
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
LLVM_ABI std::string str() const
Return the twine contents as a std::string.
Twine concat(const Twine &Suffix) const
A Use represents the edge between a Value definition and its users.
LLVM Value Representation.
std::pair< iterator, bool > insert(const ValueT &V)
bool contains(const_arg_type_t< ValueT > V) const
Check if the set contains the given element.
size_type count(const_arg_type_t< ValueT > V) const
Return 1 if the specified key is in the set, 0 otherwise.
This class implements an extremely fast bulk output stream that can only output to a stream.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
SmallVector< ValueIDNum, 0 > ValueTable
Type for a table of values in a block.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
initializer< Ty > init(const Ty &Val)
Scope
Defines the scope in which this symbol should be visible: Default – Visible in the public interface o...
NodeAddr< DefNode * > Def
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
std::tuple< const DIScope *, const DIScope *, const DILocalVariable * > VarID
A unique key that represents a debug variable.
auto find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
MachineBasicBlock::instr_iterator getBundleStart(MachineBasicBlock::instr_iterator I)
Returns an iterator to the first instruction in the bundle containing I.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
APInt operator*(APInt a, uint64_t RHS)
bool operator!=(uint64_t V1, const APInt &V2)
constexpr NextUseDistance min(NextUseDistance A, NextUseDistance B)
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
LDVImpl * makeInstrRefBasedLiveDebugValues()
bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)
auto map_range(ContainerTy &&C, FuncTy F)
Return a range that applies F to the elements of C.
detail::concat_range< ValueT, RangeTs... > concat(RangeTs &&...Ranges)
Returns a concatenated range across two or more ranges.
auto reverse(ContainerTy &&C)
void sort(IteratorTy Start, IteratorTy End)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool none_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly.
iterator_range< filter_iterator< detail::IterOfRange< RangeT >, PredicateT > > make_filter_range(RangeT &&Range, PredicateT Pred)
Convenience function that takes a range of elements and a predicate, and return a new filter_iterator...
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
RNSuccIterator< NodeRef, BlockT, RegionT > succ_begin(NodeRef Node)
RNSuccIterator< NodeRef, BlockT, RegionT > succ_end(NodeRef Node)
auto lower_bound(R &&Range, T &&Value)
Provide wrappers to std::lower_bound which take ranges instead of having to pass begin/end explicitly...
void replace(R &&Range, const T &OldValue, const T &NewValue)
Provide wrappers to std::replace which take ranges instead of having to pass begin/end explicitly.
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
DWARFExpression::Operation Op
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
OutputIt replace_copy(R &&Range, OutputIt Out, const T &OldValue, const T &NewValue)
Provide wrappers to std::replace_copy which take ranges instead of having to pass begin/end explicitl...
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
bool equal(L &&LRange, R &&RRange)
Wrapper function around std::equal to detect if pair-wise elements between two ranges are the same.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
An ID used in the DbgOpIDMap (below) to lookup a stored DbgOp.
void dump(const MLocTracker *MTrack, const DbgOpIDMap *OpStore) const
static LLVM_ABI_FOR_TEST DbgOpID UndefID
TODO: Might pack better if we changed this to a Struct of Arrays, since MachineOperand is width 32,...
void dump(const MLocTracker *MTrack) const
A collection of ValueTables, one per BB in a function, with convenient accessor methods.
void ejectTableForBlock(const MachineBasicBlock &MBB)
Frees the memory of the ValueTable associated with MBB.
ValueTable & tableForEntryMBB() const
Returns the ValueTable associated with the entry MachineBasicBlock.
bool hasTableFor(MachineBasicBlock &MBB) const
Returns true if the ValueTable associated with MBB has not been freed.
A DbgOp whose ID (if any) has resolved to an actual location, LocIdx.
void dump(const MLocTracker *MTrack) const
Stores the resolved operands (machine locations and constants) and qualifying meta-information needed...
SmallVector< ResolvedDbgOp > Ops
DbgValueProperties Properties
ResolvedDbgValue(SmallVectorImpl< ResolvedDbgOp > &Ops, DbgValueProperties Properties)
auto loc_indices() const
Returns all the LocIdx values used in this struct, in the order in which they appear as operands in t...
Record of all changes in variable locations at a block position.
SmallVector< std::pair< DebugVariableID, MachineInstr * >, 4 > Insts
non-null if we should insert after.
MachineBasicBlock * MBB
Position to insert DBG_VALUes.
MachineBasicBlock::instr_iterator Pos
UseBeforeDef(ArrayRef< DbgOp > Values, DebugVariableID VarID, const DbgValueProperties &Properties)
DbgValueProperties Properties
Additional variable properties.
DebugVariableID VarID
Identity of this variable.
SmallVector< DbgOp > Values
Value of this variable, def'd in block.