137#include "llvm/Config/llvm-config.h"
159#define DEBUG_TYPE "livedebugvalues"
161STATISTIC(NumInserted,
"Number of DBG_VALUE instructions inserted");
178 return Reg && Reg != SP && Reg !=
FP;
214 static constexpr u32_location_t kUniversalLocation = 0;
218 static constexpr u32_location_t kFirstRegLocation = 1;
222 static constexpr u32_location_t kFirstInvalidRegLocation = 1 << 30;
226 static constexpr u32_location_t kSpillLocation = kFirstInvalidRegLocation;
230 static constexpr u32_location_t kEntryValueBackupLocation =
231 kFirstInvalidRegLocation + 1;
239 static constexpr u32_location_t kWasmLocation = kFirstInvalidRegLocation + 2;
243 static constexpr u32_location_t kFirstVirtualRegLocation = 1 << 31;
245 LocIndex(u32_location_t Location, u32_index_t Index)
252 template<
typename IntT>
static LocIndex fromRawInteger(IntT
ID) {
253 static_assert(std::is_unsigned_v<IntT> &&
sizeof(
ID) ==
sizeof(
uint64_t),
254 "Cannot convert raw integer to LocIndex");
255 return {
static_cast<u32_location_t
>(
ID >> 32),
256 static_cast<u32_index_t
>(
ID)};
262 return LocIndex(Reg, 0).getAsRawInteger();
267 static auto indexRangeForLocation(
const VarLocSet &Set,
268 u32_location_t Location) {
269 uint64_t Start = LocIndex(Location, 0).getAsRawInteger();
270 uint64_t End = LocIndex(Location + 1, 0).getAsRawInteger();
271 return Set.half_open_range(Start,
End);
282class VarLocBasedLDV :
public LDVImpl {
290 VarLocSet::Allocator
Alloc;
294 enum struct TransferKind { TransferCopy, TransferSpill, TransferRestore };
297 using OptFragmentInfo = std::optional<DIExpression::FragmentInfo>;
307 return SpillBase ==
Other.SpillBase && SpillOffset ==
Other.SpillOffset;
310 return !(*
this ==
Other);
339 enum class MachineLocKind {
347 enum class EntryValueLocKind {
348 NonEntryValueKind = 0,
350 EntryValueBackupKind,
351 EntryValueCopyBackupKind
352 } EVKind = EntryValueLocKind::NonEntryValueKind;
356 union MachineLocValue {
363 WasmLoc WasmLocation;
364 MachineLocValue() : Hash(0) {}
373 MachineLocValue
Value;
375 if (Kind !=
Other.Kind)
378 case MachineLocKind::SpillLocKind:
379 return Value.SpillLocation ==
Other.Value.SpillLocation;
380 case MachineLocKind::WasmLocKind:
381 return Value.WasmLocation ==
Other.Value.WasmLocation;
382 case MachineLocKind::RegisterKind:
383 case MachineLocKind::ImmediateKind:
391 case MachineLocKind::SpillLocKind:
392 return std::make_tuple(
393 Kind,
Value.SpillLocation.SpillBase,
394 Value.SpillLocation.SpillOffset.getFixed(),
395 Value.SpillLocation.SpillOffset.getScalable()) <
397 Other.Kind,
Other.Value.SpillLocation.SpillBase,
398 Other.Value.SpillLocation.SpillOffset.getFixed(),
399 Other.Value.SpillLocation.SpillOffset.getScalable());
400 case MachineLocKind::WasmLocKind:
401 return std::make_tuple(Kind,
Value.WasmLocation.Index,
402 Value.WasmLocation.Offset) <
403 std::make_tuple(
Other.Kind,
Other.Value.WasmLocation.Index,
404 Other.Value.WasmLocation.Offset);
405 case MachineLocKind::RegisterKind:
406 case MachineLocKind::ImmediateKind:
407 return std::tie(Kind,
Value.Hash) <
426 : Var(
MI.getDebugVariable(),
MI.getDebugExpression(),
428 Expr(
MI.getDebugExpression()),
MI(
MI) {
429 assert(
MI.isDebugValue() &&
"not a DBG_VALUE");
430 assert((
MI.isDebugValueList() ||
MI.getNumOperands() == 4) &&
431 "malformed DBG_VALUE");
433 MachineLoc
ML = GetLocForOp(
Op);
435 if (It == Locs.
end()) {
441 unsigned OpIdx = Locs.
size();
442 unsigned DuplicatingIdx = std::distance(Locs.
begin(), It);
449 assert(EVKind != EntryValueLocKind::EntryValueKind &&
450 !isEntryBackupLoc());
457 Kind = MachineLocKind::RegisterKind;
458 Loc.RegNo =
Op.getReg();
459 }
else if (
Op.isImm()) {
460 Kind = MachineLocKind::ImmediateKind;
461 Loc.Immediate =
Op.getImm();
462 }
else if (
Op.isFPImm()) {
463 Kind = MachineLocKind::ImmediateKind;
464 Loc.FPImm =
Op.getFPImm();
465 }
else if (
Op.isCImm()) {
466 Kind = MachineLocKind::ImmediateKind;
467 Loc.CImm =
Op.getCImm();
468 }
else if (
Op.isTargetIndex()) {
469 Kind = MachineLocKind::WasmLocKind;
470 Loc.WasmLocation = {
Op.getIndex(),
Op.getOffset()};
481 assert(VL.Locs.size() == 1 &&
482 VL.Locs[0].Kind == MachineLocKind::RegisterKind);
483 VL.EVKind = EntryValueLocKind::EntryValueKind;
485 VL.Locs[0].Value.RegNo =
Reg;
493 static VarLoc CreateEntryBackupLoc(
const MachineInstr &MI,
496 assert(VL.Locs.size() == 1 &&
497 VL.Locs[0].Kind == MachineLocKind::RegisterKind);
498 VL.EVKind = EntryValueLocKind::EntryValueBackupKind;
506 static VarLoc CreateEntryCopyBackupLoc(
const MachineInstr &MI,
510 assert(VL.Locs.size() == 1 &&
511 VL.Locs[0].Kind == MachineLocKind::RegisterKind);
512 VL.EVKind = EntryValueLocKind::EntryValueCopyBackupKind;
514 VL.Locs[0].Value.RegNo = NewReg;
520 static VarLoc CreateCopyLoc(
const VarLoc &OldVL,
const MachineLoc &OldML,
523 for (MachineLoc &
ML : VL.Locs)
525 ML.Kind = MachineLocKind::RegisterKind;
526 ML.Value.RegNo = NewReg;
534 static VarLoc CreateSpillLoc(
const VarLoc &OldVL,
const MachineLoc &OldML,
537 for (MachineLoc &
ML : VL.Locs)
539 ML.Kind = MachineLocKind::SpillLocKind;
540 ML.Value.SpillLocation = {SpillBase, SpillOffset};
551 assert(!isEntryBackupLoc() &&
552 "Tried to produce DBG_VALUE for backup VarLoc");
555 const auto &IID =
MI.getDesc();
561 for (
unsigned I = 0, E = Locs.
size();
I < E; ++
I) {
562 MachineLocKind LocKind = Locs[
I].Kind;
563 MachineLocValue Loc = Locs[
I].Value;
566 case MachineLocKind::RegisterKind:
574 EVKind == EntryValueLocKind::EntryValueKind ? Orig.
getReg()
578 case MachineLocKind::SpillLocKind: {
583 unsigned Base = Loc.SpillLocation.SpillBase;
585 if (
MI.isNonListDebugValue()) {
587 DIExpr =
TRI->prependOffsetExpression(
589 Loc.SpillLocation.SpillOffset);
593 TRI->getOffsetOpcodes(Loc.SpillLocation.SpillOffset, Ops);
600 case MachineLocKind::ImmediateKind: {
604 case MachineLocKind::WasmLocKind: {
608 case MachineLocKind::InvalidKind:
612 return BuildMI(MF, DbgLoc, IID, Indirect, MOs, Var, DIExpr);
617 return Kind == MachineLocKind::ImmediateKind;
621 bool isEntryBackupLoc()
const {
622 return EVKind == EntryValueLocKind::EntryValueBackupKind ||
623 EVKind == EntryValueLocKind::EntryValueCopyBackupKind;
628 bool isEntryValueBackupReg(
Register Reg)
const {
629 return EVKind == EntryValueLocKind::EntryValueBackupKind && usesReg(Reg);
634 bool isEntryValueCopyBackupReg(
Register Reg)
const {
635 return EVKind == EntryValueLocKind::EntryValueCopyBackupKind &&
642 RegML.Kind = MachineLocKind::RegisterKind;
643 RegML.Value.RegNo =
Reg;
648 unsigned getRegIdx(
Register Reg)
const {
650 if (Locs[
Idx].Kind == MachineLocKind::RegisterKind &&
659 bool AnyRegs =
false;
660 for (
const auto &Loc : Locs)
661 if (Loc.Kind == MachineLocKind::RegisterKind) {
668 bool containsSpillLocs()
const {
669 return any_of(Locs, [](VarLoc::MachineLoc
ML) {
670 return ML.Kind == VarLoc::MachineLocKind::SpillLocKind;
676 bool usesSpillLoc(
SpillLoc SpillLocation)
const {
678 SpillML.Kind = MachineLocKind::SpillLocKind;
679 SpillML.Value.SpillLocation = SpillLocation;
685 unsigned getSpillLocIdx(
SpillLoc SpillLocation)
const {
686 for (
unsigned Idx = 0;
Idx < Locs.size(); ++
Idx)
687 if (Locs[
Idx].Kind == MachineLocKind::SpillLocKind &&
688 Locs[
Idx].
Value.SpillLocation == SpillLocation)
693 bool containsWasmLocs()
const {
694 return any_of(Locs, [](VarLoc::MachineLoc
ML) {
695 return ML.Kind == VarLoc::MachineLocKind::WasmLocKind;
701 bool usesWasmLoc(WasmLoc WasmLocation)
const {
703 WasmML.Kind = MachineLocKind::WasmLocKind;
704 WasmML.Value.WasmLocation = WasmLocation;
711 return LS.dominates(
MI.getDebugLoc().get(), &
MBB);
714#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
719 for (
const MachineLoc &MLoc : Locs) {
720 if (Locs.begin() != &MLoc)
723 case MachineLocKind::RegisterKind:
724 Out <<
printReg(MLoc.Value.RegNo, TRI);
726 case MachineLocKind::SpillLocKind:
727 Out <<
printReg(MLoc.Value.SpillLocation.SpillBase, TRI);
728 Out <<
"[" << MLoc.Value.SpillLocation.SpillOffset.getFixed() <<
" + "
729 << MLoc.Value.SpillLocation.SpillOffset.getScalable()
733 case MachineLocKind::ImmediateKind:
734 Out << MLoc.Value.Immediate;
736 case MachineLocKind::WasmLocKind: {
738 auto Indices =
TII->getSerializableTargetIndices();
740 find_if(Indices, [&](
const std::pair<int, const char *> &
I) {
741 return I.first == MLoc.Value.WasmLocation.Index;
743 assert(Found != Indices.end());
744 Out << Found->second;
745 if (MLoc.Value.WasmLocation.Offset > 0)
746 Out <<
" + " << MLoc.Value.WasmLocation.Offset;
752 case MachineLocKind::InvalidKind:
757 Out <<
", \"" << Var.getVariable()->
getName() <<
"\", " << *Expr <<
", ";
758 if (Var.getInlinedAt())
763 if (isEntryBackupLoc())
764 Out <<
" (backup loc)\n";
771 return std::tie(EVKind, Var, Expr, Locs) ==
777 return std::tie(Var, EVKind, Locs, Expr) <
793 std::map<VarLoc, LocIndices> Var2Indices;
801 LocIndices insert(
const VarLoc &VL) {
802 LocIndices &Indices = Var2Indices[VL];
804 if (!Indices.empty())
812 if (VL.EVKind == VarLoc::EntryValueLocKind::NonEntryValueKind) {
813 VL.getDescribingRegs(Locations);
816 return (RegNo < LocIndex::kFirstInvalidRegLocation) ||
817 (LocIndex::kFirstVirtualRegLocation <= RegNo);
819 "Physical or virtual register out of range?");
820 if (VL.containsSpillLocs())
821 Locations.push_back(LocIndex::kSpillLocation);
822 if (VL.containsWasmLocs())
823 Locations.push_back(LocIndex::kWasmLocation);
824 }
else if (VL.EVKind != VarLoc::EntryValueLocKind::EntryValueKind) {
828 Locations.push_back(LocIndex::kUniversalLocation);
838 LocIndices getAllIndices(
const VarLoc &VL)
const {
839 auto IndIt = Var2Indices.
find(VL);
840 assert(IndIt != Var2Indices.end() &&
"VarLoc not tracked");
841 return IndIt->second;
845 const VarLoc &operator[](LocIndex
ID)
const {
846 auto LocIt = Loc2Vars.
find(
ID.Location);
847 assert(LocIt != Loc2Vars.
end() &&
"Location not tracked");
848 return LocIt->second[
ID.Index];
854 struct TransferDebugPair {
861 using InstToEntryLocMap = std::multimap<const MachineInstr *, LocIndex>;
868 std::pair<const DILocalVariable *, DIExpression::FragmentInfo>;
874 using VarToFragments =
880 const VarLocSet &CollectFrom,
881 const VarLocMap &VarLocIDs);
885 void getUsedRegs(
const VarLocSet &CollectFrom,
897 class OpenRangesSet {
898 VarLocSet::Allocator &Alloc;
907 OpenRangesSet(VarLocSet::Allocator &Alloc,
OverlapMap &_OLapMap)
908 : Alloc(Alloc), VarLocs(Alloc), OverlappingFragments(_OLapMap) {}
910 const VarLocSet &getVarLocs()
const {
return VarLocs; }
918 const VarLocMap &VarLocIDs)
const {
919 collectAllVarLocs(Collected, VarLocs, VarLocIDs);
923 void erase(
const VarLoc &VL);
927 void erase(
const VarLocsInRange &KillSet,
const VarLocMap &VarLocIDs,
931 void insert(LocIndices VarLocIDs,
const VarLoc &VL);
934 void insertFromLocSet(
const VarLocSet &ToLoad,
const VarLocMap &Map);
936 std::optional<LocIndices> getEntryValueBackup(
DebugVariable Var);
942 EntryValuesBackupVars.
clear();
948 Vars.
empty() == VarLocs.empty() &&
949 "open ranges are inconsistent");
950 return VarLocs.empty();
954 auto getEmptyVarLocRange()
const {
960 auto getRegisterVarLocs(
Register Reg)
const {
961 return LocIndex::indexRangeForLocation(getVarLocs(), Reg);
965 auto getSpillVarLocs()
const {
966 return LocIndex::indexRangeForLocation(getVarLocs(),
967 LocIndex::kSpillLocation);
972 auto getEntryValueBackupVarLocs()
const {
973 return LocIndex::indexRangeForLocation(
974 getVarLocs(), LocIndex::kEntryValueBackupLocation);
978 auto getWasmVarLocs()
const {
979 return LocIndex::indexRangeForLocation(getVarLocs(),
980 LocIndex::kWasmLocation);
988 static void collectIDsForRegs(VarLocsInRange &Collected,
989 const DefinedRegsSet &Regs,
990 const VarLocSet &CollectFrom,
991 const VarLocMap &VarLocIDs);
994 std::unique_ptr<VarLocSet> &VLS = Locs[
MBB];
996 VLS = std::make_unique<VarLocSet>(Alloc);
1001 const VarLocInMBB &Locs)
const {
1002 auto It = Locs.find(
MBB);
1003 assert(It != Locs.end() &&
"MBB not in map");
1025 const DefinedRegsSet &Regs)
const;
1029 std::optional<VarLoc::SpillLoc> isRestoreInstruction(
const MachineInstr &
MI,
1034 VarLoc::SpillLoc extractSpillBaseRegAndOffset(
const MachineInstr &
MI);
1035 void insertTransferDebugPair(
MachineInstr &
MI, OpenRangesSet &OpenRanges,
1036 TransferMap &Transfers, VarLocMap &VarLocIDs,
1037 LocIndex OldVarID, TransferKind Kind,
1038 const VarLoc::MachineLoc &OldLoc,
1041 void transferDebugValue(
const MachineInstr &
MI, OpenRangesSet &OpenRanges,
1042 VarLocMap &VarLocIDs,
1043 InstToEntryLocMap &EntryValTransfers,
1044 RegDefToInstMap &RegSetInstrs);
1045 void transferSpillOrRestoreInst(
MachineInstr &
MI, OpenRangesSet &OpenRanges,
1046 VarLocMap &VarLocIDs, TransferMap &Transfers);
1048 OpenRangesSet &OpenRanges,
1049 VarLocMap &VarLocIDs,
const VarLoc &EntryVL,
1050 InstToEntryLocMap &EntryValTransfers);
1051 void removeEntryValue(
const MachineInstr &
MI, OpenRangesSet &OpenRanges,
1052 VarLocMap &VarLocIDs,
const VarLoc &EntryVL,
1053 InstToEntryLocMap &EntryValTransfers,
1054 RegDefToInstMap &RegSetInstrs);
1055 void emitEntryValues(
MachineInstr &
MI, OpenRangesSet &OpenRanges,
1056 VarLocMap &VarLocIDs,
1057 InstToEntryLocMap &EntryValTransfers,
1058 VarLocsInRange &KillSet);
1060 const DefinedRegsSet &DefinedRegs,
1061 OpenRangesSet &OpenRanges, VarLocMap &VarLocIDs);
1062 void transferRegisterCopy(
MachineInstr &
MI, OpenRangesSet &OpenRanges,
1063 VarLocMap &VarLocIDs, TransferMap &Transfers);
1064 void transferRegisterDef(
MachineInstr &
MI, OpenRangesSet &OpenRanges,
1065 VarLocMap &VarLocIDs,
1066 InstToEntryLocMap &EntryValTransfers,
1067 RegDefToInstMap &RegSetInstrs);
1068 void transferWasmDef(
MachineInstr &
MI, OpenRangesSet &OpenRanges,
1069 VarLocMap &VarLocIDs);
1071 VarLocInMBB &OutLocs,
const VarLocMap &VarLocIDs);
1074 VarLocMap &VarLocIDs, TransferMap &Transfers,
1075 InstToEntryLocMap &EntryValTransfers,
1076 RegDefToInstMap &RegSetInstrs);
1078 void accumulateFragmentMap(
MachineInstr &
MI, VarToFragments &SeenFragments,
1082 const VarLocMap &VarLocIDs,
1088 void flushPendingLocs(VarLocInMBB &PendingInLocs, VarLocMap &VarLocIDs);
1092 unsigned InputDbgValLimit)
override;
1101 void printVarLocInMBB(
const MachineFunction &MF,
const VarLocInMBB &V,
1102 const VarLocMap &VarLocIDs,
const char *msg,
1112VarLocBasedLDV::VarLocBasedLDV() =
default;
1114VarLocBasedLDV::~VarLocBasedLDV() =
default;
1121void VarLocBasedLDV::OpenRangesSet::erase(
const VarLoc &VL) {
1124 auto *EraseFrom = VL.isEntryBackupLoc() ? &EntryValuesBackupVars : &Vars;
1125 auto It = EraseFrom->
find(VarToErase);
1126 if (It != EraseFrom->end()) {
1127 LocIndices IDs = It->second;
1128 for (LocIndex
ID : IDs)
1129 VarLocs.reset(
ID.getAsRawInteger());
1130 EraseFrom->erase(It);
1145 auto MapIt = OverlappingFragments.
find({Var.
getVariable(), ThisFragment});
1146 if (MapIt != OverlappingFragments.
end()) {
1147 for (
auto Fragment : MapIt->second) {
1148 VarLocBasedLDV::OptFragmentInfo FragmentHolder;
1150 FragmentHolder = VarLocBasedLDV::OptFragmentInfo(Fragment);
1156void VarLocBasedLDV::OpenRangesSet::erase(
const VarLocsInRange &KillSet,
1157 const VarLocMap &VarLocIDs,
1159 VarLocSet RemoveSet(Alloc);
1161 const VarLoc &VL = VarLocIDs[LocIndex(Location,
ID)];
1162 auto *EraseFrom = VL.isEntryBackupLoc() ? &EntryValuesBackupVars : &Vars;
1163 EraseFrom->
erase(VL.Var);
1164 LocIndices VLI = VarLocIDs.getAllIndices(VL);
1165 for (LocIndex
ID : VLI)
1166 RemoveSet.set(
ID.getAsRawInteger());
1168 VarLocs.intersectWithComplement(RemoveSet);
1171void VarLocBasedLDV::OpenRangesSet::insertFromLocSet(
const VarLocSet &ToLoad,
1172 const VarLocMap &Map) {
1173 VarLocsInRange UniqueVarLocIDs;
1174 DefinedRegsSet Regs;
1175 Regs.
insert(LocIndex::kUniversalLocation);
1176 collectIDsForRegs(UniqueVarLocIDs, Regs, ToLoad, Map);
1178 LocIndex
Idx = LocIndex::fromRawInteger(
ID);
1179 const VarLoc &VarL =
Map[
Idx];
1180 const LocIndices Indices =
Map.getAllIndices(VarL);
1181 insert(Indices, VarL);
1185void VarLocBasedLDV::OpenRangesSet::insert(LocIndices VarLocIDs,
1187 auto *InsertInto = VL.isEntryBackupLoc() ? &EntryValuesBackupVars : &Vars;
1188 for (LocIndex
ID : VarLocIDs)
1189 VarLocs.set(
ID.getAsRawInteger());
1190 InsertInto->
insert({VL.Var, VarLocIDs});
1195std::optional<LocIndices>
1196VarLocBasedLDV::OpenRangesSet::getEntryValueBackup(
DebugVariable Var) {
1197 auto It = EntryValuesBackupVars.
find(Var);
1198 if (It != EntryValuesBackupVars.
end())
1201 return std::nullopt;
1204void VarLocBasedLDV::collectIDsForRegs(VarLocsInRange &Collected,
1205 const DefinedRegsSet &Regs,
1206 const VarLocSet &CollectFrom,
1207 const VarLocMap &VarLocIDs) {
1208 assert(!Regs.empty() &&
"Nothing to collect");
1212 auto It = CollectFrom.find(LocIndex::rawIndexForReg(SortedRegs.
front()));
1213 auto End = CollectFrom.end();
1218 uint64_t FirstIndexForReg = LocIndex::rawIndexForReg(Reg);
1219 uint64_t FirstInvalidIndex = LocIndex::rawIndexForReg(Reg + 1);
1220 It.advanceToLowerBound(FirstIndexForReg);
1223 for (; It !=
End && *It < FirstInvalidIndex; ++It) {
1224 LocIndex ItIdx = LocIndex::fromRawInteger(*It);
1225 const VarLoc &VL = VarLocIDs[ItIdx];
1226 LocIndices LI = VarLocIDs.getAllIndices(VL);
1228 assert(LI.back().Location == LocIndex::kUniversalLocation &&
1229 "Unexpected order of LocIndices for VarLoc; was it inserted into "
1230 "the VarLocMap correctly?");
1231 Collected.insert(LI.back().Index);
1239void VarLocBasedLDV::getUsedRegs(
const VarLocSet &CollectFrom,
1244 LocIndex::rawIndexForReg(LocIndex::kFirstRegLocation);
1246 LocIndex::rawIndexForReg(LocIndex::kFirstInvalidRegLocation);
1248 LocIndex::rawIndexForReg(LocIndex::kFirstVirtualRegLocation);
1249 auto doGetUsedRegs = [&](VarLocSet::const_iterator &It) {
1252 uint32_t FoundReg = LocIndex::fromRawInteger(*It).Location;
1254 "Duplicate used reg");
1260 uint64_t NextRegIndex = LocIndex::rawIndexForReg(FoundReg + 1);
1261 It.advanceToLowerBound(NextRegIndex);
1263 for (
auto It = CollectFrom.find(FirstRegIndex),
1264 End = CollectFrom.find(FirstInvalidIndex);
1268 for (
auto It = CollectFrom.find(FirstVirtualRegIndex),
1269 End = CollectFrom.end();
1281 const VarLocInMBB &V,
1282 const VarLocMap &VarLocIDs,
1285 Out <<
'\n' << msg <<
'\n';
1289 const VarLocSet &
L = getVarLocsInMBB(&BB, V);
1293 collectAllVarLocs(VarLocs, L, VarLocIDs);
1294 Out <<
"MBB: " << BB.getNumber() <<
":\n";
1295 for (
const VarLoc &VL : VarLocs) {
1296 Out <<
" Var: " << VL.Var.getVariable()->getName();
1305VarLocBasedLDV::VarLoc::SpillLoc
1306VarLocBasedLDV::extractSpillBaseRegAndOffset(
const MachineInstr &
MI) {
1308 "Spill instruction does not have exactly one memory operand?");
1309 auto MMOI =
MI.memoperands_begin();
1312 "Inconsistent memory operand in spill instruction");
1313 int FI = cast<FixedStackPseudoSourceValue>(PVal)->getFrameIndex();
1322void VarLocBasedLDV::cleanupEntryValueTransfers(
1323 const MachineInstr *TRInst, OpenRangesSet &OpenRanges, VarLocMap &VarLocIDs,
1324 const VarLoc &EntryVL, InstToEntryLocMap &EntryValTransfers) {
1325 if (EntryValTransfers.empty() || TRInst ==
nullptr)
1328 auto TransRange = EntryValTransfers.equal_range(TRInst);
1330 const VarLoc &EmittedEV = VarLocIDs[TDPair.second];
1331 if (std::tie(EntryVL.Var, EntryVL.Locs[0].Value.RegNo, EntryVL.Expr) ==
1332 std::tie(EmittedEV.Var, EmittedEV.Locs[0].Value.RegNo,
1334 OpenRanges.erase(EmittedEV);
1335 EntryValTransfers.erase(TRInst);
1346 OpenRangesSet &OpenRanges,
1347 VarLocMap &VarLocIDs,
1348 const VarLoc &EntryVL,
1349 InstToEntryLocMap &EntryValTransfers,
1350 RegDefToInstMap &RegSetInstrs) {
1352 if (&
MI == &EntryVL.MI)
1358 if (!
MI.getDebugOperand(0).isReg())
1364 if (
Reg.isValid() && RegSetInstrs.contains(Reg))
1365 TransferInst = RegSetInstrs.find(Reg)->second;
1368 if (!TransferInst && !LastNonDbgMI &&
MI.getParent()->isEntryBlock())
1374 if (
MI.getDebugExpression()->getNumElements() == 0 && TransferInst) {
1381 auto DestSrc =
TII->isCopyLikeInstr(*TransferInst);
1384 SrcRegOp = DestSrc->Source;
1385 DestRegOp = DestSrc->Destination;
1386 if (Reg == DestRegOp->
getReg()) {
1387 for (
uint64_t ID : OpenRanges.getEntryValueBackupVarLocs()) {
1388 const VarLoc &VL = VarLocIDs[LocIndex::fromRawInteger(
ID)];
1389 if (VL.isEntryValueCopyBackupReg(Reg) &&
1391 VL.MI.getDebugOperand(0).getReg() == SrcRegOp->
getReg())
1402 cleanupEntryValueTransfers(TransferInst, OpenRanges, VarLocIDs, EntryVL,
1404 OpenRanges.erase(EntryVL);
1410 OpenRangesSet &OpenRanges,
1411 VarLocMap &VarLocIDs,
1412 InstToEntryLocMap &EntryValTransfers,
1413 RegDefToInstMap &RegSetInstrs) {
1414 if (!
MI.isDebugValue())
1421 "Expected inlined-at fields to agree");
1427 auto EntryValBackupID = OpenRanges.getEntryValueBackup(V);
1429 const VarLoc &EntryVL = VarLocIDs[EntryValBackupID->back()];
1430 removeEntryValue(
MI, OpenRanges, VarLocIDs, EntryVL, EntryValTransfers,
1435 return (MO.isReg() && MO.getReg()) || MO.isImm() || MO.isFPImm() ||
1436 MO.isCImm() || MO.isTargetIndex();
1441 OpenRanges.erase(VL);
1443 LocIndices IDs = VarLocIDs.insert(VL);
1445 OpenRanges.insert(IDs, VL);
1446 }
else if (
MI.memoperands().size() > 0) {
1447 llvm_unreachable(
"DBG_VALUE with mem operand encountered after regalloc?");
1451 "Unexpected non-undef DBG_VALUE encountered");
1453 OpenRanges.erase(VL);
1459 const VarLocSet &CollectFrom,
1460 const VarLocMap &VarLocIDs) {
1464 uint64_t FirstIndex = LocIndex::rawIndexForReg(LocIndex::kUniversalLocation);
1466 LocIndex::rawIndexForReg(LocIndex::kUniversalLocation + 1);
1468 for (
auto It = CollectFrom.find(FirstIndex),
End = CollectFrom.end();
1469 It !=
End && *It < FirstInvalidIndex; ++It) {
1470 LocIndex RegIdx = LocIndex::fromRawInteger(*It);
1477 OpenRangesSet &OpenRanges,
1478 VarLocMap &VarLocIDs,
1479 InstToEntryLocMap &EntryValTransfers,
1480 VarLocsInRange &KillSet) {
1482 if (
MI.isTerminator())
1487 LocIndex
Idx = LocIndex(LocIndex::kUniversalLocation,
ID);
1488 const VarLoc &VL = VarLocIDs[
Idx];
1489 if (!VL.Var.getVariable()->isParameter())
1492 auto DebugVar = VL.Var;
1493 std::optional<LocIndices> EntryValBackupIDs =
1494 OpenRanges.getEntryValueBackup(DebugVar);
1498 if (!EntryValBackupIDs)
1501 const VarLoc &EntryVL = VarLocIDs[EntryValBackupIDs->back()];
1502 VarLoc EntryLoc = VarLoc::CreateEntryLoc(EntryVL.MI, EntryVL.Expr,
1503 EntryVL.Locs[0].Value.RegNo);
1504 LocIndices EntryValueIDs = VarLocIDs.insert(EntryLoc);
1505 assert(EntryValueIDs.size() == 1 &&
1506 "EntryValue loc should not be variadic");
1507 EntryValTransfers.insert({&
MI, EntryValueIDs.back()});
1508 OpenRanges.insert(EntryValueIDs, EntryLoc);
1517void VarLocBasedLDV::insertTransferDebugPair(
1518 MachineInstr &
MI, OpenRangesSet &OpenRanges, TransferMap &Transfers,
1519 VarLocMap &VarLocIDs, LocIndex OldVarID, TransferKind Kind,
1520 const VarLoc::MachineLoc &OldLoc,
Register NewReg) {
1521 const VarLoc &OldVarLoc = VarLocIDs[OldVarID];
1523 auto ProcessVarLoc = [&
MI, &OpenRanges, &Transfers, &VarLocIDs](VarLoc &VL) {
1524 LocIndices LocIds = VarLocIDs.insert(VL);
1527 OpenRanges.erase(VL);
1531 OpenRanges.insert(LocIds, VL);
1532 assert(!
MI.isTerminator() &&
"Cannot insert DBG_VALUE after terminator");
1533 TransferDebugPair MIP = {&
MI, LocIds.back()};
1534 Transfers.push_back(MIP);
1538 OpenRanges.erase(VarLocIDs[OldVarID]);
1540 case TransferKind::TransferCopy: {
1542 "No register supplied when handling a copy of a debug value");
1545 VarLoc VL = VarLoc::CreateCopyLoc(OldVarLoc, OldLoc, NewReg);
1548 dbgs() <<
"Creating VarLoc for register copy:";
1553 case TransferKind::TransferSpill: {
1556 VarLoc::SpillLoc SpillLocation = extractSpillBaseRegAndOffset(
MI);
1557 VarLoc VL = VarLoc::CreateSpillLoc(
1558 OldVarLoc, OldLoc, SpillLocation.SpillBase, SpillLocation.SpillOffset);
1561 dbgs() <<
"Creating VarLoc for spill:";
1566 case TransferKind::TransferRestore: {
1568 "No register supplied when handling a restore of a debug value");
1571 VarLoc VL = VarLoc::CreateCopyLoc(OldVarLoc, OldLoc, NewReg);
1574 dbgs() <<
"Creating VarLoc for restore:";
1585 OpenRangesSet &OpenRanges,
1586 VarLocMap &VarLocIDs,
1587 InstToEntryLocMap &EntryValTransfers,
1588 RegDefToInstMap &RegSetInstrs) {
1592 if (
MI.isMetaInstruction())
1600 DefinedRegsSet DeadRegs;
1605 !(
MI.isCall() && MO.
getReg() == SP)) {
1610 RegSetInstrs.erase(MO.
getReg());
1611 RegSetInstrs.insert({MO.
getReg(), &
MI});
1620 if (!RegMasks.
empty()) {
1622 getUsedRegs(OpenRanges.getVarLocs(), UsedRegs);
1632 bool AnyRegMaskKillsReg =
1636 if (AnyRegMaskKillsReg)
1637 DeadRegs.insert(Reg);
1638 if (AnyRegMaskKillsReg) {
1639 RegSetInstrs.erase(Reg);
1640 RegSetInstrs.insert({
Reg, &
MI});
1645 if (DeadRegs.empty())
1648 VarLocsInRange KillSet;
1649 collectIDsForRegs(KillSet, DeadRegs, OpenRanges.getVarLocs(), VarLocIDs);
1650 OpenRanges.erase(KillSet, VarLocIDs, LocIndex::kUniversalLocation);
1654 if (
TM.Options.ShouldEmitDebugEntryValues())
1655 emitEntryValues(
MI, OpenRanges, VarLocIDs, EntryValTransfers, KillSet);
1660 OpenRangesSet &OpenRanges,
1661 VarLocMap &VarLocIDs) {
1666 if (!
TII->isExplicitTargetIndexDef(
MI, Index,
Offset))
1671 VarLocsInRange KillSet;
1673 for (
uint64_t ID : OpenRanges.getWasmVarLocs()) {
1674 LocIndex
Idx = LocIndex::fromRawInteger(
ID);
1675 const VarLoc &VL = VarLocIDs[
Idx];
1676 assert(VL.containsWasmLocs() &&
"Broken VarLocSet?");
1677 if (VL.usesWasmLoc(Loc))
1680 OpenRanges.erase(KillSet, VarLocIDs, LocIndex::kWasmLocation);
1686 if (!
MI.hasOneMemOperand())
1689 if (!
MI.getSpillSize(
TII) && !
MI.getFoldedSpillSize(
TII))
1698 if (!isSpillInstruction(
MI, MF))
1713 if (isKilledReg(MO, Reg))
1719 auto NextI = std::next(
MI.getIterator());
1721 if (
MI.getParent()->end() == NextI)
1727 if (isKilledReg(MONext, RegNext) && RegNext == Reg)
1736std::optional<VarLocBasedLDV::VarLoc::SpillLoc>
1739 if (!
MI.hasOneMemOperand())
1740 return std::nullopt;
1744 if (
MI.getRestoreSize(
TII)) {
1745 Reg =
MI.getOperand(0).getReg();
1746 return extractSpillBaseRegAndOffset(
MI);
1748 return std::nullopt;
1759 OpenRangesSet &OpenRanges,
1760 VarLocMap &VarLocIDs,
1761 TransferMap &Transfers) {
1765 std::optional<VarLoc::SpillLoc> Loc;
1772 VarLocsInRange KillSet;
1773 if (isSpillInstruction(
MI, MF)) {
1774 Loc = extractSpillBaseRegAndOffset(
MI);
1775 for (
uint64_t ID : OpenRanges.getSpillVarLocs()) {
1776 LocIndex
Idx = LocIndex::fromRawInteger(
ID);
1777 const VarLoc &VL = VarLocIDs[
Idx];
1778 assert(VL.containsSpillLocs() &&
"Broken VarLocSet?");
1779 if (VL.usesSpillLoc(*Loc)) {
1791 unsigned SpillLocIdx = VL.getSpillLocIdx(*Loc);
1792 VarLoc::MachineLoc OldLoc = VL.Locs[SpillLocIdx];
1793 VarLoc UndefVL = VarLoc::CreateCopyLoc(VL, OldLoc, 0);
1794 LocIndices UndefLocIDs = VarLocIDs.insert(UndefVL);
1795 Transfers.push_back({&
MI, UndefLocIDs.back()});
1798 OpenRanges.erase(KillSet, VarLocIDs, LocIndex::kSpillLocation);
1803 if (isLocationSpill(
MI, MF, Reg)) {
1804 TKind = TransferKind::TransferSpill;
1809 if (!(Loc = isRestoreInstruction(
MI, MF, Reg)))
1811 TKind = TransferKind::TransferRestore;
1817 auto TransferCandidates = OpenRanges.getEmptyVarLocRange();
1818 if (TKind == TransferKind::TransferSpill)
1819 TransferCandidates = OpenRanges.getRegisterVarLocs(Reg);
1820 else if (TKind == TransferKind::TransferRestore)
1821 TransferCandidates = OpenRanges.getSpillVarLocs();
1823 LocIndex
Idx = LocIndex::fromRawInteger(
ID);
1824 const VarLoc &VL = VarLocIDs[
Idx];
1826 if (TKind == TransferKind::TransferSpill) {
1827 assert(VL.usesReg(Reg) &&
"Broken VarLocSet?");
1829 << VL.Var.getVariable()->getName() <<
")\n");
1830 LocIdx = VL.getRegIdx(Reg);
1832 assert(TKind == TransferKind::TransferRestore && VL.containsSpillLocs() &&
1833 "Broken VarLocSet?");
1834 if (!VL.usesSpillLoc(*Loc))
1838 << VL.Var.getVariable()->getName() <<
")\n");
1839 LocIdx = VL.getSpillLocIdx(*Loc);
1841 VarLoc::MachineLoc MLoc = VL.Locs[
LocIdx];
1842 insertTransferDebugPair(
MI, OpenRanges, Transfers, VarLocIDs,
Idx, TKind,
1854 OpenRangesSet &OpenRanges,
1855 VarLocMap &VarLocIDs,
1856 TransferMap &Transfers) {
1857 auto DestSrc =
TII->isCopyLikeInstr(
MI);
1864 if (!DestRegOp->
isDef())
1869 if (CalleeSavedRegs.
test(*RAI))
1882 if (!isCalleeSavedReg(DestReg))
1889 for (
uint64_t ID : OpenRanges.getEntryValueBackupVarLocs()) {
1890 LocIndex
Idx = LocIndex::fromRawInteger(
ID);
1891 const VarLoc &VL = VarLocIDs[
Idx];
1892 if (VL.isEntryValueBackupReg(SrcReg)) {
1894 VarLoc EntryValLocCopyBackup =
1895 VarLoc::CreateEntryCopyBackupLoc(VL.MI, VL.Expr, DestReg);
1897 OpenRanges.erase(VL);
1900 LocIndices EntryValCopyLocIDs = VarLocIDs.insert(EntryValLocCopyBackup);
1901 OpenRanges.insert(EntryValCopyLocIDs, EntryValLocCopyBackup);
1910 for (
uint64_t ID : OpenRanges.getRegisterVarLocs(SrcReg)) {
1911 LocIndex
Idx = LocIndex::fromRawInteger(
ID);
1912 assert(VarLocIDs[
Idx].usesReg(SrcReg) &&
"Broken VarLocSet?");
1913 VarLoc::MachineLocValue Loc;
1915 VarLoc::MachineLoc MLoc{VarLoc::MachineLocKind::RegisterKind, Loc};
1916 insertTransferDebugPair(
MI, OpenRanges, Transfers, VarLocIDs,
Idx,
1917 TransferKind::TransferCopy, MLoc, DestReg);
1926 OpenRangesSet &OpenRanges,
1927 VarLocInMBB &OutLocs,
1928 const VarLocMap &VarLocIDs) {
1929 bool Changed =
false;
1932 OpenRanges.getUniqueVarLocs(VarLocs, VarLocIDs);
1933 for (VarLoc &VL : VarLocs) {
1935 dbgs() <<
"Add to OutLocs in MBB #" << CurMBB->
getNumber() <<
": ";
1939 VarLocSet &VLS = getVarLocsInMBB(CurMBB, OutLocs);
1940 Changed = VLS != OpenRanges.getVarLocs();
1944 VLS = OpenRanges.getVarLocs();
1960 VarToFragments &SeenFragments,
1963 MI.getDebugLoc()->getInlinedAt());
1964 FragmentInfo ThisFragment = MIVar.getFragmentOrDefault();
1969 auto [SeenIt,
Inserted] = SeenFragments.try_emplace(MIVar.getVariable());
1971 SeenIt->second.insert(ThisFragment);
1973 OverlappingFragments.
insert({{MIVar.getVariable(), ThisFragment}, {}});
1980 OverlappingFragments.
insert({{MIVar.getVariable(), ThisFragment}, {}});
1981 if (!IsInOLapMap.second)
1984 auto &ThisFragmentsOverlaps = IsInOLapMap.first->second;
1985 auto &AllSeenFragments = SeenIt->second;
1990 for (
const auto &ASeenFragment : AllSeenFragments) {
1994 ThisFragmentsOverlaps.push_back(ASeenFragment);
1997 auto ASeenFragmentsOverlaps =
1998 OverlappingFragments.
find({MIVar.getVariable(), ASeenFragment});
1999 assert(ASeenFragmentsOverlaps != OverlappingFragments.
end() &&
2000 "Previously seen var fragment has no vector of overlaps");
2001 ASeenFragmentsOverlaps->second.push_back(ThisFragment);
2005 AllSeenFragments.insert(ThisFragment);
2009void VarLocBasedLDV::process(
MachineInstr &
MI, OpenRangesSet &OpenRanges,
2010 VarLocMap &VarLocIDs, TransferMap &Transfers,
2011 InstToEntryLocMap &EntryValTransfers,
2012 RegDefToInstMap &RegSetInstrs) {
2013 if (!
MI.isDebugInstr())
2015 transferDebugValue(
MI, OpenRanges, VarLocIDs, EntryValTransfers,
2017 transferRegisterDef(
MI, OpenRanges, VarLocIDs, EntryValTransfers,
2019 transferWasmDef(
MI, OpenRanges, VarLocIDs);
2020 transferRegisterCopy(
MI, OpenRanges, VarLocIDs, Transfers);
2021 transferSpillOrRestoreInst(
MI, OpenRanges, VarLocIDs, Transfers);
2027bool VarLocBasedLDV::join(
2029 const VarLocMap &VarLocIDs,
2034 VarLocSet InLocsT(Alloc);
2045 if (!Visited.
count(p)) {
2046 LLVM_DEBUG(
dbgs() <<
" ignoring unvisited pred MBB: " <<
p->getNumber()
2050 auto OL = OutLocs.find(p);
2052 if (OL == OutLocs.end())
2057 VarLocSet &OutLocVLS = *OL->second;
2059 InLocsT = OutLocVLS;
2061 InLocsT &= OutLocVLS;
2064 if (!InLocsT.empty()) {
2066 collectAllVarLocs(VarLocs, InLocsT, VarLocIDs);
2067 for (const VarLoc &VL : VarLocs)
2068 dbgs() <<
" gathered candidate incoming var: "
2069 << VL.Var.getVariable()->getName() <<
"\n";
2077 VarLocSet KillSet(Alloc);
2078 bool IsArtificial = ArtificialBlocks.
count(&
MBB);
2079 if (!IsArtificial) {
2081 LocIndex
Idx = LocIndex::fromRawInteger(
ID);
2086 dbgs() <<
" killing " <<
Name <<
", it doesn't dominate MBB\n";
2091 InLocsT.intersectWithComplement(KillSet);
2097 "Should have processed at least one predecessor");
2099 VarLocSet &ILS = getVarLocsInMBB(&
MBB, InLocs);
2100 bool Changed =
false;
2101 if (ILS != InLocsT) {
2109void VarLocBasedLDV::flushPendingLocs(VarLocInMBB &PendingInLocs,
2110 VarLocMap &VarLocIDs) {
2113 for (
auto &Iter : PendingInLocs) {
2116 VarLocSet &Pending = *Iter.second;
2119 collectAllVarLocs(VarLocs, Pending, VarLocIDs);
2121 for (VarLoc DiffIt : VarLocs) {
2124 if (DiffIt.isEntryBackupLoc())
2135bool VarLocBasedLDV::isEntryValueCandidate(
2136 const MachineInstr &
MI,
const DefinedRegsSet &DefinedRegs)
const {
2137 assert(
MI.isDebugValue() &&
"This must be DBG_VALUE.");
2143 auto *DIVar =
MI.getDebugVariable();
2144 if (!DIVar->isParameter())
2148 if (
MI.getDebugLoc()->getInlinedAt())
2161 if (DefinedRegs.count(
MI.getDebugOperand(0).getReg()))
2179 Regs.insert(MO.
getReg());
2190 const DefinedRegsSet &DefinedRegs,
2191 OpenRangesSet &OpenRanges,
2192 VarLocMap &VarLocIDs) {
2195 if (!
TM.Options.ShouldEmitDebugEntryValues())
2200 MI.getDebugLoc()->getInlinedAt());
2202 if (!isEntryValueCandidate(
MI, DefinedRegs) ||
2203 OpenRanges.getEntryValueBackup(V))
2212 VarLoc EntryValLocAsBackup = VarLoc::CreateEntryBackupLoc(
MI,
NewExpr);
2213 LocIndices EntryValLocIDs = VarLocIDs.insert(EntryValLocAsBackup);
2214 OpenRanges.insert(EntryValLocIDs, EntryValLocAsBackup);
2222 unsigned InputDbgValLimit) {
2242 bool Changed =
false;
2243 bool OLChanged =
false;
2244 bool MBBJoined =
false;
2246 VarLocMap VarLocIDs;
2248 OpenRangesSet OpenRanges(Alloc, OverlapFragments);
2250 VarLocInMBB OutLocs;
2252 TransferMap Transfers;
2255 InstToEntryLocMap EntryValTransfers;
2257 RegDefToInstMap RegSetInstrs;
2259 VarToFragments SeenFragments;
2267 std::priority_queue<unsigned int, std::vector<unsigned int>,
2268 std::greater<unsigned int>>
2270 std::priority_queue<unsigned int, std::vector<unsigned int>,
2271 std::greater<unsigned int>>
2276 DefinedRegsSet DefinedRegs;
2281 for (
auto &
MI : First_MBB) {
2283 if (
MI.isDebugValue())
2284 recordEntryValue(
MI, DefinedRegs, OpenRanges, VarLocIDs);
2288 for (
auto &
MBB : MF)
2289 for (
auto &
MI :
MBB)
2290 if (
MI.isDebugValue())
2291 accumulateFragmentMap(
MI, SeenFragments, OverlapFragments);
2293 auto hasNonArtificialLocation = [](
const MachineInstr &
MI) ->
bool {
2295 return DL.getLine() != 0;
2298 for (
auto &
MBB : MF)
2302 LLVM_DEBUG(printVarLocInMBB(MF, OutLocs, VarLocIDs,
2303 "OutLocs after initialization",
dbgs()));
2306 unsigned int RPONumber = 0;
2308 OrderToBB[RPONumber] =
MBB;
2309 BBToOrder[
MBB] = RPONumber;
2310 Worklist.push(RPONumber);
2315 unsigned NumInputDbgValues = 0;
2316 for (
auto &
MBB : MF)
2317 for (
auto &
MI :
MBB)
2318 if (
MI.isDebugValue())
2319 ++NumInputDbgValues;
2320 if (NumInputDbgValues > InputDbgValLimit) {
2321 LLVM_DEBUG(
dbgs() <<
"Disabling VarLocBasedLDV: " << MF.getName()
2322 <<
" has " << RPONumber <<
" basic blocks and "
2323 << NumInputDbgValues
2324 <<
" input DBG_VALUEs, exceeding limits.\n");
2334 while (!Worklist.empty() || !Pending.empty()) {
2340 while (!Worklist.empty()) {
2343 MBBJoined = join(*
MBB, OutLocs, InLocs, VarLocIDs, Visited,
2345 MBBJoined |= Visited.
insert(
MBB).second;
2353 OpenRanges.insertFromLocSet(getVarLocsInMBB(
MBB, InLocs), VarLocIDs);
2354 LastNonDbgMI =
nullptr;
2355 RegSetInstrs.clear();
2356 for (
auto &
MI : *
MBB)
2357 process(
MI, OpenRanges, VarLocIDs, Transfers, EntryValTransfers,
2359 OLChanged |= transferTerminator(
MBB, OpenRanges, OutLocs, VarLocIDs);
2361 LLVM_DEBUG(printVarLocInMBB(MF, OutLocs, VarLocIDs,
2362 "OutLocs after propagating",
dbgs()));
2363 LLVM_DEBUG(printVarLocInMBB(MF, InLocs, VarLocIDs,
2364 "InLocs after propagating",
dbgs()));
2369 if (OnPending.
insert(s).second) {
2370 Pending.push(BBToOrder[s]);
2375 Worklist.swap(Pending);
2378 assert(Pending.empty() &&
"Pending should be empty");
2382 for (
auto &TR : Transfers) {
2383 assert(!TR.TransferInst->isTerminator() &&
2384 "Cannot insert DBG_VALUE after terminator");
2386 const VarLoc &VL = VarLocIDs[TR.LocationID];
2393 for (
auto &TR : EntryValTransfers) {
2396 "Cannot insert DBG_VALUE after terminator");
2398 const VarLoc &VL = VarLocIDs[TR.second];
2402 EntryValTransfers.clear();
2406 flushPendingLocs(InLocs, VarLocIDs);
2408 LLVM_DEBUG(printVarLocInMBB(MF, OutLocs, VarLocIDs,
"Final OutLocs",
dbgs()));
2409 LLVM_DEBUG(printVarLocInMBB(MF, InLocs, VarLocIDs,
"Final InLocs",
dbgs()));
2416 return new VarLocBasedLDV();
static bool isConstant(const MachineInstr &MI)
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
A bitvector that uses an IntervalMap to coalesce adjacent elements into intervals.
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.
std::optional< std::vector< StOtherPiece > > Other
const HexagonInstrInfo * TII
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)
static DebugLoc getDebugLoc(MachineBasicBlock::instr_iterator FirstMI, MachineBasicBlock::instr_iterator LastMI)
Return the first found DebugLoc that has a DILocation, given a range of instructions.
unsigned const TargetRegisterInfo * TRI
This file builds on the ADT/GraphTraits.h file to build a generic graph post order iterator.
static StringRef getName(Value *V)
static bool dominates(InstrPosIndexes &PosIndexes, const MachineInstr &A, const MachineInstr &B)
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 defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
This file describes how to lower LLVM code to machine code.
Target-Independent Code Generator Pass Configuration Options pass.
static bool isRegOtherThanSPAndFP(const MachineOperand &Op, const MachineInstr &MI, const TargetRegisterInfo *TRI)
If Op is a stack or frame register return true, otherwise return false.
static void collectRegDefs(const MachineInstr &MI, DefinedRegsSet &Regs, const TargetRegisterInfo *TRI)
Collect all register defines (including aliases) for the given instruction.
Handle-class for a particular "location".
bool test(unsigned Idx) const
A bitvector that, under the hood, relies on an IntervalMap to coalesce elements into intervals.
ConstantFP - Floating Point Values [float, double].
This is the shared class of boolean and integer constants.
unsigned getNumElements() const
DbgVariableFragmentInfo FragmentInfo
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 isDeref() const
Return whether there is exactly one operator and it is a DW_OP_deref;.
static DIExpression * replaceArg(const DIExpression *Expr, uint64_t OldArg, uint64_t NewArg)
Create a copy of Expr with each instance of DW_OP_LLVM_arg, \p OldArg replaced with DW_OP_LLVM_arg,...
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 isValidLocationForIntrinsic(const DILocation *DL) const
Check that a location is valid for this variable.
StringRef getName() const
This class represents an Operation in the Expression.
Identifies a unique instance of a variable.
static bool isDefaultFragment(const FragmentInfo F)
const DILocation * getInlinedAt() const
FragmentInfo getFragmentOrDefault() 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)
DISubprogram * getSubprogram() const
Get the attached subprogram.
LexicalScopes - This class provides interface to collect and use lexical scoping information from mac...
MCRegAliasIterator enumerates all registers aliasing Reg.
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...
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,...
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
Function & getFunction()
Return the LLVM function that this machine code represents.
Representation of each machine instruction.
bool isTerminator(QueryType Type=AnyInBundle) const
Returns true if this instruction part of the terminator for a basic block.
const MachineBasicBlock * getParent() const
MachineOperand class - Representation of each machine instruction operand.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
bool isRegMask() const
isRegMask - Tests if this is a MO_RegisterMask operand.
Register getReg() const
getReg - Returns the register number.
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)
virtual void print(raw_ostream &OS, const Module *M) const
print - Print out the internal state of the pass.
Special value supplied for machine level alias analysis.
Wrapper class representing virtual and physical registers.
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
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...
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
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.
Information about stack frame layout on the target.
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.
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.
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...
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
LLVM Value Representation.
self_iterator getIterator()
A range adaptor for a pair of iterators.
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.
std::pair< const DILocalVariable *, DIExpression::FragmentInfo > FragmentOfVar
Types for recording sets of variable fragments that overlap.
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.
const_iterator end(StringRef path)
Get end iterator over path.
This is an optimization pass for GlobalISel generic memory operations.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
bool operator<(int64_t V1, const APSInt &V2)
auto find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
bool operator!=(uint64_t V1, const APInt &V2)
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)
void erase(Container &C, ValueType V)
Wrapper function to remove a value from a container:
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool none_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly.
LDVImpl * makeVarLocBasedLiveDebugValues()
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
void array_pod_sort(IteratorTy Start, IteratorTy End)
array_pod_sort - This sorts an array with the specified start and end extent.
Printable printReg(Register Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)
Prints virtual and physical registers with or without a TRI instance.