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);
1019 for (
unsigned Idx = 0; Idx <
getDbgOpIDs().size(); ++Idx) {
1046 Register SP =
TLI.getStackPointerRegisterToSaveRestore();
1068 for (
unsigned int I = 1;
I <
TRI.getNumSubRegIndices(); ++
I) {
1069 unsigned Size =
TRI.getSubRegIdxSize(
I);
1070 unsigned Offs =
TRI.getSubRegIdxOffset(
I);
1075 if (
Size > 60000 || Offs > 60000)
1083 unsigned Size =
TRI.getRegSizeInBits(*RC);
1111 if (MaskPair.first->clobbersPhysReg(
ID)) {
1113 ValNum = {
CurBB, MaskPair.second, NewIdx};
1134 Masks.push_back(std::make_pair(MO, InstID));
1140 if (SpillID.
id() == 0) {
1144 return std::nullopt;
1149 for (
unsigned StackIdx = 0; StackIdx <
NumSlotIdxes; ++StackIdx) {
1170 return Twine(
"slot ")
1175 return TRI.getRegAsmName(
ID).str();
1187 std::string MLocName =
LocIdxToName(Location.Value.getLoc());
1188 std::string DefName = Location.Value.asString(MLocName);
1196 dbgs() <<
"Idx " << Location.Idx.asU64() <<
" " << foo <<
"\n";
1208 ?
TII.get(TargetOpcode::DBG_VALUE_LIST)
1209 :
TII.get(TargetOpcode::DBG_VALUE);
1211#ifdef EXPENSIVE_CHECKS
1214 return Op.IsConst || !
Op.Loc.isIllegal();
1216 "Did not expect illegal ops in DbgOps.");
1219 "Expected to have either one DbgOp per MI LocationOp, or none.");
1232 auto EmitUndef = [&]() {
1244 bool Indirect = Properties.
Indirect;
1266 unsigned short Offset = StackIdx.second;
1277 unsigned Base = Spill.SpillBase;
1293 bool UseDerefSize =
false;
1295 unsigned DerefSizeInBytes = ValueSizeInBits / 8;
1297 unsigned VariableSizeInBits = Fragment->SizeInBits;
1298 if (VariableSizeInBits != ValueSizeInBits || Expr->
isComplex())
1299 UseDerefSize =
true;
1301 if (*
Size != ValueSizeInBits) {
1302 UseDerefSize =
true;
1324 if (ValueSizeInBits >
MF.getTarget().getPointerSizeInBits(0))
1325 UseDerefSize =
false;
1328 TRI.getOffsetOpcodes(Spill.SpillOffset, OffsetOps);
1329 bool StackValue =
false;
1336 OffsetOps.
push_back(dwarf::DW_OP_deref);
1343 OffsetOps.
push_back(dwarf::DW_OP_deref_size);
1349 OffsetOps.
push_back(dwarf::DW_OP_deref);
1377 unsigned Reg = MTracker->LocIdxToLocID[L];
1382 if (CalleeSavedRegs.test((*RAI).id()))
1396std::optional<SpillLocationNo>
1397InstrRefBasedLDV::extractSpillBaseRegAndOffset(
const MachineInstr &
MI) {
1399 "Spill instruction does not have exactly one memory operand?");
1400 auto MMOI =
MI.memoperands_begin();
1403 "Inconsistent memory operand in spill instruction");
1411std::optional<LocIdx>
1413 std::optional<SpillLocationNo>
SpillLoc = extractSpillBaseRegAndOffset(
MI);
1415 return std::nullopt;
1421 auto *MemOperand = *
MI.memoperands_begin();
1423 assert(SizeInBits.
hasValue() &&
"Expected to find a valid size!");
1426 auto IdxIt = MTracker->StackSlotIdxes.find({SizeInBits.
getValue(), 0});
1427 if (IdxIt == MTracker->StackSlotIdxes.end())
1430 return std::nullopt;
1432 unsigned SpillID = MTracker->getSpillIDWithIdx(*
SpillLoc, IdxIt->second);
1433 return MTracker->getSpillMLoc(SpillID);
1438bool InstrRefBasedLDV::transferDebugValue(
const MachineInstr &
MI) {
1439 if (!
MI.isDebugValue())
1442 assert(
MI.getDebugVariable()->isValidLocationForIntrinsic(
MI.getDebugLoc()) &&
1443 "Expected inlined-at fields to agree");
1448 if (Scope ==
nullptr)
1454 if (MO.isReg() && MO.getReg() != 0)
1455 (void)MTracker->
readReg(MO.getReg());
1464 if (!
MI.isUndefDebugValue()) {
1470 }
else if (MO.isImm() || MO.isFPImm() || MO.isCImm()) {
1477 VTracker->defVar(
MI, DbgValueProperties(
MI), DebugOps);
1483 TTracker->redefVar(
MI);
1487std::optional<ValueIDNum> InstrRefBasedLDV::getValueForInstrRef(
1494 const MachineFunction &MF = *
MI.getParent()->getParent();
1498 MachineFunction::DebugSubstitution({InstNo, OpNo}, {0, 0}, 0);
1500 SmallVector<unsigned, 4> SeenSubregs;
1503 LowerBoundIt->Src == SoughtSub.Src) {
1504 std::tie(InstNo, OpNo) = LowerBoundIt->Dest;
1505 SoughtSub.Src = LowerBoundIt->Dest;
1506 if (
unsigned Subreg = LowerBoundIt->Subreg)
1507 SeenSubregs.push_back(Subreg);
1513 std::optional<ValueIDNum> NewID;
1517 auto InstrIt = DebugInstrNumToInstr.find(InstNo);
1519 if (InstrIt != DebugInstrNumToInstr.end()) {
1520 const MachineInstr &TargetInstr = *InstrIt->second.first;
1529 NewID = ValueIDNum(BlockNo, InstrIt->second.second, *L);
1537 const MachineOperand &MO = TargetInstr.
getOperand(OpNo);
1540 unsigned LocID = MTracker->getLocID(MO.
getReg());
1541 LocIdx
L = MTracker->LocIDToLocIdx[LocID];
1542 NewID = ValueIDNum(BlockNo, InstrIt->second.second, L);
1548 {
dbgs() <<
"Seen instruction reference to illegal operand\n"; });
1552 }
else if (PHIIt != DebugPHINumToValue.end() && PHIIt->InstrNum == InstNo) {
1555 assert(MLiveOuts && MLiveIns);
1556 NewID = resolveDbgPHIs(*
MI.getParent()->getParent(), *MLiveOuts, *MLiveIns,
1569 if (NewID && !SeenSubregs.empty()) {
1577 for (
unsigned Subreg :
reverse(SeenSubregs)) {
1578 unsigned ThisSize = TRI->getSubRegIdxSize(Subreg);
1579 unsigned ThisOffset = TRI->getSubRegIdxOffset(Subreg);
1581 Size = (
Size == 0) ? ThisSize : std::min(
Size, ThisSize);
1588 LocIdx
L = NewID->getLoc();
1589 if (NewID && !MTracker->isSpill(L)) {
1593 const TargetRegisterClass *TRC =
nullptr;
1594 for (
const auto *TRCI : TRI->regclasses())
1595 if (TRCI->contains(
Reg))
1597 assert(TRC &&
"Couldn't find target register class?");
1601 unsigned MainRegSize = TRI->getRegSizeInBits(*TRC);
1605 for (MCRegister SR : TRI->subregs(
Reg)) {
1606 unsigned Subreg = TRI->getSubRegIndex(
Reg, SR);
1607 unsigned SubregSize = TRI->getSubRegIdxSize(Subreg);
1608 unsigned SubregOffset = TRI->getSubRegIdxOffset(Subreg);
1609 if (SubregSize ==
Size && SubregOffset ==
Offset) {
1617 NewID = std::nullopt;
1622 MTracker->lookupOrTrackRegister(MTracker->getLocID(NewReg));
1623 NewID = ValueIDNum(NewID->getBlock(), NewID->getInst(), NewLoc);
1628 NewID = std::nullopt;
1638 if (!
MI.isDebugRef())
1643 if (!VTracker && !TTracker)
1646 const DILocalVariable *Var =
MI.getDebugVariable();
1647 const DIExpression *Expr =
MI.getDebugExpression();
1648 const DILocation *
DebugLoc =
MI.getDebugLoc();
1649 const DILocation *InlinedAt =
DebugLoc->getInlinedAt();
1651 "Expected inlined-at fields to agree");
1653 DebugVariable
V(Var, Expr, InlinedAt);
1655 auto *
Scope = LS.findLexicalScope(
MI.getDebugLoc().get());
1656 if (Scope ==
nullptr)
1660 for (
const MachineOperand &MO :
MI.debug_operands()) {
1662 assert(!MO.
isReg() &&
"DBG_INSTR_REF should not contain registers");
1663 DbgOpID ConstOpID = DbgOpStore.insert(DbgOp(MO));
1673 std::optional<ValueIDNum> NewID =
1674 getValueForInstrRef(InstNo, OpNo,
MI, MLiveOuts, MLiveIns);
1678 DbgOpIDs.
push_back(DbgOpStore.insert(*NewID));
1689 DbgValueProperties Properties(Expr,
false,
true);
1691 VTracker->defVar(
MI, Properties, DbgOpIDs);
1700 for (DbgOpID OpID : DbgOpIDs) {
1701 DbgOps.
push_back(DbgOpStore.find(OpID));
1706 SmallDenseMap<ValueIDNum, TransferTracker::LocationAndQuality> FoundLocs;
1710 for (
const DbgOp &
Op : DbgOps) {
1716 for (
auto Location : MTracker->locations()) {
1718 ValueIDNum
ID = MTracker->readMLoc(CurL);
1719 auto ValueToFindIt =
find(ValuesToFind,
ID);
1720 if (ValueToFindIt == ValuesToFind.
end())
1722 auto &Previous = FoundLocs.
find(
ID)->second;
1725 std::optional<TransferTracker::LocationQuality> ReplacementQuality =
1726 TTracker->getLocQualityIfBetter(CurL, Previous.getQuality());
1727 if (ReplacementQuality) {
1728 Previous = TransferTracker::LocationAndQuality(CurL, *ReplacementQuality);
1729 if (Previous.isBest()) {
1730 ValuesToFind.
erase(ValueToFindIt);
1731 if (ValuesToFind.
empty())
1738 for (
const DbgOp &DbgOp : DbgOps) {
1739 if (DbgOp.IsConst) {
1743 LocIdx FoundLoc = FoundLocs.
find(DbgOp.ID)->second.getLoc();
1751 TTracker->redefVar(
MI, Properties, NewLocs);
1755 if (!DbgOps.empty() && NewLocs.
empty()) {
1756 bool IsValidUseBeforeDef =
true;
1757 uint64_t LastUseBeforeDef = 0;
1758 for (
auto ValueLoc : FoundLocs) {
1759 ValueIDNum NewID = ValueLoc.first;
1760 LocIdx FoundLoc = ValueLoc.second.getLoc();
1766 IsValidUseBeforeDef =
false;
1769 LastUseBeforeDef = std::max(LastUseBeforeDef, NewID.
getInst());
1771 if (IsValidUseBeforeDef) {
1773 TTracker->addUseBeforeDef(VID, {
MI.getDebugExpression(),
false,
true},
1774 DbgOps, LastUseBeforeDef);
1782 MachineInstr *DbgMI =
1783 MTracker->emitLoc(NewLocs, V,
MI.getDebugLoc().get(), Properties);
1786 TTracker->PendingDbgValues.push_back(std::make_pair(
ID, DbgMI));
1787 TTracker->flushDbgValues(
MI.getIterator(),
nullptr);
1792 if (!
MI.isDebugPHI())
1796 if (VTracker || TTracker)
1801 const MachineOperand &MO =
MI.getOperand(0);
1802 unsigned InstrNum =
MI.getOperand(1).getImm();
1804 auto EmitBadPHI = [
this, &
MI, InstrNum]() ->
bool {
1809 DebugPHINumToValue.push_back(
1810 {InstrNum,
MI.getParent(), std::nullopt, std::nullopt});
1818 ValueIDNum Num = MTracker->readReg(
Reg);
1819 auto PHIRec = DebugPHIRecord(
1820 {InstrNum,
MI.getParent(), Num,
1821 MTracker->lookupOrTrackRegister(MTracker->getLocID(
Reg))});
1822 DebugPHINumToValue.push_back(PHIRec);
1825 for (MCRegAliasIterator RAI(MO.
getReg(), TRI,
true); RAI.isValid(); ++RAI)
1826 MTracker->lookupOrTrackRegister(MTracker->getLocID(*RAI));
1827 }
else if (MO.
isFI()) {
1833 if (MFI->isDeadObjectIndex(FI))
1834 return EmitBadPHI();
1838 StackOffset Offs = TFI->getFrameIndexReference(*
MI.getMF(), FI,
Base);
1839 SpillLoc SL = {
Base, Offs};
1840 std::optional<SpillLocationNo> SpillNo = MTracker->getOrTrackSpillLoc(SL);
1845 return EmitBadPHI();
1848 assert(
MI.getNumOperands() == 3 &&
"Stack DBG_PHI with no size?");
1849 unsigned slotBitSize =
MI.getOperand(2).getImm();
1851 unsigned SpillID = MTracker->getLocID(*SpillNo, {slotBitSize, 0});
1852 LocIdx SpillLoc = MTracker->getSpillMLoc(SpillID);
1853 ValueIDNum
Result = MTracker->readMLoc(SpillLoc);
1856 auto DbgPHI = DebugPHIRecord({InstrNum,
MI.getParent(),
Result, SpillLoc});
1857 DebugPHINumToValue.push_back(DbgPHI);
1864 {
dbgs() <<
"Seen DBG_PHI with unrecognised operand format\n"; });
1865 return EmitBadPHI();
1874 if (
MI.isImplicitDef()) {
1879 ValueIDNum Num = MTracker->readReg(
MI.getOperand(0).getReg());
1884 }
else if (
MI.isMetaInstruction())
1892 bool CallChangesSP =
false;
1893 if (AdjustsStackInCalls &&
MI.isCall() &&
MI.getOperand(0).isSymbol() &&
1894 !strcmp(
MI.getOperand(0).getSymbolName(), StackProbeSymbolName.data()))
1895 CallChangesSP =
true;
1899 auto IgnoreSPAlias = [
this, &
MI, CallChangesSP](
Register R) ->
bool {
1902 return MI.isCall() && MTracker->SPAliases.count(R);
1908 SmallSet<uint32_t, 32> DeadRegs;
1909 SmallVector<const uint32_t *, 4> RegMasks;
1911 for (
const MachineOperand &MO :
MI.operands()) {
1914 !IgnoreSPAlias(MO.
getReg())) {
1916 for (MCRegAliasIterator RAI(MO.
getReg(), TRI,
true); RAI.isValid(); ++RAI)
1918 DeadRegs.
insert((*RAI).id());
1926 for (uint32_t DeadReg : DeadRegs)
1927 MTracker->defReg(DeadReg, CurBB, CurInst);
1929 for (
const auto *MO : RegMaskPtrs)
1930 MTracker->writeRegMask(MO, CurBB, CurInst);
1934 if (std::optional<SpillLocationNo> SpillNo =
1935 extractSpillBaseRegAndOffset(
MI)) {
1936 for (
unsigned int I = 0;
I < MTracker->NumSlotIdxes; ++
I) {
1937 unsigned SpillID = MTracker->getSpillIDWithIdx(*SpillNo,
I);
1938 LocIdx
L = MTracker->getSpillMLoc(SpillID);
1939 MTracker->setMLoc(L, ValueIDNum(CurBB, CurInst, L));
1952 for (MCRegister DeadReg : DeadRegs) {
1953 LocIdx Loc = MTracker->lookupOrTrackRegister(MTracker->getLocID(DeadReg));
1954 TTracker->clobberMloc(Loc,
MI.getIterator(),
false);
1959 if (!RegMaskPtrs.empty()) {
1960 for (
auto L : MTracker->locations()) {
1962 if (MTracker->isSpill(
L.Idx))
1966 if (IgnoreSPAlias(
Reg))
1969 for (
const auto *MO : RegMaskPtrs)
1971 TTracker->clobberMloc(
L.Idx,
MI.getIterator(),
false);
1977 if (std::optional<SpillLocationNo> SpillNo =
1978 extractSpillBaseRegAndOffset(
MI)) {
1979 for (
unsigned int I = 0;
I < MTracker->NumSlotIdxes; ++
I) {
1980 unsigned SpillID = MTracker->getSpillIDWithIdx(*SpillNo,
I);
1981 LocIdx
L = MTracker->getSpillMLoc(SpillID);
1982 TTracker->clobberMloc(L,
MI.getIterator(),
true);
1988void InstrRefBasedLDV::performCopy(
Register SrcRegNum,
Register DstRegNum) {
1990 for (MCRegAliasIterator RAI(DstRegNum, TRI,
true); RAI.isValid(); ++RAI)
1991 MTracker->defReg(*RAI, CurBB, CurInst);
1993 ValueIDNum SrcValue = MTracker->readReg(SrcRegNum);
1994 MTracker->setReg(DstRegNum, SrcValue);
1997 for (MCSubRegIndexIterator SRI(SrcRegNum, TRI); SRI.isValid(); ++SRI) {
1998 MCRegister SrcSubReg = SRI.getSubReg();
1999 unsigned SubRegIdx = SRI.getSubRegIndex();
2000 MCRegister DstSubReg = TRI->getSubReg(DstRegNum, SubRegIdx);
2010 MTracker->lookupOrTrackRegister(MTracker->getLocID(SrcSubReg));
2012 MTracker->lookupOrTrackRegister(MTracker->getLocID(DstSubReg));
2015 ValueIDNum CpyValue = MTracker->readReg(SrcSubReg);
2017 MTracker->setReg(DstSubReg, CpyValue);
2021std::optional<SpillLocationNo>
2025 if (!
MI.hasOneMemOperand())
2026 return std::nullopt;
2029 auto MMOI =
MI.memoperands_begin();
2030 const PseudoSourceValue *PVal = (*MMOI)->getPseudoValue();
2032 return std::nullopt;
2034 if (!
MI.getSpillSize(TII) && !
MI.getFoldedSpillSize(TII))
2035 return std::nullopt;
2038 return extractSpillBaseRegAndOffset(
MI);
2043 if (!isSpillInstruction(
MI, MF))
2047 Reg = TII->isStoreToStackSlotPostFE(
MI, FI);
2051std::optional<SpillLocationNo>
2054 if (!
MI.hasOneMemOperand())
2055 return std::nullopt;
2059 if (
MI.getRestoreSize(TII)) {
2060 Reg =
MI.getOperand(0).getReg();
2061 return extractSpillBaseRegAndOffset(
MI);
2063 return std::nullopt;
2066bool InstrRefBasedLDV::transferSpillOrRestoreInst(
MachineInstr &
MI) {
2076 if (!TII->isStoreToStackSlotPostFE(
MI, DummyFI) &&
2077 !TII->isLoadFromStackSlotPostFE(
MI, DummyFI))
2080 MachineFunction *MF =
MI.getMF();
2088 if (!TII->isStoreToStackSlotPostFE(
MI, FIDummy) &&
2089 !TII->isLoadFromStackSlotPostFE(
MI, FIDummy))
2095 if (std::optional<SpillLocationNo> Loc = isSpillInstruction(
MI, MF)) {
2098 for (
unsigned SlotIdx = 0; SlotIdx < MTracker->NumSlotIdxes; ++SlotIdx) {
2099 unsigned SpillID = MTracker->getSpillIDWithIdx(*Loc, SlotIdx);
2100 std::optional<LocIdx> MLoc = MTracker->getSpillMLoc(SpillID);
2108 ValueIDNum
Def(CurBB, CurInst, *MLoc);
2109 MTracker->setMLoc(*MLoc, Def);
2111 TTracker->clobberMloc(*MLoc,
MI.getIterator());
2116 if (isLocationSpill(
MI, MF,
Reg)) {
2119 SpillLocationNo Loc = *extractSpillBaseRegAndOffset(
MI);
2121 auto DoTransfer = [&](
Register SrcReg,
unsigned SpillID) {
2122 auto ReadValue = MTracker->readReg(SrcReg);
2123 LocIdx DstLoc = MTracker->getSpillMLoc(SpillID);
2124 MTracker->setMLoc(DstLoc, ReadValue);
2127 LocIdx SrcLoc = MTracker->getRegMLoc(SrcReg);
2128 TTracker->transferMlocs(SrcLoc, DstLoc,
MI.getIterator());
2135 (void)MTracker->lookupOrTrackRegister(MTracker->getLocID(SR));
2136 unsigned SubregIdx = TRI->getSubRegIndex(
Reg, SR);
2137 unsigned SpillID = MTracker->getLocID(Loc, SubregIdx);
2138 DoTransfer(SR, SpillID);
2142 unsigned Size = TRI->getRegSizeInBits(
Reg, *MRI);
2143 unsigned SpillID = MTracker->getLocID(Loc, {
Size, 0});
2144 DoTransfer(
Reg, SpillID);
2146 std::optional<SpillLocationNo> Loc = isRestoreInstruction(
MI, MF,
Reg);
2157 for (MCRegAliasIterator RAI(
Reg, TRI,
true); RAI.isValid(); ++RAI)
2158 MTracker->defReg(*RAI, CurBB, CurInst);
2162 auto DoTransfer = [&](
Register DestReg,
unsigned SpillID) {
2163 LocIdx SrcIdx = MTracker->getSpillMLoc(SpillID);
2164 auto ReadValue = MTracker->readMLoc(SrcIdx);
2165 MTracker->setReg(DestReg, ReadValue);
2169 unsigned Subreg = TRI->getSubRegIndex(
Reg, SR);
2170 unsigned SpillID = MTracker->getLocID(*Loc, Subreg);
2171 DoTransfer(SR, SpillID);
2175 unsigned Size = TRI->getRegSizeInBits(
Reg, *MRI);
2176 unsigned SpillID = MTracker->getLocID(*Loc, {
Size, 0});
2177 DoTransfer(
Reg, SpillID);
2183 auto DestSrc = TII->isCopyLikeInstr(
MI);
2187 const MachineOperand *DestRegOp = DestSrc->Destination;
2188 const MachineOperand *SrcRegOp = DestSrc->Source;
2194 if (SrcReg == DestReg)
2216 DenseMap<LocIdx, ValueIDNum> ClobberedLocs;
2218 for (MCRegAliasIterator RAI(DestReg, TRI,
true); RAI.isValid(); ++RAI) {
2219 LocIdx ClobberedLoc = MTracker->getRegMLoc(*RAI);
2220 auto MLocIt = TTracker->ActiveMLocs.find(ClobberedLoc);
2223 if (MLocIt == TTracker->ActiveMLocs.end() || MLocIt->second.empty())
2225 ValueIDNum
Value = MTracker->readReg(*RAI);
2226 ClobberedLocs[ClobberedLoc] =
Value;
2231 InstrRefBasedLDV::performCopy(SrcReg, DestReg);
2237 for (
auto LocVal : ClobberedLocs) {
2238 TTracker->clobberMloc(LocVal.first, LocVal.second,
MI.getIterator(),
false);
2246 TTracker->transferMlocs(MTracker->getRegMLoc(SrcReg),
2247 MTracker->getRegMLoc(DestReg),
MI.getIterator());
2251 MTracker->defReg(SrcReg, CurBB, CurInst);
2264 DebugVariable MIVar(
MI.getDebugVariable(),
MI.getDebugExpression(),
2265 MI.getDebugLoc()->getInlinedAt());
2266 FragmentInfo ThisFragment = MIVar.getFragmentOrDefault();
2271 auto [SeenIt,
Inserted] = SeenFragments.try_emplace(MIVar.getVariable());
2273 SeenIt->second.insert(ThisFragment);
2275 OverlapFragments.insert({{MIVar.getVariable(), ThisFragment}, {}});
2282 OverlapFragments.insert({{MIVar.getVariable(), ThisFragment}, {}});
2283 if (!IsInOLapMap.second)
2286 auto &ThisFragmentsOverlaps = IsInOLapMap.first->second;
2287 auto &AllSeenFragments = SeenIt->second;
2292 for (
const auto &ASeenFragment : AllSeenFragments) {
2296 ThisFragmentsOverlaps.push_back(ASeenFragment);
2299 auto ASeenFragmentsOverlaps =
2300 OverlapFragments.find({MIVar.getVariable(), ASeenFragment});
2301 assert(ASeenFragmentsOverlaps != OverlapFragments.end() &&
2302 "Previously seen var fragment has no vector of overlaps");
2303 ASeenFragmentsOverlaps->second.push_back(ThisFragment);
2307 AllSeenFragments.insert(ThisFragment);
2316 if (transferDebugValue(
MI))
2318 if (transferDebugInstrRef(
MI, MLiveOuts, MLiveIns))
2320 if (transferDebugPHI(
MI))
2322 if (transferRegisterCopy(
MI))
2324 if (transferSpillOrRestoreInst(
MI))
2326 transferRegisterDef(
MI);
2329void InstrRefBasedLDV::produceMLocTransferFunction(
2345 for (
auto &BV : BlockMasks)
2346 BV.resize(TRI->getNumRegs(),
true);
2349 for (
auto &
MBB : MF) {
2358 MTracker->setMPhis(CurBB);
2361 for (
auto &
MI :
MBB) {
2364 process(
MI,
nullptr,
nullptr);
2367 if (
MI.isDebugValueLike())
2368 accumulateFragmentMap(
MI);
2372 if (uint64_t InstrNo =
MI.peekDebugInstrNum()) {
2373 auto InstrAndPos = std::make_pair(&
MI, CurInst);
2375 DebugInstrNumToInstr.insert(std::make_pair(InstrNo, InstrAndPos));
2378 assert(InsertResult.second);
2389 for (
auto Location : MTracker->locations()) {
2392 if (
P.isPHI() &&
P.getLoc() == Idx.
asU64())
2396 auto &TransferMap = MLocTransfer[CurBB];
2397 auto Result = TransferMap.insert(std::make_pair(Idx.
asU64(),
P));
2404 for (
auto &
P : MTracker->Masks) {
2405 BlockMasks[CurBB].clearBitsNotInMask(
P.first->getRegMask(), BVWords);
2410 BitVector UsedRegs(TRI->getNumRegs());
2411 for (
auto Location : MTracker->locations()) {
2412 unsigned ID = MTracker->LocIdxToLocID[
Location.Idx];
2414 if (
ID >= TRI->getNumRegs() || MTracker->SPAliases.count(
ID))
2423 BitVector &BV = BlockMasks[
I];
2429 for (
unsigned Bit : BV.
set_bits()) {
2430 unsigned ID = MTracker->getLocID(Bit);
2431 LocIdx Idx = MTracker->LocIDToLocIdx[
ID];
2432 auto &TransferMap = MLocTransfer[
I];
2439 ValueIDNum NotGeneratedNum = ValueIDNum(
I, 1, Idx);
2441 TransferMap.insert(std::make_pair(Idx.
asU64(), NotGeneratedNum));
2443 ValueIDNum &ValueID =
Result.first->second;
2446 ValueID = NotGeneratedNum;
2452bool InstrRefBasedLDV::mlocJoin(
2466 auto Cmp = [&](
const MachineBasicBlock *
A,
const MachineBasicBlock *
B) {
2467 return BBToOrder.find(
A)->second < BBToOrder.find(
B)->second;
2472 if (BlockOrders.size() == 0) {
2477 <<
" from entry which may lead out of "
2478 "bound access to VarLocs\n");
2484 for (
auto Location : MTracker->locations()) {
2489 ValueIDNum FirstVal = OutLocs[*BlockOrders[0]][Idx.
asU64()];
2494 if (InLocs[Idx.
asU64()] != FirstVal) {
2495 InLocs[Idx.
asU64()] = FirstVal;
2503 bool Disagree =
false;
2504 for (
unsigned int I = 1;
I < BlockOrders.size(); ++
I) {
2505 const MachineBasicBlock *PredMBB = BlockOrders[
I];
2506 const ValueIDNum &PredLiveOut = OutLocs[*PredMBB][Idx.
asU64()];
2509 if (FirstVal == PredLiveOut)
2513 if (PredLiveOut == ValueIDNum(
MBB.
getNumber(), 0, Idx))
2522 InLocs[Idx.
asU64()] = FirstVal;
2531void InstrRefBasedLDV::findStackIndexInterference(
2544 auto It = MTracker->StackSlotIdxes.find({8, 0});
2545 assert(It != MTracker->StackSlotIdxes.end());
2549 for (
auto &Pair : MTracker->StackSlotIdxes) {
2551 if (!Pair.first.second)
2557void InstrRefBasedLDV::placeMLocPHIs(
2560 SmallVector<unsigned, 4> StackUnits;
2561 findStackIndexInterference(StackUnits);
2570 SmallSet<Register, 32> RegUnitsToPHIUp;
2571 SmallSet<LocIdx, 32> NormalLocsToPHI;
2572 SmallSet<SpillLocationNo, 32> StackSlots;
2573 for (
auto Location : MTracker->locations()) {
2575 if (MTracker->isSpill(L)) {
2576 StackSlots.
insert(MTracker->locIDToSpill(MTracker->LocIdxToLocID[L]));
2581 SmallSet<Register, 8> FoundRegUnits;
2582 bool AnyIllegal =
false;
2583 for (MCRegUnit Unit : TRI->regunits(
R.asMCReg())) {
2584 for (MCRegUnitRootIterator URoot(Unit, TRI); URoot.isValid(); ++URoot) {
2585 if (!MTracker->isRegisterTracked(*URoot)) {
2591 FoundRegUnits.
insert(*URoot);
2597 NormalLocsToPHI.
insert(L);
2606 SmallVector<MachineBasicBlock *, 32> PHIBlocks;
2607 auto CollectPHIsForLoc = [&](LocIdx
L) {
2609 SmallPtrSet<MachineBasicBlock *, 32> DefBlocks;
2610 for (MachineBasicBlock *
MBB : OrderToBB) {
2611 const auto &TransferFunc = MLocTransfer[
MBB->
getNumber()];
2612 if (TransferFunc.contains(L))
2619 if (!DefBlocks.
empty())
2625 BlockPHIPlacement(AllBlocks, DefBlocks, PHIBlocks);
2628 auto InstallPHIsAtLoc = [&PHIBlocks, &MInLocs](LocIdx
L) {
2629 for (
const MachineBasicBlock *
MBB : PHIBlocks)
2634 for (LocIdx L : NormalLocsToPHI) {
2635 CollectPHIsForLoc(L);
2637 InstallPHIsAtLoc(L);
2642 for (SpillLocationNo Slot : StackSlots) {
2643 for (
unsigned Idx : StackUnits) {
2644 unsigned SpillID = MTracker->getSpillIDWithIdx(Slot, Idx);
2645 LocIdx
L = MTracker->getSpillMLoc(SpillID);
2646 CollectPHIsForLoc(L);
2647 InstallPHIsAtLoc(L);
2651 std::tie(
Size,
Offset) = MTracker->StackIdxesToPos[Idx];
2652 for (
auto &Pair : MTracker->StackSlotIdxes) {
2653 unsigned ThisSize, ThisOffset;
2654 std::tie(ThisSize, ThisOffset) = Pair.first;
2658 unsigned ThisID = MTracker->getSpillIDWithIdx(Slot, Pair.second);
2659 LocIdx ThisL = MTracker->getSpillMLoc(ThisID);
2660 InstallPHIsAtLoc(ThisL);
2666 for (
Register R : RegUnitsToPHIUp) {
2667 LocIdx
L = MTracker->lookupOrTrackRegister(MTracker->getLocID(R));
2668 CollectPHIsForLoc(L);
2671 InstallPHIsAtLoc(L);
2674 for (MCRegAliasIterator RAI(R, TRI,
true); RAI.isValid(); ++RAI) {
2677 if (!MTracker->isRegisterTracked(*RAI))
2681 MTracker->lookupOrTrackRegister(MTracker->getLocID(*RAI));
2682 InstallPHIsAtLoc(AliasLoc);
2687void InstrRefBasedLDV::buildMLocValueMap(
2690 std::priority_queue<unsigned int, std::vector<unsigned int>,
2691 std::greater<unsigned int>>
2697 SmallPtrSet<MachineBasicBlock *, 16> OnPending, OnWorklist;
2701 SmallPtrSet<MachineBasicBlock *, 32> AllBlocks;
2702 for (
unsigned int I = 0;
I < BBToOrder.size(); ++
I) {
2704 OnWorklist.
insert(OrderToBB[
I]);
2705 AllBlocks.
insert(OrderToBB[
I]);
2709 for (
auto Location : MTracker->locations())
2718 placeMLocPHIs(MF, AllBlocks, MInLocs, MLocTransfer);
2728 SmallPtrSet<const MachineBasicBlock *, 16> Visited;
2729 while (!Worklist.empty() || !Pending.empty()) {
2733 while (!Worklist.empty()) {
2734 MachineBasicBlock *
MBB = OrderToBB[Worklist.top()];
2740 InLocsChanged = mlocJoin(*
MBB, Visited, MOutLocs, MInLocs[*
MBB]);
2741 InLocsChanged |= Visited.
insert(
MBB).second;
2749 MTracker->loadFromArray(MInLocs[*
MBB], CurBB);
2754 for (
auto &
P : MLocTransfer[CurBB]) {
2755 if (
P.second.getBlock() == CurBB &&
P.second.isPHI()) {
2757 ValueIDNum NewID = MTracker->readMLoc(
P.second.getLoc());
2758 ToRemap.
push_back(std::make_pair(
P.first, NewID));
2761 assert(
P.second.getBlock() == CurBB);
2762 ToRemap.
push_back(std::make_pair(
P.first,
P.second));
2768 for (
auto &
P : ToRemap)
2769 MTracker->setMLoc(
P.first,
P.second);
2774 bool OLChanged =
false;
2775 for (
auto Location : MTracker->locations()) {
2791 unsigned Order = BBToOrder[s];
2792 if (Order > BBToOrder[
MBB]) {
2794 if (OnWorklist.
insert(s).second)
2795 Worklist.push(Order);
2798 if (OnPending.
insert(s).second)
2799 Pending.push(Order);
2804 Worklist.swap(Pending);
2809 assert(Pending.empty() &&
"Pending should be empty");
2816void InstrRefBasedLDV::BlockPHIPlacement(
2823 IDFCalculatorBase<MachineBasicBlock, false> IDF(*DomTree);
2825 IDF.setLiveInBlocks(AllBlocks);
2826 IDF.setDefiningBlocks(DefBlocks);
2827 IDF.calculate(PHIBlocks);
2830bool InstrRefBasedLDV::pickVPHILoc(
2836 if (BlockOrders.
empty())
2841 SmallDenseSet<unsigned> LocOpsToJoin;
2843 auto FirstValueIt = LiveOuts.find(BlockOrders[0]);
2844 if (FirstValueIt == LiveOuts.end())
2846 const DbgValue &FirstValue = *FirstValueIt->second;
2848 for (
const auto p : BlockOrders) {
2849 auto OutValIt = LiveOuts.find(p);
2850 if (OutValIt == LiveOuts.end())
2853 const DbgValue &OutVal = *OutValIt->second;
2871 LocOpsToJoin.
insert(Idx);
2874 DbgOpID FirstValOp = FirstValue.
getDbgOpID(Idx);
2876 if (FirstValOp != OutValOp) {
2882 LocOpsToJoin.
insert(Idx);
2897 std::optional<ValueIDNum> JoinedOpLoc =
2898 pickOperandPHILoc(Idx,
MBB, LiveOuts, MOutLocs, BlockOrders);
2903 NewDbgOps.
push_back(DbgOpStore.insert(*JoinedOpLoc));
2906 OutValues.
append(NewDbgOps);
2910std::optional<ValueIDNum> InstrRefBasedLDV::pickOperandPHILoc(
2918 unsigned NumLocs = MTracker->getNumLocs();
2920 for (
const auto p : BlockOrders) {
2921 auto OutValIt = LiveOuts.find(p);
2922 assert(OutValIt != LiveOuts.end());
2923 const DbgValue &OutVal = *OutValIt->second;
2924 DbgOpID OutValOpID = OutVal.
getDbgOpID(DbgOpIdx);
2925 DbgOp OutValOp = DbgOpStore.find(OutValOpID);
2936 ValueIDNum ValToLookFor = OutValOp.
ID;
2938 for (
unsigned int I = 0;
I < NumLocs; ++
I) {
2939 if (MOutLocs[*p][
I] == ValToLookFor)
2940 Locs.
back().push_back(LocIdx(
I));
2950 for (
unsigned int I = 0;
I < NumLocs; ++
I) {
2952 if (MOutLocs[*p][
I] == MPHI)
2953 Locs.
back().push_back(LocIdx(
I));
2963 for (
unsigned int I = 1;
I < Locs.
size(); ++
I) {
2964 auto &LocVec = Locs[
I];
2966 std::set_intersection(CandidateLocs.
begin(), CandidateLocs.
end(),
2967 LocVec.begin(), LocVec.end(), std::inserter(NewCandidates, NewCandidates.
begin()));
2968 CandidateLocs = std::move(NewCandidates);
2970 if (CandidateLocs.
empty())
2971 return std::nullopt;
2976 LocIdx
L = *CandidateLocs.
begin();
2983bool InstrRefBasedLDV::vlocJoin(
2993 auto Cmp = [&](MachineBasicBlock *
A, MachineBasicBlock *
B) {
2994 return BBToOrder[
A] < BBToOrder[
B];
2999 unsigned CurBlockRPONum = BBToOrder[&
MBB];
3005 int BackEdgesStart = 0;
3006 for (
auto *p : BlockOrders) {
3009 if (!BlocksToExplore.
contains(p)) {
3015 DbgValue &OutLoc = *VLOCOutLocs.find(p)->second;
3019 unsigned ThisBBRPONum = BBToOrder[
p];
3020 if (ThisBBRPONum < CurBlockRPONum)
3023 Values.
push_back(std::make_pair(p, &OutLoc));
3029 if (Bail || Values.
size() == 0)
3035 const DbgValue &FirstVal = *Values[0].second;
3050 for (
const auto &V : Values) {
3051 if (!
V.second->Properties.isJoinable(FirstVal.
Properties))
3055 if (!
V.second->hasJoinableLocOps(FirstVal))
3060 bool Disagree =
false;
3061 for (
auto &V : Values) {
3062 if (*
V.second == FirstVal)
3068 if (
V.second->hasIdenticalValidLocOps(FirstVal))
3075 std::distance(Values.begin(), &V) >= BackEdgesStart)
3097void InstrRefBasedLDV::getBlocksForScope(
3102 LS.getMachineBasicBlocks(DILoc, BlocksToExplore);
3110 DenseSet<const MachineBasicBlock *> ToAdd;
3117 for (
const auto *
MBB : BlocksToExplore) {
3127 if (BlocksToExplore.count(succ))
3129 if (!ArtificialBlocks.count(succ))
3132 DFS.push_back({succ, succ->succ_begin()});
3136 while (!DFS.empty()) {
3137 const MachineBasicBlock *CurBB = DFS.back().first;
3140 if (CurSucc == CurBB->succ_end()) {
3147 if (!ToAdd.
count(*CurSucc) && ArtificialBlocks.count(*CurSucc)) {
3149 DFS.push_back({*CurSucc, (*CurSucc)->succ_begin()});
3157 BlocksToExplore.insert_range(ToAdd);
3160void InstrRefBasedLDV::buildVLocValueMap(
3170 std::priority_queue<unsigned int, std::vector<unsigned int>,
3171 std::greater<unsigned int>>
3173 SmallPtrSet<MachineBasicBlock *, 16> OnWorklist, OnPending;
3176 SmallPtrSet<const MachineBasicBlock *, 8> BlocksToExplore;
3180 SmallVector<unsigned, 32> BlockOrderNums;
3182 getBlocksForScope(DILoc, BlocksToExplore, AssignBlocks);
3188 if (BlocksToExplore.
size() == 1)
3194 SmallPtrSet<MachineBasicBlock *, 8> MutBlocksToExplore;
3195 for (
const auto *
MBB : BlocksToExplore)
3196 MutBlocksToExplore.
insert(
const_cast<MachineBasicBlock *
>(
MBB));
3201 for (
const auto *
MBB : BlocksToExplore)
3205 for (
unsigned int I : BlockOrderNums)
3207 BlockOrderNums.clear();
3208 unsigned NumBlocks = BlockOrders.
size();
3217 DbgValueProperties EmptyProperties(EmptyExpr,
false,
false);
3218 for (
unsigned int I = 0;
I < NumBlocks; ++
I) {
3227 LiveOutIdx.reserve(NumBlocks);
3228 LiveInIdx.reserve(NumBlocks);
3229 for (
unsigned I = 0;
I < NumBlocks; ++
I) {
3230 LiveOutIdx[BlockOrders[
I]] = &LiveOuts[
I];
3231 LiveInIdx[BlockOrders[
I]] = &LiveIns[
I];
3241 for (
unsigned int I = 0;
I < NumBlocks; ++
I) {
3243 LiveIns[
I] = EmptyDbgValue;
3244 LiveOuts[
I] = EmptyDbgValue;
3249 SmallPtrSet<MachineBasicBlock *, 32> DefBlocks;
3250 for (
const MachineBasicBlock *ExpMBB : BlocksToExplore) {
3251 auto &TransferFunc = AllTheVLocs[ExpMBB->getNumber()].Vars;
3252 if (TransferFunc.contains(
VarID))
3253 DefBlocks.
insert(
const_cast<MachineBasicBlock *
>(ExpMBB));
3256 SmallVector<MachineBasicBlock *, 32> PHIBlocks;
3260 if (DefBlocks.
size() == 1) {
3261 placePHIsForSingleVarDefinition(MutBlocksToExplore, *DefBlocks.
begin(),
3262 AllTheVLocs,
VarID, Output);
3267 BlockPHIPlacement(MutBlocksToExplore, DefBlocks, PHIBlocks);
3270 for (MachineBasicBlock *PHIMBB : PHIBlocks) {
3271 unsigned BlockNo = PHIMBB->getNumber();
3272 DbgValue *LiveIn = LiveInIdx[PHIMBB];
3276 for (
auto *
MBB : BlockOrders) {
3277 Worklist.push(BBToOrder[
MBB]);
3288 bool FirstTrip =
true;
3289 while (!Worklist.empty() || !Pending.empty()) {
3290 while (!Worklist.empty()) {
3291 auto *
MBB = OrderToBB[Worklist.top()];
3295 auto LiveInsIt = LiveInIdx.find(
MBB);
3296 assert(LiveInsIt != LiveInIdx.end());
3297 DbgValue *LiveIn = LiveInsIt->second;
3301 bool InLocsChanged =
3302 vlocJoin(*
MBB, LiveOutIdx, BlocksToExplore, *LiveIn);
3317 if (pickVPHILoc(JoinedOps, *
MBB, LiveOutIdx, MOutLocs, Preds)) {
3319 InLocsChanged |= NewLocPicked;
3325 if (!InLocsChanged && !FirstTrip)
3328 DbgValue *LiveOut = LiveOutIdx[
MBB];
3329 bool OLChanged =
false;
3333 auto TransferIt = VTracker.Vars.find(
VarID);
3334 if (TransferIt != VTracker.Vars.end()) {
3338 if (*LiveOut != NewVal) {
3344 if (*LiveOut != TransferIt->second) {
3345 *LiveOut = TransferIt->second;
3351 if (*LiveOut != *LiveIn) {
3366 if (!LiveInIdx.contains(s))
3369 unsigned Order = BBToOrder[s];
3370 if (Order > BBToOrder[
MBB]) {
3371 if (OnWorklist.
insert(s).second)
3372 Worklist.push(Order);
3373 }
else if (OnPending.
insert(s).second && (FirstTrip || OLChanged)) {
3374 Pending.push(Order);
3378 Worklist.swap(Pending);
3388 for (
auto *
MBB : BlockOrders) {
3389 DbgValue *BlockLiveIn = LiveInIdx[
MBB];
3396 [[maybe_unused]]
auto &[Var, DILoc] = DVMap.lookupDVID(
VarID);
3398 Var.getFragment() &&
3399 "Fragment info missing during value prop");
3404 BlockOrders.clear();
3405 BlocksToExplore.clear();
3408void InstrRefBasedLDV::placePHIsForSingleVarDefinition(
3423 VLocTracker &VLocs = AllTheVLocs[AssignMBB->
getNumber()];
3425 const DbgValue &
Value = ValueIt->second;
3435 for (
auto *ScopeBlock : InScopeBlocks) {
3436 if (!DomTree->properlyDominates(AssignMBB, ScopeBlock))
3439 Output[ScopeBlock->getNumber()].push_back({
VarID,
Value});
3446#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
3449 for (
const auto &
P : mloc_transfer) {
3450 std::string foo = MTracker->LocIdxToName(
P.first);
3451 std::string bar = MTracker->IDAsString(
P.second);
3452 dbgs() <<
"Loc " << foo <<
" --> " << bar <<
"\n";
3463 auto hasNonArtificialLocation = [](
const MachineInstr &
MI) ->
bool {
3465 return DL.getLine() != 0;
3471 unsigned int Size = 0;
3472 for (
auto &
MBB : MF) {
3475 ArtificialBlocks.insert(&
MBB);
3479 ReversePostOrderTraversal<MachineFunction *> RPOT(&MF);
3480 unsigned int RPONumber = 0;
3481 OrderToBB.reserve(
Size);
3482 BBToOrder.reserve(
Size);
3483 BBNumToRPO.reserve(
Size);
3484 auto processMBB = [&](MachineBasicBlock *
MBB) {
3485 OrderToBB.push_back(
MBB);
3486 BBToOrder[
MBB] = RPONumber;
3490 for (MachineBasicBlock *
MBB : RPOT)
3492 for (MachineBasicBlock &
MBB : MF)
3493 if (!BBToOrder.contains(&
MBB))
3499#ifdef EXPENSIVE_CHECKS
3502 if (MF.DebugValueSubstitutions.size() > 2) {
3503 for (
auto It = MF.DebugValueSubstitutions.begin();
3504 It != std::prev(MF.DebugValueSubstitutions.end()); ++It) {
3505 assert(It->Src != std::next(It)->Src &&
"Duplicate variable location "
3506 "substitution seen");
3515void InstrRefBasedLDV::makeDepthFirstEjectionMap(
3517 const ScopeToDILocT &ScopeToDILocation,
3518 ScopeToAssignBlocksT &ScopeToAssignBlocks) {
3519 SmallPtrSet<const MachineBasicBlock *, 8> BlocksToExplore;
3521 auto *TopScope = LS.getCurrentFunctionScope();
3525 WorkStack.
push_back({TopScope, TopScope->getChildren().size() - 1});
3527 while (!WorkStack.
empty()) {
3528 auto &ScopePosition = WorkStack.
back();
3529 LexicalScope *WS = ScopePosition.first;
3530 ssize_t ChildNum = ScopePosition.second--;
3533 if (ChildNum >= 0) {
3536 auto &ChildScope =
Children[ChildNum];
3538 std::make_pair(ChildScope, ChildScope->getChildren().size() - 1));
3545 auto DILocationIt = ScopeToDILocation.find(WS);
3546 if (DILocationIt != ScopeToDILocation.end()) {
3547 getBlocksForScope(DILocationIt->second, BlocksToExplore,
3548 ScopeToAssignBlocks.find(WS)->second);
3549 for (
const auto *
MBB : BlocksToExplore) {
3551 if (EjectionMap[BBNum] == 0)
3555 BlocksToExplore.clear();
3561bool InstrRefBasedLDV::depthFirstVLocAndEmit(
3562 unsigned MaxNumBlocks,
const ScopeToDILocT &ScopeToDILocation,
3563 const ScopeToVarsT &ScopeToVars, ScopeToAssignBlocksT &ScopeToAssignBlocks,
3566 bool ShouldEmitDebugEntryValues) {
3567 TTracker =
new TransferTracker(TII, MTracker, MF, DVMap, *TRI,
3568 CalleeSavedRegs, ShouldEmitDebugEntryValues);
3569 unsigned NumLocs = MTracker->getNumLocs();
3573 if (!LS.getCurrentFunctionScope())
3577 SmallVector<unsigned, 16> EjectionMap;
3579 makeDepthFirstEjectionMap(EjectionMap, ScopeToDILocation,
3580 ScopeToAssignBlocks);
3585 auto EjectBlock = [&](MachineBasicBlock &
MBB) ->
void {
3587 AllTheVLocs[BBNum].
clear();
3592 MTracker->loadFromArray(MInLocs[
MBB], BBNum);
3593 TTracker->loadInlocs(
MBB, MInLocs[
MBB], DbgOpStore, Output[BBNum], NumLocs);
3597 for (
auto &
MI :
MBB) {
3598 process(
MI, &MOutLocs, &MInLocs);
3599 TTracker->checkInstForNewValues(CurInst,
MI.getIterator());
3607 Output[BBNum].clear();
3608 AllTheVLocs[BBNum].
clear();
3611 SmallPtrSet<const MachineBasicBlock *, 8> BlocksToExplore;
3613 WorkStack.
push_back({LS.getCurrentFunctionScope(), 0});
3614 unsigned HighestDFSIn = 0;
3617 while (!WorkStack.
empty()) {
3618 auto &ScopePosition = WorkStack.
back();
3619 LexicalScope *WS = ScopePosition.first;
3620 ssize_t ChildNum = ScopePosition.second++;
3627 auto DILocIt = ScopeToDILocation.find(WS);
3628 if (HighestDFSIn <= WS->getDFSIn() && DILocIt != ScopeToDILocation.end()) {
3629 const DILocation *DILoc = DILocIt->second;
3630 auto &VarsWeCareAbout = ScopeToVars.find(WS)->second;
3631 auto &BlocksInScope = ScopeToAssignBlocks.find(WS)->second;
3633 buildVLocValueMap(DILoc, VarsWeCareAbout, BlocksInScope, Output, MOutLocs,
3634 MInLocs, AllTheVLocs);
3637 HighestDFSIn = std::max(HighestDFSIn, WS->
getDFSIn());
3641 if (ChildNum < (ssize_t)
Children.size()) {
3643 auto &ChildScope =
Children[ChildNum];
3644 WorkStack.
push_back(std::make_pair(ChildScope, 0));
3650 auto DILocationIt = ScopeToDILocation.find(WS);
3651 if (DILocationIt == ScopeToDILocation.end())
3654 getBlocksForScope(DILocationIt->second, BlocksToExplore,
3655 ScopeToAssignBlocks.find(WS)->second);
3656 for (
const auto *
MBB : BlocksToExplore)
3658 EjectBlock(
const_cast<MachineBasicBlock &
>(*
MBB));
3660 BlocksToExplore.clear();
3669 for (
auto *
MBB : ArtificialBlocks)
3673 return emitTransfers();
3676bool InstrRefBasedLDV::emitTransfers() {
3680 for (
auto &
P : TTracker->Transfers) {
3689 MachineBasicBlock &
MBB = *
P.MBB;
3690 for (
const auto &Pair :
P.Insts)
3695 if (
P.Pos->isTerminator())
3699 for (
const auto &Pair :
P.Insts)
3704 return TTracker->Transfers.size() != 0;
3711 bool ShouldEmitDebugEntryValues,
3713 unsigned InputDbgValLimit) {
3720 this->DomTree = DomTree;
3727 LS.scanFunction(MF);
3730 AdjustsStackInCalls = MFI->adjustsStack() &&
3732 if (AdjustsStackInCalls)
3733 StackProbeSymbolName = STI.getTargetLowering()->getStackProbeSymbolName(MF);
3745 for (
auto &
MBB : MF)
3756 produceMLocTransferFunction(MF, MLocTransfer,
MaxNumBlocks);
3761 unsigned NumLocs = MTracker->getNumLocs();
3769 buildMLocValueMap(MF, MInLocs, MOutLocs, MLocTransfer);
3773 for (
auto &DBG_PHI : DebugPHINumToValue) {
3775 if (!DBG_PHI.ValueRead)
3778 ValueIDNum &Num = *DBG_PHI.ValueRead;
3783 LocIdx LocNo = Num.
getLoc();
3784 ValueIDNum ResolvedValue = MInLocs[BlockNo][LocNo.
asU64()];
3789 Num = ResolvedValue;
3796 for (MachineBasicBlock *
MBB : OrderToBB) {
3798 VTracker = &vlocs[CurBB];
3799 VTracker->MBB =
MBB;
3800 MTracker->loadFromArray(MInLocs[*
MBB], CurBB);
3802 for (
auto &
MI : *
MBB) {
3803 process(
MI, &MOutLocs, &MInLocs);
3821 unsigned VarAssignCount = 0;
3822 for (MachineBasicBlock *
MBB : OrderToBB) {
3825 for (
auto &idx : VTracker->Vars) {
3827 const DILocation *ScopeLoc = VTracker->Scopes[
VarID];
3828 assert(ScopeLoc !=
nullptr);
3829 auto *
Scope = LS.findLexicalScope(ScopeLoc);
3832 assert(Scope !=
nullptr);
3835 ScopeToAssignBlocks[
Scope].insert(VTracker->MBB);
3836 ScopeToDILocation[
Scope] = ScopeLoc;
3847 VarAssignCount > InputDbgValLimit) {
3848 LLVM_DEBUG(
dbgs() <<
"Disabling InstrRefBasedLDV: " << MF.getName()
3851 <<
" variable assignments, exceeding limits.\n");
3856 Changed = depthFirstVLocAndEmit(
3857 MaxNumBlocks, ScopeToDILocation, ScopeToVars, ScopeToAssignBlocks,
3858 SavedLiveIns, MOutLocs, MInLocs, vlocs, MF, ShouldEmitDebugEntryValues);
3867 ArtificialBlocks.clear();
3871 DebugInstrNumToInstr.clear();
3872 DebugPHINumToValue.clear();
3873 OverlapFragments.clear();
3874 SeenFragments.clear();
3875 SeenDbgPHIs.clear();
3901 LDVSSABlock *ParentBlock;
3902 BlockValueNum PHIValNum;
3903 LDVSSAPhi(BlockValueNum PHIValNum, LDVSSABlock *ParentBlock)
3904 : ParentBlock(ParentBlock), PHIValNum(PHIValNum) {}
3906 LDVSSABlock *
getParent() {
return ParentBlock; }
3911class LDVSSABlockIterator {
3914 LDVSSAUpdater &Updater;
3917 LDVSSAUpdater &Updater)
3918 : PredIt(PredIt), Updater(Updater) {}
3920 bool operator!=(
const LDVSSABlockIterator &OtherIt)
const {
3921 return OtherIt.PredIt != PredIt;
3924 LDVSSABlockIterator &operator++() {
3937 MachineBasicBlock &BB;
3938 LDVSSAUpdater &Updater;
3939 using PHIListT = SmallVector<LDVSSAPhi, 1>;
3943 LDVSSABlock(MachineBasicBlock &BB, LDVSSAUpdater &Updater)
3944 : BB(BB), Updater(Updater) {}
3947 return LDVSSABlockIterator(BB.
succ_begin(), Updater);
3951 return LDVSSABlockIterator(BB.
succ_end(), Updater);
3955 LDVSSAPhi *newPHI(BlockValueNum
Value) {
3956 PHIList.emplace_back(
Value,
this);
3957 return &PHIList.back();
3961 PHIListT &phis() {
return PHIList; }
3967class LDVSSAUpdater {
3970 DenseMap<BlockValueNum, LDVSSAPhi *> PHIs;
3973 DenseMap<MachineBasicBlock *, BlockValueNum> PoisonMap;
3975 DenseMap<MachineBasicBlock *, LDVSSABlock *> BlockMap;
3979 const FuncValueTable &MLiveIns;
3981 LDVSSAUpdater(LocIdx L,
const FuncValueTable &MLiveIns)
3982 : Loc(
L), MLiveIns(MLiveIns) {}
3985 for (
auto &
Block : BlockMap)
3986 delete Block.second;
3993 ~LDVSSAUpdater() { reset(); }
3997 LDVSSABlock *getSSALDVBlock(MachineBasicBlock *BB) {
3998 auto [It,
Inserted] = BlockMap.try_emplace(BB);
4000 It->second =
new LDVSSABlock(*BB, *
this);
4006 BlockValueNum getValue(LDVSSABlock *LDVBB) {
4007 return MLiveIns[LDVBB->BB][Loc.
asU64()].asU64();
4011LDVSSABlock *LDVSSABlockIterator::operator*() {
4012 return Updater.getSSALDVBlock(*PredIt);
4018 out <<
"SSALDVPHI " <<
PHI.PHIValNum;
4053 : PHI(
P), Idx(PHI->IncomingValues.
size()) {}
4078 Preds->
push_back(BB->Updater.getSSALDVBlock(Pred));
4084 static BlockValueNum
GetPoisonVal(LDVSSABlock *BB, LDVSSAUpdater *Updater) {
4089 Updater->PoisonMap[&BB->BB] = Num;
4099 LDVSSAUpdater *Updater) {
4100 BlockValueNum PHIValNum = Updater->getValue(BB);
4101 LDVSSAPhi *
PHI = BB->newPHI(PHIValNum);
4102 Updater->PHIs[PHIValNum] =
PHI;
4109 PHI->IncomingValues.push_back(std::make_pair(Pred, Val));
4114 static LDVSSAPhi *
ValueIsPHI(BlockValueNum Val, LDVSSAUpdater *Updater) {
4115 return Updater->PHIs.lookup(Val);
4122 if (
PHI &&
PHI->IncomingValues.size() == 0)
4134std::optional<ValueIDNum> InstrRefBasedLDV::resolveDbgPHIs(
4139 auto SeenDbgPHIIt = SeenDbgPHIs.find(std::make_pair(&Here, InstrNum));
4140 if (SeenDbgPHIIt != SeenDbgPHIs.end())
4141 return SeenDbgPHIIt->second;
4143 std::optional<ValueIDNum>
Result =
4144 resolveDbgPHIsImpl(MF, MLiveOuts, MLiveIns, Here, InstrNum);
4145 SeenDbgPHIs.insert({std::make_pair(&Here, InstrNum),
Result});
4149std::optional<ValueIDNum> InstrRefBasedLDV::resolveDbgPHIsImpl(
4154 auto RangePair = std::equal_range(DebugPHINumToValue.begin(),
4155 DebugPHINumToValue.end(), InstrNum);
4156 auto LowerIt = RangePair.first;
4157 auto UpperIt = RangePair.second;
4160 if (LowerIt == UpperIt)
4161 return std::nullopt;
4167 auto DBGPHIRange =
make_range(LowerIt, UpperIt);
4168 for (
const DebugPHIRecord &DBG_PHI : DBGPHIRange)
4169 if (!DBG_PHI.ValueRead)
4170 return std::nullopt;
4173 if (std::distance(LowerIt, UpperIt) == 1)
4174 return *LowerIt->ValueRead;
4180 LocIdx Loc = *LowerIt->ReadLoc;
4189 LDVSSAUpdater Updater(Loc, MLiveIns);
4191 DenseMap<LDVSSABlock *, BlockValueNum> AvailableValues;
4197 for (
const auto &DBG_PHI : DBGPHIRange) {
4198 LDVSSABlock *
Block = Updater.getSSALDVBlock(DBG_PHI.MBB);
4199 const ValueIDNum &Num = *DBG_PHI.ValueRead;
4203 LDVSSABlock *HereBlock = Updater.getSSALDVBlock(Here.
getParent());
4204 const auto &AvailIt = AvailableValues.
find(HereBlock);
4205 if (AvailIt != AvailableValues.
end()) {
4213 SSAUpdaterImpl<LDVSSAUpdater> Impl(&Updater, &AvailableValues, &CreatedPHIs);
4214 BlockValueNum ResultInt = Impl.GetValue(Updater.getSSALDVBlock(Here.
getParent()));
4228 DenseMap<LDVSSABlock *, ValueIDNum> ValidatedValues;
4231 for (
const auto &DBG_PHI : DBGPHIRange) {
4232 LDVSSABlock *
Block = Updater.getSSALDVBlock(DBG_PHI.MBB);
4233 const ValueIDNum &Num = *DBG_PHI.ValueRead;
4234 ValidatedValues.
insert(std::make_pair(
Block, Num));
4240 llvm::sort(SortedPHIs, [&](LDVSSAPhi *
A, LDVSSAPhi *
B) {
4241 return BBToOrder[&
A->getParent()->BB] < BBToOrder[&
B->getParent()->BB];
4244 for (
auto &
PHI : SortedPHIs) {
4245 ValueIDNum ThisBlockValueNum = MLiveIns[
PHI->ParentBlock->BB][Loc.
asU64()];
4248 for (
auto &PHIIt :
PHI->IncomingValues) {
4250 if (Updater.PoisonMap.contains(&PHIIt.first->BB))
4251 return std::nullopt;
4253 ValueIDNum ValueToCheck;
4254 const ValueTable &BlockLiveOuts = MLiveOuts[PHIIt.first->BB];
4256 auto VVal = ValidatedValues.
find(PHIIt.first);
4257 if (VVal == ValidatedValues.
end()) {
4262 ValueToCheck = ThisBlockValueNum;
4266 ValueToCheck = VVal->second;
4269 if (BlockLiveOuts[Loc.
asU64()] != ValueToCheck)
4270 return std::nullopt;
4274 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 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.
static TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton 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
static LLVM_ABI_FOR_TEST ValueIDNum TombstoneValue
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)
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
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)
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.