105#include "llvm/Config/llvm-config.h"
137#define DEBUG_TYPE "livedebugvalues"
142 cl::desc(
"Act like old LiveDebugValues did"),
156 cl::desc(
"livedebugvalues-stack-ws-limit"),
302 unsigned Location : 24;
303 unsigned Quality : 8;
308 : Location(L.asU64()), Quality(static_cast<
unsigned>(Q)) {}
321 std::optional<LocationQuality>
351 bool IsValueValid =
true;
352 unsigned LastUseBeforeDef = 0;
368 IsValueValid =
false;
378 auto ValuesPreferredLoc = ValueToLoc.
find(Num);
379 if (ValuesPreferredLoc->second.isIllegal()) {
385 LastUseBeforeDef = std::max(LastUseBeforeDef,
386 static_cast<unsigned>(Num.
getInst()));
390 IsValueValid =
false;
396 LocIdx M = ValuesPreferredLoc->second.getLoc();
406 if (LastUseBeforeDef) {
418 auto Result =
ActiveVLocs.insert(std::make_pair(Var, NewValue));
420 Result.first->second = NewValue;
447 for (
const auto &VLoc : VLocs)
449 for (
DbgOpID OpID : VLoc.second.getDbgOpIDs())
450 if (!OpID.ID.IsConst)
467 auto VIt = ValueToLoc.
find(VNum);
468 if (VIt == ValueToLoc.
end())
471 auto &Previous = VIt->second;
474 std::optional<LocationQuality> ReplacementQuality =
476 if (ReplacementQuality)
481 for (
const auto &Var : VLocs) {
511 for (
auto &
Use : MIt->second) {
516 assert(!
Op.isUndef() &&
"UseBeforeDef erroneously created for a "
517 "DbgValue with undef values.");
526 if (ValueToLoc.
empty())
535 auto VIt = ValueToLoc.
find(LocValueID);
536 if (VIt == ValueToLoc.
end())
539 auto &Previous = VIt->second;
542 std::optional<LocationQuality> ReplacementQuality =
544 if (ReplacementQuality)
550 for (
auto &
Use : MIt->second) {
561 LocIdx NewLoc = ValueToLoc.
find(
Op.ID)->second.getLoc();
570 if (DbgOps.
size() !=
Use.Values.size())
622 return Reg != SP && Reg !=
FP;
639 auto NonVariadicExpression =
641 if (!NonVariadicExpression)
643 DIExpr = *NonVariadicExpression;
668 MI.getDebugLoc()->getInlinedAt());
672 if (
MI.isUndefDebugValue() ||
677 for (
LocIdx Loc : It->second.loc_indices())
707 MI.getDebugLoc()->getInlinedAt());
714 for (
LocIdx Loc : It->second.loc_indices())
719 if (NewLocs.
empty()) {
739 for (
LocIdx Loc : LostVLocIt->second.loc_indices()) {
749 for (
const auto &LostMLoc : LostMLocs)
764 It->second.Ops.assign(NewLocs);
765 It->second.Properties = Properties;
774 bool MakeUndef =
true) {
796 std::optional<LocIdx> NewLoc;
798 if (Loc.Value == OldValue)
803 if (!NewLoc && !MakeUndef) {
805 for (
const auto &Var : ActiveMLocIt->second) {
806 auto &Prop =
ActiveVLocs.find(Var)->second.Properties;
818 for (
const auto &Var : ActiveMLocIt->second) {
833 DbgOps.
insert(DbgOps.
begin(), ActiveVLocIt->second.Ops.size(),
843 for (
LocIdx Loc : ActiveVLocIt->second.loc_indices()) {
849 ActiveVLocIt->second.Ops = DbgOps;
856 for (
auto &LocVarIt : LostMLocs) {
859 "Variable was using this MLoc, but ActiveMLocs[MLoc] has no "
861 LostMLocIt->second.erase(LocVarIt.second);
867 VarLocs[NewLoc->asU64()] = OldValue;
872 ActiveMLocIt->second.clear();
873 if (!NewMLocs.
empty())
874 for (
auto &Var : NewMLocs)
898 for (
const auto &Var : MovingVars) {
903 std::replace(ActiveVLocIt->second.Ops.begin(),
904 ActiveVLocIt->second.Ops.end(),
SrcOp,
DstOp);
907 ActiveVLocIt->second.Properties);
932 MIB.addMetadata(Properties.
DIExpr);
993 LocIdxToIDNum(
ValueIDNum::EmptyValue), LocIdxToLocID(0) {
1031 if (
Size > 60000 || Offs > 60000)
1067 if (MaskPair.first->clobbersPhysReg(
ID)) {
1069 ValNum = {
CurBB, MaskPair.second, NewIdx};
1090 Masks.push_back(std::make_pair(MO, InstID));
1096 if (SpillID.
id() == 0) {
1100 return std::nullopt;
1105 for (
unsigned StackIdx = 0; StackIdx <
NumSlotIdxes; ++StackIdx) {
1126 return Twine(
"slot ")
1143 std::string MLocName =
LocIdxToName(Location.Value.getLoc());
1144 std::string DefName = Location.Value.asString(MLocName);
1152 dbgs() <<
"Idx " << Location.Idx.asU64() <<
" " << foo <<
"\n";
1166 ?
TII.
get(TargetOpcode::DBG_VALUE_LIST)
1167 :
TII.
get(TargetOpcode::DBG_VALUE);
1169#ifdef EXPENSIVE_CHECKS
1172 return Op.IsConst || !
Op.Loc.isIllegal();
1174 "Did not expect illegal ops in DbgOps.");
1177 "Expected to have either one DbgOp per MI LocationOp, or none.");
1190 auto EmitUndef = [&]() {
1202 bool Indirect = Properties.
Indirect;
1224 unsigned short Offset = StackIdx.second;
1251 bool UseDerefSize =
false;
1253 unsigned DerefSizeInBytes = ValueSizeInBits / 8;
1255 unsigned VariableSizeInBits = Fragment->SizeInBits;
1256 if (VariableSizeInBits != ValueSizeInBits || Expr->
isComplex())
1257 UseDerefSize =
true;
1259 if (*
Size != ValueSizeInBits) {
1260 UseDerefSize =
true;
1266 bool StackValue =
false;
1273 OffsetOps.
push_back(dwarf::DW_OP_deref);
1280 OffsetOps.
push_back(dwarf::DW_OP_deref_size);
1286 OffsetOps.
push_back(dwarf::DW_OP_deref);
1319 if (CalleeSavedRegs.
test(*RAI))
1333std::optional<SpillLocationNo>
1334InstrRefBasedLDV::extractSpillBaseRegAndOffset(
const MachineInstr &
MI) {
1336 "Spill instruction does not have exactly one memory operand?");
1337 auto MMOI =
MI.memoperands_begin();
1340 "Inconsistent memory operand in spill instruction");
1341 int FI = cast<FixedStackPseudoSourceValue>(PVal)->getFrameIndex();
1348std::optional<LocIdx>
1350 std::optional<SpillLocationNo>
SpillLoc = extractSpillBaseRegAndOffset(
MI);
1352 return std::nullopt;
1358 auto *MemOperand = *
MI.memoperands_begin();
1359 unsigned SizeInBits = MemOperand->getSizeInBits();
1366 return std::nullopt;
1374bool InstrRefBasedLDV::transferDebugValue(
const MachineInstr &
MI) {
1375 if (!
MI.isDebugValue())
1383 "Expected inlined-at fields to agree");
1391 if (Scope ==
nullptr)
1397 if (MO.isReg() && MO.getReg() != 0)
1398 (void)MTracker->
readReg(MO.getReg());
1407 if (!
MI.isUndefDebugValue()) {
1413 }
else if (MO.isImm() || MO.isFPImm() || MO.isCImm()) {
1420 VTracker->
defVar(
MI, Properties, DebugOps);
1430std::optional<ValueIDNum> InstrRefBasedLDV::getValueForInstrRef(
1446 LowerBoundIt->Src == SoughtSub.Src) {
1447 std::tie(InstNo, OpNo) = LowerBoundIt->Dest;
1448 SoughtSub.Src = LowerBoundIt->Dest;
1449 if (
unsigned Subreg = LowerBoundIt->Subreg)
1450 SeenSubregs.push_back(Subreg);
1456 std::optional<ValueIDNum> NewID;
1460 auto InstrIt = DebugInstrNumToInstr.find(InstNo);
1462 if (InstrIt != DebugInstrNumToInstr.end()) {
1463 const MachineInstr &TargetInstr = *InstrIt->second.first;
1472 NewID =
ValueIDNum(BlockNo, InstrIt->second.second, *L);
1485 NewID =
ValueIDNum(BlockNo, InstrIt->second.second, L);
1491 {
dbgs() <<
"Seen instruction reference to illegal operand\n"; });
1495 }
else if (PHIIt != DebugPHINumToValue.
end() && PHIIt->InstrNum == InstNo) {
1498 NewID = resolveDbgPHIs(*
MI.getParent()->getParent(), MLiveOuts, MLiveIns,
1511 if (NewID && !SeenSubregs.empty()) {
1519 for (
unsigned Subreg :
reverse(SeenSubregs)) {
1523 Size = (
Size == 0) ? ThisSize : std::min(
Size, ThisSize);
1531 if (NewID && !MTracker->
isSpill(L)) {
1537 if (TRCI->contains(Reg))
1539 assert(TRC &&
"Couldn't find target register class?");
1551 if (SubregSize ==
Size && SubregOffset ==
Offset) {
1559 NewID = std::nullopt;
1564 NewID =
ValueIDNum(NewID->getBlock(), NewID->getInst(), NewLoc);
1569 NewID = std::nullopt;
1579 if (!
MI.isDebugRef())
1584 if (!VTracker && !TTracker)
1592 "Expected inlined-at fields to agree");
1597 if (Scope ==
nullptr)
1603 assert(!MO.
isReg() &&
"DBG_INSTR_REF should not contain registers");
1614 std::optional<ValueIDNum> NewID =
1615 getValueForInstrRef(InstNo, OpNo,
MI, MLiveOuts, MLiveIns);
1632 VTracker->
defVar(
MI, Properties, DbgOpIDs);
1641 for (
DbgOpID OpID : DbgOpIDs) {
1651 for (
const DbgOp &
Op : DbgOps) {
1653 if (FoundLocs.
insert({Op.ID, TransferTracker::LocationAndQuality()})
1658 for (
auto Location : MTracker->
locations()) {
1661 auto ValueToFindIt =
find(ValuesToFind,
ID);
1662 if (ValueToFindIt == ValuesToFind.
end())
1664 auto &Previous = FoundLocs.
find(
ID)->second;
1667 std::optional<TransferTracker::LocationQuality> ReplacementQuality =
1669 if (ReplacementQuality) {
1671 if (Previous.isBest()) {
1672 ValuesToFind.
erase(ValueToFindIt);
1673 if (ValuesToFind.
empty())
1697 if (!DbgOps.empty() && NewLocs.
empty()) {
1698 bool IsValidUseBeforeDef =
true;
1700 for (
auto ValueLoc : FoundLocs) {
1702 LocIdx FoundLoc = ValueLoc.second.getLoc();
1708 IsValidUseBeforeDef =
false;
1711 LastUseBeforeDef = std::max(LastUseBeforeDef, NewID.
getInst());
1713 if (IsValidUseBeforeDef) {
1715 DbgOps, LastUseBeforeDef);
1731 if (!
MI.isDebugPHI())
1735 if (VTracker || TTracker)
1741 unsigned InstrNum =
MI.getOperand(1).getImm();
1743 auto EmitBadPHI = [
this, &
MI, InstrNum]() ->
bool {
1749 {InstrNum,
MI.getParent(), std::nullopt, std::nullopt});
1758 auto PHIRec = DebugPHIRecord(
1765 }
else if (MO.
isFI()) {
1772 return EmitBadPHI();
1783 return EmitBadPHI();
1786 assert(
MI.getNumOperands() == 3 &&
"Stack DBG_PHI with no size?");
1787 unsigned slotBitSize =
MI.getOperand(2).getImm();
1789 unsigned SpillID = MTracker->
getLocID(*SpillNo, {slotBitSize, 0});
1794 auto DbgPHI = DebugPHIRecord({InstrNum,
MI.getParent(), Result,
SpillLoc});
1802 {
dbgs() <<
"Seen DBG_PHI with unrecognised operand format\n"; });
1803 return EmitBadPHI();
1812 if (
MI.isImplicitDef()) {
1822 }
else if (
MI.isMetaInstruction())
1830 bool CallChangesSP =
false;
1831 if (AdjustsStackInCalls &&
MI.isCall() &&
MI.getOperand(0).isSymbol() &&
1832 !strcmp(
MI.getOperand(0).getSymbolName(), StackProbeSymbolName.
data()))
1833 CallChangesSP =
true;
1837 auto IgnoreSPAlias = [
this, &
MI, CallChangesSP](
Register R) ->
bool {
1840 return MI.isCall() && MTracker->
SPAliases.count(R);
1852 !IgnoreSPAlias(MO.
getReg())) {
1865 MTracker->
defReg(DeadReg, CurBB, CurInst);
1867 for (
const auto *MO : RegMaskPtrs)
1872 if (std::optional<SpillLocationNo> SpillNo =
1873 extractSpillBaseRegAndOffset(
MI)) {
1890 for (
uint32_t DeadReg : DeadRegs) {
1897 if (!RegMaskPtrs.empty()) {
1904 if (IgnoreSPAlias(Reg))
1907 for (
const auto *MO : RegMaskPtrs)
1915 if (std::optional<SpillLocationNo> SpillNo =
1916 extractSpillBaseRegAndOffset(
MI)) {
1926void InstrRefBasedLDV::performCopy(
Register SrcRegNum,
Register DstRegNum) {
1929 MTracker->
defReg(*RAI, CurBB, CurInst);
1932 MTracker->
setReg(DstRegNum, SrcValue);
1936 unsigned SrcSubReg = SRI.getSubReg();
1937 unsigned SubRegIdx = SRI.getSubRegIndex();
1938 unsigned DstSubReg = TRI->
getSubReg(DstRegNum, SubRegIdx);
1953 MTracker->
setReg(DstSubReg, CpyValue);
1957std::optional<SpillLocationNo>
1961 if (!
MI.hasOneMemOperand())
1962 return std::nullopt;
1965 auto MMOI =
MI.memoperands_begin();
1968 return std::nullopt;
1970 if (!
MI.getSpillSize(TII) && !
MI.getFoldedSpillSize(TII))
1971 return std::nullopt;
1974 return extractSpillBaseRegAndOffset(
MI);
1979 if (!isSpillInstruction(
MI, MF))
1987std::optional<SpillLocationNo>
1990 if (!
MI.hasOneMemOperand())
1991 return std::nullopt;
1995 if (
MI.getRestoreSize(TII)) {
1996 Reg =
MI.getOperand(0).getReg();
1997 return extractSpillBaseRegAndOffset(
MI);
1999 return std::nullopt;
2002bool InstrRefBasedLDV::transferSpillOrRestoreInst(
MachineInstr &
MI) {
2031 if (std::optional<SpillLocationNo> Loc = isSpillInstruction(
MI, MF)) {
2034 for (
unsigned SlotIdx = 0; SlotIdx < MTracker->
NumSlotIdxes; ++SlotIdx) {
2036 std::optional<LocIdx> MLoc = MTracker->
getSpillMLoc(SpillID);
2045 MTracker->
setMLoc(*MLoc, Def);
2052 if (isLocationSpill(
MI, MF, Reg)) {
2057 auto DoTransfer = [&](
Register SrcReg,
unsigned SpillID) {
2058 auto ReadValue = MTracker->
readReg(SrcReg);
2060 MTracker->
setMLoc(DstLoc, ReadValue);
2073 unsigned SpillID = MTracker->
getLocID(Loc, SubregIdx);
2074 DoTransfer(SR, SpillID);
2080 DoTransfer(Reg, SpillID);
2082 std::optional<SpillLocationNo> Loc = isRestoreInstruction(
MI, MF, Reg);
2094 MTracker->
defReg(*RAI, CurBB, CurInst);
2098 auto DoTransfer = [&](
Register DestReg,
unsigned SpillID) {
2100 auto ReadValue = MTracker->
readMLoc(SrcIdx);
2101 MTracker->
setReg(DestReg, ReadValue);
2106 unsigned SpillID = MTracker->
getLocID(*Loc, Subreg);
2107 DoTransfer(SR, SpillID);
2112 unsigned SpillID = MTracker->
getLocID(*Loc, {
Size, 0});
2113 DoTransfer(Reg, SpillID);
2130 if (SrcReg == DestReg)
2159 if (MLocIt == TTracker->
ActiveMLocs.
end() || MLocIt->second.empty())
2162 ClobberedLocs[ClobberedLoc] =
Value;
2167 InstrRefBasedLDV::performCopy(SrcReg, DestReg);
2173 for (
auto LocVal : ClobberedLocs) {
2174 TTracker->
clobberMloc(LocVal.first, LocVal.second,
MI.getIterator(),
false);
2187 MTracker->
defReg(SrcReg, CurBB, CurInst);
2201 MI.getDebugLoc()->getInlinedAt());
2202 FragmentInfo ThisFragment = MIVar.getFragmentOrDefault();
2207 auto SeenIt = SeenFragments.
find(MIVar.getVariable());
2208 if (SeenIt == SeenFragments.
end()) {
2210 OneFragment.
insert(ThisFragment);
2211 SeenFragments.
insert({MIVar.getVariable(), OneFragment});
2213 OverlapFragments.
insert({{MIVar.getVariable(), ThisFragment}, {}});
2220 OverlapFragments.
insert({{MIVar.getVariable(), ThisFragment}, {}});
2221 if (!IsInOLapMap.second)
2224 auto &ThisFragmentsOverlaps = IsInOLapMap.first->second;
2225 auto &AllSeenFragments = SeenIt->second;
2230 for (
const auto &ASeenFragment : AllSeenFragments) {
2234 ThisFragmentsOverlaps.push_back(ASeenFragment);
2237 auto ASeenFragmentsOverlaps =
2238 OverlapFragments.
find({MIVar.getVariable(), ASeenFragment});
2239 assert(ASeenFragmentsOverlaps != OverlapFragments.
end() &&
2240 "Previously seen var fragment has no vector of overlaps");
2241 ASeenFragmentsOverlaps->second.push_back(ThisFragment);
2245 AllSeenFragments.insert(ThisFragment);
2253 if (transferDebugValue(
MI))
2255 if (transferDebugInstrRef(
MI, MLiveOuts, MLiveIns))
2257 if (transferDebugPHI(
MI))
2259 if (transferRegisterCopy(
MI))
2261 if (transferSpillOrRestoreInst(
MI))
2263 transferRegisterDef(
MI);
2266void InstrRefBasedLDV::produceMLocTransferFunction(
2282 for (
auto &BV : BlockMasks)
2286 for (
auto &
MBB : MF) {
2298 for (
auto &
MI :
MBB) {
2301 process(
MI,
nullptr,
nullptr);
2304 if (
MI.isDebugValueLike())
2305 accumulateFragmentMap(
MI);
2309 if (
uint64_t InstrNo =
MI.peekDebugInstrNum()) {
2310 auto InstrAndPos = std::make_pair(&
MI, CurInst);
2312 DebugInstrNumToInstr.insert(std::make_pair(InstrNo, InstrAndPos));
2315 assert(InsertResult.second);
2326 for (
auto Location : MTracker->
locations()) {
2329 if (
P.isPHI() &&
P.getLoc() ==
Idx.asU64())
2333 auto &TransferMap = MLocTransfer[CurBB];
2334 auto Result = TransferMap.insert(std::make_pair(
Idx.asU64(),
P));
2341 for (
auto &
P : MTracker->
Masks) {
2342 BlockMasks[CurBB].clearBitsNotInMask(
P.first->getRegMask(), BVWords);
2348 for (
auto Location : MTracker->
locations()) {
2366 for (
unsigned Bit : BV.
set_bits()) {
2369 auto &TransferMap = MLocTransfer[
I];
2378 TransferMap.insert(std::make_pair(
Idx.asU64(), NotGeneratedNum));
2383 ValueID = NotGeneratedNum;
2389bool InstrRefBasedLDV::mlocJoin(
2393 bool Changed =
false;
2406 return BBToOrder.find(
A)->second < BBToOrder.find(
B)->second;
2411 if (BlockOrders.
size() == 0)
2416 for (
auto Location : MTracker->
locations()) {
2421 ValueIDNum FirstVal = OutLocs[BlockOrders[0]->getNumber()][
Idx.asU64()];
2426 if (InLocs[
Idx.asU64()] != FirstVal) {
2427 InLocs[
Idx.asU64()] = FirstVal;
2435 bool Disagree =
false;
2436 for (
unsigned int I = 1;
I < BlockOrders.size(); ++
I) {
2442 if (FirstVal == PredLiveOut)
2455 InLocs[
Idx.asU64()] = FirstVal;
2464void InstrRefBasedLDV::findStackIndexInterference(
2484 if (!Pair.first.second)
2490void InstrRefBasedLDV::placeMLocPHIs(
2494 findStackIndexInterference(StackUnits);
2506 for (
auto Location : MTracker->
locations()) {
2515 bool AnyIllegal =
false;
2524 FoundRegUnits.
insert(*URoot);
2530 NormalLocsToPHI.
insert(L);
2534 RegUnitsToPHIUp.
insert(FoundRegUnits.
begin(), FoundRegUnits.
end());
2540 auto CollectPHIsForLoc = [&](
LocIdx L) {
2543 for (
unsigned int I = 0;
I < OrderToBB.size(); ++
I) {
2545 const auto &TransferFunc = MLocTransfer[
MBB->
getNumber()];
2546 if (TransferFunc.contains(L))
2553 if (!DefBlocks.
empty())
2559 BlockPHIPlacement(AllBlocks, DefBlocks, PHIBlocks);
2562 auto InstallPHIsAtLoc = [&PHIBlocks, &MInLocs](
LocIdx L) {
2568 for (
LocIdx L : NormalLocsToPHI) {
2569 CollectPHIsForLoc(L);
2571 InstallPHIsAtLoc(L);
2577 for (
unsigned Idx : StackUnits) {
2580 CollectPHIsForLoc(L);
2581 InstallPHIsAtLoc(L);
2587 unsigned ThisSize, ThisOffset;
2588 std::tie(ThisSize, ThisOffset) = Pair.first;
2594 InstallPHIsAtLoc(ThisL);
2600 for (
Register R : RegUnitsToPHIUp) {
2602 CollectPHIsForLoc(L);
2605 InstallPHIsAtLoc(L);
2615 InstallPHIsAtLoc(AliasLoc);
2620void InstrRefBasedLDV::buildMLocValueMap(
2623 std::priority_queue<unsigned int, std::vector<unsigned int>,
2624 std::greater<unsigned int>>
2635 for (
unsigned int I = 0;
I < BBToOrder.size(); ++
I) {
2637 OnWorklist.
insert(OrderToBB[
I]);
2638 AllBlocks.
insert(OrderToBB[
I]);
2642 for (
auto Location : MTracker->
locations())
2650 placeMLocPHIs(MF, AllBlocks, MInLocs, MLocTransfer);
2661 while (!Worklist.empty() || !Pending.empty()) {
2665 while (!Worklist.empty()) {
2672 InLocsChanged = mlocJoin(*
MBB, Visited, MOutLocs, MInLocs[CurBB]);
2673 InLocsChanged |= Visited.
insert(
MBB).second;
2686 for (
auto &
P : MLocTransfer[CurBB]) {
2687 if (
P.second.getBlock() == CurBB &&
P.second.isPHI()) {
2690 ToRemap.
push_back(std::make_pair(
P.first, NewID));
2693 assert(
P.second.getBlock() == CurBB);
2694 ToRemap.
push_back(std::make_pair(
P.first,
P.second));
2700 for (
auto &
P : ToRemap)
2706 bool OLChanged =
false;
2707 for (
auto Location : MTracker->
locations()) {
2723 if (BBToOrder[s] > BBToOrder[
MBB]) {
2725 if (OnWorklist.
insert(s).second)
2726 Worklist.push(BBToOrder[s]);
2729 if (OnPending.
insert(s).second)
2730 Pending.push(BBToOrder[s]);
2735 Worklist.swap(Pending);
2740 assert(Pending.empty() &&
"Pending should be empty");
2747void InstrRefBasedLDV::BlockPHIPlacement(
2756 IDF.setLiveInBlocks(AllBlocks);
2757 IDF.setDefiningBlocks(DefBlocks);
2758 IDF.calculate(PHIBlocks);
2761bool InstrRefBasedLDV::pickVPHILoc(
2767 if (BlockOrders.
empty())
2774 auto FirstValueIt = LiveOuts.
find(BlockOrders[0]);
2775 if (FirstValueIt == LiveOuts.end())
2777 const DbgValue &FirstValue = *FirstValueIt->second;
2779 for (
const auto p : BlockOrders) {
2780 auto OutValIt = LiveOuts.find(p);
2781 if (OutValIt == LiveOuts.end())
2784 const DbgValue &OutVal = *OutValIt->second;
2807 if (FirstValOp != OutValOp) {
2828 std::optional<ValueIDNum> JoinedOpLoc =
2829 pickOperandPHILoc(
Idx,
MBB, LiveOuts, MOutLocs, BlockOrders);
2837 OutValues.
append(NewDbgOps);
2841std::optional<ValueIDNum> InstrRefBasedLDV::pickOperandPHILoc(
2851 for (
const auto p : BlockOrders) {
2852 unsigned ThisBBNum =
p->getNumber();
2853 auto OutValIt = LiveOuts.find(p);
2854 assert(OutValIt != LiveOuts.end());
2855 const DbgValue &OutVal = *OutValIt->second;
2857 DbgOp OutValOp = DbgOpStore.
find(OutValOpID);
2870 for (
unsigned int I = 0;
I < NumLocs; ++
I) {
2871 if (MOutLocs[ThisBBNum][
I] == ValToLookFor)
2882 for (
unsigned int I = 0;
I < NumLocs; ++
I) {
2884 if (MOutLocs[ThisBBNum][
I] == MPHI)
2895 for (
unsigned int I = 1;
I < Locs.
size(); ++
I) {
2896 auto &LocVec = Locs[
I];
2898 std::set_intersection(CandidateLocs.
begin(), CandidateLocs.
end(),
2899 LocVec.begin(), LocVec.end(), std::inserter(NewCandidates, NewCandidates.
begin()));
2900 CandidateLocs = NewCandidates;
2902 if (CandidateLocs.
empty())
2903 return std::nullopt;
2915bool InstrRefBasedLDV::vlocJoin(
2920 bool Changed =
false;
2926 return BBToOrder[
A] < BBToOrder[
B];
2931 unsigned CurBlockRPONum = BBToOrder[&
MBB];
2937 int BackEdgesStart = 0;
2938 for (
auto *p : BlockOrders) {
2941 if (!BlocksToExplore.
contains(p)) {
2947 DbgValue &OutLoc = *VLOCOutLocs.find(p)->second;
2951 unsigned ThisBBRPONum = BBToOrder[
p];
2952 if (ThisBBRPONum < CurBlockRPONum)
2955 Values.
push_back(std::make_pair(p, &OutLoc));
2961 if (Bail || Values.
size() == 0)
2967 const DbgValue &FirstVal = *Values[0].second;
2973 Changed = LiveIn != FirstVal;
2982 for (
const auto &V : Values) {
2983 if (!
V.second->Properties.isJoinable(FirstVal.
Properties))
2987 if (!
V.second->hasJoinableLocOps(FirstVal))
2992 bool Disagree =
false;
2993 for (
auto &V : Values) {
2994 if (*
V.second == FirstVal)
3000 if (
V.second->hasIdenticalValidLocOps(FirstVal))
3007 std::distance(Values.begin(), &V) >= BackEdgesStart)
3015 Changed = LiveIn != FirstVal;
3022 Changed = LiveIn != VPHI;
3029void InstrRefBasedLDV::getBlocksForScope(
3039 BlocksToExplore.
insert(AssignBlocks.
begin(), AssignBlocks.
end());
3049 for (
const auto *
MBB : BlocksToExplore) {
3059 if (BlocksToExplore.count(succ))
3061 if (!ArtificialBlocks.count(succ))
3064 DFS.push_back({succ, succ->succ_begin()});
3068 while (!DFS.empty()) {
3072 if (CurSucc == CurBB->
succ_end()) {
3079 if (!ToAdd.
count(*CurSucc) && ArtificialBlocks.count(*CurSucc)) {
3081 DFS.push_back({*CurSucc, (*CurSucc)->succ_begin()});
3089 BlocksToExplore.insert(ToAdd.
begin(), ToAdd.
end());
3092void InstrRefBasedLDV::buildVLocValueMap(
3101 std::priority_queue<unsigned int, std::vector<unsigned int>,
3102 std::greater<unsigned int>>
3114 return BBToOrder[
A] < BBToOrder[
B];
3117 getBlocksForScope(DILoc, BlocksToExplore, AssignBlocks);
3123 if (BlocksToExplore.
size() == 1)
3130 for (
const auto *
MBB : BlocksToExplore)
3134 for (
const auto *
MBB : BlocksToExplore)
3138 unsigned NumBlocks = BlockOrders.
size();
3148 for (
unsigned int I = 0;
I < NumBlocks; ++
I) {
3157 LiveOutIdx.reserve(NumBlocks);
3158 LiveInIdx.reserve(NumBlocks);
3159 for (
unsigned I = 0;
I < NumBlocks; ++
I) {
3160 LiveOutIdx[BlockOrders[
I]] = &LiveOuts[
I];
3161 LiveInIdx[BlockOrders[
I]] = &LiveIns[
I];
3168 for (
const auto &Var : VarsWeCareAbout) {
3171 for (
unsigned int I = 0;
I < NumBlocks; ++
I) {
3173 LiveIns[
I] = EmptyDbgValue;
3174 LiveOuts[
I] = EmptyDbgValue;
3181 auto &TransferFunc = AllTheVLocs[ExpMBB->getNumber()].Vars;
3182 if (TransferFunc.contains(Var))
3190 if (DefBlocks.
size() == 1) {
3191 placePHIsForSingleVarDefinition(MutBlocksToExplore, *DefBlocks.
begin(),
3192 AllTheVLocs, Var, Output);
3197 BlockPHIPlacement(MutBlocksToExplore, DefBlocks, PHIBlocks);
3201 unsigned BlockNo = PHIMBB->getNumber();
3202 DbgValue *LiveIn = LiveInIdx[PHIMBB];
3206 for (
auto *
MBB : BlockOrders) {
3207 Worklist.push(BBToOrder[
MBB]);
3218 bool FirstTrip =
true;
3219 while (!Worklist.empty() || !Pending.empty()) {
3220 while (!Worklist.empty()) {
3221 auto *
MBB = OrderToBB[Worklist.top()];
3225 auto LiveInsIt = LiveInIdx.find(
MBB);
3226 assert(LiveInsIt != LiveInIdx.end());
3227 DbgValue *LiveIn = LiveInsIt->second;
3231 bool InLocsChanged =
3232 vlocJoin(*
MBB, LiveOutIdx, BlocksToExplore, *LiveIn);
3249 if (pickVPHILoc(JoinedOps, *
MBB, LiveOutIdx, MOutLocs, Preds)) {
3251 InLocsChanged |= NewLocPicked;
3257 if (!InLocsChanged && !FirstTrip)
3261 bool OLChanged =
false;
3265 auto TransferIt = VTracker.
Vars.find(Var);
3266 if (TransferIt != VTracker.
Vars.end()) {
3270 if (*LiveOut != NewVal) {
3276 if (*LiveOut != TransferIt->second) {
3277 *LiveOut = TransferIt->second;
3283 if (*LiveOut != *LiveIn) {
3298 if (!LiveInIdx.contains(s))
3301 if (BBToOrder[s] > BBToOrder[
MBB]) {
3302 if (OnWorklist.
insert(s).second)
3303 Worklist.push(BBToOrder[s]);
3304 }
else if (OnPending.
insert(s).second && (FirstTrip || OLChanged)) {
3305 Pending.push(BBToOrder[s]);
3309 Worklist.swap(Pending);
3319 for (
auto *
MBB : BlockOrders) {
3328 Var.getFragment() &&
"Fragment info missing during value prop");
3329 Output[
MBB->
getNumber()].push_back(std::make_pair(Var, *BlockLiveIn));
3333 BlockOrders.clear();
3334 BlocksToExplore.clear();
3337void InstrRefBasedLDV::placePHIsForSingleVarDefinition(
3353 auto ValueIt = VLocs.
Vars.find(Var);
3364 for (
auto *ScopeBlock : InScopeBlocks) {
3368 Output[ScopeBlock->getNumber()].push_back({Var,
Value});
3375#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
3378 for (
const auto &
P : mloc_transfer) {
3381 dbgs() <<
"Loc " << foo <<
" --> " << bar <<
"\n";
3390 EmptyExpr = DIExpression::get(Context, {});
3392 auto hasNonArtificialLocation = [](
const MachineInstr &
MI) ->
bool {
3394 return DL.getLine() != 0;
3398 for (
auto &
MBB : MF)
3400 ArtificialBlocks.insert(&
MBB);
3404 unsigned int RPONumber = 0;
3406 OrderToBB[RPONumber] =
MBB;
3407 BBToOrder[
MBB] = RPONumber;
3414 if (!BBToOrder.contains(&
MBB))
3420#ifdef EXPENSIVE_CHECKS
3423 if (MF.DebugValueSubstitutions.size() > 2) {
3424 for (
auto It = MF.DebugValueSubstitutions.begin();
3425 It != std::prev(MF.DebugValueSubstitutions.end()); ++It) {
3426 assert(It->Src != std::next(It)->Src &&
"Duplicate variable location "
3427 "substitution seen");
3436void InstrRefBasedLDV::makeDepthFirstEjectionMap(
3438 const ScopeToDILocT &ScopeToDILocation,
3439 ScopeToAssignBlocksT &ScopeToAssignBlocks) {
3446 WorkStack.
push_back({TopScope, TopScope->getChildren().
size() - 1});
3448 while (!WorkStack.
empty()) {
3449 auto &ScopePosition = WorkStack.
back();
3451 ssize_t ChildNum = ScopePosition.second--;
3454 if (ChildNum >= 0) {
3457 auto &ChildScope =
Children[ChildNum];
3459 std::make_pair(ChildScope, ChildScope->getChildren().size() - 1));
3466 auto DILocationIt = ScopeToDILocation.find(WS);
3467 if (DILocationIt != ScopeToDILocation.end()) {
3468 getBlocksForScope(DILocationIt->second, BlocksToExplore,
3469 ScopeToAssignBlocks.find(WS)->second);
3470 for (
const auto *
MBB : BlocksToExplore) {
3472 if (EjectionMap[BBNum] == 0)
3476 BlocksToExplore.clear();
3482bool InstrRefBasedLDV::depthFirstVLocAndEmit(
3483 unsigned MaxNumBlocks,
const ScopeToDILocT &ScopeToDILocation,
3484 const ScopeToVarsT &ScopeToVars, ScopeToAssignBlocksT &ScopeToAssignBlocks,
3489 TTracker =
new TransferTracker(TII, MTracker, MF, *TRI, CalleeSavedRegs, TPC);
3500 makeDepthFirstEjectionMap(EjectionMap, ScopeToDILocation,
3501 ScopeToAssignBlocks);
3508 AllTheVLocs[BBNum].
clear();
3514 TTracker->
loadInlocs(
MBB, MInLocs[BBNum], DbgOpStore, Output[BBNum],
3519 for (
auto &
MI :
MBB) {
3520 process(
MI, MOutLocs.get(), MInLocs.get());
3526 MInLocs[BBNum].reset();
3527 MOutLocs[BBNum].reset();
3529 Output[BBNum].clear();
3530 AllTheVLocs[BBNum].
clear();
3536 unsigned HighestDFSIn = 0;
3539 while (!WorkStack.
empty()) {
3540 auto &ScopePosition = WorkStack.
back();
3542 ssize_t ChildNum = ScopePosition.second++;
3549 auto DILocIt = ScopeToDILocation.find(WS);
3550 if (HighestDFSIn <= WS->getDFSIn() && DILocIt != ScopeToDILocation.end()) {
3552 auto &VarsWeCareAbout = ScopeToVars.find(WS)->second;
3553 auto &BlocksInScope = ScopeToAssignBlocks.find(WS)->second;
3555 buildVLocValueMap(DILoc, VarsWeCareAbout, BlocksInScope, Output, MOutLocs,
3556 MInLocs, AllTheVLocs);
3559 HighestDFSIn = std::max(HighestDFSIn, WS->
getDFSIn());
3563 if (ChildNum < (ssize_t)
Children.size()) {
3565 auto &ChildScope =
Children[ChildNum];
3566 WorkStack.
push_back(std::make_pair(ChildScope, 0));
3572 auto DILocationIt = ScopeToDILocation.find(WS);
3573 if (DILocationIt == ScopeToDILocation.end())
3576 getBlocksForScope(DILocationIt->second, BlocksToExplore,
3577 ScopeToAssignBlocks.find(WS)->second);
3578 for (
const auto *
MBB : BlocksToExplore)
3582 BlocksToExplore.clear();
3591 for (
auto *
MBB : ArtificialBlocks)
3595 return emitTransfers(AllVarsNumbering);
3598bool InstrRefBasedLDV::emitTransfers(
3611 MI->getDebugLoc()->getInlinedAt());
3619 for (
const auto &Pair : Insts)
3624 if (
P.Pos->isTerminator())
3628 for (
const auto &Pair : Insts)
3642 unsigned InputDbgValLimit) {
3650 this->DomTree = DomTree;
3661 STI.getFrameLowering()->stackProbeFunctionModifiesSP();
3662 if (AdjustsStackInCalls)
3663 StackProbeSymbolName = STI.getTargetLowering()->getStackProbeSymbolName(MF);
3675 for (
auto &
MBB : MF)
3686 produceMLocTransferFunction(MF, MLocTransfer,
MaxNumBlocks);
3696 MOutLocs[i] = std::make_unique<ValueIDNum[]>(NumLocs);
3697 MInLocs[i] = std::make_unique<ValueIDNum[]>(NumLocs);
3704 buildMLocValueMap(MF, MInLocs, MOutLocs, MLocTransfer);
3708 for (
auto &DBG_PHI : DebugPHINumToValue) {
3710 if (!DBG_PHI.ValueRead)
3724 Num = ResolvedValue;
3731 for (
auto &OrderPair : OrderToBB) {
3734 VTracker = &vlocs[CurBB];
3738 for (
auto &
MI :
MBB) {
3739 process(
MI, MOutLocs.get(), MInLocs.get());
3761 unsigned VarAssignCount = 0;
3762 for (
unsigned int I = 0;
I < OrderToBB.size(); ++
I) {
3763 auto *
MBB = OrderToBB[
I];
3766 for (
auto &idx : VTracker->
Vars) {
3767 const auto &Var = idx.first;
3769 assert(ScopeLoc !=
nullptr);
3773 assert(Scope !=
nullptr);
3775 AllVarsNumbering.
insert(std::make_pair(Var, AllVarsNumbering.
size()));
3776 ScopeToVars[
Scope].insert(Var);
3777 ScopeToAssignBlocks[
Scope].insert(VTracker->
MBB);
3778 ScopeToDILocation[
Scope] = ScopeLoc;
3783 bool Changed =
false;
3789 VarAssignCount > InputDbgValLimit) {
3790 LLVM_DEBUG(
dbgs() <<
"Disabling InstrRefBasedLDV: " << MF.getName()
3793 <<
" variable assignments, exceeding limits.\n");
3798 Changed = depthFirstVLocAndEmit(
3799 MaxNumBlocks, ScopeToDILocation, ScopeToVars, ScopeToAssignBlocks,
3800 SavedLiveIns, MOutLocs, MInLocs, vlocs, MF, AllVarsNumbering, *TPC);
3809 ArtificialBlocks.clear();
3813 DebugInstrNumToInstr.clear();
3814 DebugPHINumToValue.clear();
3815 OverlapFragments.
clear();
3816 SeenFragments.
clear();
3817 SeenDbgPHIs.clear();
3842 LDVSSABlock *ParentBlock;
3843 BlockValueNum PHIValNum;
3844 LDVSSAPhi(BlockValueNum PHIValNum, LDVSSABlock *ParentBlock)
3845 : ParentBlock(ParentBlock), PHIValNum(PHIValNum) {}
3847 LDVSSABlock *
getParent() {
return ParentBlock; }
3852class LDVSSABlockIterator {
3855 LDVSSAUpdater &Updater;
3858 LDVSSAUpdater &Updater)
3859 : PredIt(PredIt), Updater(Updater) {}
3861 bool operator!=(
const LDVSSABlockIterator &OtherIt)
const {
3862 return OtherIt.PredIt != PredIt;
3865 LDVSSABlockIterator &operator++() {
3879 LDVSSAUpdater &Updater;
3885 : BB(BB), Updater(Updater) {}
3888 return LDVSSABlockIterator(BB.
succ_begin(), Updater);
3892 return LDVSSABlockIterator(BB.
succ_end(), Updater);
3896 LDVSSAPhi *newPHI(BlockValueNum
Value) {
3897 PHIList.emplace_back(
Value,
this);
3898 return &PHIList.back();
3902 PHIListT &phis() {
return PHIList; }
3908class LDVSSAUpdater {
3923 : Loc(
L), MLiveIns(MLiveIns) {}
3926 for (
auto &
Block : BlockMap)
3927 delete Block.second;
3934 ~LDVSSAUpdater() { reset(); }
3939 auto it = BlockMap.find(BB);
3940 if (it == BlockMap.end()) {
3941 BlockMap[BB] =
new LDVSSABlock(*BB, *
this);
3942 it = BlockMap.find(BB);
3949 BlockValueNum getValue(LDVSSABlock *LDVBB) {
3950 return MLiveIns[LDVBB->BB.getNumber()][Loc.
asU64()].asU64();
3954LDVSSABlock *LDVSSABlockIterator::operator*() {
3955 return Updater.getSSALDVBlock(*PredIt);
3961 out <<
"SSALDVPHI " <<
PHI.PHIValNum;
3987 class PHI_iterator {
4013 return PHI_iterator(
PHI,
true);
4021 Preds->
push_back(BB->Updater.getSSALDVBlock(Pred));
4027 static BlockValueNum
GetUndefVal(LDVSSABlock *BB, LDVSSAUpdater *Updater) {
4031 BlockValueNum Num =
ValueIDNum(BB->BB.getNumber(), 0, Updater->Loc).
asU64();
4032 Updater->UndefMap[&BB->BB] = Num;
4042 LDVSSAUpdater *Updater) {
4043 BlockValueNum PHIValNum = Updater->getValue(BB);
4044 LDVSSAPhi *
PHI = BB->newPHI(PHIValNum);
4045 Updater->PHIs[PHIValNum] =
PHI;
4052 PHI->IncomingValues.push_back(std::make_pair(Pred, Val));
4057 static LDVSSAPhi *
ValueIsPHI(BlockValueNum Val, LDVSSAUpdater *Updater) {
4058 return Updater->PHIs.lookup(Val);
4064 LDVSSAPhi *
PHI = ValueIsPHI(Val, Updater);
4065 if (
PHI &&
PHI->IncomingValues.size() == 0)
4077std::optional<ValueIDNum> InstrRefBasedLDV::resolveDbgPHIs(
4080 assert(MLiveOuts && MLiveIns &&
4081 "Tried to resolve DBG_PHI before location "
4082 "tables allocated?");
4086 auto SeenDbgPHIIt = SeenDbgPHIs.find(std::make_pair(&Here, InstrNum));
4087 if (SeenDbgPHIIt != SeenDbgPHIs.end())
4088 return SeenDbgPHIIt->second;
4090 std::optional<ValueIDNum>
Result =
4091 resolveDbgPHIsImpl(MF, MLiveOuts, MLiveIns, Here, InstrNum);
4092 SeenDbgPHIs.insert({std::make_pair(&Here, InstrNum),
Result});
4096std::optional<ValueIDNum> InstrRefBasedLDV::resolveDbgPHIsImpl(
4101 auto RangePair = std::equal_range(DebugPHINumToValue.begin(),
4102 DebugPHINumToValue.end(), InstrNum);
4103 auto LowerIt = RangePair.first;
4104 auto UpperIt = RangePair.second;
4107 if (LowerIt == UpperIt)
4108 return std::nullopt;
4114 auto DBGPHIRange =
make_range(LowerIt, UpperIt);
4115 for (
const DebugPHIRecord &DBG_PHI : DBGPHIRange)
4116 if (!DBG_PHI.ValueRead)
4117 return std::nullopt;
4120 if (std::distance(LowerIt, UpperIt) == 1)
4121 return *LowerIt->ValueRead;
4127 LocIdx Loc = *LowerIt->ReadLoc;
4136 LDVSSAUpdater Updater(Loc, MLiveIns);
4144 for (
const auto &DBG_PHI : DBGPHIRange) {
4145 LDVSSABlock *
Block = Updater.getSSALDVBlock(DBG_PHI.MBB);
4150 LDVSSABlock *HereBlock = Updater.getSSALDVBlock(Here.
getParent());
4151 const auto &AvailIt = AvailableValues.
find(HereBlock);
4152 if (AvailIt != AvailableValues.
end()) {
4161 BlockValueNum ResultInt = Impl.GetValue(Updater.getSSALDVBlock(Here.
getParent()));
4178 for (
const auto &DBG_PHI : DBGPHIRange) {
4179 LDVSSABlock *
Block = Updater.getSSALDVBlock(DBG_PHI.MBB);
4181 ValidatedValues.
insert(std::make_pair(
Block, Num));
4186 for (
auto &
PHI : CreatedPHIs)
4189 llvm::sort(SortedPHIs, [&](LDVSSAPhi *
A, LDVSSAPhi *
B) {
4190 return BBToOrder[&
A->getParent()->BB] < BBToOrder[&
B->getParent()->BB];
4193 for (
auto &
PHI : SortedPHIs) {
4195 MLiveIns[
PHI->ParentBlock->BB.getNumber()][Loc.
asU64()];
4198 for (
auto &PHIIt :
PHI->IncomingValues) {
4200 if (Updater.UndefMap.contains(&PHIIt.first->BB))
4201 return std::nullopt;
4204 const ValueTable &BlockLiveOuts = MLiveOuts[PHIIt.first->BB.getNumber()];
4206 auto VVal = ValidatedValues.
find(PHIIt.first);
4207 if (VVal == ValidatedValues.
end()) {
4212 ValueToCheck = ThisBlockValueNum;
4216 ValueToCheck = VVal->second;
4219 if (BlockLiveOuts[Loc.
asU64()] != ValueToCheck)
4220 return std::nullopt;
4224 ValidatedValues.
insert({
PHI->ParentBlock, ThisBlockValueNum});
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< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
This file defines the DenseMap class.
This file contains constants used for implementing Dwarf debug support.
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
Compute iterated dominance frontiers using a linear time algorithm.
const HexagonInstrInfo * TII
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)
unsigned const TargetRegisterInfo * TRI
const char LLVMTargetMachineRef TM
This file builds on the ADT/GraphTraits.h file to build a generic graph post order iterator.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallPtrSet class.
This file defines the SmallSet class.
This file defines the SmallVector class.
This file describes how to lower LLVM code to machine code.
Target-Independent Code Generator Pass Configuration Options pass.
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
DenseMap< const MachineBasicBlock *, DbgValue * > LiveIdxT
Live in/out structure for the variable values: a per-block map of variables to their values.
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.
InstrRefBasedLDV()
Default construct and initialize the pass.
DIExpression::FragmentInfo FragmentInfo
bool hasFoldedStackStore(const MachineInstr &MI)
bool isCalleeSaved(LocIdx L) const
DenseMap< const LexicalScope *, SmallPtrSet< MachineBasicBlock *, 4 > > ScopeToAssignBlocksT
Mapping from lexical scopes to blocks where variables in that scope are assigned.
bool isCalleeSavedReg(Register R) const
LLVM_DUMP_METHOD void dump_mloc_transfer(const MLocTransferMap &mloc_transfer) const
DenseMap< const LexicalScope *, SmallSet< DebugVariable, 4 > > ScopeToVarsT
Mapping from lexical scopes to variables in that scope.
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?).
bool isRegisterTracked(Register R)
Is register R currently tracked by MLocTracker?
std::optional< SpillLocationNo > getOrTrackSpillLoc(SpillLoc L)
Find LocIdx for SpillLoc L, creating a new one if it's not tracked.
void loadFromArray(ValueTable &Locs, unsigned NewCurBB)
Load values for each location from array of ValueIDNums.
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.
unsigned getNumLocs() const
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)
void setReg(Register R, ValueIDNum ValueID)
Set a register to a value number.
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
bool isSpill(LocIdx Idx) const
Return true if Idx is a spill machine location.
LocIdx getRegMLoc(Register R)
Determine the LocIdx of an existing register.
void setMLoc(LocIdx L, ValueIDNum Num)
Set a locaiton to a certain value.
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...
MachineInstrBuilder emitLoc(const SmallVectorImpl< ResolvedDbgOp > &DbgOps, const DebugVariable &Var, const DbgValueProperties &Properties)
Create a DBG_VALUE based on debug operands DbgOps.
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 readMLoc(LocIdx L)
Read the value of a particular location.
void setMPhis(unsigned NewCurBB)
Reset all locations to contain a PHI value at the designated block.
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()
LocIdx trackRegister(unsigned ID)
Create a LocIdx for an untracked register ID.
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.
LocIdx getSpillMLoc(unsigned SpillID)
std::string LocIdxToName(LocIdx Idx) const
Thin wrapper around an integer – designed to give more type safety to spill location numbers.
Collection of DBG_VALUEs observed when traversing a block.
void defVar(const MachineInstr &MI, const DbgValueProperties &Properties, const SmallVectorImpl< DbgOpID > &DebugOps)
SmallDenseMap< DebugVariable, const DILocation *, 8 > Scopes
MapVector< DebugVariable, DbgValue > 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 ValueIDNum EmptyValue
static ValueIDNum TombstoneValue
uint64_t getBlock() const
LocationAndQuality(LocIdx L, LocationQuality Q)
LocationQuality getQuality() const
Tracker for converting machine value locations and variable values into variable locations (the outpu...
void loadVarInloc(MachineBasicBlock &MBB, DbgOpIDMap &DbgOpStore, const DenseMap< ValueIDNum, LocationAndQuality > &ValueToLoc, DebugVariable Var, DbgValue Value)
For a variable Var with the live-in value Value, attempts to resolve the DbgValue to a concrete DBG_V...
void loadInlocs(MachineBasicBlock &MBB, ValueTable &MLocs, DbgOpIDMap &DbgOpStore, const SmallVectorImpl< std::pair< DebugVariable, DbgValue > > &VLocs, unsigned NumLocs)
Load object with live-in variable values.
const BitVector & CalleeSavedRegs
const TargetLowering * TLI
DenseSet< DebugVariable > UseBeforeDefVariables
The set of variables that are in UseBeforeDefs and can become a location once the relevant value is d...
SmallVector< ValueIDNum, 32 > VarLocs
Local cache of what-value-is-in-what-LocIdx.
DenseMap< DebugVariable, ResolvedDbgValue > ActiveVLocs
Map from DebugVariable to it's current location and qualifying meta information.
MLocTracker * MTracker
This machine location tracker is assumed to always contain the up-to-date value mapping for all machi...
TransferTracker(const TargetInstrInfo *TII, MLocTracker *MTracker, MachineFunction &MF, const TargetRegisterInfo &TRI, const BitVector &CalleeSavedRegs, const TargetPassConfig &TPC)
DenseMap< LocIdx, SmallSet< DebugVariable, 4 > > ActiveMLocs
Map from LocIdxes to which DebugVariables are based that location.
bool recoverAsEntryValue(const DebugVariable &Var, const DbgValueProperties &Prop, const ValueIDNum &Num)
SmallVector< MachineInstr *, 4 > PendingDbgValues
Temporary cache of DBG_VALUEs to be entered into the Transfers collection.
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
void addUseBeforeDef(const DebugVariable &Var, const DbgValueProperties &Properties, const SmallVectorImpl< DbgOp > &DbgOps, unsigned Inst)
Record that Var has value ID, a value that becomes available later in the function.
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
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 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< 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.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
bool test(unsigned Idx) const
iterator_range< const_set_bits_iterator > set_bits() const
unsigned getNumElements() const
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 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...
bool isComplex() const
Return whether the location is computed on the expression stack, meaning it cannot be a simple regist...
static std::optional< FragmentInfo > getFragmentInfo(expr_op_iterator Start, expr_op_iterator End)
Retrieve the details of this fragment expression.
static std::optional< const DIExpression * > convertToNonVariadicExpression(const DIExpression *Expr)
If Expr is a valid single-location expression, i.e.
bool isDeref() const
Return whether there is exactly one operator and it is a DW_OP_deref;.
static 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 ...
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.
std::optional< uint64_t > getSizeInBits() const
Determines the size of the variable's type.
This class represents an Operation in the Expression.
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)
bool erase(const KeyT &Val)
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
void reserve(size_type NumEntries)
Grow the densemap so that it can contain at least NumEntries items before resizing again.
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.
Determine the iterated dominance frontier, given a set of defining blocks, and optionally,...
StorageT::size_type size() const
This is an important class for using LLVM in a threaded context.
LexicalScope - This class is used to track scope information.
unsigned getDFSIn() const
SmallVectorImpl< LexicalScope * > & getChildren()
unsigned getDFSOut() const
void initialize(const MachineFunction &)
initialize - Scan machine function and constuct lexical scope nest, resets the instance if necessary.
LexicalScope * findLexicalScope(const DILocation *DL)
findLexicalScope - Find lexical scope, either regular or inlined, for the given DebugLoc.
void getMachineBasicBlocks(const DILocation *DL, SmallPtrSetImpl< const MachineBasicBlock * > &MBBs)
getMachineBasicBlocks - Populate given set using machine basic blocks which have machine instructions...
LexicalScope * getCurrentFunctionScope() const
getCurrentFunctionScope - Return lexical scope for the current function.
Describe properties that are true of each instruction in the target description file.
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode.
MCRegAliasIterator enumerates all registers aliasing Reg.
MCRegUnitRootIterator enumerates the root registers of a register unit.
bool isValid() const
Check if the iterator is at the end of the list.
unsigned getNumSubRegIndices() const
Return the number of sub-register indices understood by the target.
unsigned getSubRegIdxSize(unsigned Idx) const
Get the size of the bit range covered by a sub-register index.
iterator_range< MCSubRegIterator > subregs(MCRegister Reg) const
Return an iterator range over all sub-registers of Reg, excluding Reg.
unsigned getSubRegIndex(MCRegister RegNo, MCRegister SubRegNo) const
For a given register pair, return the sub-register index if the second register is a sub-register of ...
unsigned getSubRegIdxOffset(unsigned Idx) const
Get the offset of the bit range covered by a sub-register index.
iterator_range< MCRegUnitIterator > regunits(MCRegister Reg) const
Returns an iterator range over all regunits for Reg.
unsigned getNumRegs() const
Return the number of registers this target has (useful for sizing arrays holding per register informa...
Iterator that enumerates the sub-registers of a Reg and the associated sub-register indices.
bool isValid() const
Returns true if this iterator is not yet at the end.
LLVMContext & getContext() const
instr_iterator instr_begin()
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...
std::vector< MachineBasicBlock * >::const_iterator const_succ_iterator
succ_iterator succ_begin()
Instructions::iterator instr_iterator
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
iterator_range< succ_iterator > successors()
iterator_range< pred_iterator > predecessors()
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,...
std::vector< MachineBasicBlock * >::iterator pred_iterator
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
bool properlyDominates(const MachineDomTreeNode *A, const MachineDomTreeNode *B) const
MachineDomTree & getBase()
bool adjustsStack() const
Return true if this function adjusts the stack – e.g., when calling another function.
bool isDeadObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to a dead object.
Replacement definition for a debug instruction reference.
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.