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)
449 Result.first->second = NewValue;
475 for (
const auto &VLoc : VLocs)
477 for (
DbgOpID OpID : VLoc.second.getDbgOpIDs())
478 if (!OpID.ID.IsConst)
489 for (
auto Location :
MTracker->locations()) {
490 LocIdx Idx = Location.Idx;
499 if (VIt == ValueToLoc.
end() || VIt->first != VNum)
502 auto &Previous = VIt->second;
505 std::optional<LocationQuality> ReplacementQuality =
507 if (ReplacementQuality)
512 for (
const auto &Var : VLocs) {
542 for (
auto &
Use : MIt->second) {
547 assert(!
Op.isUndef() &&
"UseBeforeDef erroneously created for a "
548 "DbgValue with undef values.");
557 if (ValueToLoc.
empty())
561 for (
auto Location :
MTracker->locations()) {
562 LocIdx Idx = Location.Idx;
566 auto VIt = ValueToLoc.
find(LocValueID);
567 if (VIt == ValueToLoc.
end())
570 auto &Previous = VIt->second;
573 std::optional<LocationQuality> ReplacementQuality =
575 if (ReplacementQuality)
581 for (
auto &
Use : MIt->second) {
592 LocIdx NewLoc = ValueToLoc.
find(
Op.ID)->second.getLoc();
601 if (DbgOps.
size() !=
Use.Values.size())
605 auto &[Var, DILoc] =
DVMap.lookupDVID(
Use.VarID);
607 Use.VarID,
MTracker->emitLoc(DbgOps, Var, DILoc,
Use.Properties)));
619 if (
MBB && Pos ==
MBB->begin())
620 BundleStart =
MBB->instr_begin();
651 Register SP =
TLI->getStackPointerRegisterToSaveRestore();
654 return Reg != SP && Reg !=
FP;
671 auto NonVariadicExpression =
673 if (!NonVariadicExpression)
675 DIExpr = *NonVariadicExpression;
711 MI.getDebugLoc()->getInlinedAt());
716 if (
MI.isUndefDebugValue() ||
MI.getDebugExpression()->isEntryValue() ||
721 for (
LocIdx Loc : It->second.loc_indices())
751 MI.getDebugLoc()->getInlinedAt());
759 for (
LocIdx Loc : It->second.loc_indices())
764 if (NewLocs.
empty()) {
784 for (
LocIdx Loc : LostVLocIt->second.loc_indices()) {
794 for (
const auto &LostMLoc : LostMLocs)
795 ActiveMLocs[LostMLoc.first].erase(LostMLoc.second);
809 It->second.Ops.assign(NewLocs);
810 It->second.Properties = Properties;
819 bool MakeUndef =
true) {
841 std::optional<LocIdx> NewLoc;
843 if (
Loc.Value == OldValue)
848 if (!NewLoc && !MakeUndef) {
878 DbgOps.
insert(DbgOps.
begin(), ActiveVLocIt->second.Ops.size(),
885 VarID, &*
MTracker->emitLoc(DbgOps, Var, DILoc, Properties)));
890 for (
LocIdx Loc : ActiveVLocIt->second.loc_indices()) {
896 ActiveVLocIt->second.Ops = DbgOps;
903 for (
auto &LocVarIt : LostMLocs) {
904 auto LostMLocIt =
ActiveMLocs.find(LocVarIt.first);
906 "Variable was using this MLoc, but ActiveMLocs[MLoc] has no "
908 LostMLocIt->second.erase(LocVarIt.second);
914 VarLocs[NewLoc->asU64()] = OldValue;
919 ActiveMLocIt->second.clear();
920 if (!NewMLocs.
empty())
953 ActiveVLocIt->second.Properties);
978 MIB.addMetadata(Properties.
DIExpr);
1021 for (
unsigned Idx = 0; Idx <
getDbgOpIDs().size(); ++Idx) {
1048 Register SP =
TLI.getStackPointerRegisterToSaveRestore();
1070 for (
unsigned int I = 1;
I <
TRI.getNumSubRegIndices(); ++
I) {
1071 unsigned Size =
TRI.getSubRegIdxSize(
I);
1072 unsigned Offs =
TRI.getSubRegIdxOffset(
I);
1077 if (
Size > 60000 || Offs > 60000)
1085 unsigned Size =
TRI.getRegSizeInBits(*RC);
1113 if (MaskPair.first->clobbersPhysReg(
ID)) {
1115 ValNum = {
CurBB, MaskPair.second, NewIdx};
1136 Masks.push_back(std::make_pair(MO, InstID));
1142 if (SpillID.
id() == 0) {
1146 return std::nullopt;
1151 for (
unsigned StackIdx = 0; StackIdx <
NumSlotIdxes; ++StackIdx) {
1172 return Twine(
"slot ")
1177 return TRI.getRegAsmName(
ID).str();
1189 std::string MLocName =
LocIdxToName(Location.Value.getLoc());
1190 std::string DefName = Location.Value.asString(MLocName);
1198 dbgs() <<
"Idx " << Location.Idx.asU64() <<
" " << foo <<
"\n";
1210 ?
TII.get(TargetOpcode::DBG_VALUE_LIST)
1211 :
TII.get(TargetOpcode::DBG_VALUE);
1213#ifdef EXPENSIVE_CHECKS
1216 return Op.IsConst || !
Op.Loc.isIllegal();
1218 "Did not expect illegal ops in DbgOps.");
1221 "Expected to have either one DbgOp per MI LocationOp, or none.");
1234 auto EmitUndef = [&]() {
1246 bool Indirect = Properties.
Indirect;
1268 unsigned short Offset = StackIdx.second;
1279 unsigned Base = Spill.SpillBase;
1295 bool UseDerefSize =
false;
1297 unsigned DerefSizeInBytes = ValueSizeInBits / 8;
1299 unsigned VariableSizeInBits = Fragment->SizeInBits;
1300 if (VariableSizeInBits != ValueSizeInBits || Expr->
isComplex())
1301 UseDerefSize =
true;
1303 if (*
Size != ValueSizeInBits) {
1304 UseDerefSize =
true;
1326 if (ValueSizeInBits >
MF.getTarget().getPointerSizeInBits(0))
1327 UseDerefSize =
false;
1330 TRI.getOffsetOpcodes(Spill.SpillOffset, OffsetOps);
1331 bool StackValue =
false;
1338 OffsetOps.
push_back(dwarf::DW_OP_deref);
1345 OffsetOps.
push_back(dwarf::DW_OP_deref_size);
1351 OffsetOps.
push_back(dwarf::DW_OP_deref);
1379 unsigned Reg = MTracker->LocIdxToLocID[L];
1384 if (CalleeSavedRegs.test((*RAI).id()))
1398std::optional<SpillLocationNo>
1399InstrRefBasedLDV::extractSpillBaseRegAndOffset(
const MachineInstr &
MI) {
1401 "Spill instruction does not have exactly one memory operand?");
1402 auto MMOI =
MI.memoperands_begin();
1405 "Inconsistent memory operand in spill instruction");
1413std::optional<LocIdx>
1415 std::optional<SpillLocationNo>
SpillLoc = extractSpillBaseRegAndOffset(
MI);
1417 return std::nullopt;
1423 auto *MemOperand = *
MI.memoperands_begin();
1425 assert(SizeInBits.
hasValue() &&
"Expected to find a valid size!");
1428 auto IdxIt = MTracker->StackSlotIdxes.find({SizeInBits.
getValue(), 0});
1429 if (IdxIt == MTracker->StackSlotIdxes.end())
1432 return std::nullopt;
1434 unsigned SpillID = MTracker->getSpillIDWithIdx(*
SpillLoc, IdxIt->second);
1435 return MTracker->getSpillMLoc(SpillID);
1440bool InstrRefBasedLDV::transferDebugValue(
const MachineInstr &
MI) {
1441 if (!
MI.isDebugValue())
1444 assert(
MI.getDebugVariable()->isValidLocationForIntrinsic(
MI.getDebugLoc()) &&
1445 "Expected inlined-at fields to agree");
1450 if (Scope ==
nullptr)
1456 if (MO.isReg() && MO.getReg() != 0)
1457 (void)MTracker->
readReg(MO.getReg());
1466 if (!
MI.isUndefDebugValue()) {
1472 }
else if (MO.isImm() || MO.isFPImm() || MO.isCImm()) {
1479 VTracker->defVar(
MI, DbgValueProperties(
MI), DebugOps);
1485 TTracker->redefVar(
MI);
1489std::optional<ValueIDNum> InstrRefBasedLDV::getValueForInstrRef(
1496 const MachineFunction &MF = *
MI.getParent()->getParent();
1500 MachineFunction::DebugSubstitution({InstNo, OpNo}, {0, 0}, 0);
1502 SmallVector<unsigned, 4> SeenSubregs;
1505 LowerBoundIt->Src == SoughtSub.Src) {
1506 std::tie(InstNo, OpNo) = LowerBoundIt->Dest;
1507 SoughtSub.Src = LowerBoundIt->Dest;
1508 if (
unsigned Subreg = LowerBoundIt->Subreg)
1509 SeenSubregs.push_back(Subreg);
1515 std::optional<ValueIDNum> NewID;
1519 auto InstrIt = DebugInstrNumToInstr.find(InstNo);
1521 if (InstrIt != DebugInstrNumToInstr.end()) {
1522 const MachineInstr &TargetInstr = *InstrIt->second.first;
1531 NewID = ValueIDNum(BlockNo, InstrIt->second.second, *L);
1539 const MachineOperand &MO = TargetInstr.
getOperand(OpNo);
1542 unsigned LocID = MTracker->getLocID(MO.
getReg());
1543 LocIdx
L = MTracker->LocIDToLocIdx[LocID];
1544 NewID = ValueIDNum(BlockNo, InstrIt->second.second, L);
1550 {
dbgs() <<
"Seen instruction reference to illegal operand\n"; });
1554 }
else if (PHIIt != DebugPHINumToValue.end() && PHIIt->InstrNum == InstNo) {
1557 assert(MLiveOuts && MLiveIns);
1558 NewID = resolveDbgPHIs(*
MI.getParent()->getParent(), *MLiveOuts, *MLiveIns,
1571 if (NewID && !SeenSubregs.empty()) {
1579 for (
unsigned Subreg :
reverse(SeenSubregs)) {
1580 unsigned ThisSize = TRI->getSubRegIdxSize(Subreg);
1581 unsigned ThisOffset = TRI->getSubRegIdxOffset(Subreg);
1583 Size = (
Size == 0) ? ThisSize : std::min(
Size, ThisSize);
1590 LocIdx
L = NewID->getLoc();
1591 if (NewID && !MTracker->isSpill(L)) {
1595 const TargetRegisterClass *TRC =
nullptr;
1596 for (
const auto *TRCI : TRI->regclasses())
1597 if (TRCI->contains(
Reg))
1599 assert(TRC &&
"Couldn't find target register class?");
1603 unsigned MainRegSize = TRI->getRegSizeInBits(*TRC);
1607 for (MCRegister SR : TRI->subregs(
Reg)) {
1608 unsigned Subreg = TRI->getSubRegIndex(
Reg, SR);
1609 unsigned SubregSize = TRI->getSubRegIdxSize(Subreg);
1610 unsigned SubregOffset = TRI->getSubRegIdxOffset(Subreg);
1611 if (SubregSize ==
Size && SubregOffset ==
Offset) {
1619 NewID = std::nullopt;
1624 MTracker->lookupOrTrackRegister(MTracker->getLocID(NewReg));
1625 NewID = ValueIDNum(NewID->getBlock(), NewID->getInst(), NewLoc);
1630 NewID = std::nullopt;
1640 if (!
MI.isDebugRef())
1645 if (!VTracker && !TTracker)
1648 const DILocalVariable *Var =
MI.getDebugVariable();
1649 const DIExpression *Expr =
MI.getDebugExpression();
1650 const DILocation *
DebugLoc =
MI.getDebugLoc();
1651 const DILocation *InlinedAt =
DebugLoc->getInlinedAt();
1653 "Expected inlined-at fields to agree");
1655 DebugVariable
V(Var, Expr, InlinedAt);
1657 auto *
Scope = LS.findLexicalScope(
MI.getDebugLoc().get());
1658 if (Scope ==
nullptr)
1662 for (
const MachineOperand &MO :
MI.debug_operands()) {
1664 assert(!MO.
isReg() &&
"DBG_INSTR_REF should not contain registers");
1665 DbgOpID ConstOpID = DbgOpStore.insert(DbgOp(MO));
1675 std::optional<ValueIDNum> NewID =
1676 getValueForInstrRef(InstNo, OpNo,
MI, MLiveOuts, MLiveIns);
1680 DbgOpIDs.
push_back(DbgOpStore.insert(*NewID));
1691 DbgValueProperties Properties(Expr,
false,
true);
1693 VTracker->defVar(
MI, Properties, DbgOpIDs);
1702 for (DbgOpID OpID : DbgOpIDs) {
1703 DbgOps.
push_back(DbgOpStore.find(OpID));
1708 SmallDenseMap<ValueIDNum, TransferTracker::LocationAndQuality> FoundLocs;
1712 for (
const DbgOp &
Op : DbgOps) {
1718 for (
auto Location : MTracker->locations()) {
1720 ValueIDNum
ID = MTracker->readMLoc(CurL);
1721 auto ValueToFindIt =
find(ValuesToFind,
ID);
1722 if (ValueToFindIt == ValuesToFind.
end())
1724 auto &Previous = FoundLocs.
find(
ID)->second;
1727 std::optional<TransferTracker::LocationQuality> ReplacementQuality =
1728 TTracker->getLocQualityIfBetter(CurL, Previous.getQuality());
1729 if (ReplacementQuality) {
1730 Previous = TransferTracker::LocationAndQuality(CurL, *ReplacementQuality);
1731 if (Previous.isBest()) {
1732 ValuesToFind.
erase(ValueToFindIt);
1733 if (ValuesToFind.
empty())
1740 for (
const DbgOp &DbgOp : DbgOps) {
1741 if (DbgOp.IsConst) {
1745 LocIdx FoundLoc = FoundLocs.
find(DbgOp.ID)->second.getLoc();
1753 TTracker->redefVar(
MI, Properties, NewLocs);
1757 if (!DbgOps.empty() && NewLocs.
empty()) {
1758 bool IsValidUseBeforeDef =
true;
1759 uint64_t LastUseBeforeDef = 0;
1760 for (
auto ValueLoc : FoundLocs) {
1761 ValueIDNum NewID = ValueLoc.first;
1762 LocIdx FoundLoc = ValueLoc.second.getLoc();
1768 IsValidUseBeforeDef =
false;
1771 LastUseBeforeDef = std::max(LastUseBeforeDef, NewID.
getInst());
1773 if (IsValidUseBeforeDef) {
1775 TTracker->addUseBeforeDef(VID, {
MI.getDebugExpression(),
false,
true},
1776 DbgOps, LastUseBeforeDef);
1784 MachineInstr *DbgMI =
1785 MTracker->emitLoc(NewLocs, V,
MI.getDebugLoc().get(), Properties);
1788 TTracker->PendingDbgValues.push_back(std::make_pair(
ID, DbgMI));
1789 TTracker->flushDbgValues(
MI.getIterator(),
nullptr);
1794 if (!
MI.isDebugPHI())
1798 if (VTracker || TTracker)
1803 const MachineOperand &MO =
MI.getOperand(0);
1804 unsigned InstrNum =
MI.getOperand(1).getImm();
1806 auto EmitBadPHI = [
this, &
MI, InstrNum]() ->
bool {
1811 DebugPHINumToValue.push_back(
1812 {InstrNum,
MI.getParent(), std::nullopt, std::nullopt});
1820 ValueIDNum Num = MTracker->readReg(
Reg);
1821 auto PHIRec = DebugPHIRecord(
1822 {InstrNum,
MI.getParent(), Num,
1823 MTracker->lookupOrTrackRegister(MTracker->getLocID(
Reg))});
1824 DebugPHINumToValue.push_back(PHIRec);
1827 for (MCRegAliasIterator RAI(MO.
getReg(), TRI,
true); RAI.isValid(); ++RAI)
1828 MTracker->lookupOrTrackRegister(MTracker->getLocID(*RAI));
1829 }
else if (MO.
isFI()) {
1835 if (MFI->isDeadObjectIndex(FI))
1836 return EmitBadPHI();
1840 StackOffset Offs = TFI->getFrameIndexReference(*
MI.getMF(), FI,
Base);
1841 SpillLoc SL = {
Base, Offs};
1842 std::optional<SpillLocationNo> SpillNo = MTracker->getOrTrackSpillLoc(SL);
1847 return EmitBadPHI();
1850 assert(
MI.getNumOperands() == 3 &&
"Stack DBG_PHI with no size?");
1851 unsigned slotBitSize =
MI.getOperand(2).getImm();
1853 unsigned SpillID = MTracker->getLocID(*SpillNo, {slotBitSize, 0});
1854 LocIdx SpillLoc = MTracker->getSpillMLoc(SpillID);
1855 ValueIDNum
Result = MTracker->readMLoc(SpillLoc);
1858 auto DbgPHI = DebugPHIRecord({InstrNum,
MI.getParent(),
Result, SpillLoc});
1859 DebugPHINumToValue.push_back(DbgPHI);
1866 {
dbgs() <<
"Seen DBG_PHI with unrecognised operand format\n"; });
1867 return EmitBadPHI();
1876 if (
MI.isImplicitDef()) {
1881 ValueIDNum Num = MTracker->readReg(
MI.getOperand(0).getReg());
1886 }
else if (
MI.isMetaInstruction())
1894 bool CallChangesSP =
false;
1895 if (AdjustsStackInCalls &&
MI.isCall() &&
MI.getOperand(0).isSymbol() &&
1896 !strcmp(
MI.getOperand(0).getSymbolName(), StackProbeSymbolName.data()))
1897 CallChangesSP =
true;
1901 auto IgnoreSPAlias = [
this, &
MI, CallChangesSP](
Register R) ->
bool {
1904 return MI.isCall() && MTracker->SPAliases.count(R);
1910 SmallSet<uint32_t, 32> DeadRegs;
1911 SmallVector<const uint32_t *, 4> RegMasks;
1913 for (
const MachineOperand &MO :
MI.operands()) {
1916 !IgnoreSPAlias(MO.
getReg())) {
1918 for (MCRegAliasIterator RAI(MO.
getReg(), TRI,
true); RAI.isValid(); ++RAI)
1920 DeadRegs.
insert((*RAI).id());
1928 for (uint32_t DeadReg : DeadRegs)
1929 MTracker->defReg(DeadReg, CurBB, CurInst);
1931 for (
const auto *MO : RegMaskPtrs)
1932 MTracker->writeRegMask(MO, CurBB, CurInst);
1936 if (std::optional<SpillLocationNo> SpillNo =
1937 extractSpillBaseRegAndOffset(
MI)) {
1938 for (
unsigned int I = 0;
I < MTracker->NumSlotIdxes; ++
I) {
1939 unsigned SpillID = MTracker->getSpillIDWithIdx(*SpillNo,
I);
1940 LocIdx
L = MTracker->getSpillMLoc(SpillID);
1941 MTracker->setMLoc(L, ValueIDNum(CurBB, CurInst, L));
1954 for (MCRegister DeadReg : DeadRegs) {
1955 LocIdx Loc = MTracker->lookupOrTrackRegister(MTracker->getLocID(DeadReg));
1956 TTracker->clobberMloc(Loc,
MI.getIterator(),
false);
1961 if (!RegMaskPtrs.empty()) {
1962 for (
auto L : MTracker->locations()) {
1964 if (MTracker->isSpill(
L.Idx))
1968 if (IgnoreSPAlias(
Reg))
1971 for (
const auto *MO : RegMaskPtrs)
1973 TTracker->clobberMloc(
L.Idx,
MI.getIterator(),
false);
1979 if (std::optional<SpillLocationNo> SpillNo =
1980 extractSpillBaseRegAndOffset(
MI)) {
1981 for (
unsigned int I = 0;
I < MTracker->NumSlotIdxes; ++
I) {
1982 unsigned SpillID = MTracker->getSpillIDWithIdx(*SpillNo,
I);
1983 LocIdx
L = MTracker->getSpillMLoc(SpillID);
1984 TTracker->clobberMloc(L,
MI.getIterator(),
true);
1990void InstrRefBasedLDV::performCopy(
Register SrcRegNum,
Register DstRegNum) {
1992 for (MCRegAliasIterator RAI(DstRegNum, TRI,
true); RAI.isValid(); ++RAI)
1993 MTracker->defReg(*RAI, CurBB, CurInst);
1995 ValueIDNum SrcValue = MTracker->readReg(SrcRegNum);
1996 MTracker->setReg(DstRegNum, SrcValue);
1999 for (MCSubRegIndexIterator SRI(SrcRegNum, TRI); SRI.isValid(); ++SRI) {
2000 MCRegister SrcSubReg = SRI.getSubReg();
2001 unsigned SubRegIdx = SRI.getSubRegIndex();
2002 MCRegister DstSubReg = TRI->getSubReg(DstRegNum, SubRegIdx);
2012 MTracker->lookupOrTrackRegister(MTracker->getLocID(SrcSubReg));
2014 MTracker->lookupOrTrackRegister(MTracker->getLocID(DstSubReg));
2017 ValueIDNum CpyValue = MTracker->readReg(SrcSubReg);
2019 MTracker->setReg(DstSubReg, CpyValue);
2023std::optional<SpillLocationNo>
2027 if (!
MI.hasOneMemOperand())
2028 return std::nullopt;
2031 auto MMOI =
MI.memoperands_begin();
2032 const PseudoSourceValue *PVal = (*MMOI)->getPseudoValue();
2034 return std::nullopt;
2036 if (!
MI.getSpillSize(TII) && !
MI.getFoldedSpillSize(TII))
2037 return std::nullopt;
2040 return extractSpillBaseRegAndOffset(
MI);
2045 if (!isSpillInstruction(
MI, MF))
2049 Reg = TII->isStoreToStackSlotPostFE(
MI, FI);
2053std::optional<SpillLocationNo>
2056 if (!
MI.hasOneMemOperand())
2057 return std::nullopt;
2061 if (
MI.getRestoreSize(TII)) {
2062 Reg =
MI.getOperand(0).getReg();
2063 return extractSpillBaseRegAndOffset(
MI);
2065 return std::nullopt;
2068bool InstrRefBasedLDV::transferSpillOrRestoreInst(
MachineInstr &
MI) {
2078 if (!TII->isStoreToStackSlotPostFE(
MI, DummyFI) &&
2079 !TII->isLoadFromStackSlotPostFE(
MI, DummyFI))
2082 MachineFunction *MF =
MI.getMF();
2090 if (!TII->isStoreToStackSlotPostFE(
MI, FIDummy) &&
2091 !TII->isLoadFromStackSlotPostFE(
MI, FIDummy))
2097 if (std::optional<SpillLocationNo> Loc = isSpillInstruction(
MI, MF)) {
2100 for (
unsigned SlotIdx = 0; SlotIdx < MTracker->NumSlotIdxes; ++SlotIdx) {
2101 unsigned SpillID = MTracker->getSpillIDWithIdx(*Loc, SlotIdx);
2102 std::optional<LocIdx> MLoc = MTracker->getSpillMLoc(SpillID);
2110 ValueIDNum
Def(CurBB, CurInst, *MLoc);
2111 MTracker->setMLoc(*MLoc, Def);
2113 TTracker->clobberMloc(*MLoc,
MI.getIterator());
2118 if (isLocationSpill(
MI, MF,
Reg)) {
2121 SpillLocationNo Loc = *extractSpillBaseRegAndOffset(
MI);
2123 auto DoTransfer = [&](
Register SrcReg,
unsigned SpillID) {
2124 auto ReadValue = MTracker->readReg(SrcReg);
2125 LocIdx DstLoc = MTracker->getSpillMLoc(SpillID);
2126 MTracker->setMLoc(DstLoc, ReadValue);
2129 LocIdx SrcLoc = MTracker->getRegMLoc(SrcReg);
2130 TTracker->transferMlocs(SrcLoc, DstLoc,
MI.getIterator());
2137 (void)MTracker->lookupOrTrackRegister(MTracker->getLocID(SR));
2138 unsigned SubregIdx = TRI->getSubRegIndex(
Reg, SR);
2139 unsigned SpillID = MTracker->getLocID(Loc, SubregIdx);
2140 DoTransfer(SR, SpillID);
2144 unsigned Size = TRI->getRegSizeInBits(
Reg, *MRI);
2145 unsigned SpillID = MTracker->getLocID(Loc, {
Size, 0});
2146 DoTransfer(
Reg, SpillID);
2148 std::optional<SpillLocationNo> Loc = isRestoreInstruction(
MI, MF,
Reg);
2159 for (MCRegAliasIterator RAI(
Reg, TRI,
true); RAI.isValid(); ++RAI)
2160 MTracker->defReg(*RAI, CurBB, CurInst);
2164 auto DoTransfer = [&](
Register DestReg,
unsigned SpillID) {
2165 LocIdx SrcIdx = MTracker->getSpillMLoc(SpillID);
2166 auto ReadValue = MTracker->readMLoc(SrcIdx);
2167 MTracker->setReg(DestReg, ReadValue);
2171 unsigned Subreg = TRI->getSubRegIndex(
Reg, SR);
2172 unsigned SpillID = MTracker->getLocID(*Loc, Subreg);
2173 DoTransfer(SR, SpillID);
2177 unsigned Size = TRI->getRegSizeInBits(
Reg, *MRI);
2178 unsigned SpillID = MTracker->getLocID(*Loc, {
Size, 0});
2179 DoTransfer(
Reg, SpillID);
2185 auto DestSrc = TII->isCopyLikeInstr(
MI);
2189 const MachineOperand *DestRegOp = DestSrc->Destination;
2190 const MachineOperand *SrcRegOp = DestSrc->Source;
2196 if (SrcReg == DestReg)
2218 DenseMap<LocIdx, ValueIDNum> ClobberedLocs;
2220 for (MCRegAliasIterator RAI(DestReg, TRI,
true); RAI.isValid(); ++RAI) {
2221 LocIdx ClobberedLoc = MTracker->getRegMLoc(*RAI);
2222 auto MLocIt = TTracker->ActiveMLocs.find(ClobberedLoc);
2225 if (MLocIt == TTracker->ActiveMLocs.end() || MLocIt->second.empty())
2227 ValueIDNum
Value = MTracker->readReg(*RAI);
2228 ClobberedLocs[ClobberedLoc] =
Value;
2233 InstrRefBasedLDV::performCopy(SrcReg, DestReg);
2239 for (
auto LocVal : ClobberedLocs) {
2240 TTracker->clobberMloc(LocVal.first, LocVal.second,
MI.getIterator(),
false);
2248 TTracker->transferMlocs(MTracker->getRegMLoc(SrcReg),
2249 MTracker->getRegMLoc(DestReg),
MI.getIterator());
2253 MTracker->defReg(SrcReg, CurBB, CurInst);
2266 DebugVariable MIVar(
MI.getDebugVariable(),
MI.getDebugExpression(),
2267 MI.getDebugLoc()->getInlinedAt());
2268 FragmentInfo ThisFragment = MIVar.getFragmentOrDefault();
2273 auto [SeenIt,
Inserted] = SeenFragments.try_emplace(MIVar.getVariable());
2275 SeenIt->second.insert(ThisFragment);
2277 OverlapFragments.insert({{MIVar.getVariable(), ThisFragment}, {}});
2284 OverlapFragments.insert({{MIVar.getVariable(), ThisFragment}, {}});
2285 if (!IsInOLapMap.second)
2288 auto &ThisFragmentsOverlaps = IsInOLapMap.first->second;
2289 auto &AllSeenFragments = SeenIt->second;
2294 for (
const auto &ASeenFragment : AllSeenFragments) {
2298 ThisFragmentsOverlaps.push_back(ASeenFragment);
2301 auto ASeenFragmentsOverlaps =
2302 OverlapFragments.find({MIVar.getVariable(), ASeenFragment});
2303 assert(ASeenFragmentsOverlaps != OverlapFragments.end() &&
2304 "Previously seen var fragment has no vector of overlaps");
2305 ASeenFragmentsOverlaps->second.push_back(ThisFragment);
2309 AllSeenFragments.insert(ThisFragment);
2318 if (transferDebugValue(
MI))
2320 if (transferDebugInstrRef(
MI, MLiveOuts, MLiveIns))
2322 if (transferDebugPHI(
MI))
2324 if (transferRegisterCopy(
MI))
2326 if (transferSpillOrRestoreInst(
MI))
2328 transferRegisterDef(
MI);
2331void InstrRefBasedLDV::produceMLocTransferFunction(
2347 for (
auto &BV : BlockMasks)
2348 BV.resize(TRI->getNumRegs(),
true);
2351 for (
auto &
MBB : MF) {
2360 MTracker->setMPhis(CurBB);
2363 for (
auto &
MI :
MBB) {
2366 process(
MI,
nullptr,
nullptr);
2369 if (
MI.isDebugValueLike())
2370 accumulateFragmentMap(
MI);
2374 if (uint64_t InstrNo =
MI.peekDebugInstrNum()) {
2375 auto InstrAndPos = std::make_pair(&
MI, CurInst);
2377 DebugInstrNumToInstr.insert(std::make_pair(InstrNo, InstrAndPos));
2380 assert(InsertResult.second);
2391 for (
auto Location : MTracker->locations()) {
2394 if (
P.isPHI() &&
P.getLoc() == Idx.
asU64())
2398 auto &TransferMap = MLocTransfer[CurBB];
2399 auto Result = TransferMap.insert(std::make_pair(Idx.
asU64(),
P));
2406 for (
auto &
P : MTracker->Masks) {
2407 BlockMasks[CurBB].clearBitsNotInMask(
P.first->getRegMask(), BVWords);
2412 BitVector UsedRegs(TRI->getNumRegs());
2413 for (
auto Location : MTracker->locations()) {
2414 unsigned ID = MTracker->LocIdxToLocID[
Location.Idx];
2416 if (
ID >= TRI->getNumRegs() || MTracker->SPAliases.count(
ID))
2425 BitVector &BV = BlockMasks[
I];
2431 for (
unsigned Bit : BV.
set_bits()) {
2432 unsigned ID = MTracker->getLocID(Bit);
2433 LocIdx Idx = MTracker->LocIDToLocIdx[
ID];
2434 auto &TransferMap = MLocTransfer[
I];
2441 ValueIDNum NotGeneratedNum = ValueIDNum(
I, 1, Idx);
2443 TransferMap.insert(std::make_pair(Idx.
asU64(), NotGeneratedNum));
2445 ValueIDNum &ValueID =
Result.first->second;
2448 ValueID = NotGeneratedNum;
2454bool InstrRefBasedLDV::mlocJoin(
2468 auto Cmp = [&](
const MachineBasicBlock *
A,
const MachineBasicBlock *
B) {
2469 return BBToOrder.find(
A)->second < BBToOrder.find(
B)->second;
2474 if (BlockOrders.size() == 0) {
2479 <<
" from entry which may lead out of "
2480 "bound access to VarLocs\n");
2486 for (
auto Location : MTracker->locations()) {
2491 ValueIDNum FirstVal = OutLocs[*BlockOrders[0]][Idx.
asU64()];
2496 if (InLocs[Idx.
asU64()] != FirstVal) {
2497 InLocs[Idx.
asU64()] = FirstVal;
2505 bool Disagree =
false;
2506 for (
unsigned int I = 1;
I < BlockOrders.size(); ++
I) {
2507 const MachineBasicBlock *PredMBB = BlockOrders[
I];
2508 const ValueIDNum &PredLiveOut = OutLocs[*PredMBB][Idx.
asU64()];
2511 if (FirstVal == PredLiveOut)
2515 if (PredLiveOut == ValueIDNum(
MBB.
getNumber(), 0, Idx))
2524 InLocs[Idx.
asU64()] = FirstVal;
2533void InstrRefBasedLDV::findStackIndexInterference(
2546 auto It = MTracker->StackSlotIdxes.find({8, 0});
2547 assert(It != MTracker->StackSlotIdxes.end());
2551 for (
auto &Pair : MTracker->StackSlotIdxes) {
2553 if (!Pair.first.second)
2559void InstrRefBasedLDV::placeMLocPHIs(
2562 SmallVector<unsigned, 4> StackUnits;
2563 findStackIndexInterference(StackUnits);
2572 SmallSet<Register, 32> RegUnitsToPHIUp;
2573 SmallSet<LocIdx, 32> NormalLocsToPHI;
2574 SmallSet<SpillLocationNo, 32> StackSlots;
2575 for (
auto Location : MTracker->locations()) {
2577 if (MTracker->isSpill(L)) {
2578 StackSlots.
insert(MTracker->locIDToSpill(MTracker->LocIdxToLocID[L]));
2583 SmallSet<Register, 8> FoundRegUnits;
2584 bool AnyIllegal =
false;
2585 for (MCRegUnit Unit : TRI->regunits(
R.asMCReg())) {
2586 for (MCRegUnitRootIterator URoot(Unit, TRI); URoot.isValid(); ++URoot) {
2587 if (!MTracker->isRegisterTracked(*URoot)) {
2593 FoundRegUnits.
insert(*URoot);
2599 NormalLocsToPHI.
insert(L);
2608 SmallVector<MachineBasicBlock *, 32> PHIBlocks;
2609 auto CollectPHIsForLoc = [&](LocIdx
L) {
2611 SmallPtrSet<MachineBasicBlock *, 32> DefBlocks;
2612 for (MachineBasicBlock *
MBB : OrderToBB) {
2613 const auto &TransferFunc = MLocTransfer[
MBB->
getNumber()];
2614 if (TransferFunc.contains(L))
2621 if (!DefBlocks.
empty())
2627 BlockPHIPlacement(AllBlocks, DefBlocks, PHIBlocks);
2630 auto InstallPHIsAtLoc = [&PHIBlocks, &MInLocs](LocIdx
L) {
2631 for (
const MachineBasicBlock *
MBB : PHIBlocks)
2636 for (LocIdx L : NormalLocsToPHI) {
2637 CollectPHIsForLoc(L);
2639 InstallPHIsAtLoc(L);
2644 for (SpillLocationNo Slot : StackSlots) {
2645 for (
unsigned Idx : StackUnits) {
2646 unsigned SpillID = MTracker->getSpillIDWithIdx(Slot, Idx);
2647 LocIdx
L = MTracker->getSpillMLoc(SpillID);
2648 CollectPHIsForLoc(L);
2649 InstallPHIsAtLoc(L);
2653 std::tie(
Size,
Offset) = MTracker->StackIdxesToPos[Idx];
2654 for (
auto &Pair : MTracker->StackSlotIdxes) {
2655 unsigned ThisSize, ThisOffset;
2656 std::tie(ThisSize, ThisOffset) = Pair.first;
2660 unsigned ThisID = MTracker->getSpillIDWithIdx(Slot, Pair.second);
2661 LocIdx ThisL = MTracker->getSpillMLoc(ThisID);
2662 InstallPHIsAtLoc(ThisL);
2668 for (
Register R : RegUnitsToPHIUp) {
2669 LocIdx
L = MTracker->lookupOrTrackRegister(MTracker->getLocID(R));
2670 CollectPHIsForLoc(L);
2673 InstallPHIsAtLoc(L);
2676 for (MCRegAliasIterator RAI(R, TRI,
true); RAI.isValid(); ++RAI) {
2679 if (!MTracker->isRegisterTracked(*RAI))
2683 MTracker->lookupOrTrackRegister(MTracker->getLocID(*RAI));
2684 InstallPHIsAtLoc(AliasLoc);
2689void InstrRefBasedLDV::buildMLocValueMap(
2692 std::priority_queue<unsigned int, std::vector<unsigned int>,
2693 std::greater<unsigned int>>
2699 SmallPtrSet<MachineBasicBlock *, 16> OnPending, OnWorklist;
2703 SmallPtrSet<MachineBasicBlock *, 32> AllBlocks;
2704 for (
unsigned int I = 0;
I < BBToOrder.size(); ++
I) {
2706 OnWorklist.
insert(OrderToBB[
I]);
2707 AllBlocks.
insert(OrderToBB[
I]);
2711 for (
auto Location : MTracker->locations())
2720 placeMLocPHIs(MF, AllBlocks, MInLocs, MLocTransfer);
2730 SmallPtrSet<const MachineBasicBlock *, 16> Visited;
2731 while (!Worklist.empty() || !Pending.empty()) {
2735 while (!Worklist.empty()) {
2736 MachineBasicBlock *
MBB = OrderToBB[Worklist.top()];
2742 InLocsChanged = mlocJoin(*
MBB, Visited, MOutLocs, MInLocs[*
MBB]);
2743 InLocsChanged |= Visited.
insert(
MBB).second;
2751 MTracker->loadFromArray(MInLocs[*
MBB], CurBB);
2756 for (
auto &
P : MLocTransfer[CurBB]) {
2757 if (
P.second.getBlock() == CurBB &&
P.second.isPHI()) {
2759 ValueIDNum NewID = MTracker->readMLoc(
P.second.getLoc());
2760 ToRemap.
push_back(std::make_pair(
P.first, NewID));
2763 assert(
P.second.getBlock() == CurBB);
2764 ToRemap.
push_back(std::make_pair(
P.first,
P.second));
2770 for (
auto &
P : ToRemap)
2771 MTracker->setMLoc(
P.first,
P.second);
2776 bool OLChanged =
false;
2777 for (
auto Location : MTracker->locations()) {
2793 unsigned Order = BBToOrder[s];
2794 if (Order > BBToOrder[
MBB]) {
2796 if (OnWorklist.
insert(s).second)
2797 Worklist.push(Order);
2800 if (OnPending.
insert(s).second)
2801 Pending.push(Order);
2806 Worklist.swap(Pending);
2811 assert(Pending.empty() &&
"Pending should be empty");
2818void InstrRefBasedLDV::BlockPHIPlacement(
2825 IDFCalculatorBase<MachineBasicBlock, false> IDF(*DomTree);
2827 IDF.setLiveInBlocks(AllBlocks);
2828 IDF.setDefiningBlocks(DefBlocks);
2829 IDF.calculate(PHIBlocks);
2832bool InstrRefBasedLDV::pickVPHILoc(
2838 if (BlockOrders.
empty())
2843 SmallDenseSet<unsigned> LocOpsToJoin;
2845 auto FirstValueIt = LiveOuts.find(BlockOrders[0]);
2846 if (FirstValueIt == LiveOuts.end())
2848 const DbgValue &FirstValue = *FirstValueIt->second;
2850 for (
const auto p : BlockOrders) {
2851 auto OutValIt = LiveOuts.find(p);
2852 if (OutValIt == LiveOuts.end())
2855 const DbgValue &OutVal = *OutValIt->second;
2873 LocOpsToJoin.
insert(Idx);
2876 DbgOpID FirstValOp = FirstValue.
getDbgOpID(Idx);
2878 if (FirstValOp != OutValOp) {
2884 LocOpsToJoin.
insert(Idx);
2899 std::optional<ValueIDNum> JoinedOpLoc =
2900 pickOperandPHILoc(Idx,
MBB, LiveOuts, MOutLocs, BlockOrders);
2905 NewDbgOps.
push_back(DbgOpStore.insert(*JoinedOpLoc));
2908 OutValues.
append(NewDbgOps);
2912std::optional<ValueIDNum> InstrRefBasedLDV::pickOperandPHILoc(
2920 unsigned NumLocs = MTracker->getNumLocs();
2922 for (
const auto p : BlockOrders) {
2923 auto OutValIt = LiveOuts.find(p);
2924 assert(OutValIt != LiveOuts.end());
2925 const DbgValue &OutVal = *OutValIt->second;
2926 DbgOpID OutValOpID = OutVal.
getDbgOpID(DbgOpIdx);
2927 DbgOp OutValOp = DbgOpStore.find(OutValOpID);
2938 ValueIDNum ValToLookFor = OutValOp.
ID;
2940 for (
unsigned int I = 0;
I < NumLocs; ++
I) {
2941 if (MOutLocs[*p][
I] == ValToLookFor)
2942 Locs.
back().push_back(LocIdx(
I));
2952 for (
unsigned int I = 0;
I < NumLocs; ++
I) {
2954 if (MOutLocs[*p][
I] == MPHI)
2955 Locs.
back().push_back(LocIdx(
I));
2965 for (
unsigned int I = 1;
I < Locs.
size(); ++
I) {
2966 auto &LocVec = Locs[
I];
2968 std::set_intersection(CandidateLocs.
begin(), CandidateLocs.
end(),
2969 LocVec.begin(), LocVec.end(), std::inserter(NewCandidates, NewCandidates.
begin()));
2970 CandidateLocs = std::move(NewCandidates);
2972 if (CandidateLocs.
empty())
2973 return std::nullopt;
2978 LocIdx
L = *CandidateLocs.
begin();
2985bool InstrRefBasedLDV::vlocJoin(
2995 auto Cmp = [&](MachineBasicBlock *
A, MachineBasicBlock *
B) {
2996 return BBToOrder[
A] < BBToOrder[
B];
3001 unsigned CurBlockRPONum = BBToOrder[&
MBB];
3007 int BackEdgesStart = 0;
3008 for (
auto *p : BlockOrders) {
3011 if (!BlocksToExplore.
contains(p)) {
3017 DbgValue &OutLoc = *VLOCOutLocs.find(p)->second;
3021 unsigned ThisBBRPONum = BBToOrder[
p];
3022 if (ThisBBRPONum < CurBlockRPONum)
3025 Values.
push_back(std::make_pair(p, &OutLoc));
3031 if (Bail || Values.
size() == 0)
3037 const DbgValue &FirstVal = *Values[0].second;
3052 for (
const auto &V : Values) {
3053 if (!
V.second->Properties.isJoinable(FirstVal.
Properties))
3057 if (!
V.second->hasJoinableLocOps(FirstVal))
3062 bool Disagree =
false;
3063 for (
auto &V : Values) {
3064 if (*
V.second == FirstVal)
3070 if (
V.second->hasIdenticalValidLocOps(FirstVal))
3077 std::distance(Values.begin(), &V) >= BackEdgesStart)
3099void InstrRefBasedLDV::getBlocksForScope(
3104 LS.getMachineBasicBlocks(DILoc, BlocksToExplore);
3112 DenseSet<const MachineBasicBlock *> ToAdd;
3119 for (
const auto *
MBB : BlocksToExplore) {
3129 if (BlocksToExplore.count(succ))
3131 if (!ArtificialBlocks.count(succ))
3134 DFS.push_back({succ, succ->succ_begin()});
3138 while (!DFS.empty()) {
3139 const MachineBasicBlock *CurBB = DFS.back().first;
3142 if (CurSucc == CurBB->succ_end()) {
3149 if (!ToAdd.
count(*CurSucc) && ArtificialBlocks.count(*CurSucc)) {
3151 DFS.push_back({*CurSucc, (*CurSucc)->succ_begin()});
3159 BlocksToExplore.insert_range(ToAdd);
3162void InstrRefBasedLDV::buildVLocValueMap(
3172 std::priority_queue<unsigned int, std::vector<unsigned int>,
3173 std::greater<unsigned int>>
3175 SmallPtrSet<MachineBasicBlock *, 16> OnWorklist, OnPending;
3178 SmallPtrSet<const MachineBasicBlock *, 8> BlocksToExplore;
3182 SmallVector<unsigned, 32> BlockOrderNums;
3184 getBlocksForScope(DILoc, BlocksToExplore, AssignBlocks);
3190 if (BlocksToExplore.
size() == 1)
3196 SmallPtrSet<MachineBasicBlock *, 8> MutBlocksToExplore;
3197 for (
const auto *
MBB : BlocksToExplore)
3198 MutBlocksToExplore.
insert(
const_cast<MachineBasicBlock *
>(
MBB));
3203 for (
const auto *
MBB : BlocksToExplore)
3207 for (
unsigned int I : BlockOrderNums)
3209 BlockOrderNums.clear();
3210 unsigned NumBlocks = BlockOrders.
size();
3219 DbgValueProperties EmptyProperties(EmptyExpr,
false,
false);
3220 for (
unsigned int I = 0;
I < NumBlocks; ++
I) {
3229 LiveOutIdx.reserve(NumBlocks);
3230 LiveInIdx.reserve(NumBlocks);
3231 for (
unsigned I = 0;
I < NumBlocks; ++
I) {
3232 LiveOutIdx[BlockOrders[
I]] = &LiveOuts[
I];
3233 LiveInIdx[BlockOrders[
I]] = &LiveIns[
I];
3243 for (
unsigned int I = 0;
I < NumBlocks; ++
I) {
3245 LiveIns[
I] = EmptyDbgValue;
3246 LiveOuts[
I] = EmptyDbgValue;
3251 SmallPtrSet<MachineBasicBlock *, 32> DefBlocks;
3252 for (
const MachineBasicBlock *ExpMBB : BlocksToExplore) {
3253 auto &TransferFunc = AllTheVLocs[ExpMBB->getNumber()].Vars;
3254 if (TransferFunc.contains(
VarID))
3255 DefBlocks.
insert(
const_cast<MachineBasicBlock *
>(ExpMBB));
3258 SmallVector<MachineBasicBlock *, 32> PHIBlocks;
3262 if (DefBlocks.
size() == 1) {
3263 placePHIsForSingleVarDefinition(MutBlocksToExplore, *DefBlocks.
begin(),
3264 AllTheVLocs,
VarID, Output);
3269 BlockPHIPlacement(MutBlocksToExplore, DefBlocks, PHIBlocks);
3272 for (MachineBasicBlock *PHIMBB : PHIBlocks) {
3273 unsigned BlockNo = PHIMBB->getNumber();
3274 DbgValue *LiveIn = LiveInIdx[PHIMBB];
3278 for (
auto *
MBB : BlockOrders) {
3279 Worklist.push(BBToOrder[
MBB]);
3290 bool FirstTrip =
true;
3291 while (!Worklist.empty() || !Pending.empty()) {
3292 while (!Worklist.empty()) {
3293 auto *
MBB = OrderToBB[Worklist.top()];
3297 auto LiveInsIt = LiveInIdx.find(
MBB);
3298 assert(LiveInsIt != LiveInIdx.end());
3299 DbgValue *LiveIn = LiveInsIt->second;
3303 bool InLocsChanged =
3304 vlocJoin(*
MBB, LiveOutIdx, BlocksToExplore, *LiveIn);
3319 if (pickVPHILoc(JoinedOps, *
MBB, LiveOutIdx, MOutLocs, Preds)) {
3321 InLocsChanged |= NewLocPicked;
3327 if (!InLocsChanged && !FirstTrip)
3330 DbgValue *LiveOut = LiveOutIdx[
MBB];
3331 bool OLChanged =
false;
3335 auto TransferIt = VTracker.Vars.find(
VarID);
3336 if (TransferIt != VTracker.Vars.end()) {
3340 if (*LiveOut != NewVal) {
3346 if (*LiveOut != TransferIt->second) {
3347 *LiveOut = TransferIt->second;
3353 if (*LiveOut != *LiveIn) {
3368 if (!LiveInIdx.contains(s))
3371 unsigned Order = BBToOrder[s];
3372 if (Order > BBToOrder[
MBB]) {
3373 if (OnWorklist.
insert(s).second)
3374 Worklist.push(Order);
3375 }
else if (OnPending.
insert(s).second && (FirstTrip || OLChanged)) {
3376 Pending.push(Order);
3380 Worklist.swap(Pending);
3390 for (
auto *
MBB : BlockOrders) {
3391 DbgValue *BlockLiveIn = LiveInIdx[
MBB];
3398 [[maybe_unused]]
auto &[Var, DILoc] = DVMap.lookupDVID(
VarID);
3400 Var.getFragment() &&
3401 "Fragment info missing during value prop");
3406 BlockOrders.clear();
3407 BlocksToExplore.clear();
3410void InstrRefBasedLDV::placePHIsForSingleVarDefinition(
3425 VLocTracker &VLocs = AllTheVLocs[AssignMBB->
getNumber()];
3427 const DbgValue &
Value = ValueIt->second;
3437 for (
auto *ScopeBlock : InScopeBlocks) {
3438 if (!DomTree->properlyDominates(AssignMBB, ScopeBlock))
3441 Output[ScopeBlock->getNumber()].push_back({
VarID,
Value});
3448#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
3451 for (
const auto &
P : mloc_transfer) {
3452 std::string foo = MTracker->LocIdxToName(
P.first);
3453 std::string bar = MTracker->IDAsString(
P.second);
3454 dbgs() <<
"Loc " << foo <<
" --> " << bar <<
"\n";
3465 auto hasNonArtificialLocation = [](
const MachineInstr &
MI) ->
bool {
3467 return DL.getLine() != 0;
3473 unsigned int Size = 0;
3474 for (
auto &
MBB : MF) {
3477 ArtificialBlocks.insert(&
MBB);
3481 ReversePostOrderTraversal<MachineFunction *> RPOT(&MF);
3482 unsigned int RPONumber = 0;
3483 OrderToBB.reserve(
Size);
3484 BBToOrder.reserve(
Size);
3485 BBNumToRPO.reserve(
Size);
3486 auto processMBB = [&](MachineBasicBlock *
MBB) {
3487 OrderToBB.push_back(
MBB);
3488 BBToOrder[
MBB] = RPONumber;
3492 for (MachineBasicBlock *
MBB : RPOT)
3494 for (MachineBasicBlock &
MBB : MF)
3495 if (!BBToOrder.contains(&
MBB))
3501#ifdef EXPENSIVE_CHECKS
3504 if (MF.DebugValueSubstitutions.size() > 2) {
3505 for (
auto It = MF.DebugValueSubstitutions.begin();
3506 It != std::prev(MF.DebugValueSubstitutions.end()); ++It) {
3507 assert(It->Src != std::next(It)->Src &&
"Duplicate variable location "
3508 "substitution seen");
3517void InstrRefBasedLDV::makeDepthFirstEjectionMap(
3519 const ScopeToDILocT &ScopeToDILocation,
3520 ScopeToAssignBlocksT &ScopeToAssignBlocks) {
3521 SmallPtrSet<const MachineBasicBlock *, 8> BlocksToExplore;
3523 auto *TopScope = LS.getCurrentFunctionScope();
3527 WorkStack.
push_back({TopScope, TopScope->getChildren().size() - 1});
3529 while (!WorkStack.
empty()) {
3530 auto &ScopePosition = WorkStack.
back();
3531 LexicalScope *WS = ScopePosition.first;
3532 ssize_t ChildNum = ScopePosition.second--;
3535 if (ChildNum >= 0) {
3538 auto &ChildScope =
Children[ChildNum];
3540 std::make_pair(ChildScope, ChildScope->getChildren().size() - 1));
3547 auto DILocationIt = ScopeToDILocation.find(WS);
3548 if (DILocationIt != ScopeToDILocation.end()) {
3549 getBlocksForScope(DILocationIt->second, BlocksToExplore,
3550 ScopeToAssignBlocks.find(WS)->second);
3551 for (
const auto *
MBB : BlocksToExplore) {
3553 if (EjectionMap[BBNum] == 0)
3557 BlocksToExplore.clear();
3563bool InstrRefBasedLDV::depthFirstVLocAndEmit(
3564 unsigned MaxNumBlocks,
const ScopeToDILocT &ScopeToDILocation,
3565 const ScopeToVarsT &ScopeToVars, ScopeToAssignBlocksT &ScopeToAssignBlocks,
3568 bool ShouldEmitDebugEntryValues) {
3569 TTracker =
new TransferTracker(TII, MTracker, MF, DVMap, *TRI,
3570 CalleeSavedRegs, ShouldEmitDebugEntryValues);
3571 unsigned NumLocs = MTracker->getNumLocs();
3575 if (!LS.getCurrentFunctionScope())
3579 SmallVector<unsigned, 16> EjectionMap;
3581 makeDepthFirstEjectionMap(EjectionMap, ScopeToDILocation,
3582 ScopeToAssignBlocks);
3587 auto EjectBlock = [&](MachineBasicBlock &
MBB) ->
void {
3589 AllTheVLocs[BBNum].
clear();
3594 MTracker->loadFromArray(MInLocs[
MBB], BBNum);
3595 TTracker->loadInlocs(
MBB, MInLocs[
MBB], DbgOpStore, Output[BBNum], NumLocs);
3599 for (
auto &
MI :
MBB) {
3600 process(
MI, &MOutLocs, &MInLocs);
3601 TTracker->checkInstForNewValues(CurInst,
MI.getIterator());
3609 Output[BBNum].clear();
3610 AllTheVLocs[BBNum].
clear();
3613 SmallPtrSet<const MachineBasicBlock *, 8> BlocksToExplore;
3615 WorkStack.
push_back({LS.getCurrentFunctionScope(), 0});
3616 unsigned HighestDFSIn = 0;
3619 while (!WorkStack.
empty()) {
3620 auto &ScopePosition = WorkStack.
back();
3621 LexicalScope *WS = ScopePosition.first;
3622 ssize_t ChildNum = ScopePosition.second++;
3629 auto DILocIt = ScopeToDILocation.find(WS);
3630 if (HighestDFSIn <= WS->getDFSIn() && DILocIt != ScopeToDILocation.end()) {
3631 const DILocation *DILoc = DILocIt->second;
3632 auto &VarsWeCareAbout = ScopeToVars.find(WS)->second;
3633 auto &BlocksInScope = ScopeToAssignBlocks.find(WS)->second;
3635 buildVLocValueMap(DILoc, VarsWeCareAbout, BlocksInScope, Output, MOutLocs,
3636 MInLocs, AllTheVLocs);
3639 HighestDFSIn = std::max(HighestDFSIn, WS->
getDFSIn());
3643 if (ChildNum < (ssize_t)
Children.size()) {
3645 auto &ChildScope =
Children[ChildNum];
3646 WorkStack.
push_back(std::make_pair(ChildScope, 0));
3652 auto DILocationIt = ScopeToDILocation.find(WS);
3653 if (DILocationIt == ScopeToDILocation.end())
3656 getBlocksForScope(DILocationIt->second, BlocksToExplore,
3657 ScopeToAssignBlocks.find(WS)->second);
3658 for (
const auto *
MBB : BlocksToExplore)
3660 EjectBlock(
const_cast<MachineBasicBlock &
>(*
MBB));
3662 BlocksToExplore.clear();
3671 for (
auto *
MBB : ArtificialBlocks)
3675 return emitTransfers();
3678bool InstrRefBasedLDV::emitTransfers() {
3682 for (
auto &
P : TTracker->Transfers) {
3691 MachineBasicBlock &
MBB = *
P.MBB;
3692 for (
const auto &Pair :
P.Insts)
3697 if (
P.Pos->isTerminator())
3701 for (
const auto &Pair :
P.Insts)
3706 return TTracker->Transfers.size() != 0;
3713 bool ShouldEmitDebugEntryValues,
3715 unsigned InputDbgValLimit) {
3722 this->DomTree = DomTree;
3729 LS.scanFunction(MF);
3732 AdjustsStackInCalls = MFI->adjustsStack() &&
3734 if (AdjustsStackInCalls)
3735 StackProbeSymbolName = STI.getTargetLowering()->getStackProbeSymbolName(MF);
3747 for (
auto &
MBB : MF)
3758 produceMLocTransferFunction(MF, MLocTransfer,
MaxNumBlocks);
3763 unsigned NumLocs = MTracker->getNumLocs();
3771 buildMLocValueMap(MF, MInLocs, MOutLocs, MLocTransfer);
3775 for (
auto &DBG_PHI : DebugPHINumToValue) {
3777 if (!DBG_PHI.ValueRead)
3780 ValueIDNum &Num = *DBG_PHI.ValueRead;
3785 LocIdx LocNo = Num.
getLoc();
3786 ValueIDNum ResolvedValue = MInLocs[BlockNo][LocNo.
asU64()];
3791 Num = ResolvedValue;
3798 for (MachineBasicBlock *
MBB : OrderToBB) {
3800 VTracker = &vlocs[CurBB];
3801 VTracker->MBB =
MBB;
3802 MTracker->loadFromArray(MInLocs[*
MBB], CurBB);
3804 for (
auto &
MI : *
MBB) {
3805 process(
MI, &MOutLocs, &MInLocs);
3823 unsigned VarAssignCount = 0;
3824 for (MachineBasicBlock *
MBB : OrderToBB) {
3827 for (
auto &idx : VTracker->Vars) {
3829 const DILocation *ScopeLoc = VTracker->Scopes[
VarID];
3830 assert(ScopeLoc !=
nullptr);
3831 auto *
Scope = LS.findLexicalScope(ScopeLoc);
3834 assert(Scope !=
nullptr);
3837 ScopeToAssignBlocks[
Scope].insert(VTracker->MBB);
3838 ScopeToDILocation[
Scope] = ScopeLoc;
3849 VarAssignCount > InputDbgValLimit) {
3850 LLVM_DEBUG(
dbgs() <<
"Disabling InstrRefBasedLDV: " << MF.getName()
3853 <<
" variable assignments, exceeding limits.\n");
3858 Changed = depthFirstVLocAndEmit(
3859 MaxNumBlocks, ScopeToDILocation, ScopeToVars, ScopeToAssignBlocks,
3860 SavedLiveIns, MOutLocs, MInLocs, vlocs, MF, ShouldEmitDebugEntryValues);
3869 ArtificialBlocks.clear();
3873 DebugInstrNumToInstr.clear();
3874 DebugPHINumToValue.clear();
3875 OverlapFragments.clear();
3876 SeenFragments.clear();
3877 SeenDbgPHIs.clear();
3903 LDVSSABlock *ParentBlock;
3904 BlockValueNum PHIValNum;
3905 LDVSSAPhi(BlockValueNum PHIValNum, LDVSSABlock *ParentBlock)
3906 : ParentBlock(ParentBlock), PHIValNum(PHIValNum) {}
3908 LDVSSABlock *
getParent() {
return ParentBlock; }
3913class LDVSSABlockIterator {
3916 LDVSSAUpdater &Updater;
3919 LDVSSAUpdater &Updater)
3920 : PredIt(PredIt), Updater(Updater) {}
3922 bool operator!=(
const LDVSSABlockIterator &OtherIt)
const {
3923 return OtherIt.PredIt != PredIt;
3926 LDVSSABlockIterator &operator++() {
3939 MachineBasicBlock &BB;
3940 LDVSSAUpdater &Updater;
3941 using PHIListT = SmallVector<LDVSSAPhi, 1>;
3945 LDVSSABlock(MachineBasicBlock &BB, LDVSSAUpdater &Updater)
3946 : BB(BB), Updater(Updater) {}
3949 return LDVSSABlockIterator(BB.
succ_begin(), Updater);
3953 return LDVSSABlockIterator(BB.
succ_end(), Updater);
3957 LDVSSAPhi *newPHI(BlockValueNum
Value) {
3958 PHIList.emplace_back(
Value,
this);
3959 return &PHIList.back();
3963 PHIListT &phis() {
return PHIList; }
3969class LDVSSAUpdater {
3972 DenseMap<BlockValueNum, LDVSSAPhi *> PHIs;
3975 DenseMap<MachineBasicBlock *, BlockValueNum> PoisonMap;
3977 DenseMap<MachineBasicBlock *, LDVSSABlock *> BlockMap;
3981 const FuncValueTable &MLiveIns;
3983 LDVSSAUpdater(LocIdx L,
const FuncValueTable &MLiveIns)
3984 : Loc(
L), MLiveIns(MLiveIns) {}
3987 for (
auto &
Block : BlockMap)
3988 delete Block.second;
3995 ~LDVSSAUpdater() { reset(); }
3999 LDVSSABlock *getSSALDVBlock(MachineBasicBlock *BB) {
4000 auto [It,
Inserted] = BlockMap.try_emplace(BB);
4002 It->second =
new LDVSSABlock(*BB, *
this);
4008 BlockValueNum getValue(LDVSSABlock *LDVBB) {
4009 return MLiveIns[LDVBB->BB][Loc.
asU64()].asU64();
4013LDVSSABlock *LDVSSABlockIterator::operator*() {
4014 return Updater.getSSALDVBlock(*PredIt);
4020 out <<
"SSALDVPHI " <<
PHI.PHIValNum;
4055 : PHI(
P), Idx(PHI->IncomingValues.
size()) {}
4080 Preds->
push_back(BB->Updater.getSSALDVBlock(Pred));
4086 static BlockValueNum
GetPoisonVal(LDVSSABlock *BB, LDVSSAUpdater *Updater) {
4091 Updater->PoisonMap[&BB->BB] = Num;
4101 LDVSSAUpdater *Updater) {
4102 BlockValueNum PHIValNum = Updater->getValue(BB);
4103 LDVSSAPhi *
PHI = BB->newPHI(PHIValNum);
4104 Updater->PHIs[PHIValNum] =
PHI;
4111 PHI->IncomingValues.push_back(std::make_pair(Pred, Val));
4116 static LDVSSAPhi *
ValueIsPHI(BlockValueNum Val, LDVSSAUpdater *Updater) {
4117 return Updater->PHIs.lookup(Val);
4124 if (
PHI &&
PHI->IncomingValues.size() == 0)
4136std::optional<ValueIDNum> InstrRefBasedLDV::resolveDbgPHIs(
4141 auto SeenDbgPHIIt = SeenDbgPHIs.find(std::make_pair(&Here, InstrNum));
4142 if (SeenDbgPHIIt != SeenDbgPHIs.end())
4143 return SeenDbgPHIIt->second;
4145 std::optional<ValueIDNum>
Result =
4146 resolveDbgPHIsImpl(MF, MLiveOuts, MLiveIns, Here, InstrNum);
4147 SeenDbgPHIs.insert({std::make_pair(&Here, InstrNum),
Result});
4151std::optional<ValueIDNum> InstrRefBasedLDV::resolveDbgPHIsImpl(
4156 auto RangePair = std::equal_range(DebugPHINumToValue.begin(),
4157 DebugPHINumToValue.end(), InstrNum);
4158 auto LowerIt = RangePair.first;
4159 auto UpperIt = RangePair.second;
4162 if (LowerIt == UpperIt)
4163 return std::nullopt;
4169 auto DBGPHIRange =
make_range(LowerIt, UpperIt);
4170 for (
const DebugPHIRecord &DBG_PHI : DBGPHIRange)
4171 if (!DBG_PHI.ValueRead)
4172 return std::nullopt;
4175 if (std::distance(LowerIt, UpperIt) == 1)
4176 return *LowerIt->ValueRead;
4182 LocIdx Loc = *LowerIt->ReadLoc;
4191 LDVSSAUpdater Updater(Loc, MLiveIns);
4193 DenseMap<LDVSSABlock *, BlockValueNum> AvailableValues;
4199 for (
const auto &DBG_PHI : DBGPHIRange) {
4200 LDVSSABlock *
Block = Updater.getSSALDVBlock(DBG_PHI.MBB);
4201 const ValueIDNum &Num = *DBG_PHI.ValueRead;
4205 LDVSSABlock *HereBlock = Updater.getSSALDVBlock(Here.
getParent());
4206 const auto &AvailIt = AvailableValues.
find(HereBlock);
4207 if (AvailIt != AvailableValues.
end()) {
4215 SSAUpdaterImpl<LDVSSAUpdater> Impl(&Updater, &AvailableValues, &CreatedPHIs);
4216 BlockValueNum ResultInt = Impl.GetValue(Updater.getSSALDVBlock(Here.
getParent()));
4230 DenseMap<LDVSSABlock *, ValueIDNum> ValidatedValues;
4233 for (
const auto &DBG_PHI : DBGPHIRange) {
4234 LDVSSABlock *
Block = Updater.getSSALDVBlock(DBG_PHI.MBB);
4235 const ValueIDNum &Num = *DBG_PHI.ValueRead;
4236 ValidatedValues.
insert(std::make_pair(
Block, Num));
4242 llvm::sort(SortedPHIs, [&](LDVSSAPhi *
A, LDVSSAPhi *
B) {
4243 return BBToOrder[&
A->getParent()->BB] < BBToOrder[&
B->getParent()->BB];
4246 for (
auto &
PHI : SortedPHIs) {
4247 ValueIDNum ThisBlockValueNum = MLiveIns[
PHI->ParentBlock->BB][Loc.
asU64()];
4250 for (
auto &PHIIt :
PHI->IncomingValues) {
4252 if (Updater.PoisonMap.contains(&PHIIt.first->BB))
4253 return std::nullopt;
4255 ValueIDNum ValueToCheck;
4256 const ValueTable &BlockLiveOuts = MLiveOuts[PHIIt.first->BB];
4258 auto VVal = ValidatedValues.
find(PHIIt.first);
4259 if (VVal == ValidatedValues.
end()) {
4264 ValueToCheck = ThisBlockValueNum;
4268 ValueToCheck = VVal->second;
4271 if (BlockLiveOuts[Loc.
asU64()] != ValueToCheck)
4272 return std::nullopt;
4276 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)
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.