104#include "llvm/Config/llvm-config.h"
136#define DEBUG_TYPE "live-debug-values"
141 cl::desc(
"Act like old LiveDebugValues did"),
155 cl::desc(
"livedebugvalues-stack-ws-limit"),
164 cl::desc(
"livedebugvalues-max-stack-slot-idxes"),
285 TLI =
MF.getSubtarget().getTargetLowering();
290 unsigned Reg =
MTracker->LocIdxToLocID[L];
313 unsigned Location : 24;
314 unsigned Quality : 8;
319 : Location(L.asU64()), Quality(static_cast<
unsigned>(Q)) {}
334 return A.first <
B.first;
339 std::optional<LocationQuality>
369 bool IsValueValid =
true;
370 unsigned LastUseBeforeDef = 0;
371 bool DbgLocAvailableAndIsEntryVal =
false;
387 IsValueValid =
false;
399 auto ValuesPreferredLoc =
403 assert(ValuesPreferredLoc != ValueToLoc.
end() &&
404 ValuesPreferredLoc->first == Num);
406 if (ValuesPreferredLoc->second.isIllegal()) {
412 LastUseBeforeDef = std::max(LastUseBeforeDef,
413 static_cast<unsigned>(Num.
getInst()));
417 IsValueValid =
false;
423 LocIdx M = ValuesPreferredLoc->second.getLoc();
425 if (
Value.Properties.DIExpr->isEntryValue())
426 DbgLocAvailableAndIsEntryVal =
true;
435 if (LastUseBeforeDef) {
442 std::make_pair(
VarID, &*
MTracker->emitLoc(ResolvedDbgOps, Var, DILoc,
447 if (DbgLocAvailableAndIsEntryVal)
482 for (
const auto &VLoc : VLocs)
484 for (
DbgOpID OpID : VLoc.second.getDbgOpIDs())
485 if (!OpID.ID.IsConst)
496 for (
auto Location :
MTracker->locations()) {
497 LocIdx Idx = Location.Idx;
506 if (VIt == ValueToLoc.
end() || VIt->first != VNum)
509 auto &Previous = VIt->second;
512 std::optional<LocationQuality> ReplacementQuality =
514 if (ReplacementQuality)
519 for (
const auto &Var : VLocs) {
549 for (
auto &
Use : MIt->second) {
554 assert(!
Op.isUndef() &&
"UseBeforeDef erroneously created for a "
555 "DbgValue with undef values.");
564 if (ValueToLoc.
empty())
568 for (
auto Location :
MTracker->locations()) {
569 LocIdx Idx = Location.Idx;
573 auto VIt = ValueToLoc.
find(LocValueID);
574 if (VIt == ValueToLoc.
end())
577 auto &Previous = VIt->second;
580 std::optional<LocationQuality> ReplacementQuality =
582 if (ReplacementQuality)
588 for (
auto &
Use : MIt->second) {
599 LocIdx NewLoc = ValueToLoc.
find(
Op.ID)->second.getLoc();
608 if (DbgOps.
size() !=
Use.Values.size())
612 auto &[Var, DILoc] =
DVMap.lookupDVID(
Use.VarID);
614 Use.VarID,
MTracker->emitLoc(DbgOps, Var, DILoc,
Use.Properties)));
626 if (
MBB && Pos ==
MBB->begin())
627 BundleStart =
MBB->instr_begin();
658 Register SP =
TLI->getStackPointerRegisterToSaveRestore();
661 return Reg != SP && Reg !=
FP;
678 auto NonVariadicExpression =
680 if (!NonVariadicExpression)
682 DIExpr = *NonVariadicExpression;
718 MI.getDebugLoc()->getInlinedAt());
723 if (
MI.isUndefDebugValue() ||
MI.getDebugExpression()->isEntryValue() ||
728 for (
LocIdx Loc : It->second.loc_indices())
758 MI.getDebugLoc()->getInlinedAt());
766 for (
LocIdx Loc : It->second.loc_indices())
771 if (NewLocs.
empty()) {
791 for (
LocIdx Loc : LostVLocIt->second.loc_indices()) {
801 for (
const auto &LostMLoc : LostMLocs)
802 ActiveMLocs[LostMLoc.first].erase(LostMLoc.second);
816 It->second.Ops.assign(NewLocs);
817 It->second.Properties = Properties;
826 bool MakeUndef =
true) {
848 std::optional<LocIdx> NewLoc;
850 if (
Loc.Value == OldValue)
855 if (!NewLoc && !MakeUndef) {
885 DbgOps.
insert(DbgOps.
begin(), ActiveVLocIt->second.Ops.size(),
892 VarID, &*
MTracker->emitLoc(DbgOps, Var, DILoc, Properties)));
897 for (
LocIdx Loc : ActiveVLocIt->second.loc_indices()) {
903 ActiveVLocIt->second.Ops = DbgOps;
910 for (
auto &LocVarIt : LostMLocs) {
911 auto LostMLocIt =
ActiveMLocs.find(LocVarIt.first);
913 "Variable was using this MLoc, but ActiveMLocs[MLoc] has no "
915 LostMLocIt->second.erase(LocVarIt.second);
921 VarLocs[NewLoc->asU64()] = OldValue;
926 ActiveMLocIt->second.clear();
927 if (!NewMLocs.
empty())
960 ActiveVLocIt->second.Properties);
980 if (Properties.Indirect)
985 MIB.addMetadata(Properties.DIExpr);
1027 for (
unsigned Idx = 0; Idx <
getDbgOpIDs().size(); ++Idx) {
1054 Register SP =
TLI.getStackPointerRegisterToSaveRestore();
1076 for (
unsigned int I = 1;
I <
TRI.getNumSubRegIndices(); ++
I) {
1077 unsigned Size =
TRI.getSubRegIdxSize(
I);
1078 unsigned Offs =
TRI.getSubRegIdxOffset(
I);
1083 if (
Size > 60000 || Offs > 60000)
1091 unsigned Size =
TRI.getRegSizeInBits(RC);
1119 if (MaskPair.first->clobbersPhysReg(ID)) {
1121 ValNum = {
CurBB, MaskPair.second, NewIdx};
1142 Masks.push_back(std::make_pair(MO, InstID));
1148 return std::nullopt;
1152 if (SpillID.
id() == 0) {
1156 return std::nullopt;
1161 for (
unsigned StackIdx = 0; StackIdx <
NumSlotIdxes; ++StackIdx) {
1182 return Twine(
"slot ")
1187 return TRI.getRegAsmName(ID).str();
1199 std::string MLocName =
LocIdxToName(Location.Value.getLoc());
1200 std::string DefName = Location.Value.asString(MLocName);
1208 dbgs() <<
"Idx " << Location.Idx.asU64() <<
" " << foo <<
"\n";
1220 ?
TII.get(TargetOpcode::DBG_VALUE_LIST)
1221 :
TII.get(TargetOpcode::DBG_VALUE);
1223#ifdef EXPENSIVE_CHECKS
1226 return Op.IsConst || !
Op.Loc.isIllegal();
1228 "Did not expect illegal ops in DbgOps.");
1230 DbgOps.
size() == Properties.getLocationOpCount()) &&
1231 "Expected to have either one DbgOp per MI LocationOp, or none.");
1244 auto EmitUndef = [&]() {
1246 MOs.
assign(Properties.getLocationOpCount(), GetRegOp(0));
1256 bool Indirect = Properties.Indirect;
1260 assert(DbgOps.
size() == Properties.getLocationOpCount());
1265 for (
size_t Idx = 0; Idx < Properties.getLocationOpCount(); ++Idx) {
1278 unsigned short Offset = StackIdx.second;
1289 unsigned Base = Spill.SpillBase;
1305 bool UseDerefSize =
false;
1307 unsigned DerefSizeInBytes = ValueSizeInBits / 8;
1309 unsigned VariableSizeInBits =
Fragment->SizeInBits;
1310 if (VariableSizeInBits != ValueSizeInBits || Expr->
isComplex())
1311 UseDerefSize =
true;
1313 if (*
Size != ValueSizeInBits) {
1314 UseDerefSize =
true;
1336 if (ValueSizeInBits >
MF.getDataLayout().getPointerSizeInBits(0))
1337 UseDerefSize =
false;
1340 TRI.getOffsetOpcodes(Spill.SpillOffset, OffsetOps);
1343 if (Properties.Indirect) {
1348 OffsetOps.
push_back(dwarf::DW_OP_deref);
1355 OffsetOps.
push_back(dwarf::DW_OP_deref_size);
1358 }
else if (Expr->
isComplex() || Properties.IsVariadic) {
1361 OffsetOps.
push_back(dwarf::DW_OP_deref);
1389 unsigned Reg = MTracker->LocIdxToLocID[L];
1394 if (CalleeSavedRegs.test((*RAI).id()))
1408std::optional<SpillLocationNo>
1409InstrRefBasedLDV::extractSpillBaseRegAndOffset(
const MachineInstr &
MI) {
1411 "Spill instruction does not have exactly one memory operand?");
1412 auto MMOI =
MI.memoperands_begin();
1415 "Inconsistent memory operand in spill instruction");
1423std::optional<LocIdx>
1425 std::optional<SpillLocationNo>
SpillLoc = extractSpillBaseRegAndOffset(
MI);
1427 return std::nullopt;
1433 auto *MemOperand = *
MI.memoperands_begin();
1435 assert(SizeInBits.
hasValue() &&
"Expected to find a valid size!");
1438 auto IdxIt = MTracker->StackSlotIdxes.find({SizeInBits.
getValue(), 0});
1439 if (IdxIt == MTracker->StackSlotIdxes.end())
1442 return std::nullopt;
1444 unsigned SpillID = MTracker->getSpillIDWithIdx(*
SpillLoc, IdxIt->second);
1445 return MTracker->getSpillMLoc(SpillID);
1450bool InstrRefBasedLDV::transferDebugValue(
const MachineInstr &
MI) {
1451 if (!
MI.isDebugValue())
1454 assert(
MI.getDebugVariable()->isValidLocationForIntrinsic(
MI.getDebugLoc()) &&
1455 "Expected inlined-at fields to agree");
1460 if (Scope ==
nullptr)
1466 if (MO.isReg() && MO.getReg() != 0)
1467 (void)MTracker->
readReg(MO.getReg());
1476 if (!
MI.isUndefDebugValue()) {
1482 }
else if (MO.isImm() || MO.isFPImm() || MO.isCImm() || MO.isGlobal()) {
1489 VTracker->defVar(
MI, DbgValueProperties(
MI), DebugOps);
1495 TTracker->redefVar(
MI);
1499std::optional<ValueIDNum> InstrRefBasedLDV::getValueForInstrRef(
1510 MachineFunction::DebugSubstitution({InstNo, OpNo}, {0, 0}, 0);
1512 SmallVector<unsigned, 4> SeenSubregs;
1515 LowerBoundIt->Src == SoughtSub.Src) {
1516 std::tie(InstNo, OpNo) = LowerBoundIt->Dest;
1517 SoughtSub.Src = LowerBoundIt->Dest;
1518 if (
unsigned Subreg = LowerBoundIt->Subreg)
1519 SeenSubregs.push_back(Subreg);
1525 std::optional<ValueIDNum> NewID;
1529 auto InstrIt = DebugInstrNumToInstr.find(InstNo);
1531 if (InstrIt != DebugInstrNumToInstr.end()) {
1532 const MachineInstr &TargetInstr = *InstrIt->second.first;
1541 NewID = ValueIDNum(BlockNo, InstrIt->second.second, *L);
1549 const MachineOperand &MO = TargetInstr.
getOperand(OpNo);
1552 unsigned LocID = MTracker->getLocID(MO.
getReg());
1553 LocIdx
L = MTracker->LocIDToLocIdx[LocID];
1554 NewID = ValueIDNum(BlockNo, InstrIt->second.second, L);
1560 {
dbgs() <<
"Seen instruction reference to illegal operand\n"; });
1564 }
else if (PHIIt != DebugPHINumToValue.end() && PHIIt->InstrNum == InstNo) {
1567 assert(MLiveOuts && MLiveIns);
1568 NewID = resolveDbgPHIs(*
MI.getParent()->getParent(), *MLiveOuts, *MLiveIns,
1581 if (NewID && !SeenSubregs.empty()) {
1589 for (
unsigned Subreg :
reverse(SeenSubregs)) {
1590 unsigned ThisSize = TRI->getSubRegIdxSize(Subreg);
1591 unsigned ThisOffset = TRI->getSubRegIdxOffset(Subreg);
1600 LocIdx
L = NewID->getLoc();
1601 if (NewID && !MTracker->isSpill(L)) {
1606 for (
const auto &TRCI : TRI->regclasses())
1607 if (TRCI.contains(
Reg))
1609 assert(TRC &&
"Couldn't find target register class?");
1613 unsigned MainRegSize = TRI->getRegSizeInBits(*TRC);
1617 for (MCRegister SR : TRI->subregs(
Reg)) {
1618 unsigned Subreg = TRI->getSubRegIndex(
Reg, SR);
1619 unsigned SubregSize = TRI->getSubRegIdxSize(Subreg);
1620 unsigned SubregOffset = TRI->getSubRegIdxOffset(Subreg);
1621 if (SubregSize ==
Size && SubregOffset ==
Offset) {
1629 NewID = std::nullopt;
1634 MTracker->lookupOrTrackRegister(MTracker->getLocID(NewReg));
1635 NewID = ValueIDNum(NewID->getBlock(), NewID->getInst(), NewLoc);
1640 NewID = std::nullopt;
1650 if (!
MI.isDebugRef())
1655 if (!VTracker && !TTracker)
1658 const DILocalVariable *Var =
MI.getDebugVariable();
1659 const DIExpression *Expr =
MI.getDebugExpression();
1660 const DILocation *
DebugLoc =
MI.getDebugLoc();
1661 const DILocation *InlinedAt =
DebugLoc->getInlinedAt();
1663 "Expected inlined-at fields to agree");
1665 DebugVariable
V(Var, Expr, InlinedAt);
1667 auto *
Scope = LS.findLexicalScope(
MI.getDebugLoc().get());
1668 if (Scope ==
nullptr)
1672 for (
const MachineOperand &MO :
MI.debug_operands()) {
1674 assert(!MO.
isReg() &&
"DBG_INSTR_REF should not contain registers");
1675 DbgOpID ConstOpID = DbgOpStore.insert(DbgOp(MO));
1685 std::optional<ValueIDNum> NewID =
1686 getValueForInstrRef(InstNo, OpNo,
MI, MLiveOuts, MLiveIns);
1690 DbgOpIDs.
push_back(DbgOpStore.insert(*NewID));
1701 DbgValueProperties
Properties(Expr,
false,
true);
1703 VTracker->defVar(
MI, Properties, DbgOpIDs);
1712 for (DbgOpID OpID : DbgOpIDs) {
1713 DbgOps.
push_back(DbgOpStore.find(OpID));
1718 SmallDenseMap<ValueIDNum, TransferTracker::LocationAndQuality> FoundLocs;
1722 for (
const DbgOp &
Op : DbgOps) {
1728 for (
auto Location : MTracker->locations()) {
1730 ValueIDNum
ID = MTracker->readMLoc(CurL);
1731 auto ValueToFindIt =
find(ValuesToFind, ID);
1732 if (ValueToFindIt == ValuesToFind.
end())
1734 auto &Previous = FoundLocs.
find(ID)->second;
1737 std::optional<TransferTracker::LocationQuality> ReplacementQuality =
1738 TTracker->getLocQualityIfBetter(CurL, Previous.getQuality());
1739 if (ReplacementQuality) {
1740 Previous = TransferTracker::LocationAndQuality(CurL, *ReplacementQuality);
1741 if (Previous.isBest()) {
1742 ValuesToFind.
erase(ValueToFindIt);
1743 if (ValuesToFind.
empty())
1750 for (
const DbgOp &DbgOp : DbgOps) {
1751 if (DbgOp.IsConst) {
1755 LocIdx FoundLoc = FoundLocs.
find(DbgOp.ID)->second.getLoc();
1763 TTracker->redefVar(
MI, Properties, NewLocs);
1767 if (!DbgOps.empty() && NewLocs.
empty()) {
1768 bool IsValidUseBeforeDef =
true;
1770 for (
auto ValueLoc : FoundLocs) {
1771 ValueIDNum NewID = ValueLoc.first;
1772 LocIdx FoundLoc = ValueLoc.second.getLoc();
1778 IsValidUseBeforeDef =
false;
1781 LastUseBeforeDef = std::max(LastUseBeforeDef, NewID.
getInst());
1783 if (IsValidUseBeforeDef) {
1785 TTracker->addUseBeforeDef(VID, {
MI.getDebugExpression(),
false,
true},
1786 DbgOps, LastUseBeforeDef);
1794 MachineInstr *DbgMI =
1795 MTracker->emitLoc(NewLocs, V,
MI.getDebugLoc().get(), Properties);
1798 TTracker->PendingDbgValues.push_back(std::make_pair(ID, DbgMI));
1799 TTracker->flushDbgValues(
MI.getIterator(),
nullptr);
1804 if (!
MI.isDebugPHI())
1808 if (VTracker || TTracker)
1813 const MachineOperand &MO =
MI.getOperand(0);
1814 unsigned InstrNum =
MI.getOperand(1).
getImm();
1816 auto EmitBadPHI = [
this, &
MI, InstrNum]() ->
bool {
1821 DebugPHINumToValue.push_back(
1822 {InstrNum,
MI.getParent(), std::nullopt, std::nullopt});
1830 ValueIDNum Num = MTracker->readReg(
Reg);
1831 auto PHIRec = DebugPHIRecord(
1832 {InstrNum,
MI.getParent(), Num,
1833 MTracker->lookupOrTrackRegister(MTracker->getLocID(
Reg))});
1834 DebugPHINumToValue.push_back(PHIRec);
1837 for (MCRegAliasIterator RAI(MO.
getReg(), TRI,
true); RAI.isValid(); ++RAI)
1838 MTracker->lookupOrTrackRegister(MTracker->getLocID(*RAI));
1839 }
else if (MO.
isFI()) {
1845 if (MFI->isDeadObjectIndex(FI))
1846 return EmitBadPHI();
1850 StackOffset Offs = TFI->getFrameIndexReference(*
MI.getMF(), FI,
Base);
1851 SpillLoc SL = {
Base, Offs};
1852 std::optional<SpillLocationNo> SpillNo = MTracker->getOrTrackSpillLoc(SL);
1857 return EmitBadPHI();
1860 assert(
MI.getNumOperands() == 3 &&
"Stack DBG_PHI with no size?");
1861 unsigned slotBitSize =
MI.getOperand(2).getImm();
1863 unsigned SpillID = MTracker->getLocID(*SpillNo, {slotBitSize, 0});
1864 LocIdx SpillLoc = MTracker->getSpillMLoc(SpillID);
1865 ValueIDNum
Result = MTracker->readMLoc(SpillLoc);
1868 auto DbgPHI = DebugPHIRecord({InstrNum,
MI.getParent(),
Result, SpillLoc});
1869 DebugPHINumToValue.push_back(DbgPHI);
1876 {
dbgs() <<
"Seen DBG_PHI with unrecognised operand format\n"; });
1877 return EmitBadPHI();
1886 if (
MI.isImplicitDef()) {
1891 ValueIDNum Num = MTracker->readReg(
MI.getOperand(0).getReg());
1896 }
else if (
MI.isMetaInstruction())
1904 bool CallChangesSP =
false;
1905 if (AdjustsStackInCalls &&
MI.isCall() &&
MI.getOperand(0).isSymbol() &&
1906 !strcmp(
MI.getOperand(0).getSymbolName(), StackProbeSymbolName.data()))
1907 CallChangesSP =
true;
1911 auto IgnoreSPAlias = [
this, &
MI, CallChangesSP](
Register R) ->
bool {
1914 return MI.isCall() && MTracker->SPAliases.count(R);
1920 SmallSet<uint32_t, 32> DeadRegs;
1921 SmallVector<const uint32_t *, 4> RegMasks;
1923 for (
const MachineOperand &MO :
MI.operands()) {
1926 !IgnoreSPAlias(MO.
getReg())) {
1928 for (MCRegAliasIterator RAI(MO.
getReg(), TRI,
true); RAI.isValid(); ++RAI)
1930 DeadRegs.
insert((*RAI).id());
1938 for (uint32_t DeadReg : DeadRegs)
1939 MTracker->defReg(DeadReg, CurBB, CurInst);
1941 for (
const auto *MO : RegMaskPtrs)
1942 MTracker->writeRegMask(MO, CurBB, CurInst);
1946 if (std::optional<SpillLocationNo> SpillNo =
1947 extractSpillBaseRegAndOffset(
MI)) {
1948 for (
unsigned int I = 0;
I < MTracker->NumSlotIdxes; ++
I) {
1949 unsigned SpillID = MTracker->getSpillIDWithIdx(*SpillNo,
I);
1950 LocIdx
L = MTracker->getSpillMLoc(SpillID);
1951 MTracker->setMLoc(L, ValueIDNum(CurBB, CurInst, L));
1964 for (MCRegister DeadReg : DeadRegs) {
1965 LocIdx Loc = MTracker->lookupOrTrackRegister(MTracker->getLocID(DeadReg));
1966 TTracker->clobberMloc(Loc,
MI.getIterator(),
false);
1971 if (!RegMaskPtrs.empty()) {
1972 for (
auto L : MTracker->locations()) {
1974 if (MTracker->isSpill(
L.Idx))
1978 if (IgnoreSPAlias(
Reg))
1981 for (
const auto *MO : RegMaskPtrs)
1983 TTracker->clobberMloc(
L.Idx,
MI.getIterator(),
false);
1989 if (std::optional<SpillLocationNo> SpillNo =
1990 extractSpillBaseRegAndOffset(
MI)) {
1991 for (
unsigned int I = 0;
I < MTracker->NumSlotIdxes; ++
I) {
1992 unsigned SpillID = MTracker->getSpillIDWithIdx(*SpillNo,
I);
1993 LocIdx
L = MTracker->getSpillMLoc(SpillID);
1994 TTracker->clobberMloc(L,
MI.getIterator(),
true);
2000void InstrRefBasedLDV::performCopy(
Register SrcRegNum,
Register DstRegNum) {
2002 for (MCRegAliasIterator RAI(DstRegNum, TRI,
true); RAI.isValid(); ++RAI)
2003 MTracker->defReg(*RAI, CurBB, CurInst);
2005 ValueIDNum SrcValue = MTracker->readReg(SrcRegNum);
2006 MTracker->setReg(DstRegNum, SrcValue);
2009 for (MCSubRegIndexIterator SRI(SrcRegNum, TRI); SRI.isValid(); ++SRI) {
2010 MCRegister SrcSubReg = SRI.getSubReg();
2011 unsigned SubRegIdx = SRI.getSubRegIndex();
2012 MCRegister DstSubReg = TRI->getSubReg(DstRegNum, SubRegIdx);
2022 MTracker->lookupOrTrackRegister(MTracker->getLocID(SrcSubReg));
2024 MTracker->lookupOrTrackRegister(MTracker->getLocID(DstSubReg));
2027 ValueIDNum CpyValue = MTracker->readReg(SrcSubReg);
2029 MTracker->setReg(DstSubReg, CpyValue);
2033std::optional<SpillLocationNo>
2037 if (!
MI.hasOneMemOperand())
2038 return std::nullopt;
2041 auto MMOI =
MI.memoperands_begin();
2042 const PseudoSourceValue *PVal = (*MMOI)->getPseudoValue();
2044 return std::nullopt;
2046 if (!
MI.getSpillSize(TII) && !
MI.getFoldedSpillSize(TII))
2047 return std::nullopt;
2050 return extractSpillBaseRegAndOffset(
MI);
2055 if (!isSpillInstruction(
MI, MF))
2059 Reg = TII->isStoreToStackSlotPostFE(
MI, FI);
2063std::optional<SpillLocationNo>
2066 if (!
MI.hasOneMemOperand())
2067 return std::nullopt;
2071 if (
MI.getRestoreSize(TII)) {
2072 Reg =
MI.getOperand(0).getReg();
2073 return extractSpillBaseRegAndOffset(
MI);
2075 return std::nullopt;
2078bool InstrRefBasedLDV::transferSpillOrRestoreInst(
MachineInstr &
MI) {
2088 if (!TII->isStoreToStackSlotPostFE(
MI, DummyFI) &&
2089 !TII->isLoadFromStackSlotPostFE(
MI, DummyFI))
2100 if (!TII->isStoreToStackSlotPostFE(
MI, FIDummy) &&
2101 !TII->isLoadFromStackSlotPostFE(
MI, FIDummy))
2107 if (std::optional<SpillLocationNo> Loc = isSpillInstruction(
MI, MF)) {
2110 for (
unsigned SlotIdx = 0; SlotIdx < MTracker->NumSlotIdxes; ++SlotIdx) {
2111 unsigned SpillID = MTracker->getSpillIDWithIdx(*Loc, SlotIdx);
2112 std::optional<LocIdx> MLoc = MTracker->getSpillMLoc(SpillID);
2120 ValueIDNum
Def(CurBB, CurInst, *MLoc);
2121 MTracker->setMLoc(*MLoc, Def);
2123 TTracker->clobberMloc(*MLoc,
MI.getIterator());
2128 if (isLocationSpill(
MI, MF,
Reg)) {
2131 SpillLocationNo Loc = *extractSpillBaseRegAndOffset(
MI);
2133 auto DoTransfer = [&](
Register SrcReg,
unsigned SpillID) {
2134 auto ReadValue = MTracker->readReg(SrcReg);
2135 LocIdx DstLoc = MTracker->getSpillMLoc(SpillID);
2136 MTracker->setMLoc(DstLoc, ReadValue);
2139 LocIdx SrcLoc = MTracker->getRegMLoc(SrcReg);
2140 TTracker->transferMlocs(SrcLoc, DstLoc,
MI.getIterator());
2147 (void)MTracker->lookupOrTrackRegister(MTracker->getLocID(SR));
2148 unsigned SubregIdx = TRI->getSubRegIndex(
Reg, SR);
2149 unsigned SpillID = MTracker->getLocID(Loc, SubregIdx);
2150 DoTransfer(SR, SpillID);
2154 unsigned Size = TRI->getRegSizeInBits(
Reg, *MRI);
2155 unsigned SpillID = MTracker->getLocID(Loc, {
Size, 0});
2156 DoTransfer(
Reg, SpillID);
2158 std::optional<SpillLocationNo> Loc = isRestoreInstruction(
MI, MF,
Reg);
2169 for (MCRegAliasIterator RAI(
Reg, TRI,
true); RAI.isValid(); ++RAI)
2170 MTracker->defReg(*RAI, CurBB, CurInst);
2174 auto DoTransfer = [&](
Register DestReg,
unsigned SpillID) {
2175 LocIdx SrcIdx = MTracker->getSpillMLoc(SpillID);
2176 auto ReadValue = MTracker->readMLoc(SrcIdx);
2177 MTracker->setReg(DestReg, ReadValue);
2181 unsigned Subreg = TRI->getSubRegIndex(
Reg, SR);
2182 unsigned SpillID = MTracker->getLocID(*Loc, Subreg);
2183 DoTransfer(SR, SpillID);
2187 unsigned Size = TRI->getRegSizeInBits(
Reg, *MRI);
2188 unsigned SpillID = MTracker->getLocID(*Loc, {
Size, 0});
2189 DoTransfer(
Reg, SpillID);
2195 auto DestSrc = TII->isCopyLikeInstr(
MI);
2199 const MachineOperand *DestRegOp = DestSrc->Destination;
2200 const MachineOperand *SrcRegOp = DestSrc->Source;
2206 if (SrcReg == DestReg)
2228 DenseMap<LocIdx, ValueIDNum> ClobberedLocs;
2230 for (MCRegAliasIterator RAI(DestReg, TRI,
true); RAI.isValid(); ++RAI) {
2231 LocIdx ClobberedLoc = MTracker->getRegMLoc(*RAI);
2232 auto MLocIt = TTracker->ActiveMLocs.find(ClobberedLoc);
2235 if (MLocIt == TTracker->ActiveMLocs.end() || MLocIt->second.empty())
2237 ValueIDNum
Value = MTracker->readReg(*RAI);
2238 ClobberedLocs[ClobberedLoc] =
Value;
2243 InstrRefBasedLDV::performCopy(SrcReg, DestReg);
2249 for (
auto LocVal : ClobberedLocs) {
2250 TTracker->clobberMloc(LocVal.first, LocVal.second,
MI.getIterator(),
false);
2258 TTracker->transferMlocs(MTracker->getRegMLoc(SrcReg),
2259 MTracker->getRegMLoc(DestReg),
MI.getIterator());
2263 MTracker->defReg(SrcReg, CurBB, CurInst);
2276 DebugVariable MIVar(
MI.getDebugVariable(),
MI.getDebugExpression(),
2277 MI.getDebugLoc()->getInlinedAt());
2278 FragmentInfo ThisFragment = MIVar.getFragmentOrDefault();
2283 auto [SeenIt,
Inserted] = SeenFragments.try_emplace(MIVar.getVariable());
2285 SeenIt->second.insert(ThisFragment);
2287 OverlapFragments.insert({{MIVar.getVariable(), ThisFragment}, {}});
2294 OverlapFragments.insert({{MIVar.getVariable(), ThisFragment}, {}});
2295 if (!IsInOLapMap.second)
2298 auto &ThisFragmentsOverlaps = IsInOLapMap.first->second;
2299 auto &AllSeenFragments = SeenIt->second;
2304 for (
const auto &ASeenFragment : AllSeenFragments) {
2308 ThisFragmentsOverlaps.push_back(ASeenFragment);
2311 auto ASeenFragmentsOverlaps =
2312 OverlapFragments.find({MIVar.getVariable(), ASeenFragment});
2313 assert(ASeenFragmentsOverlaps != OverlapFragments.end() &&
2314 "Previously seen var fragment has no vector of overlaps");
2315 ASeenFragmentsOverlaps->second.push_back(ThisFragment);
2319 AllSeenFragments.insert(ThisFragment);
2328 if (transferDebugValue(
MI))
2330 if (transferDebugInstrRef(
MI, MLiveOuts, MLiveIns))
2332 if (transferDebugPHI(
MI))
2334 if (transferRegisterCopy(
MI))
2336 if (transferSpillOrRestoreInst(
MI))
2338 transferRegisterDef(
MI);
2341void InstrRefBasedLDV::produceMLocTransferFunction(
2357 for (
auto &BV : BlockMasks)
2358 BV.resize(TRI->getNumRegs(),
true);
2361 for (
auto &
MBB : MF) {
2370 MTracker->setMPhis(CurBB);
2373 for (
auto &
MI :
MBB) {
2376 process(
MI,
nullptr,
nullptr);
2379 if (
MI.isDebugValueLike())
2380 accumulateFragmentMap(
MI);
2384 if (
uint64_t InstrNo =
MI.peekDebugInstrNum()) {
2385 auto InstrAndPos = std::make_pair(&
MI, CurInst);
2387 DebugInstrNumToInstr.insert(std::make_pair(InstrNo, InstrAndPos));
2390 assert(InsertResult.second);
2401 for (
auto Location : MTracker->locations()) {
2404 if (
P.isPHI() &&
P.getLoc() ==
Idx.asU64())
2408 auto &TransferMap = MLocTransfer[CurBB];
2409 auto Result = TransferMap.insert(std::make_pair(
Idx.asU64(),
P));
2416 for (
auto &
P : MTracker->Masks) {
2417 BlockMasks[CurBB].clearBitsNotInMask(
P.first->getRegMask(), BVWords);
2422 BitVector UsedRegs(TRI->getNumRegs());
2423 for (
auto Location : MTracker->locations()) {
2424 unsigned ID = MTracker->LocIdxToLocID[
Location.Idx];
2426 if (ID >= TRI->getNumRegs() || MTracker->SPAliases.count(ID))
2435 BitVector &BV = BlockMasks[
I];
2441 for (
unsigned Bit : BV.
set_bits()) {
2442 unsigned ID = MTracker->getLocID(Bit);
2443 LocIdx
Idx = MTracker->LocIDToLocIdx[
ID];
2444 auto &TransferMap = MLocTransfer[
I];
2451 ValueIDNum NotGeneratedNum = ValueIDNum(
I, 1, Idx);
2453 TransferMap.insert(std::make_pair(
Idx.asU64(), NotGeneratedNum));
2455 ValueIDNum &ValueID =
Result.first->second;
2458 ValueID = NotGeneratedNum;
2464bool InstrRefBasedLDV::mlocJoin(
2478 auto Cmp = [&](
const MachineBasicBlock *
A,
const MachineBasicBlock *
B) {
2479 return BBToOrder.find(
A)->second < BBToOrder.find(
B)->second;
2484 if (BlockOrders.size() == 0) {
2489 <<
" from entry which may lead out of "
2490 "bound access to VarLocs\n");
2496 for (
auto Location : MTracker->locations()) {
2501 ValueIDNum FirstVal = OutLocs[*BlockOrders[0]][
Idx.asU64()];
2506 if (InLocs[
Idx.asU64()] != FirstVal) {
2507 InLocs[
Idx.asU64()] = FirstVal;
2515 bool Disagree =
false;
2516 for (
unsigned int I = 1;
I < BlockOrders.size(); ++
I) {
2517 const MachineBasicBlock *PredMBB = BlockOrders[
I];
2518 const ValueIDNum &PredLiveOut = OutLocs[*PredMBB][
Idx.asU64()];
2521 if (FirstVal == PredLiveOut)
2525 if (PredLiveOut == ValueIDNum(
MBB.
getNumber(), 0, Idx))
2534 InLocs[
Idx.asU64()] = FirstVal;
2543void InstrRefBasedLDV::findStackIndexInterference(
2556 auto It = MTracker->StackSlotIdxes.find({8, 0});
2557 assert(It != MTracker->StackSlotIdxes.end());
2561 for (
auto &Pair : MTracker->StackSlotIdxes) {
2563 if (!Pair.first.second)
2569void InstrRefBasedLDV::placeMLocPHIs(
2572 SmallVector<unsigned, 4> StackUnits;
2573 findStackIndexInterference(StackUnits);
2582 SmallSet<Register, 32> RegUnitsToPHIUp;
2583 SmallSet<LocIdx, 32> NormalLocsToPHI;
2584 SmallSet<SpillLocationNo, 32> StackSlots;
2585 for (
auto Location : MTracker->locations()) {
2587 if (MTracker->isSpill(L)) {
2588 StackSlots.
insert(MTracker->locIDToSpill(MTracker->LocIdxToLocID[L]));
2593 SmallSet<Register, 8> FoundRegUnits;
2594 bool AnyIllegal =
false;
2595 for (MCRegUnit Unit : TRI->regunits(
R.asMCReg())) {
2596 for (MCRegUnitRootIterator URoot(Unit, TRI); URoot.isValid(); ++URoot) {
2597 if (!MTracker->isRegisterTracked(*URoot)) {
2603 FoundRegUnits.
insert(*URoot);
2609 NormalLocsToPHI.
insert(L);
2618 SmallVector<MachineBasicBlock *, 32> PHIBlocks;
2619 auto CollectPHIsForLoc = [&](LocIdx
L) {
2621 SmallPtrSet<MachineBasicBlock *, 32> DefBlocks;
2622 for (MachineBasicBlock *
MBB : OrderToBB) {
2623 const auto &TransferFunc = MLocTransfer[
MBB->
getNumber()];
2624 if (TransferFunc.contains(L))
2631 if (!DefBlocks.
empty())
2637 BlockPHIPlacement(AllBlocks, DefBlocks, PHIBlocks);
2640 auto InstallPHIsAtLoc = [&PHIBlocks, &MInLocs](LocIdx
L) {
2641 for (
const MachineBasicBlock *
MBB : PHIBlocks)
2646 for (LocIdx L : NormalLocsToPHI) {
2647 CollectPHIsForLoc(L);
2649 InstallPHIsAtLoc(L);
2654 for (SpillLocationNo Slot : StackSlots) {
2655 for (
unsigned Idx : StackUnits) {
2656 unsigned SpillID = MTracker->getSpillIDWithIdx(Slot, Idx);
2657 LocIdx
L = MTracker->getSpillMLoc(SpillID);
2658 CollectPHIsForLoc(L);
2659 InstallPHIsAtLoc(L);
2664 for (
auto &Pair : MTracker->StackSlotIdxes) {
2665 unsigned ThisSize, ThisOffset;
2666 std::tie(ThisSize, ThisOffset) = Pair.first;
2670 unsigned ThisID = MTracker->getSpillIDWithIdx(Slot, Pair.second);
2671 LocIdx ThisL = MTracker->getSpillMLoc(ThisID);
2672 InstallPHIsAtLoc(ThisL);
2678 for (
Register R : RegUnitsToPHIUp) {
2679 LocIdx
L = MTracker->lookupOrTrackRegister(MTracker->getLocID(R));
2680 CollectPHIsForLoc(L);
2683 InstallPHIsAtLoc(L);
2686 for (MCRegAliasIterator RAI(R, TRI,
true); RAI.isValid(); ++RAI) {
2689 if (!MTracker->isRegisterTracked(*RAI))
2693 MTracker->lookupOrTrackRegister(MTracker->getLocID(*RAI));
2694 InstallPHIsAtLoc(AliasLoc);
2699void InstrRefBasedLDV::buildMLocValueMap(
2702 std::priority_queue<unsigned int, std::vector<unsigned int>,
2703 std::greater<unsigned int>>
2709 SmallPtrSet<MachineBasicBlock *, 16> OnPending, OnWorklist;
2713 SmallPtrSet<MachineBasicBlock *, 32> AllBlocks;
2714 for (
unsigned int I = 0;
I < BBToOrder.size(); ++
I) {
2716 OnWorklist.
insert(OrderToBB[
I]);
2717 AllBlocks.
insert(OrderToBB[
I]);
2721 for (
auto Location : MTracker->locations())
2730 placeMLocPHIs(MF, AllBlocks, MInLocs, MLocTransfer);
2740 SmallPtrSet<const MachineBasicBlock *, 16> Visited;
2741 while (!Worklist.empty() || !Pending.empty()) {
2745 while (!Worklist.empty()) {
2746 MachineBasicBlock *
MBB = OrderToBB[Worklist.top()];
2752 InLocsChanged = mlocJoin(*
MBB, Visited, MOutLocs, MInLocs[*
MBB]);
2753 InLocsChanged |= Visited.
insert(
MBB).second;
2761 MTracker->loadFromArray(MInLocs[*
MBB], CurBB);
2766 for (
auto &
P : MLocTransfer[CurBB]) {
2767 if (
P.second.getBlock() == CurBB &&
P.second.isPHI()) {
2769 ValueIDNum NewID = MTracker->readMLoc(
P.second.getLoc());
2770 ToRemap.
push_back(std::make_pair(
P.first, NewID));
2773 assert(
P.second.getBlock() == CurBB);
2774 ToRemap.
push_back(std::make_pair(
P.first,
P.second));
2780 for (
auto &
P : ToRemap)
2781 MTracker->setMLoc(
P.first,
P.second);
2786 bool OLChanged =
false;
2787 for (
auto Location : MTracker->locations()) {
2803 unsigned Order = BBToOrder[s];
2804 if (Order > BBToOrder[
MBB]) {
2806 if (OnWorklist.
insert(s).second)
2807 Worklist.push(Order);
2810 if (OnPending.
insert(s).second)
2811 Pending.push(Order);
2816 Worklist.swap(Pending);
2821 assert(Pending.empty() &&
"Pending should be empty");
2828void InstrRefBasedLDV::BlockPHIPlacement(
2835 IDFCalculatorBase<MachineBasicBlock, false> IDF(*DomTree);
2837 IDF.setLiveInBlocks(AllBlocks);
2838 IDF.setDefiningBlocks(DefBlocks);
2839 IDF.calculate(PHIBlocks);
2842bool InstrRefBasedLDV::pickVPHILoc(
2848 if (BlockOrders.
empty())
2853 SmallDenseSet<unsigned> LocOpsToJoin;
2855 auto FirstValueIt = LiveOuts.find(BlockOrders[0]);
2856 if (FirstValueIt == LiveOuts.end())
2858 const DbgValue &FirstValue = *FirstValueIt->second;
2860 for (
const auto p : BlockOrders) {
2861 auto OutValIt = LiveOuts.find(p);
2862 if (OutValIt == LiveOuts.end())
2865 const DbgValue &OutVal = *OutValIt->second;
2883 LocOpsToJoin.
insert(Idx);
2886 DbgOpID FirstValOp = FirstValue.
getDbgOpID(Idx);
2888 if (FirstValOp != OutValOp) {
2894 LocOpsToJoin.
insert(Idx);
2909 std::optional<ValueIDNum> JoinedOpLoc =
2910 pickOperandPHILoc(Idx,
MBB, LiveOuts, MOutLocs, BlockOrders);
2915 NewDbgOps.
push_back(DbgOpStore.insert(*JoinedOpLoc));
2918 OutValues.
append(NewDbgOps);
2922std::optional<ValueIDNum> InstrRefBasedLDV::pickOperandPHILoc(
2930 unsigned NumLocs = MTracker->getNumLocs();
2932 for (
const auto p : BlockOrders) {
2933 auto OutValIt = LiveOuts.find(p);
2934 assert(OutValIt != LiveOuts.end());
2935 const DbgValue &OutVal = *OutValIt->second;
2936 DbgOpID OutValOpID = OutVal.
getDbgOpID(DbgOpIdx);
2937 DbgOp OutValOp = DbgOpStore.find(OutValOpID);
2948 ValueIDNum ValToLookFor = OutValOp.
ID;
2950 for (
unsigned int I = 0;
I < NumLocs; ++
I) {
2951 if (MOutLocs[*p][
I] == ValToLookFor)
2952 Locs.
back().push_back(LocIdx(
I));
2962 for (
unsigned int I = 0;
I < NumLocs; ++
I) {
2964 if (MOutLocs[*p][
I] == MPHI)
2965 Locs.
back().push_back(LocIdx(
I));
2975 for (
unsigned int I = 1;
I < Locs.
size(); ++
I) {
2976 auto &LocVec = Locs[
I];
2978 std::set_intersection(CandidateLocs.
begin(), CandidateLocs.
end(),
2979 LocVec.begin(), LocVec.end(), std::inserter(NewCandidates, NewCandidates.
begin()));
2980 CandidateLocs = std::move(NewCandidates);
2982 if (CandidateLocs.
empty())
2983 return std::nullopt;
2988 LocIdx
L = *CandidateLocs.
begin();
2995bool InstrRefBasedLDV::vlocJoin(
3005 auto Cmp = [&](MachineBasicBlock *
A, MachineBasicBlock *
B) {
3006 return BBToOrder[
A] < BBToOrder[
B];
3011 unsigned CurBlockRPONum = BBToOrder[&
MBB];
3017 int BackEdgesStart = 0;
3018 for (
auto *p : BlockOrders) {
3021 if (!BlocksToExplore.
contains(p)) {
3027 DbgValue &OutLoc = *VLOCOutLocs.find(p)->second;
3031 unsigned ThisBBRPONum = BBToOrder[
p];
3032 if (ThisBBRPONum < CurBlockRPONum)
3035 Values.push_back(std::make_pair(p, &OutLoc));
3041 if (Bail ||
Values.size() == 0)
3047 const DbgValue &FirstVal = *
Values[0].second;
3062 for (
const auto &V :
Values) {
3063 if (!
V.second->Properties.isJoinable(FirstVal.
Properties))
3067 if (!
V.second->hasJoinableLocOps(FirstVal))
3072 bool Disagree =
false;
3074 if (*
V.second == FirstVal)
3080 if (
V.second->hasIdenticalValidLocOps(FirstVal))
3087 std::distance(
Values.begin(), &V) >= BackEdgesStart)
3109void InstrRefBasedLDV::getBlocksForScope(
3114 LS.getMachineBasicBlocks(DILoc, BlocksToExplore);
3122 DenseSet<const MachineBasicBlock *> ToAdd;
3129 for (
const auto *
MBB : BlocksToExplore) {
3139 if (BlocksToExplore.count(succ))
3141 if (!ArtificialBlocks.count(succ))
3144 DFS.push_back({succ, succ->succ_begin()});
3148 while (!DFS.empty()) {
3149 const MachineBasicBlock *CurBB = DFS.back().first;
3152 if (CurSucc == CurBB->succ_end()) {
3159 if (!ToAdd.
count(*CurSucc) && ArtificialBlocks.count(*CurSucc)) {
3161 DFS.push_back({*CurSucc, (*CurSucc)->succ_begin()});
3169 BlocksToExplore.insert_range(ToAdd);
3172void InstrRefBasedLDV::buildVLocValueMap(
3182 std::priority_queue<unsigned int, std::vector<unsigned int>,
3183 std::greater<unsigned int>>
3185 SmallPtrSet<MachineBasicBlock *, 16> OnWorklist, OnPending;
3188 SmallPtrSet<const MachineBasicBlock *, 8> BlocksToExplore;
3192 SmallVector<unsigned, 32> BlockOrderNums;
3194 getBlocksForScope(DILoc, BlocksToExplore, AssignBlocks);
3200 if (BlocksToExplore.
size() == 1)
3206 SmallPtrSet<MachineBasicBlock *, 8> MutBlocksToExplore;
3207 for (
const auto *
MBB : BlocksToExplore)
3208 MutBlocksToExplore.
insert(
const_cast<MachineBasicBlock *
>(
MBB));
3213 for (
const auto *
MBB : BlocksToExplore)
3217 for (
unsigned int I : BlockOrderNums)
3219 BlockOrderNums.clear();
3220 unsigned NumBlocks = BlockOrders.
size();
3229 DbgValueProperties EmptyProperties(EmptyExpr,
false,
false);
3230 for (
unsigned int I = 0;
I < NumBlocks; ++
I) {
3239 LiveOutIdx.reserve(NumBlocks);
3240 LiveInIdx.reserve(NumBlocks);
3241 for (
unsigned I = 0;
I < NumBlocks; ++
I) {
3242 LiveOutIdx[BlockOrders[
I]] = &LiveOuts[
I];
3243 LiveInIdx[BlockOrders[
I]] = &LiveIns[
I];
3253 for (
unsigned int I = 0;
I < NumBlocks; ++
I) {
3255 LiveIns[
I] = EmptyDbgValue;
3256 LiveOuts[
I] = EmptyDbgValue;
3261 SmallPtrSet<MachineBasicBlock *, 32> DefBlocks;
3262 for (
const MachineBasicBlock *ExpMBB : BlocksToExplore) {
3263 auto &TransferFunc = AllTheVLocs[ExpMBB->getNumber()].Vars;
3264 if (TransferFunc.contains(
VarID))
3265 DefBlocks.
insert(
const_cast<MachineBasicBlock *
>(ExpMBB));
3268 SmallVector<MachineBasicBlock *, 32> PHIBlocks;
3272 if (DefBlocks.
size() == 1) {
3273 placePHIsForSingleVarDefinition(MutBlocksToExplore, *DefBlocks.
begin(),
3274 AllTheVLocs,
VarID, Output);
3279 BlockPHIPlacement(MutBlocksToExplore, DefBlocks, PHIBlocks);
3282 for (MachineBasicBlock *PHIMBB : PHIBlocks) {
3283 unsigned BlockNo = PHIMBB->getNumber();
3284 DbgValue *LiveIn = LiveInIdx[PHIMBB];
3288 for (
auto *
MBB : BlockOrders) {
3289 Worklist.push(BBToOrder[
MBB]);
3300 bool FirstTrip =
true;
3301 while (!Worklist.empty() || !Pending.empty()) {
3302 while (!Worklist.empty()) {
3303 auto *
MBB = OrderToBB[Worklist.top()];
3307 auto LiveInsIt = LiveInIdx.find(
MBB);
3308 assert(LiveInsIt != LiveInIdx.end());
3309 DbgValue *LiveIn = LiveInsIt->second;
3313 bool InLocsChanged =
3314 vlocJoin(*
MBB, LiveOutIdx, BlocksToExplore, *LiveIn);
3329 if (pickVPHILoc(JoinedOps, *
MBB, LiveOutIdx, MOutLocs, Preds)) {
3331 InLocsChanged |= NewLocPicked;
3337 if (!InLocsChanged && !FirstTrip)
3340 DbgValue *LiveOut = LiveOutIdx[
MBB];
3341 bool OLChanged =
false;
3345 auto TransferIt = VTracker.Vars.find(
VarID);
3346 if (TransferIt != VTracker.Vars.end()) {
3350 if (*LiveOut != NewVal) {
3356 if (*LiveOut != TransferIt->second) {
3357 *LiveOut = TransferIt->second;
3363 if (*LiveOut != *LiveIn) {
3378 if (!LiveInIdx.contains(s))
3381 unsigned Order = BBToOrder[s];
3382 if (Order > BBToOrder[
MBB]) {
3383 if (OnWorklist.
insert(s).second)
3384 Worklist.push(Order);
3385 }
else if (OnPending.
insert(s).second && (FirstTrip || OLChanged)) {
3386 Pending.push(Order);
3390 Worklist.swap(Pending);
3400 for (
auto *
MBB : BlockOrders) {
3401 DbgValue *BlockLiveIn = LiveInIdx[
MBB];
3408 [[maybe_unused]]
auto &[Var, DILoc] = DVMap.lookupDVID(
VarID);
3410 Var.getFragment() &&
3411 "Fragment info missing during value prop");
3416 BlockOrders.clear();
3417 BlocksToExplore.clear();
3420void InstrRefBasedLDV::placePHIsForSingleVarDefinition(
3435 VLocTracker &VLocs = AllTheVLocs[AssignMBB->
getNumber()];
3437 const DbgValue &
Value = ValueIt->second;
3447 for (
auto *ScopeBlock : InScopeBlocks) {
3448 if (!DomTree->properlyDominates(AssignMBB, ScopeBlock))
3451 Output[ScopeBlock->getNumber()].push_back({
VarID,
Value});
3458#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
3461 for (
const auto &
P : mloc_transfer) {
3462 std::string foo = MTracker->LocIdxToName(
P.first);
3463 std::string bar = MTracker->IDAsString(
P.second);
3464 dbgs() <<
"Loc " << foo <<
" --> " << bar <<
"\n";
3475 auto hasNonArtificialLocation = [](
const MachineInstr &
MI) ->
bool {
3477 return DL.getLine() != 0;
3483 unsigned int Size = 0;
3484 for (
auto &
MBB : MF) {
3487 ArtificialBlocks.insert(&
MBB);
3491 ReversePostOrderTraversal<MachineFunction *> RPOT(&MF);
3492 unsigned int RPONumber = 0;
3493 OrderToBB.reserve(
Size);
3494 BBToOrder.reserve(
Size);
3495 BBNumToRPO.reserve(
Size);
3496 auto processMBB = [&](MachineBasicBlock *
MBB) {
3497 OrderToBB.push_back(
MBB);
3498 BBToOrder[
MBB] = RPONumber;
3502 for (MachineBasicBlock *
MBB : RPOT)
3504 for (MachineBasicBlock &
MBB : MF)
3505 if (!BBToOrder.contains(&
MBB))
3511#ifdef EXPENSIVE_CHECKS
3514 if (MF.DebugValueSubstitutions.size() > 2) {
3515 for (
auto It = MF.DebugValueSubstitutions.begin();
3516 It != std::prev(MF.DebugValueSubstitutions.end()); ++It) {
3517 assert(It->Src != std::next(It)->Src &&
"Duplicate variable location "
3518 "substitution seen");
3527void InstrRefBasedLDV::makeDepthFirstEjectionMap(
3529 const ScopeToDILocT &ScopeToDILocation,
3530 ScopeToAssignBlocksT &ScopeToAssignBlocks) {
3531 SmallPtrSet<const MachineBasicBlock *, 8> BlocksToExplore;
3533 auto *TopScope = LS.getCurrentFunctionScope();
3537 WorkStack.
push_back({TopScope, TopScope->getChildren().size() - 1});
3539 while (!WorkStack.
empty()) {
3540 auto &ScopePosition = WorkStack.
back();
3541 LexicalScope *WS = ScopePosition.first;
3542 ssize_t ChildNum = ScopePosition.second--;
3545 if (ChildNum >= 0) {
3548 auto &ChildScope =
Children[ChildNum];
3550 std::make_pair(ChildScope, ChildScope->getChildren().size() - 1));
3557 auto DILocationIt = ScopeToDILocation.find(WS);
3558 if (DILocationIt != ScopeToDILocation.end()) {
3559 getBlocksForScope(DILocationIt->second, BlocksToExplore,
3560 ScopeToAssignBlocks.find(WS)->second);
3561 for (
const auto *
MBB : BlocksToExplore) {
3563 if (EjectionMap[BBNum] == 0)
3567 BlocksToExplore.clear();
3573bool InstrRefBasedLDV::depthFirstVLocAndEmit(
3574 unsigned MaxNumBlocks,
const ScopeToDILocT &ScopeToDILocation,
3575 const ScopeToVarsT &ScopeToVars, ScopeToAssignBlocksT &ScopeToAssignBlocks,
3578 bool ShouldEmitDebugEntryValues) {
3579 TTracker =
new TransferTracker(TII, MTracker, MF, DVMap, *TRI,
3580 CalleeSavedRegs, ShouldEmitDebugEntryValues);
3581 unsigned NumLocs = MTracker->getNumLocs();
3585 if (!LS.getCurrentFunctionScope())
3589 SmallVector<unsigned, 16> EjectionMap;
3591 makeDepthFirstEjectionMap(EjectionMap, ScopeToDILocation,
3592 ScopeToAssignBlocks);
3597 auto EjectBlock = [&](MachineBasicBlock &
MBB) ->
void {
3599 AllTheVLocs[BBNum].
clear();
3604 MTracker->loadFromArray(MInLocs[
MBB], BBNum);
3605 TTracker->loadInlocs(
MBB, MInLocs[
MBB], DbgOpStore, Output[BBNum], NumLocs);
3609 for (
auto &
MI :
MBB) {
3610 process(
MI, &MOutLocs, &MInLocs);
3611 TTracker->checkInstForNewValues(CurInst,
MI.getIterator());
3619 Output[BBNum].clear();
3620 AllTheVLocs[BBNum].
clear();
3623 SmallPtrSet<const MachineBasicBlock *, 8> BlocksToExplore;
3625 WorkStack.
push_back({LS.getCurrentFunctionScope(), 0});
3626 unsigned HighestDFSIn = 0;
3629 while (!WorkStack.
empty()) {
3630 auto &ScopePosition = WorkStack.
back();
3631 LexicalScope *WS = ScopePosition.first;
3632 ssize_t ChildNum = ScopePosition.second++;
3639 auto DILocIt = ScopeToDILocation.find(WS);
3640 if (HighestDFSIn <= WS->getDFSIn() && DILocIt != ScopeToDILocation.end()) {
3641 const DILocation *DILoc = DILocIt->second;
3642 auto &VarsWeCareAbout = ScopeToVars.find(WS)->second;
3643 auto &BlocksInScope = ScopeToAssignBlocks.find(WS)->second;
3645 buildVLocValueMap(DILoc, VarsWeCareAbout, BlocksInScope, Output, MOutLocs,
3646 MInLocs, AllTheVLocs);
3649 HighestDFSIn = std::max(HighestDFSIn, WS->
getDFSIn());
3653 if (ChildNum < (ssize_t)
Children.size()) {
3655 auto &ChildScope =
Children[ChildNum];
3656 WorkStack.
push_back(std::make_pair(ChildScope, 0));
3662 auto DILocationIt = ScopeToDILocation.find(WS);
3663 if (DILocationIt == ScopeToDILocation.end())
3666 getBlocksForScope(DILocationIt->second, BlocksToExplore,
3667 ScopeToAssignBlocks.find(WS)->second);
3668 for (
const auto *
MBB : BlocksToExplore)
3670 EjectBlock(
const_cast<MachineBasicBlock &
>(*
MBB));
3672 BlocksToExplore.clear();
3681 for (
auto *
MBB : ArtificialBlocks)
3685 return emitTransfers();
3688bool InstrRefBasedLDV::emitTransfers() {
3692 for (
auto &
P : TTracker->Transfers) {
3701 MachineBasicBlock &
MBB = *
P.MBB;
3702 for (
const auto &Pair :
P.Insts)
3707 if (
P.Pos->isTerminator())
3711 for (
const auto &Pair :
P.Insts)
3716 return TTracker->Transfers.size() != 0;
3723 bool ShouldEmitDebugEntryValues,
3725 unsigned InputDbgValLimit) {
3732 this->DomTree = DomTree;
3739 LS.scanFunction(MF);
3742 AdjustsStackInCalls = MFI->adjustsStack() &&
3744 if (AdjustsStackInCalls)
3745 StackProbeSymbolName = STI.getTargetLowering()->getStackProbeSymbolName(MF);
3753 dbgs() <<
"Disabling InstrRefBasedLDV spill tracking for " << MF.getName()
3754 <<
" since target has too many potential stack slot indexes ("
3755 << MTracker->NumSlotIdxes <<
", limit is " << StackSlotIdxesLimit
3764 for (
auto &
MBB : MF)
3775 produceMLocTransferFunction(MF, MLocTransfer,
MaxNumBlocks);
3780 unsigned NumLocs = MTracker->getNumLocs();
3788 buildMLocValueMap(MF, MInLocs, MOutLocs, MLocTransfer);
3792 for (
auto &DBG_PHI : DebugPHINumToValue) {
3794 if (!DBG_PHI.ValueRead)
3797 ValueIDNum &Num = *DBG_PHI.ValueRead;
3802 LocIdx LocNo = Num.
getLoc();
3803 ValueIDNum ResolvedValue = MInLocs[BlockNo][LocNo.
asU64()];
3808 Num = ResolvedValue;
3815 for (MachineBasicBlock *
MBB : OrderToBB) {
3817 VTracker = &vlocs[CurBB];
3818 VTracker->MBB =
MBB;
3819 MTracker->loadFromArray(MInLocs[*
MBB], CurBB);
3821 for (
auto &
MI : *
MBB) {
3822 process(
MI, &MOutLocs, &MInLocs);
3840 unsigned VarAssignCount = 0;
3841 for (MachineBasicBlock *
MBB : OrderToBB) {
3844 for (
auto &idx : VTracker->Vars) {
3846 const DILocation *ScopeLoc = VTracker->Scopes[
VarID];
3847 assert(ScopeLoc !=
nullptr);
3848 auto *
Scope = LS.findLexicalScope(ScopeLoc);
3851 assert(Scope !=
nullptr);
3854 ScopeToAssignBlocks[
Scope].insert(VTracker->MBB);
3855 ScopeToDILocation[
Scope] = ScopeLoc;
3866 VarAssignCount > InputDbgValLimit) {
3867 LLVM_DEBUG(
dbgs() <<
"Disabling InstrRefBasedLDV: " << MF.getName()
3870 <<
" variable assignments, exceeding limits.\n");
3875 Changed = depthFirstVLocAndEmit(
3876 MaxNumBlocks, ScopeToDILocation, ScopeToVars, ScopeToAssignBlocks,
3877 SavedLiveIns, MOutLocs, MInLocs, vlocs, MF, ShouldEmitDebugEntryValues);
3886 ArtificialBlocks.clear();
3890 DebugInstrNumToInstr.clear();
3891 DebugPHINumToValue.clear();
3892 OverlapFragments.clear();
3893 SeenFragments.clear();
3894 SeenDbgPHIs.clear();
3920 LDVSSABlock *ParentBlock;
3921 BlockValueNum PHIValNum;
3922 LDVSSAPhi(BlockValueNum PHIValNum, LDVSSABlock *ParentBlock)
3923 : ParentBlock(ParentBlock), PHIValNum(PHIValNum) {}
3925 LDVSSABlock *
getParent() {
return ParentBlock; }
3930class LDVSSABlockIterator {
3933 LDVSSAUpdater &Updater;
3936 LDVSSAUpdater &Updater)
3937 : PredIt(PredIt), Updater(Updater) {}
3939 bool operator!=(
const LDVSSABlockIterator &OtherIt)
const {
3940 return OtherIt.PredIt != PredIt;
3943 LDVSSABlockIterator &operator++() {
3956 MachineBasicBlock &BB;
3957 LDVSSAUpdater &Updater;
3958 using PHIListT = SmallVector<LDVSSAPhi, 1>;
3962 LDVSSABlock(MachineBasicBlock &BB, LDVSSAUpdater &Updater)
3963 : BB(BB), Updater(Updater) {}
3966 return LDVSSABlockIterator(BB.
succ_begin(), Updater);
3970 return LDVSSABlockIterator(BB.
succ_end(), Updater);
3974 LDVSSAPhi *newPHI(BlockValueNum
Value) {
3975 PHIList.emplace_back(
Value,
this);
3976 return &PHIList.back();
3980 PHIListT &phis() {
return PHIList; }
3986class LDVSSAUpdater {
3989 DenseMap<BlockValueNum, LDVSSAPhi *> PHIs;
3992 DenseMap<MachineBasicBlock *, BlockValueNum> PoisonMap;
3994 DenseMap<MachineBasicBlock *, LDVSSABlock *> BlockMap;
3998 const FuncValueTable &MLiveIns;
4000 LDVSSAUpdater(LocIdx L,
const FuncValueTable &MLiveIns)
4001 : Loc(
L), MLiveIns(MLiveIns) {}
4004 for (
auto &
Block : BlockMap)
4005 delete Block.second;
4012 ~LDVSSAUpdater() { reset(); }
4016 LDVSSABlock *getSSALDVBlock(MachineBasicBlock *BB) {
4017 auto [It,
Inserted] = BlockMap.try_emplace(BB);
4019 It->second =
new LDVSSABlock(*BB, *
this);
4025 BlockValueNum
getValue(LDVSSABlock *LDVBB) {
4026 return MLiveIns[LDVBB->BB][Loc.
asU64()].asU64();
4030LDVSSABlock *LDVSSABlockIterator::operator*() {
4031 return Updater.getSSALDVBlock(*PredIt);
4037 out <<
"SSALDVPHI " <<
PHI.PHIValNum;
4072 : PHI(
P), Idx(PHI->IncomingValues.
size()) {}
4097 Preds->
push_back(BB->Updater.getSSALDVBlock(Pred));
4103 static BlockValueNum
GetPoisonVal(LDVSSABlock *BB, LDVSSAUpdater *Updater) {
4108 Updater->PoisonMap[&BB->BB] = Num;
4118 LDVSSAUpdater *Updater) {
4119 BlockValueNum PHIValNum = Updater->getValue(BB);
4120 LDVSSAPhi *
PHI = BB->newPHI(PHIValNum);
4121 Updater->PHIs[PHIValNum] =
PHI;
4128 PHI->IncomingValues.push_back(std::make_pair(Pred, Val));
4133 static LDVSSAPhi *
ValueIsPHI(BlockValueNum Val, LDVSSAUpdater *Updater) {
4134 return Updater->PHIs.lookup(Val);
4141 if (
PHI &&
PHI->IncomingValues.size() == 0)
4153std::optional<ValueIDNum> InstrRefBasedLDV::resolveDbgPHIs(
4158 auto SeenDbgPHIIt = SeenDbgPHIs.find(std::make_pair(&Here, InstrNum));
4159 if (SeenDbgPHIIt != SeenDbgPHIs.end())
4160 return SeenDbgPHIIt->second;
4162 std::optional<ValueIDNum>
Result =
4163 resolveDbgPHIsImpl(MF, MLiveOuts, MLiveIns, Here, InstrNum);
4164 SeenDbgPHIs.insert({std::make_pair(&Here, InstrNum),
Result});
4168std::optional<ValueIDNum> InstrRefBasedLDV::resolveDbgPHIsImpl(
4173 auto RangePair = std::equal_range(DebugPHINumToValue.begin(),
4174 DebugPHINumToValue.end(), InstrNum);
4175 auto LowerIt = RangePair.first;
4176 auto UpperIt = RangePair.second;
4179 if (LowerIt == UpperIt)
4180 return std::nullopt;
4186 auto DBGPHIRange =
make_range(LowerIt, UpperIt);
4187 for (
const DebugPHIRecord &DBG_PHI : DBGPHIRange)
4188 if (!DBG_PHI.ValueRead)
4189 return std::nullopt;
4192 if (std::distance(LowerIt, UpperIt) == 1)
4193 return *LowerIt->ValueRead;
4199 LocIdx Loc = *LowerIt->ReadLoc;
4208 LDVSSAUpdater Updater(Loc, MLiveIns);
4210 DenseMap<LDVSSABlock *, BlockValueNum> AvailableValues;
4216 for (
const auto &DBG_PHI : DBGPHIRange) {
4217 LDVSSABlock *
Block = Updater.getSSALDVBlock(DBG_PHI.MBB);
4218 const ValueIDNum &Num = *DBG_PHI.ValueRead;
4222 LDVSSABlock *HereBlock = Updater.getSSALDVBlock(Here.
getParent());
4223 const auto &AvailIt = AvailableValues.
find(HereBlock);
4224 if (AvailIt != AvailableValues.
end()) {
4232 SSAUpdaterImpl<LDVSSAUpdater> Impl(&Updater, &AvailableValues, &CreatedPHIs);
4233 BlockValueNum ResultInt = Impl.GetValue(Updater.getSSALDVBlock(Here.
getParent()));
4247 DenseMap<LDVSSABlock *, ValueIDNum> ValidatedValues;
4250 for (
const auto &DBG_PHI : DBGPHIRange) {
4251 LDVSSABlock *
Block = Updater.getSSALDVBlock(DBG_PHI.MBB);
4252 const ValueIDNum &Num = *DBG_PHI.ValueRead;
4253 ValidatedValues.
insert(std::make_pair(
Block, Num));
4259 llvm::sort(SortedPHIs, [&](LDVSSAPhi *
A, LDVSSAPhi *
B) {
4260 return BBToOrder[&
A->getParent()->BB] < BBToOrder[&
B->getParent()->BB];
4263 for (
auto &
PHI : SortedPHIs) {
4264 ValueIDNum ThisBlockValueNum = MLiveIns[
PHI->ParentBlock->BB][Loc.
asU64()];
4267 for (
auto &PHIIt :
PHI->IncomingValues) {
4269 if (Updater.PoisonMap.contains(&PHIIt.first->BB))
4270 return std::nullopt;
4272 ValueIDNum ValueToCheck;
4273 const ValueTable &BlockLiveOuts = MLiveOuts[PHIIt.first->BB];
4275 auto VVal = ValidatedValues.
find(PHIIt.first);
4276 if (VVal == ValidatedValues.
end()) {
4281 ValueToCheck = ThisBlockValueNum;
4285 ValueToCheck = VVal->second;
4288 if (BlockLiveOuts[Loc.
asU64()] != ValueToCheck)
4289 return std::nullopt;
4293 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 > StackSlotIdxesLimit("livedebugvalues-max-stack-slot-idxes", cl::Hidden, cl::desc("livedebugvalues-max-stack-slot-idxes"), cl::init(128))
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
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 > insert(const std::pair< KeyT, ValueT > &KV)
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
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.
initializer< Ty > init(const Ty &Val)
Scope
Defines the scope in which this symbol should be visible: Default – Visible in the public interface o...
EnumSet< Property > Properties
NodeAddr< DefNode * > Def
This is an optimization pass for GlobalISel generic memory operations.
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.
RelativeUniformCounterPtr Values
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.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
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.
MCRegisterClass TargetRegisterClass
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.