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"),
305 unsigned Location : 24;
306 unsigned Quality : 8;
311 : Location(L.asU64()), Quality(static_cast<
unsigned>(Q)) {}
326 return A.first <
B.first;
331 std::optional<LocationQuality>
361 bool IsValueValid =
true;
362 unsigned LastUseBeforeDef = 0;
378 IsValueValid =
false;
390 auto ValuesPreferredLoc = std::lower_bound(
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();
424 if (LastUseBeforeDef) {
437 Result.first->second = NewValue;
467 for (
const auto &VLoc : VLocs)
469 for (
DbgOpID OpID : VLoc.second.getDbgOpIDs())
470 if (!OpID.ID.IsConst)
490 auto VIt = std::lower_bound(ValueToLoc.
begin(), ValueToLoc.
end(), Probe,
492 if (VIt == ValueToLoc.
end() || VIt->first != VNum)
495 auto &Previous = VIt->second;
498 std::optional<LocationQuality> ReplacementQuality =
500 if (ReplacementQuality)
505 for (
const auto &Var : VLocs) {
535 for (
auto &
Use : MIt->second) {
540 assert(!
Op.isUndef() &&
"UseBeforeDef erroneously created for a "
541 "DbgValue with undef values.");
550 if (ValueToLoc.
empty())
559 auto VIt = ValueToLoc.
find(LocValueID);
560 if (VIt == ValueToLoc.
end())
563 auto &Previous = VIt->second;
566 std::optional<LocationQuality> ReplacementQuality =
568 if (ReplacementQuality)
574 for (
auto &
Use : MIt->second) {
585 LocIdx NewLoc = ValueToLoc.
find(
Op.ID)->second.getLoc();
594 if (DbgOps.
size() !=
Use.Values.size())
647 return Reg != SP && Reg !=
FP;
664 auto NonVariadicExpression =
666 if (!NonVariadicExpression)
668 DIExpr = *NonVariadicExpression;
694 MI.getDebugLoc()->getInlinedAt());
699 if (
MI.isUndefDebugValue() ||
704 for (
LocIdx Loc : It->second.loc_indices())
734 MI.getDebugLoc()->getInlinedAt());
742 for (
LocIdx Loc : It->second.loc_indices())
747 if (NewLocs.
empty()) {
767 for (
LocIdx Loc : LostVLocIt->second.loc_indices()) {
777 for (
const auto &LostMLoc : LostMLocs)
792 It->second.Ops.assign(NewLocs);
793 It->second.Properties = Properties;
802 bool MakeUndef =
true) {
824 std::optional<LocIdx> NewLoc;
826 if (Loc.Value == OldValue)
831 if (!NewLoc && !MakeUndef) {
861 DbgOps.
insert(DbgOps.
begin(), ActiveVLocIt->second.Ops.size(),
873 for (
LocIdx Loc : ActiveVLocIt->second.loc_indices()) {
879 ActiveVLocIt->second.Ops = DbgOps;
886 for (
auto &LocVarIt : LostMLocs) {
889 "Variable was using this MLoc, but ActiveMLocs[MLoc] has no "
891 LostMLocIt->second.erase(LocVarIt.second);
897 VarLocs[NewLoc->asU64()] = OldValue;
902 ActiveMLocIt->second.clear();
903 if (!NewMLocs.
empty())
933 std::replace(ActiveVLocIt->second.Ops.begin(),
934 ActiveVLocIt->second.Ops.end(),
SrcOp,
DstOp);
938 ActiveVLocIt->second.Properties);
963 MIB.addMetadata(Properties.
DIExpr);
1024 LocIdxToIDNum(
ValueIDNum::EmptyValue), LocIdxToLocID(0) {
1062 if (
Size > 60000 || Offs > 60000)
1098 if (MaskPair.first->clobbersPhysReg(
ID)) {
1100 ValNum = {
CurBB, MaskPair.second, NewIdx};
1121 Masks.push_back(std::make_pair(MO, InstID));
1127 if (SpillID.
id() == 0) {
1131 return std::nullopt;
1136 for (
unsigned StackIdx = 0; StackIdx <
NumSlotIdxes; ++StackIdx) {
1157 return Twine(
"slot ")
1174 std::string MLocName =
LocIdxToName(Location.Value.getLoc());
1175 std::string DefName = Location.Value.asString(MLocName);
1183 dbgs() <<
"Idx " << Location.Idx.asU64() <<
" " << foo <<
"\n";
1195 ?
TII.
get(TargetOpcode::DBG_VALUE_LIST)
1196 :
TII.
get(TargetOpcode::DBG_VALUE);
1198#ifdef EXPENSIVE_CHECKS
1201 return Op.IsConst || !
Op.Loc.isIllegal();
1203 "Did not expect illegal ops in DbgOps.");
1206 "Expected to have either one DbgOp per MI LocationOp, or none.");
1219 auto EmitUndef = [&]() {
1231 bool Indirect = Properties.
Indirect;
1253 unsigned short Offset = StackIdx.second;
1264 unsigned Base = Spill.SpillBase;
1280 bool UseDerefSize =
false;
1282 unsigned DerefSizeInBytes = ValueSizeInBits / 8;
1284 unsigned VariableSizeInBits = Fragment->SizeInBits;
1285 if (VariableSizeInBits != ValueSizeInBits || Expr->
isComplex())
1286 UseDerefSize =
true;
1288 if (*
Size != ValueSizeInBits) {
1289 UseDerefSize =
true;
1312 UseDerefSize =
false;
1316 bool StackValue =
false;
1323 OffsetOps.
push_back(dwarf::DW_OP_deref);
1330 OffsetOps.
push_back(dwarf::DW_OP_deref_size);
1336 OffsetOps.
push_back(dwarf::DW_OP_deref);
1369 if (CalleeSavedRegs.
test((*RAI).id()))
1383std::optional<SpillLocationNo>
1384InstrRefBasedLDV::extractSpillBaseRegAndOffset(
const MachineInstr &
MI) {
1386 "Spill instruction does not have exactly one memory operand?");
1387 auto MMOI =
MI.memoperands_begin();
1390 "Inconsistent memory operand in spill instruction");
1391 int FI = cast<FixedStackPseudoSourceValue>(PVal)->getFrameIndex();
1398std::optional<LocIdx>
1400 std::optional<SpillLocationNo>
SpillLoc = extractSpillBaseRegAndOffset(
MI);
1402 return std::nullopt;
1408 auto *MemOperand = *
MI.memoperands_begin();
1410 assert(SizeInBits.
hasValue() &&
"Expected to find a valid size!");
1417 return std::nullopt;
1425bool InstrRefBasedLDV::transferDebugValue(
const MachineInstr &
MI) {
1426 if (!
MI.isDebugValue())
1429 assert(
MI.getDebugVariable()->isValidLocationForIntrinsic(
MI.getDebugLoc()) &&
1430 "Expected inlined-at fields to agree");
1435 if (Scope ==
nullptr)
1441 if (MO.isReg() && MO.getReg() != 0)
1442 (void)MTracker->
readReg(MO.getReg());
1451 if (!
MI.isUndefDebugValue()) {
1457 }
else if (MO.isImm() || MO.isFPImm() || MO.isCImm()) {
1474std::optional<ValueIDNum> InstrRefBasedLDV::getValueForInstrRef(
1490 LowerBoundIt->Src == SoughtSub.Src) {
1491 std::tie(InstNo, OpNo) = LowerBoundIt->Dest;
1492 SoughtSub.Src = LowerBoundIt->Dest;
1493 if (
unsigned Subreg = LowerBoundIt->Subreg)
1494 SeenSubregs.push_back(Subreg);
1500 std::optional<ValueIDNum> NewID;
1504 auto InstrIt = DebugInstrNumToInstr.find(InstNo);
1506 if (InstrIt != DebugInstrNumToInstr.end()) {
1507 const MachineInstr &TargetInstr = *InstrIt->second.first;
1516 NewID =
ValueIDNum(BlockNo, InstrIt->second.second, *L);
1529 NewID =
ValueIDNum(BlockNo, InstrIt->second.second, L);
1535 {
dbgs() <<
"Seen instruction reference to illegal operand\n"; });
1539 }
else if (PHIIt != DebugPHINumToValue.
end() && PHIIt->InstrNum == InstNo) {
1542 assert(MLiveOuts && MLiveIns);
1543 NewID = resolveDbgPHIs(*
MI.getParent()->getParent(), *MLiveOuts, *MLiveIns,
1556 if (NewID && !SeenSubregs.empty()) {
1564 for (
unsigned Subreg :
reverse(SeenSubregs)) {
1568 Size = (
Size == 0) ? ThisSize : std::min(
Size, ThisSize);
1576 if (NewID && !MTracker->
isSpill(L)) {
1582 if (TRCI->contains(Reg))
1584 assert(TRC &&
"Couldn't find target register class?");
1596 if (SubregSize ==
Size && SubregOffset ==
Offset) {
1604 NewID = std::nullopt;
1609 NewID =
ValueIDNum(NewID->getBlock(), NewID->getInst(), NewLoc);
1614 NewID = std::nullopt;
1624 if (!
MI.isDebugRef())
1629 if (!VTracker && !TTracker)
1637 "Expected inlined-at fields to agree");
1642 if (Scope ==
nullptr)
1648 assert(!MO.
isReg() &&
"DBG_INSTR_REF should not contain registers");
1659 std::optional<ValueIDNum> NewID =
1660 getValueForInstrRef(InstNo, OpNo,
MI, MLiveOuts, MLiveIns);
1677 VTracker->
defVar(
MI, Properties, DbgOpIDs);
1686 for (
DbgOpID OpID : DbgOpIDs) {
1696 for (
const DbgOp &
Op : DbgOps) {
1698 if (FoundLocs.
insert({Op.ID, TransferTracker::LocationAndQuality()})
1703 for (
auto Location : MTracker->
locations()) {
1706 auto ValueToFindIt =
find(ValuesToFind,
ID);
1707 if (ValueToFindIt == ValuesToFind.
end())
1709 auto &Previous = FoundLocs.
find(
ID)->second;
1712 std::optional<TransferTracker::LocationQuality> ReplacementQuality =
1714 if (ReplacementQuality) {
1716 if (Previous.isBest()) {
1717 ValuesToFind.
erase(ValueToFindIt);
1718 if (ValuesToFind.
empty())
1742 if (!DbgOps.empty() && NewLocs.
empty()) {
1743 bool IsValidUseBeforeDef =
true;
1745 for (
auto ValueLoc : FoundLocs) {
1747 LocIdx FoundLoc = ValueLoc.second.getLoc();
1753 IsValidUseBeforeDef =
false;
1756 LastUseBeforeDef = std::max(LastUseBeforeDef, NewID.
getInst());
1758 if (IsValidUseBeforeDef) {
1761 DbgOps, LastUseBeforeDef);
1770 MTracker->
emitLoc(NewLocs, V,
MI.getDebugLoc().get(), Properties);
1779 if (!
MI.isDebugPHI())
1783 if (VTracker || TTracker)
1789 unsigned InstrNum =
MI.getOperand(1).getImm();
1791 auto EmitBadPHI = [
this, &
MI, InstrNum]() ->
bool {
1797 {InstrNum,
MI.getParent(), std::nullopt, std::nullopt});
1806 auto PHIRec = DebugPHIRecord(
1813 }
else if (MO.
isFI()) {
1820 return EmitBadPHI();
1831 return EmitBadPHI();
1834 assert(
MI.getNumOperands() == 3 &&
"Stack DBG_PHI with no size?");
1835 unsigned slotBitSize =
MI.getOperand(2).getImm();
1837 unsigned SpillID = MTracker->
getLocID(*SpillNo, {slotBitSize, 0});
1842 auto DbgPHI = DebugPHIRecord({InstrNum,
MI.getParent(), Result,
SpillLoc});
1850 {
dbgs() <<
"Seen DBG_PHI with unrecognised operand format\n"; });
1851 return EmitBadPHI();
1860 if (
MI.isImplicitDef()) {
1870 }
else if (
MI.isMetaInstruction())
1878 bool CallChangesSP =
false;
1879 if (AdjustsStackInCalls &&
MI.isCall() &&
MI.getOperand(0).isSymbol() &&
1880 !strcmp(
MI.getOperand(0).getSymbolName(), StackProbeSymbolName.
data()))
1881 CallChangesSP =
true;
1885 auto IgnoreSPAlias = [
this, &
MI, CallChangesSP](
Register R) ->
bool {
1888 return MI.isCall() && MTracker->
SPAliases.count(R);
1900 !IgnoreSPAlias(MO.
getReg())) {
1904 DeadRegs.
insert((*RAI).id());
1913 MTracker->
defReg(DeadReg, CurBB, CurInst);
1915 for (
const auto *MO : RegMaskPtrs)
1920 if (std::optional<SpillLocationNo> SpillNo =
1921 extractSpillBaseRegAndOffset(
MI)) {
1938 for (
uint32_t DeadReg : DeadRegs) {
1945 if (!RegMaskPtrs.empty()) {
1952 if (IgnoreSPAlias(Reg))
1955 for (
const auto *MO : RegMaskPtrs)
1963 if (std::optional<SpillLocationNo> SpillNo =
1964 extractSpillBaseRegAndOffset(
MI)) {
1974void InstrRefBasedLDV::performCopy(
Register SrcRegNum,
Register DstRegNum) {
1977 MTracker->
defReg(*RAI, CurBB, CurInst);
1980 MTracker->
setReg(DstRegNum, SrcValue);
1984 unsigned SrcSubReg = SRI.getSubReg();
1985 unsigned SubRegIdx = SRI.getSubRegIndex();
1986 unsigned DstSubReg = TRI->
getSubReg(DstRegNum, SubRegIdx);
2001 MTracker->
setReg(DstSubReg, CpyValue);
2005std::optional<SpillLocationNo>
2009 if (!
MI.hasOneMemOperand())
2010 return std::nullopt;
2013 auto MMOI =
MI.memoperands_begin();
2016 return std::nullopt;
2018 if (!
MI.getSpillSize(TII) && !
MI.getFoldedSpillSize(TII))
2019 return std::nullopt;
2022 return extractSpillBaseRegAndOffset(
MI);
2027 if (!isSpillInstruction(
MI, MF))
2035std::optional<SpillLocationNo>
2038 if (!
MI.hasOneMemOperand())
2039 return std::nullopt;
2043 if (
MI.getRestoreSize(TII)) {
2044 Reg =
MI.getOperand(0).getReg();
2045 return extractSpillBaseRegAndOffset(
MI);
2047 return std::nullopt;
2050bool InstrRefBasedLDV::transferSpillOrRestoreInst(
MachineInstr &
MI) {
2079 if (std::optional<SpillLocationNo> Loc = isSpillInstruction(
MI, MF)) {
2082 for (
unsigned SlotIdx = 0; SlotIdx < MTracker->
NumSlotIdxes; ++SlotIdx) {
2084 std::optional<LocIdx> MLoc = MTracker->
getSpillMLoc(SpillID);
2093 MTracker->
setMLoc(*MLoc, Def);
2100 if (isLocationSpill(
MI, MF, Reg)) {
2105 auto DoTransfer = [&](
Register SrcReg,
unsigned SpillID) {
2106 auto ReadValue = MTracker->
readReg(SrcReg);
2108 MTracker->
setMLoc(DstLoc, ReadValue);
2121 unsigned SpillID = MTracker->
getLocID(Loc, SubregIdx);
2122 DoTransfer(SR, SpillID);
2128 DoTransfer(Reg, SpillID);
2130 std::optional<SpillLocationNo> Loc = isRestoreInstruction(
MI, MF, Reg);
2142 MTracker->
defReg(*RAI, CurBB, CurInst);
2146 auto DoTransfer = [&](
Register DestReg,
unsigned SpillID) {
2148 auto ReadValue = MTracker->
readMLoc(SrcIdx);
2149 MTracker->
setReg(DestReg, ReadValue);
2154 unsigned SpillID = MTracker->
getLocID(*Loc, Subreg);
2155 DoTransfer(SR, SpillID);
2160 unsigned SpillID = MTracker->
getLocID(*Loc, {
Size, 0});
2161 DoTransfer(Reg, SpillID);
2178 if (SrcReg == DestReg)
2207 if (MLocIt == TTracker->
ActiveMLocs.
end() || MLocIt->second.empty())
2210 ClobberedLocs[ClobberedLoc] =
Value;
2215 InstrRefBasedLDV::performCopy(SrcReg, DestReg);
2221 for (
auto LocVal : ClobberedLocs) {
2222 TTracker->
clobberMloc(LocVal.first, LocVal.second,
MI.getIterator(),
false);
2235 MTracker->
defReg(SrcReg, CurBB, CurInst);
2249 MI.getDebugLoc()->getInlinedAt());
2250 FragmentInfo ThisFragment = MIVar.getFragmentOrDefault();
2257 SeenIt->second.insert(ThisFragment);
2259 OverlapFragments.
insert({{MIVar.getVariable(), ThisFragment}, {}});
2266 OverlapFragments.
insert({{MIVar.getVariable(), ThisFragment}, {}});
2267 if (!IsInOLapMap.second)
2270 auto &ThisFragmentsOverlaps = IsInOLapMap.first->second;
2271 auto &AllSeenFragments = SeenIt->second;
2276 for (
const auto &ASeenFragment : AllSeenFragments) {
2280 ThisFragmentsOverlaps.push_back(ASeenFragment);
2283 auto ASeenFragmentsOverlaps =
2284 OverlapFragments.
find({MIVar.getVariable(), ASeenFragment});
2285 assert(ASeenFragmentsOverlaps != OverlapFragments.
end() &&
2286 "Previously seen var fragment has no vector of overlaps");
2287 ASeenFragmentsOverlaps->second.push_back(ThisFragment);
2291 AllSeenFragments.insert(ThisFragment);
2300 if (transferDebugValue(
MI))
2302 if (transferDebugInstrRef(
MI, MLiveOuts, MLiveIns))
2304 if (transferDebugPHI(
MI))
2306 if (transferRegisterCopy(
MI))
2308 if (transferSpillOrRestoreInst(
MI))
2310 transferRegisterDef(
MI);
2313void InstrRefBasedLDV::produceMLocTransferFunction(
2329 for (
auto &BV : BlockMasks)
2333 for (
auto &
MBB : MF) {
2345 for (
auto &
MI :
MBB) {
2348 process(
MI,
nullptr,
nullptr);
2351 if (
MI.isDebugValueLike())
2352 accumulateFragmentMap(
MI);
2356 if (
uint64_t InstrNo =
MI.peekDebugInstrNum()) {
2357 auto InstrAndPos = std::make_pair(&
MI, CurInst);
2359 DebugInstrNumToInstr.insert(std::make_pair(InstrNo, InstrAndPos));
2362 assert(InsertResult.second);
2373 for (
auto Location : MTracker->
locations()) {
2376 if (
P.isPHI() &&
P.getLoc() ==
Idx.asU64())
2380 auto &TransferMap = MLocTransfer[CurBB];
2381 auto Result = TransferMap.insert(std::make_pair(
Idx.asU64(),
P));
2388 for (
auto &
P : MTracker->
Masks) {
2389 BlockMasks[CurBB].clearBitsNotInMask(
P.first->getRegMask(), BVWords);
2395 for (
auto Location : MTracker->
locations()) {
2413 for (
unsigned Bit : BV.
set_bits()) {
2416 auto &TransferMap = MLocTransfer[
I];
2425 TransferMap.insert(std::make_pair(
Idx.asU64(), NotGeneratedNum));
2430 ValueID = NotGeneratedNum;
2436bool InstrRefBasedLDV::mlocJoin(
2440 bool Changed =
false;
2451 return BBToOrder.find(
A)->second < BBToOrder.find(
B)->second;
2456 if (BlockOrders.size() == 0) {
2461 <<
" from entry which may lead out of "
2462 "bound access to VarLocs\n");
2468 for (
auto Location : MTracker->
locations()) {
2473 ValueIDNum FirstVal = OutLocs[*BlockOrders[0]][
Idx.asU64()];
2478 if (InLocs[
Idx.asU64()] != FirstVal) {
2479 InLocs[
Idx.asU64()] = FirstVal;
2487 bool Disagree =
false;
2488 for (
unsigned int I = 1;
I < BlockOrders.size(); ++
I) {
2490 const ValueIDNum &PredLiveOut = OutLocs[*PredMBB][
Idx.asU64()];
2493 if (FirstVal == PredLiveOut)
2506 InLocs[
Idx.asU64()] = FirstVal;
2515void InstrRefBasedLDV::findStackIndexInterference(
2535 if (!Pair.first.second)
2541void InstrRefBasedLDV::placeMLocPHIs(
2545 findStackIndexInterference(StackUnits);
2557 for (
auto Location : MTracker->
locations()) {
2566 bool AnyIllegal =
false;
2575 FoundRegUnits.
insert(*URoot);
2581 NormalLocsToPHI.
insert(L);
2585 RegUnitsToPHIUp.
insert(FoundRegUnits.
begin(), FoundRegUnits.
end());
2591 auto CollectPHIsForLoc = [&](
LocIdx L) {
2594 for (
unsigned int I = 0;
I < OrderToBB.size(); ++
I) {
2596 const auto &TransferFunc = MLocTransfer[
MBB->
getNumber()];
2597 if (TransferFunc.contains(L))
2604 if (!DefBlocks.
empty())
2610 BlockPHIPlacement(AllBlocks, DefBlocks, PHIBlocks);
2613 auto InstallPHIsAtLoc = [&PHIBlocks, &MInLocs](
LocIdx L) {
2619 for (
LocIdx L : NormalLocsToPHI) {
2620 CollectPHIsForLoc(L);
2622 InstallPHIsAtLoc(L);
2628 for (
unsigned Idx : StackUnits) {
2631 CollectPHIsForLoc(L);
2632 InstallPHIsAtLoc(L);
2638 unsigned ThisSize, ThisOffset;
2639 std::tie(ThisSize, ThisOffset) = Pair.first;
2645 InstallPHIsAtLoc(ThisL);
2651 for (
Register R : RegUnitsToPHIUp) {
2653 CollectPHIsForLoc(L);
2656 InstallPHIsAtLoc(L);
2666 InstallPHIsAtLoc(AliasLoc);
2671void InstrRefBasedLDV::buildMLocValueMap(
2674 std::priority_queue<unsigned int, std::vector<unsigned int>,
2675 std::greater<unsigned int>>
2686 for (
unsigned int I = 0;
I < BBToOrder.size(); ++
I) {
2688 OnWorklist.
insert(OrderToBB[
I]);
2689 AllBlocks.
insert(OrderToBB[
I]);
2693 for (
auto Location : MTracker->
locations())
2702 placeMLocPHIs(MF, AllBlocks, MInLocs, MLocTransfer);
2713 while (!Worklist.empty() || !Pending.empty()) {
2717 while (!Worklist.empty()) {
2724 InLocsChanged = mlocJoin(*
MBB, Visited, MOutLocs, MInLocs[*
MBB]);
2725 InLocsChanged |= Visited.
insert(
MBB).second;
2738 for (
auto &
P : MLocTransfer[CurBB]) {
2739 if (
P.second.getBlock() == CurBB &&
P.second.isPHI()) {
2742 ToRemap.
push_back(std::make_pair(
P.first, NewID));
2745 assert(
P.second.getBlock() == CurBB);
2746 ToRemap.
push_back(std::make_pair(
P.first,
P.second));
2752 for (
auto &
P : ToRemap)
2758 bool OLChanged =
false;
2759 for (
auto Location : MTracker->
locations()) {
2775 if (BBToOrder[s] > BBToOrder[
MBB]) {
2777 if (OnWorklist.
insert(s).second)
2778 Worklist.push(BBToOrder[s]);
2781 if (OnPending.
insert(s).second)
2782 Pending.push(BBToOrder[s]);
2787 Worklist.swap(Pending);
2792 assert(Pending.empty() &&
"Pending should be empty");
2799void InstrRefBasedLDV::BlockPHIPlacement(
2808 IDF.setLiveInBlocks(AllBlocks);
2809 IDF.setDefiningBlocks(DefBlocks);
2810 IDF.calculate(PHIBlocks);
2813bool InstrRefBasedLDV::pickVPHILoc(
2819 if (BlockOrders.
empty())
2826 auto FirstValueIt = LiveOuts.
find(BlockOrders[0]);
2827 if (FirstValueIt == LiveOuts.end())
2829 const DbgValue &FirstValue = *FirstValueIt->second;
2831 for (
const auto p : BlockOrders) {
2832 auto OutValIt = LiveOuts.find(p);
2833 if (OutValIt == LiveOuts.end())
2836 const DbgValue &OutVal = *OutValIt->second;
2859 if (FirstValOp != OutValOp) {
2880 std::optional<ValueIDNum> JoinedOpLoc =
2881 pickOperandPHILoc(
Idx,
MBB, LiveOuts, MOutLocs, BlockOrders);
2889 OutValues.
append(NewDbgOps);
2893std::optional<ValueIDNum> InstrRefBasedLDV::pickOperandPHILoc(
2903 for (
const auto p : BlockOrders) {
2904 auto OutValIt = LiveOuts.find(p);
2905 assert(OutValIt != LiveOuts.end());
2906 const DbgValue &OutVal = *OutValIt->second;
2908 DbgOp OutValOp = DbgOpStore.
find(OutValOpID);
2921 for (
unsigned int I = 0;
I < NumLocs; ++
I) {
2922 if (MOutLocs[*p][
I] == ValToLookFor)
2933 for (
unsigned int I = 0;
I < NumLocs; ++
I) {
2935 if (MOutLocs[*p][
I] == MPHI)
2946 for (
unsigned int I = 1;
I < Locs.
size(); ++
I) {
2947 auto &LocVec = Locs[
I];
2949 std::set_intersection(CandidateLocs.
begin(), CandidateLocs.
end(),
2950 LocVec.begin(), LocVec.end(), std::inserter(NewCandidates, NewCandidates.
begin()));
2951 CandidateLocs = std::move(NewCandidates);
2953 if (CandidateLocs.
empty())
2954 return std::nullopt;
2966bool InstrRefBasedLDV::vlocJoin(
2971 bool Changed =
false;
2977 return BBToOrder[
A] < BBToOrder[
B];
2982 unsigned CurBlockRPONum = BBToOrder[&
MBB];
2988 int BackEdgesStart = 0;
2989 for (
auto *p : BlockOrders) {
2992 if (!BlocksToExplore.
contains(p)) {
2998 DbgValue &OutLoc = *VLOCOutLocs.find(p)->second;
3002 unsigned ThisBBRPONum = BBToOrder[
p];
3003 if (ThisBBRPONum < CurBlockRPONum)
3006 Values.
push_back(std::make_pair(p, &OutLoc));
3012 if (Bail || Values.
size() == 0)
3018 const DbgValue &FirstVal = *Values[0].second;
3024 Changed = LiveIn != FirstVal;
3033 for (
const auto &V : Values) {
3034 if (!
V.second->Properties.isJoinable(FirstVal.
Properties))
3038 if (!
V.second->hasJoinableLocOps(FirstVal))
3043 bool Disagree =
false;
3044 for (
auto &V : Values) {
3045 if (*
V.second == FirstVal)
3051 if (
V.second->hasIdenticalValidLocOps(FirstVal))
3058 std::distance(Values.begin(), &V) >= BackEdgesStart)
3066 Changed = LiveIn != FirstVal;
3073 Changed = LiveIn != VPHI;
3080void InstrRefBasedLDV::getBlocksForScope(
3090 BlocksToExplore.
insert(AssignBlocks.
begin(), AssignBlocks.
end());
3100 for (
const auto *
MBB : BlocksToExplore) {
3110 if (BlocksToExplore.count(succ))
3112 if (!ArtificialBlocks.count(succ))
3115 DFS.push_back({succ, succ->succ_begin()});
3119 while (!DFS.empty()) {
3123 if (CurSucc == CurBB->
succ_end()) {
3130 if (!ToAdd.
count(*CurSucc) && ArtificialBlocks.count(*CurSucc)) {
3132 DFS.push_back({*CurSucc, (*CurSucc)->succ_begin()});
3140 BlocksToExplore.insert(ToAdd.
begin(), ToAdd.
end());
3143void InstrRefBasedLDV::buildVLocValueMap(
3153 std::priority_queue<unsigned int, std::vector<unsigned int>,
3154 std::greater<unsigned int>>
3165 getBlocksForScope(DILoc, BlocksToExplore, AssignBlocks);
3171 if (BlocksToExplore.
size() == 1)
3178 for (
const auto *
MBB : BlocksToExplore)
3184 for (
const auto *
MBB : BlocksToExplore)
3188 for (
unsigned int I : BlockOrderNums)
3190 BlockOrderNums.clear();
3191 unsigned NumBlocks = BlockOrders.
size();
3201 for (
unsigned int I = 0;
I < NumBlocks; ++
I) {
3210 LiveOutIdx.reserve(NumBlocks);
3211 LiveInIdx.reserve(NumBlocks);
3212 for (
unsigned I = 0;
I < NumBlocks; ++
I) {
3213 LiveOutIdx[BlockOrders[
I]] = &LiveOuts[
I];
3214 LiveInIdx[BlockOrders[
I]] = &LiveIns[
I];
3224 for (
unsigned int I = 0;
I < NumBlocks; ++
I) {
3226 LiveIns[
I] = EmptyDbgValue;
3227 LiveOuts[
I] = EmptyDbgValue;
3234 auto &TransferFunc = AllTheVLocs[ExpMBB->getNumber()].Vars;
3235 if (TransferFunc.contains(
VarID))
3243 if (DefBlocks.
size() == 1) {
3244 placePHIsForSingleVarDefinition(MutBlocksToExplore, *DefBlocks.
begin(),
3245 AllTheVLocs,
VarID, Output);
3250 BlockPHIPlacement(MutBlocksToExplore, DefBlocks, PHIBlocks);
3254 unsigned BlockNo = PHIMBB->getNumber();
3255 DbgValue *LiveIn = LiveInIdx[PHIMBB];
3259 for (
auto *
MBB : BlockOrders) {
3260 Worklist.push(BBToOrder[
MBB]);
3271 bool FirstTrip =
true;
3272 while (!Worklist.empty() || !Pending.empty()) {
3273 while (!Worklist.empty()) {
3274 auto *
MBB = OrderToBB[Worklist.top()];
3278 auto LiveInsIt = LiveInIdx.find(
MBB);
3279 assert(LiveInsIt != LiveInIdx.end());
3280 DbgValue *LiveIn = LiveInsIt->second;
3284 bool InLocsChanged =
3285 vlocJoin(*
MBB, LiveOutIdx, BlocksToExplore, *LiveIn);
3300 if (pickVPHILoc(JoinedOps, *
MBB, LiveOutIdx, MOutLocs, Preds)) {
3302 InLocsChanged |= NewLocPicked;
3308 if (!InLocsChanged && !FirstTrip)
3312 bool OLChanged =
false;
3316 auto TransferIt = VTracker.
Vars.find(
VarID);
3317 if (TransferIt != VTracker.
Vars.end()) {
3321 if (*LiveOut != NewVal) {
3327 if (*LiveOut != TransferIt->second) {
3328 *LiveOut = TransferIt->second;
3334 if (*LiveOut != *LiveIn) {
3349 if (!LiveInIdx.contains(s))
3352 if (BBToOrder[s] > BBToOrder[
MBB]) {
3353 if (OnWorklist.
insert(s).second)
3354 Worklist.push(BBToOrder[s]);
3355 }
else if (OnPending.
insert(s).second && (FirstTrip || OLChanged)) {
3356 Pending.push(BBToOrder[s]);
3360 Worklist.swap(Pending);
3370 for (
auto *
MBB : BlockOrders) {
3380 Var.getFragment() &&
3381 "Fragment info missing during value prop");
3386 BlockOrders.clear();
3387 BlocksToExplore.clear();
3390void InstrRefBasedLDV::placePHIsForSingleVarDefinition(
3417 for (
auto *ScopeBlock : InScopeBlocks) {
3421 Output[ScopeBlock->getNumber()].push_back({
VarID,
Value});
3428#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
3431 for (
const auto &
P : mloc_transfer) {
3434 dbgs() <<
"Loc " << foo <<
" --> " << bar <<
"\n";
3443 EmptyExpr = DIExpression::get(Context, {});
3445 auto hasNonArtificialLocation = [](
const MachineInstr &
MI) ->
bool {
3447 return DL.getLine() != 0;
3453 unsigned int Size = 0;
3454 for (
auto &
MBB : MF) {
3457 ArtificialBlocks.insert(&
MBB);
3462 unsigned int RPONumber = 0;
3463 OrderToBB.reserve(
Size);
3464 BBToOrder.reserve(
Size);
3467 OrderToBB.push_back(
MBB);
3468 BBToOrder[
MBB] = RPONumber;
3475 if (!BBToOrder.contains(&
MBB))
3481#ifdef EXPENSIVE_CHECKS
3484 if (MF.DebugValueSubstitutions.size() > 2) {
3485 for (
auto It = MF.DebugValueSubstitutions.begin();
3486 It != std::prev(MF.DebugValueSubstitutions.end()); ++It) {
3487 assert(It->Src != std::next(It)->Src &&
"Duplicate variable location "
3488 "substitution seen");
3497void InstrRefBasedLDV::makeDepthFirstEjectionMap(
3499 const ScopeToDILocT &ScopeToDILocation,
3500 ScopeToAssignBlocksT &ScopeToAssignBlocks) {
3507 WorkStack.
push_back({TopScope, TopScope->getChildren().
size() - 1});
3509 while (!WorkStack.
empty()) {
3510 auto &ScopePosition = WorkStack.
back();
3512 ssize_t ChildNum = ScopePosition.second--;
3515 if (ChildNum >= 0) {
3518 auto &ChildScope =
Children[ChildNum];
3520 std::make_pair(ChildScope, ChildScope->getChildren().size() - 1));
3527 auto DILocationIt = ScopeToDILocation.find(WS);
3528 if (DILocationIt != ScopeToDILocation.end()) {
3529 getBlocksForScope(DILocationIt->second, BlocksToExplore,
3530 ScopeToAssignBlocks.find(WS)->second);
3531 for (
const auto *
MBB : BlocksToExplore) {
3533 if (EjectionMap[BBNum] == 0)
3537 BlocksToExplore.clear();
3543bool InstrRefBasedLDV::depthFirstVLocAndEmit(
3544 unsigned MaxNumBlocks,
const ScopeToDILocT &ScopeToDILocation,
3545 const ScopeToVarsT &ScopeToVars, ScopeToAssignBlocksT &ScopeToAssignBlocks,
3550 new TransferTracker(TII, MTracker, MF, DVMap, *TRI, CalleeSavedRegs, TPC);
3561 makeDepthFirstEjectionMap(EjectionMap, ScopeToDILocation,
3562 ScopeToAssignBlocks);
3569 AllTheVLocs[BBNum].
clear();
3575 TTracker->
loadInlocs(
MBB, MInLocs[
MBB], DbgOpStore, Output[BBNum], NumLocs);
3579 for (
auto &
MI :
MBB) {
3580 process(
MI, &MOutLocs, &MInLocs);
3589 Output[BBNum].clear();
3590 AllTheVLocs[BBNum].
clear();
3596 unsigned HighestDFSIn = 0;
3599 while (!WorkStack.
empty()) {
3600 auto &ScopePosition = WorkStack.
back();
3602 ssize_t ChildNum = ScopePosition.second++;
3609 auto DILocIt = ScopeToDILocation.find(WS);
3610 if (HighestDFSIn <= WS->getDFSIn() && DILocIt != ScopeToDILocation.end()) {
3612 auto &VarsWeCareAbout = ScopeToVars.find(WS)->second;
3613 auto &BlocksInScope = ScopeToAssignBlocks.find(WS)->second;
3615 buildVLocValueMap(DILoc, VarsWeCareAbout, BlocksInScope, Output, MOutLocs,
3616 MInLocs, AllTheVLocs);
3619 HighestDFSIn = std::max(HighestDFSIn, WS->
getDFSIn());
3623 if (ChildNum < (ssize_t)
Children.size()) {
3625 auto &ChildScope =
Children[ChildNum];
3626 WorkStack.
push_back(std::make_pair(ChildScope, 0));
3632 auto DILocationIt = ScopeToDILocation.find(WS);
3633 if (DILocationIt == ScopeToDILocation.end())
3636 getBlocksForScope(DILocationIt->second, BlocksToExplore,
3637 ScopeToAssignBlocks.find(WS)->second);
3638 for (
const auto *
MBB : BlocksToExplore)
3642 BlocksToExplore.clear();
3651 for (
auto *
MBB : ArtificialBlocks)
3655 return emitTransfers();
3658bool InstrRefBasedLDV::emitTransfers() {
3672 for (
const auto &Pair :
P.Insts)
3677 if (
P.Pos->isTerminator())
3681 for (
const auto &Pair :
P.Insts)
3695 unsigned InputDbgValLimit) {
3703 this->DomTree = DomTree;
3714 STI.getFrameLowering()->stackProbeFunctionModifiesSP();
3715 if (AdjustsStackInCalls)
3716 StackProbeSymbolName = STI.getTargetLowering()->getStackProbeSymbolName(MF);
3728 for (
auto &
MBB : MF)
3739 produceMLocTransferFunction(MF, MLocTransfer,
MaxNumBlocks);
3752 buildMLocValueMap(MF, MInLocs, MOutLocs, MLocTransfer);
3756 for (
auto &DBG_PHI : DebugPHINumToValue) {
3758 if (!DBG_PHI.ValueRead)
3772 Num = ResolvedValue;
3781 VTracker = &vlocs[CurBB];
3785 for (
auto &
MI : *
MBB) {
3786 process(
MI, &MOutLocs, &MInLocs);
3804 unsigned VarAssignCount = 0;
3805 for (
unsigned int I = 0;
I < OrderToBB.size(); ++
I) {
3806 auto *
MBB = OrderToBB[
I];
3809 for (
auto &idx : VTracker->
Vars) {
3812 assert(ScopeLoc !=
nullptr);
3816 assert(Scope !=
nullptr);
3819 ScopeToAssignBlocks[
Scope].insert(VTracker->
MBB);
3820 ScopeToDILocation[
Scope] = ScopeLoc;
3825 bool Changed =
false;
3831 VarAssignCount > InputDbgValLimit) {
3832 LLVM_DEBUG(
dbgs() <<
"Disabling InstrRefBasedLDV: " << MF.getName()
3835 <<
" variable assignments, exceeding limits.\n");
3840 Changed = depthFirstVLocAndEmit(
3841 MaxNumBlocks, ScopeToDILocation, ScopeToVars, ScopeToAssignBlocks,
3842 SavedLiveIns, MOutLocs, MInLocs, vlocs, MF, *TPC);
3851 ArtificialBlocks.clear();
3855 DebugInstrNumToInstr.clear();
3856 DebugPHINumToValue.clear();
3857 OverlapFragments.
clear();
3858 SeenFragments.
clear();
3859 SeenDbgPHIs.clear();
3885 LDVSSABlock *ParentBlock;
3886 BlockValueNum PHIValNum;
3887 LDVSSAPhi(BlockValueNum PHIValNum, LDVSSABlock *ParentBlock)
3888 : ParentBlock(ParentBlock), PHIValNum(PHIValNum) {}
3890 LDVSSABlock *
getParent() {
return ParentBlock; }
3895class LDVSSABlockIterator {
3898 LDVSSAUpdater &Updater;
3901 LDVSSAUpdater &Updater)
3902 : PredIt(PredIt), Updater(Updater) {}
3904 bool operator!=(
const LDVSSABlockIterator &OtherIt)
const {
3905 return OtherIt.PredIt != PredIt;
3908 LDVSSABlockIterator &operator++() {
3922 LDVSSAUpdater &Updater;
3928 : BB(BB), Updater(Updater) {}
3931 return LDVSSABlockIterator(BB.
succ_begin(), Updater);
3935 return LDVSSABlockIterator(BB.
succ_end(), Updater);
3939 LDVSSAPhi *newPHI(BlockValueNum
Value) {
3940 PHIList.emplace_back(
Value,
this);
3941 return &PHIList.back();
3945 PHIListT &phis() {
return PHIList; }
3951class LDVSSAUpdater {
3966 : Loc(
L), MLiveIns(MLiveIns) {}
3969 for (
auto &
Block : BlockMap)
3970 delete Block.second;
3977 ~LDVSSAUpdater() { reset(); }
3982 auto [It,
Inserted] = BlockMap.try_emplace(BB);
3984 It->second =
new LDVSSABlock(*BB, *
this);
3990 BlockValueNum getValue(LDVSSABlock *LDVBB) {
3991 return MLiveIns[LDVBB->BB][Loc.
asU64()].asU64();
3995LDVSSABlock *LDVSSABlockIterator::operator*() {
3996 return Updater.getSSALDVBlock(*PredIt);
4002 out <<
"SSALDVPHI " <<
PHI.PHIValNum;
4028 class PHI_iterator {
4054 return PHI_iterator(
PHI,
true);
4062 Preds->
push_back(BB->Updater.getSSALDVBlock(Pred));
4068 static BlockValueNum
GetPoisonVal(LDVSSABlock *BB, LDVSSAUpdater *Updater) {
4072 BlockValueNum Num =
ValueIDNum(BB->BB.getNumber(), 0, Updater->Loc).
asU64();
4073 Updater->PoisonMap[&BB->BB] = Num;
4083 LDVSSAUpdater *Updater) {
4084 BlockValueNum PHIValNum = Updater->getValue(BB);
4085 LDVSSAPhi *
PHI = BB->newPHI(PHIValNum);
4086 Updater->PHIs[PHIValNum] =
PHI;
4093 PHI->IncomingValues.push_back(std::make_pair(Pred, Val));
4098 static LDVSSAPhi *
ValueIsPHI(BlockValueNum Val, LDVSSAUpdater *Updater) {
4099 return Updater->PHIs.lookup(Val);
4105 LDVSSAPhi *
PHI = ValueIsPHI(Val, Updater);
4106 if (
PHI &&
PHI->IncomingValues.size() == 0)
4118std::optional<ValueIDNum> InstrRefBasedLDV::resolveDbgPHIs(
4123 auto SeenDbgPHIIt = SeenDbgPHIs.find(std::make_pair(&Here, InstrNum));
4124 if (SeenDbgPHIIt != SeenDbgPHIs.end())
4125 return SeenDbgPHIIt->second;
4127 std::optional<ValueIDNum>
Result =
4128 resolveDbgPHIsImpl(MF, MLiveOuts, MLiveIns, Here, InstrNum);
4129 SeenDbgPHIs.insert({std::make_pair(&Here, InstrNum),
Result});
4133std::optional<ValueIDNum> InstrRefBasedLDV::resolveDbgPHIsImpl(
4138 auto RangePair = std::equal_range(DebugPHINumToValue.begin(),
4139 DebugPHINumToValue.end(), InstrNum);
4140 auto LowerIt = RangePair.first;
4141 auto UpperIt = RangePair.second;
4144 if (LowerIt == UpperIt)
4145 return std::nullopt;
4151 auto DBGPHIRange =
make_range(LowerIt, UpperIt);
4152 for (
const DebugPHIRecord &DBG_PHI : DBGPHIRange)
4153 if (!DBG_PHI.ValueRead)
4154 return std::nullopt;
4157 if (std::distance(LowerIt, UpperIt) == 1)
4158 return *LowerIt->ValueRead;
4164 LocIdx Loc = *LowerIt->ReadLoc;
4173 LDVSSAUpdater Updater(Loc, MLiveIns);
4181 for (
const auto &DBG_PHI : DBGPHIRange) {
4182 LDVSSABlock *
Block = Updater.getSSALDVBlock(DBG_PHI.MBB);
4187 LDVSSABlock *HereBlock = Updater.getSSALDVBlock(Here.
getParent());
4188 const auto &AvailIt = AvailableValues.
find(HereBlock);
4189 if (AvailIt != AvailableValues.
end()) {
4198 BlockValueNum ResultInt = Impl.GetValue(Updater.getSSALDVBlock(Here.
getParent()));
4215 for (
const auto &DBG_PHI : DBGPHIRange) {
4216 LDVSSABlock *
Block = Updater.getSSALDVBlock(DBG_PHI.MBB);
4218 ValidatedValues.
insert(std::make_pair(
Block, Num));
4223 for (
auto &
PHI : CreatedPHIs)
4226 llvm::sort(SortedPHIs, [&](LDVSSAPhi *
A, LDVSSAPhi *
B) {
4227 return BBToOrder[&
A->getParent()->BB] < BBToOrder[&
B->getParent()->BB];
4230 for (
auto &
PHI : SortedPHIs) {
4234 for (
auto &PHIIt :
PHI->IncomingValues) {
4236 if (Updater.PoisonMap.contains(&PHIIt.first->BB))
4237 return std::nullopt;
4240 const ValueTable &BlockLiveOuts = MLiveOuts[PHIIt.first->BB];
4242 auto VVal = ValidatedValues.
find(PHIIt.first);
4243 if (VVal == ValidatedValues.
end()) {
4248 ValueToCheck = ThisBlockValueNum;
4252 ValueToCheck = VVal->second;
4255 if (BlockLiveOuts[Loc.
asU64()] != ValueToCheck)
4256 return std::nullopt;
4260 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
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
Mapping from DebugVariable to/from a unique identifying number.
const VarAndLoc & lookupDVID(DebugVariableID ID) const
DebugVariableID insertDVID(DebugVariable &Var, const DILocation *Loc)
DebugVariableID getDVID(const DebugVariable &Var) const
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
SmallDenseMap< const MachineBasicBlock *, DbgValue *, 16 > LiveIdxT
Live in/out structure for the variable values: a per-block map of variables to their values.
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< DebugVariableID, 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.
MachineInstrBuilder emitLoc(const SmallVectorImpl< ResolvedDbgOp > &DbgOps, const DebugVariable &Var, const DILocation *DILoc, const DbgValueProperties &Properties)
Create a DBG_VALUE based on debug operands DbgOps.
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...
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.
SmallDenseMap< DebugVariableID, const DILocation *, 8 > Scopes
SmallMapVector< DebugVariableID, DbgValue, 8 > Vars
Map DebugVariable to the latest Value it's defined to have.
void defVar(const MachineInstr &MI, const DbgValueProperties &Properties, const SmallVectorImpl< DbgOpID > &DebugOps)
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...
const DebugVariableMap & DVMap
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)
TransferTracker(const TargetInstrInfo *TII, MLocTracker *MTracker, MachineFunction &MF, const DebugVariableMap &DVMap, const TargetRegisterInfo &TRI, const BitVector &CalleeSavedRegs, const TargetPassConfig &TPC)
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),...
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)
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
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.
bool properlyDominates(const DomTreeNodeBase< NodeT > *A, const DomTreeNodeBase< NodeT > *B) const
properlyDominates - Returns true iff A dominates B and A != B.
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.
TypeSize getValue() const
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.
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 ...
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()
SmallVectorImpl< MachineBasicBlock * >::const_iterator const_succ_iterator
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...
succ_iterator succ_begin()
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.
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()
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...
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.
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
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.
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)
Implements a dense probed hash-table based set with some number of buckets stored inline.
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
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...
const_iterator begin() const
const_iterator end() const
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.
std::string str() const
str - Get the contents as an std::string.
constexpr const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
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.
std::optional< DestSourcePair > isCopyLikeInstr(const MachineInstr &MI) const
virtual Register isStoreToStackSlotPostFE(const MachineInstr &MI, int &FrameIndex) const
Check for post-frame ptr elimination stack locations as well.
virtual Register isLoadFromStackSlotPostFE(const MachineInstr &MI, int &FrameIndex) const
Check for post-frame ptr elimination stack locations as well.
Register getStackPointerRegisterToSaveRestore() const
If a physical register, this specifies the register that llvm.savestack/llvm.restorestack should save...
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
Primary interface to the complete machine description for the target machine.
unsigned getPointerSizeInBits(unsigned AS) const
Target-Independent Code Generator Pass Configuration Options.
TMC & getTM() const
Get the right type of TargetMachine for this target.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
iterator_range< regclass_iterator > regclasses() const
TypeSize getRegSizeInBits(const TargetRegisterClass &RC) const
Return the size in bits of a register from class RC.
unsigned getSubRegIdxSize(unsigned Idx) const
Get the size of the bit range covered by a sub-register index.
MCRegister getSubReg(MCRegister Reg, unsigned Idx) const
Returns the physical register number of sub-register "Index" for physical register RegNo.
virtual StringRef getRegAsmName(MCRegister Reg) const
Return the assembly name for Reg.
unsigned getSubRegIdxOffset(unsigned Idx) const
Get the offset of the bit range covered by a sub-register index.
virtual Register getFrameRegister(const MachineFunction &MF) const =0
Debug information queries.
virtual void getOffsetOpcodes(const StackOffset &Offset, SmallVectorImpl< uint64_t > &Ops) const
Gets the DWARF expression opcodes for Offset.
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
virtual const TargetFrameLowering * getFrameLowering() const
virtual const TargetInstrInfo * getInstrInfo() const
virtual const TargetLowering * getTargetLowering() const
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
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)
iterator find(const_arg_type_t< ValueT > V)
bool contains(const_arg_type_t< ValueT > V) const
Check if the set contains the given element.
bool erase(const ValueT &V)
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.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Reg
All possible values of the reg field in the ModR/M byte.
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.
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)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
std::tuple< const DIScope *, const DIScope *, const DILocalVariable * > VarID
A unique key that represents a debug variable.
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...
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...
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...
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
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
Record of a use-before-def: created when a value that's live-in to the current block isn't available ...
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.
Description of the encoding of one expression Op.
Function object to check whether the first component of a container supported by std::get (like std::...