137#include "llvm/Config/llvm-config.h"
160#define DEBUG_TYPE "livedebugvalues"
162STATISTIC(NumInserted,
"Number of DBG_VALUE instructions inserted");
179 return Reg && Reg != SP && Reg !=
FP;
215 static constexpr u32_location_t kUniversalLocation = 0;
219 static constexpr u32_location_t kFirstRegLocation = 1;
223 static constexpr u32_location_t kFirstInvalidRegLocation = 1 << 30;
227 static constexpr u32_location_t kSpillLocation = kFirstInvalidRegLocation;
231 static constexpr u32_location_t kEntryValueBackupLocation =
232 kFirstInvalidRegLocation + 1;
240 static constexpr u32_location_t kWasmLocation = kFirstInvalidRegLocation + 2;
242 LocIndex(u32_location_t Location, u32_index_t
Index)
249 template<
typename IntT>
static LocIndex fromRawInteger(IntT
ID) {
250 static_assert(std::is_unsigned_v<IntT> &&
sizeof(
ID) ==
sizeof(
uint64_t),
251 "Cannot convert raw integer to LocIndex");
252 return {
static_cast<u32_location_t
>(
ID >> 32),
253 static_cast<u32_index_t
>(
ID)};
259 return LocIndex(Reg, 0).getAsRawInteger();
264 static auto indexRangeForLocation(
const VarLocSet &Set,
265 u32_location_t Location) {
266 uint64_t Start = LocIndex(Location, 0).getAsRawInteger();
267 uint64_t End = LocIndex(Location + 1, 0).getAsRawInteger();
268 return Set.half_open_range(Start,
End);
279class VarLocBasedLDV :
public LDVImpl {
287 VarLocSet::Allocator Alloc;
291 enum struct TransferKind { TransferCopy, TransferSpill, TransferRestore };
294 using OptFragmentInfo = std::optional<DIExpression::FragmentInfo>;
304 return SpillBase ==
Other.SpillBase && SpillOffset ==
Other.SpillOffset;
307 return !(*
this ==
Other);
336 enum class MachineLocKind {
344 enum class EntryValueLocKind {
345 NonEntryValueKind = 0,
347 EntryValueBackupKind,
348 EntryValueCopyBackupKind
349 } EVKind = EntryValueLocKind::NonEntryValueKind;
353 union MachineLocValue {
360 WasmLoc WasmLocation;
361 MachineLocValue() : Hash(0) {}
370 MachineLocValue
Value;
372 if (Kind !=
Other.Kind)
375 case MachineLocKind::SpillLocKind:
376 return Value.SpillLocation ==
Other.Value.SpillLocation;
377 case MachineLocKind::WasmLocKind:
378 return Value.WasmLocation ==
Other.Value.WasmLocation;
379 case MachineLocKind::RegisterKind:
380 case MachineLocKind::ImmediateKind:
388 case MachineLocKind::SpillLocKind:
389 return std::make_tuple(
390 Kind,
Value.SpillLocation.SpillBase,
391 Value.SpillLocation.SpillOffset.getFixed(),
392 Value.SpillLocation.SpillOffset.getScalable()) <
394 Other.Kind,
Other.Value.SpillLocation.SpillBase,
395 Other.Value.SpillLocation.SpillOffset.getFixed(),
396 Other.Value.SpillLocation.SpillOffset.getScalable());
397 case MachineLocKind::WasmLocKind:
398 return std::make_tuple(Kind,
Value.WasmLocation.Index,
399 Value.WasmLocation.Offset) <
400 std::make_tuple(
Other.Kind,
Other.Value.WasmLocation.Index,
401 Other.Value.WasmLocation.Offset);
402 case MachineLocKind::RegisterKind:
403 case MachineLocKind::ImmediateKind:
404 return std::tie(Kind,
Value.Hash) <
423 : Var(
MI.getDebugVariable(),
MI.getDebugExpression(),
425 Expr(
MI.getDebugExpression()),
MI(
MI) {
426 assert(
MI.isDebugValue() &&
"not a DBG_VALUE");
427 assert((
MI.isDebugValueList() ||
MI.getNumOperands() == 4) &&
428 "malformed DBG_VALUE");
430 MachineLoc
ML = GetLocForOp(
Op);
432 if (It == Locs.
end()) {
438 unsigned OpIdx = Locs.
size();
439 unsigned DuplicatingIdx = std::distance(Locs.
begin(), It);
446 assert(EVKind != EntryValueLocKind::EntryValueKind &&
447 !isEntryBackupLoc());
454 Kind = MachineLocKind::RegisterKind;
455 Loc.RegNo =
Op.getReg();
456 }
else if (
Op.isImm()) {
457 Kind = MachineLocKind::ImmediateKind;
458 Loc.Immediate =
Op.getImm();
459 }
else if (
Op.isFPImm()) {
460 Kind = MachineLocKind::ImmediateKind;
461 Loc.FPImm =
Op.getFPImm();
462 }
else if (
Op.isCImm()) {
463 Kind = MachineLocKind::ImmediateKind;
464 Loc.CImm =
Op.getCImm();
465 }
else if (
Op.isTargetIndex()) {
466 Kind = MachineLocKind::WasmLocKind;
467 Loc.WasmLocation = {
Op.getIndex(),
Op.getOffset()};
478 assert(VL.Locs.size() == 1 &&
479 VL.Locs[0].Kind == MachineLocKind::RegisterKind);
480 VL.EVKind = EntryValueLocKind::EntryValueKind;
482 VL.Locs[0].Value.RegNo =
Reg;
490 static VarLoc CreateEntryBackupLoc(
const MachineInstr &MI,
493 assert(VL.Locs.size() == 1 &&
494 VL.Locs[0].Kind == MachineLocKind::RegisterKind);
495 VL.EVKind = EntryValueLocKind::EntryValueBackupKind;
503 static VarLoc CreateEntryCopyBackupLoc(
const MachineInstr &MI,
507 assert(VL.Locs.size() == 1 &&
508 VL.Locs[0].Kind == MachineLocKind::RegisterKind);
509 VL.EVKind = EntryValueLocKind::EntryValueCopyBackupKind;
511 VL.Locs[0].Value.RegNo = NewReg;
517 static VarLoc CreateCopyLoc(
const VarLoc &OldVL,
const MachineLoc &OldML,
520 for (MachineLoc &
ML : VL.Locs)
522 ML.Kind = MachineLocKind::RegisterKind;
523 ML.Value.RegNo = NewReg;
531 static VarLoc CreateSpillLoc(
const VarLoc &OldVL,
const MachineLoc &OldML,
534 for (MachineLoc &
ML : VL.Locs)
536 ML.Kind = MachineLocKind::SpillLocKind;
537 ML.Value.SpillLocation = {SpillBase, SpillOffset};
548 assert(!isEntryBackupLoc() &&
549 "Tried to produce DBG_VALUE for backup VarLoc");
552 const auto &IID =
MI.getDesc();
558 for (
unsigned I = 0, E = Locs.
size();
I < E; ++
I) {
559 MachineLocKind LocKind = Locs[
I].Kind;
560 MachineLocValue Loc = Locs[
I].Value;
563 case MachineLocKind::RegisterKind:
571 EVKind == EntryValueLocKind::EntryValueKind ? Orig.
getReg()
575 case MachineLocKind::SpillLocKind: {
580 unsigned Base = Loc.SpillLocation.SpillBase;
582 if (
MI.isNonListDebugValue()) {
584 DIExpr =
TRI->prependOffsetExpression(
586 Loc.SpillLocation.SpillOffset);
590 TRI->getOffsetOpcodes(Loc.SpillLocation.SpillOffset, Ops);
597 case MachineLocKind::ImmediateKind: {
601 case MachineLocKind::WasmLocKind: {
605 case MachineLocKind::InvalidKind:
609 return BuildMI(MF, DbgLoc, IID, Indirect, MOs, Var, DIExpr);
614 return Kind == MachineLocKind::ImmediateKind;
618 bool isEntryBackupLoc()
const {
619 return EVKind == EntryValueLocKind::EntryValueBackupKind ||
620 EVKind == EntryValueLocKind::EntryValueCopyBackupKind;
625 bool isEntryValueBackupReg(
Register Reg)
const {
626 return EVKind == EntryValueLocKind::EntryValueBackupKind && usesReg(Reg);
631 bool isEntryValueCopyBackupReg(
Register Reg)
const {
632 return EVKind == EntryValueLocKind::EntryValueCopyBackupKind &&
639 RegML.Kind = MachineLocKind::RegisterKind;
640 RegML.Value.RegNo =
Reg;
645 unsigned getRegIdx(
Register Reg)
const {
647 if (Locs[
Idx].Kind == MachineLocKind::RegisterKind &&
656 bool AnyRegs =
false;
657 for (
const auto &Loc : Locs)
658 if (Loc.Kind == MachineLocKind::RegisterKind) {
665 bool containsSpillLocs()
const {
666 return any_of(Locs, [](VarLoc::MachineLoc
ML) {
667 return ML.Kind == VarLoc::MachineLocKind::SpillLocKind;
673 bool usesSpillLoc(
SpillLoc SpillLocation)
const {
675 SpillML.Kind = MachineLocKind::SpillLocKind;
676 SpillML.Value.SpillLocation = SpillLocation;
682 unsigned getSpillLocIdx(
SpillLoc SpillLocation)
const {
683 for (
unsigned Idx = 0;
Idx < Locs.size(); ++
Idx)
684 if (Locs[
Idx].Kind == MachineLocKind::SpillLocKind &&
685 Locs[
Idx].
Value.SpillLocation == SpillLocation)
690 bool containsWasmLocs()
const {
691 return any_of(Locs, [](VarLoc::MachineLoc
ML) {
692 return ML.Kind == VarLoc::MachineLocKind::WasmLocKind;
698 bool usesWasmLoc(WasmLoc WasmLocation)
const {
700 WasmML.Kind = MachineLocKind::WasmLocKind;
701 WasmML.Value.WasmLocation = WasmLocation;
708 return LS.dominates(
MI.getDebugLoc().get(), &
MBB);
711#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
716 for (
const MachineLoc &MLoc : Locs) {
717 if (Locs.begin() != &MLoc)
720 case MachineLocKind::RegisterKind:
721 Out <<
printReg(MLoc.Value.RegNo, TRI);
723 case MachineLocKind::SpillLocKind:
724 Out <<
printReg(MLoc.Value.SpillLocation.SpillBase, TRI);
725 Out <<
"[" << MLoc.Value.SpillLocation.SpillOffset.getFixed() <<
" + "
726 << MLoc.Value.SpillLocation.SpillOffset.getScalable()
730 case MachineLocKind::ImmediateKind:
731 Out << MLoc.Value.Immediate;
733 case MachineLocKind::WasmLocKind: {
735 auto Indices =
TII->getSerializableTargetIndices();
737 find_if(Indices, [&](
const std::pair<int, const char *> &
I) {
738 return I.first == MLoc.Value.WasmLocation.Index;
740 assert(Found != Indices.end());
741 Out << Found->second;
742 if (MLoc.Value.WasmLocation.Offset > 0)
743 Out <<
" + " << MLoc.Value.WasmLocation.Offset;
749 case MachineLocKind::InvalidKind:
754 Out <<
", \"" << Var.getVariable()->
getName() <<
"\", " << *Expr <<
", ";
755 if (Var.getInlinedAt())
760 if (isEntryBackupLoc())
761 Out <<
" (backup loc)\n";
768 return std::tie(EVKind, Var, Expr, Locs) ==
774 return std::tie(Var, EVKind, Locs, Expr) <
790 std::map<VarLoc, LocIndices> Var2Indices;
798 LocIndices insert(
const VarLoc &VL) {
799 LocIndices &Indices = Var2Indices[VL];
801 if (!Indices.empty())
809 if (VL.EVKind == VarLoc::EntryValueLocKind::NonEntryValueKind) {
810 VL.getDescribingRegs(Locations);
813 return RegNo < LocIndex::kFirstInvalidRegLocation;
815 "Physreg out of range?");
816 if (VL.containsSpillLocs())
817 Locations.push_back(LocIndex::kSpillLocation);
818 if (VL.containsWasmLocs())
819 Locations.push_back(LocIndex::kWasmLocation);
820 }
else if (VL.EVKind != VarLoc::EntryValueLocKind::EntryValueKind) {
824 Locations.push_back(LocIndex::kUniversalLocation);
834 LocIndices getAllIndices(
const VarLoc &VL)
const {
835 auto IndIt = Var2Indices.
find(VL);
836 assert(IndIt != Var2Indices.end() &&
"VarLoc not tracked");
837 return IndIt->second;
841 const VarLoc &operator[](LocIndex
ID)
const {
842 auto LocIt = Loc2Vars.
find(
ID.Location);
843 assert(LocIt != Loc2Vars.
end() &&
"Location not tracked");
844 return LocIt->second[
ID.Index];
850 struct TransferDebugPair {
857 using InstToEntryLocMap = std::multimap<const MachineInstr *, LocIndex>;
864 std::pair<const DILocalVariable *, DIExpression::FragmentInfo>;
870 using VarToFragments =
876 const VarLocSet &CollectFrom,
877 const VarLocMap &VarLocIDs);
881 void getUsedRegs(
const VarLocSet &CollectFrom,
893 class OpenRangesSet {
894 VarLocSet::Allocator &Alloc;
903 OpenRangesSet(VarLocSet::Allocator &Alloc,
OverlapMap &_OLapMap)
904 : Alloc(Alloc), VarLocs(Alloc), OverlappingFragments(_OLapMap) {}
906 const VarLocSet &getVarLocs()
const {
return VarLocs; }
914 const VarLocMap &VarLocIDs)
const {
915 collectAllVarLocs(Collected, VarLocs, VarLocIDs);
919 void erase(
const VarLoc &VL);
923 void erase(
const VarLocsInRange &KillSet,
const VarLocMap &VarLocIDs,
927 void insert(LocIndices VarLocIDs,
const VarLoc &VL);
930 void insertFromLocSet(
const VarLocSet &ToLoad,
const VarLocMap &Map);
932 std::optional<LocIndices> getEntryValueBackup(
DebugVariable Var);
938 EntryValuesBackupVars.
clear();
944 Vars.
empty() == VarLocs.empty() &&
945 "open ranges are inconsistent");
946 return VarLocs.empty();
950 auto getEmptyVarLocRange()
const {
956 auto getRegisterVarLocs(
Register Reg)
const {
957 return LocIndex::indexRangeForLocation(getVarLocs(), Reg);
961 auto getSpillVarLocs()
const {
962 return LocIndex::indexRangeForLocation(getVarLocs(),
963 LocIndex::kSpillLocation);
968 auto getEntryValueBackupVarLocs()
const {
969 return LocIndex::indexRangeForLocation(
970 getVarLocs(), LocIndex::kEntryValueBackupLocation);
974 auto getWasmVarLocs()
const {
975 return LocIndex::indexRangeForLocation(getVarLocs(),
976 LocIndex::kWasmLocation);
984 static void collectIDsForRegs(VarLocsInRange &Collected,
985 const DefinedRegsSet &Regs,
986 const VarLocSet &CollectFrom,
987 const VarLocMap &VarLocIDs);
990 std::unique_ptr<VarLocSet> &VLS = Locs[
MBB];
992 VLS = std::make_unique<VarLocSet>(Alloc);
997 const VarLocInMBB &Locs)
const {
998 auto It = Locs.find(
MBB);
999 assert(It != Locs.end() &&
"MBB not in map");
1021 const DefinedRegsSet &Regs)
const;
1025 std::optional<VarLoc::SpillLoc> isRestoreInstruction(
const MachineInstr &
MI,
1030 VarLoc::SpillLoc extractSpillBaseRegAndOffset(
const MachineInstr &
MI);
1031 void insertTransferDebugPair(
MachineInstr &
MI, OpenRangesSet &OpenRanges,
1032 TransferMap &Transfers, VarLocMap &VarLocIDs,
1033 LocIndex OldVarID, TransferKind Kind,
1034 const VarLoc::MachineLoc &OldLoc,
1037 void transferDebugValue(
const MachineInstr &
MI, OpenRangesSet &OpenRanges,
1038 VarLocMap &VarLocIDs,
1039 InstToEntryLocMap &EntryValTransfers,
1040 RegDefToInstMap &RegSetInstrs);
1041 void transferSpillOrRestoreInst(
MachineInstr &
MI, OpenRangesSet &OpenRanges,
1042 VarLocMap &VarLocIDs, TransferMap &Transfers);
1044 OpenRangesSet &OpenRanges,
1045 VarLocMap &VarLocIDs,
const VarLoc &EntryVL,
1046 InstToEntryLocMap &EntryValTransfers);
1047 void removeEntryValue(
const MachineInstr &
MI, OpenRangesSet &OpenRanges,
1048 VarLocMap &VarLocIDs,
const VarLoc &EntryVL,
1049 InstToEntryLocMap &EntryValTransfers,
1050 RegDefToInstMap &RegSetInstrs);
1051 void emitEntryValues(
MachineInstr &
MI, OpenRangesSet &OpenRanges,
1052 VarLocMap &VarLocIDs,
1053 InstToEntryLocMap &EntryValTransfers,
1054 VarLocsInRange &KillSet);
1056 const DefinedRegsSet &DefinedRegs,
1057 OpenRangesSet &OpenRanges, VarLocMap &VarLocIDs);
1058 void transferRegisterCopy(
MachineInstr &
MI, OpenRangesSet &OpenRanges,
1059 VarLocMap &VarLocIDs, TransferMap &Transfers);
1060 void transferRegisterDef(
MachineInstr &
MI, OpenRangesSet &OpenRanges,
1061 VarLocMap &VarLocIDs,
1062 InstToEntryLocMap &EntryValTransfers,
1063 RegDefToInstMap &RegSetInstrs);
1064 void transferWasmDef(
MachineInstr &
MI, OpenRangesSet &OpenRanges,
1065 VarLocMap &VarLocIDs);
1067 VarLocInMBB &OutLocs,
const VarLocMap &VarLocIDs);
1070 VarLocMap &VarLocIDs, TransferMap &Transfers,
1071 InstToEntryLocMap &EntryValTransfers,
1072 RegDefToInstMap &RegSetInstrs);
1074 void accumulateFragmentMap(
MachineInstr &
MI, VarToFragments &SeenFragments,
1078 const VarLocMap &VarLocIDs,
1084 void flushPendingLocs(VarLocInMBB &PendingInLocs, VarLocMap &VarLocIDs);
1088 unsigned InputDbgValLimit)
override;
1097 void printVarLocInMBB(
const MachineFunction &MF,
const VarLocInMBB &V,
1098 const VarLocMap &VarLocIDs,
const char *msg,
1108VarLocBasedLDV::VarLocBasedLDV() =
default;
1110VarLocBasedLDV::~VarLocBasedLDV() =
default;
1117void VarLocBasedLDV::OpenRangesSet::erase(
const VarLoc &VL) {
1120 auto *EraseFrom = VL.isEntryBackupLoc() ? &EntryValuesBackupVars : &Vars;
1121 auto It = EraseFrom->
find(VarToErase);
1122 if (It != EraseFrom->end()) {
1123 LocIndices IDs = It->second;
1124 for (LocIndex
ID : IDs)
1125 VarLocs.reset(
ID.getAsRawInteger());
1126 EraseFrom->erase(It);
1141 auto MapIt = OverlappingFragments.
find({Var.
getVariable(), ThisFragment});
1142 if (MapIt != OverlappingFragments.
end()) {
1143 for (
auto Fragment : MapIt->second) {
1144 VarLocBasedLDV::OptFragmentInfo FragmentHolder;
1146 FragmentHolder = VarLocBasedLDV::OptFragmentInfo(Fragment);
1152void VarLocBasedLDV::OpenRangesSet::erase(
const VarLocsInRange &KillSet,
1153 const VarLocMap &VarLocIDs,
1155 VarLocSet RemoveSet(Alloc);
1157 const VarLoc &VL = VarLocIDs[LocIndex(Location,
ID)];
1158 auto *EraseFrom = VL.isEntryBackupLoc() ? &EntryValuesBackupVars : &Vars;
1159 EraseFrom->
erase(VL.Var);
1160 LocIndices VLI = VarLocIDs.getAllIndices(VL);
1161 for (LocIndex
ID : VLI)
1162 RemoveSet.set(
ID.getAsRawInteger());
1164 VarLocs.intersectWithComplement(RemoveSet);
1167void VarLocBasedLDV::OpenRangesSet::insertFromLocSet(
const VarLocSet &ToLoad,
1168 const VarLocMap &Map) {
1169 VarLocsInRange UniqueVarLocIDs;
1170 DefinedRegsSet Regs;
1171 Regs.
insert(LocIndex::kUniversalLocation);
1172 collectIDsForRegs(UniqueVarLocIDs, Regs, ToLoad, Map);
1174 LocIndex
Idx = LocIndex::fromRawInteger(
ID);
1175 const VarLoc &VarL =
Map[
Idx];
1176 const LocIndices Indices =
Map.getAllIndices(VarL);
1177 insert(Indices, VarL);
1181void VarLocBasedLDV::OpenRangesSet::insert(LocIndices VarLocIDs,
1183 auto *InsertInto = VL.isEntryBackupLoc() ? &EntryValuesBackupVars : &Vars;
1184 for (LocIndex
ID : VarLocIDs)
1185 VarLocs.set(
ID.getAsRawInteger());
1186 InsertInto->
insert({VL.Var, VarLocIDs});
1191std::optional<LocIndices>
1192VarLocBasedLDV::OpenRangesSet::getEntryValueBackup(
DebugVariable Var) {
1193 auto It = EntryValuesBackupVars.
find(Var);
1194 if (It != EntryValuesBackupVars.
end())
1197 return std::nullopt;
1200void VarLocBasedLDV::collectIDsForRegs(VarLocsInRange &Collected,
1201 const DefinedRegsSet &Regs,
1202 const VarLocSet &CollectFrom,
1203 const VarLocMap &VarLocIDs) {
1204 assert(!Regs.empty() &&
"Nothing to collect");
1208 auto It = CollectFrom.find(LocIndex::rawIndexForReg(SortedRegs.
front()));
1209 auto End = CollectFrom.end();
1214 uint64_t FirstIndexForReg = LocIndex::rawIndexForReg(Reg);
1215 uint64_t FirstInvalidIndex = LocIndex::rawIndexForReg(Reg + 1);
1216 It.advanceToLowerBound(FirstIndexForReg);
1219 for (; It !=
End && *It < FirstInvalidIndex; ++It) {
1220 LocIndex ItIdx = LocIndex::fromRawInteger(*It);
1221 const VarLoc &VL = VarLocIDs[ItIdx];
1222 LocIndices LI = VarLocIDs.getAllIndices(VL);
1224 assert(LI.back().Location == LocIndex::kUniversalLocation &&
1225 "Unexpected order of LocIndices for VarLoc; was it inserted into "
1226 "the VarLocMap correctly?");
1227 Collected.insert(LI.back().Index);
1235void VarLocBasedLDV::getUsedRegs(
const VarLocSet &CollectFrom,
1240 LocIndex::rawIndexForReg(LocIndex::kFirstRegLocation);
1242 LocIndex::rawIndexForReg(LocIndex::kFirstInvalidRegLocation);
1243 for (
auto It = CollectFrom.find(FirstRegIndex),
1244 End = CollectFrom.find(FirstInvalidIndex);
1248 uint32_t FoundReg = LocIndex::fromRawInteger(*It).Location;
1250 "Duplicate used reg");
1256 uint64_t NextRegIndex = LocIndex::rawIndexForReg(FoundReg + 1);
1257 It.advanceToLowerBound(NextRegIndex);
1267 const VarLocInMBB &V,
1268 const VarLocMap &VarLocIDs,
1271 Out <<
'\n' << msg <<
'\n';
1275 const VarLocSet &
L = getVarLocsInMBB(&BB, V);
1279 collectAllVarLocs(VarLocs, L, VarLocIDs);
1280 Out <<
"MBB: " << BB.getNumber() <<
":\n";
1281 for (
const VarLoc &VL : VarLocs) {
1282 Out <<
" Var: " << VL.Var.getVariable()->getName();
1291VarLocBasedLDV::VarLoc::SpillLoc
1292VarLocBasedLDV::extractSpillBaseRegAndOffset(
const MachineInstr &
MI) {
1294 "Spill instruction does not have exactly one memory operand?");
1295 auto MMOI =
MI.memoperands_begin();
1298 "Inconsistent memory operand in spill instruction");
1299 int FI = cast<FixedStackPseudoSourceValue>(PVal)->getFrameIndex();
1308void VarLocBasedLDV::cleanupEntryValueTransfers(
1309 const MachineInstr *TRInst, OpenRangesSet &OpenRanges, VarLocMap &VarLocIDs,
1310 const VarLoc &EntryVL, InstToEntryLocMap &EntryValTransfers) {
1311 if (EntryValTransfers.empty() || TRInst ==
nullptr)
1314 auto TransRange = EntryValTransfers.equal_range(TRInst);
1315 for (
auto &TDPair :
llvm::make_range(TransRange.first, TransRange.second)) {
1316 const VarLoc &EmittedEV = VarLocIDs[TDPair.second];
1317 if (std::tie(EntryVL.Var, EntryVL.Locs[0].Value.RegNo, EntryVL.Expr) ==
1318 std::tie(EmittedEV.Var, EmittedEV.Locs[0].Value.RegNo,
1320 OpenRanges.erase(EmittedEV);
1321 EntryValTransfers.erase(TRInst);
1332 OpenRangesSet &OpenRanges,
1333 VarLocMap &VarLocIDs,
1334 const VarLoc &EntryVL,
1335 InstToEntryLocMap &EntryValTransfers,
1336 RegDefToInstMap &RegSetInstrs) {
1338 if (&
MI == &EntryVL.MI)
1344 if (!
MI.getDebugOperand(0).isReg())
1350 if (
Reg.isValid() && RegSetInstrs.contains(Reg))
1351 TransferInst = RegSetInstrs.find(Reg)->second;
1354 if (!TransferInst && !LastNonDbgMI &&
MI.getParent()->isEntryBlock())
1360 if (
MI.getDebugExpression()->getNumElements() == 0 && TransferInst) {
1367 auto DestSrc =
TII->isCopyLikeInstr(*TransferInst);
1370 SrcRegOp = DestSrc->Source;
1371 DestRegOp = DestSrc->Destination;
1372 if (Reg == DestRegOp->
getReg()) {
1373 for (
uint64_t ID : OpenRanges.getEntryValueBackupVarLocs()) {
1374 const VarLoc &VL = VarLocIDs[LocIndex::fromRawInteger(
ID)];
1375 if (VL.isEntryValueCopyBackupReg(Reg) &&
1377 VL.MI.getDebugOperand(0).getReg() == SrcRegOp->
getReg())
1388 cleanupEntryValueTransfers(TransferInst, OpenRanges, VarLocIDs, EntryVL,
1390 OpenRanges.erase(EntryVL);
1396 OpenRangesSet &OpenRanges,
1397 VarLocMap &VarLocIDs,
1398 InstToEntryLocMap &EntryValTransfers,
1399 RegDefToInstMap &RegSetInstrs) {
1400 if (!
MI.isDebugValue())
1407 "Expected inlined-at fields to agree");
1413 auto EntryValBackupID = OpenRanges.getEntryValueBackup(V);
1415 const VarLoc &EntryVL = VarLocIDs[EntryValBackupID->back()];
1416 removeEntryValue(
MI, OpenRanges, VarLocIDs, EntryVL, EntryValTransfers,
1421 return (MO.isReg() && MO.getReg()) || MO.isImm() || MO.isFPImm() ||
1422 MO.isCImm() || MO.isTargetIndex();
1427 OpenRanges.erase(VL);
1429 LocIndices IDs = VarLocIDs.insert(VL);
1431 OpenRanges.insert(IDs, VL);
1432 }
else if (
MI.memoperands().size() > 0) {
1433 llvm_unreachable(
"DBG_VALUE with mem operand encountered after regalloc?");
1437 "Unexpected non-undef DBG_VALUE encountered");
1439 OpenRanges.erase(VL);
1445 const VarLocSet &CollectFrom,
1446 const VarLocMap &VarLocIDs) {
1450 uint64_t FirstIndex = LocIndex::rawIndexForReg(LocIndex::kUniversalLocation);
1452 LocIndex::rawIndexForReg(LocIndex::kUniversalLocation + 1);
1454 for (
auto It = CollectFrom.find(FirstIndex),
End = CollectFrom.end();
1455 It !=
End && *It < FirstInvalidIndex; ++It) {
1456 LocIndex RegIdx = LocIndex::fromRawInteger(*It);
1463 OpenRangesSet &OpenRanges,
1464 VarLocMap &VarLocIDs,
1465 InstToEntryLocMap &EntryValTransfers,
1466 VarLocsInRange &KillSet) {
1468 if (
MI.isTerminator())
1473 LocIndex
Idx = LocIndex(LocIndex::kUniversalLocation,
ID);
1474 const VarLoc &VL = VarLocIDs[
Idx];
1475 if (!VL.Var.getVariable()->isParameter())
1478 auto DebugVar = VL.Var;
1479 std::optional<LocIndices> EntryValBackupIDs =
1480 OpenRanges.getEntryValueBackup(DebugVar);
1484 if (!EntryValBackupIDs)
1487 const VarLoc &EntryVL = VarLocIDs[EntryValBackupIDs->back()];
1488 VarLoc EntryLoc = VarLoc::CreateEntryLoc(EntryVL.MI, EntryVL.Expr,
1489 EntryVL.Locs[0].Value.RegNo);
1490 LocIndices EntryValueIDs = VarLocIDs.insert(EntryLoc);
1491 assert(EntryValueIDs.size() == 1 &&
1492 "EntryValue loc should not be variadic");
1493 EntryValTransfers.insert({&
MI, EntryValueIDs.back()});
1494 OpenRanges.insert(EntryValueIDs, EntryLoc);
1503void VarLocBasedLDV::insertTransferDebugPair(
1504 MachineInstr &
MI, OpenRangesSet &OpenRanges, TransferMap &Transfers,
1505 VarLocMap &VarLocIDs, LocIndex OldVarID, TransferKind Kind,
1506 const VarLoc::MachineLoc &OldLoc,
Register NewReg) {
1507 const VarLoc &OldVarLoc = VarLocIDs[OldVarID];
1509 auto ProcessVarLoc = [&
MI, &OpenRanges, &Transfers, &VarLocIDs](VarLoc &VL) {
1510 LocIndices LocIds = VarLocIDs.insert(VL);
1513 OpenRanges.erase(VL);
1517 OpenRanges.insert(LocIds, VL);
1518 assert(!
MI.isTerminator() &&
"Cannot insert DBG_VALUE after terminator");
1519 TransferDebugPair MIP = {&
MI, LocIds.back()};
1520 Transfers.push_back(MIP);
1524 OpenRanges.erase(VarLocIDs[OldVarID]);
1526 case TransferKind::TransferCopy: {
1528 "No register supplied when handling a copy of a debug value");
1531 VarLoc VL = VarLoc::CreateCopyLoc(OldVarLoc, OldLoc, NewReg);
1534 dbgs() <<
"Creating VarLoc for register copy:";
1539 case TransferKind::TransferSpill: {
1542 VarLoc::SpillLoc SpillLocation = extractSpillBaseRegAndOffset(
MI);
1543 VarLoc VL = VarLoc::CreateSpillLoc(
1544 OldVarLoc, OldLoc, SpillLocation.SpillBase, SpillLocation.SpillOffset);
1547 dbgs() <<
"Creating VarLoc for spill:";
1552 case TransferKind::TransferRestore: {
1554 "No register supplied when handling a restore of a debug value");
1557 VarLoc VL = VarLoc::CreateCopyLoc(OldVarLoc, OldLoc, NewReg);
1560 dbgs() <<
"Creating VarLoc for restore:";
1571 OpenRangesSet &OpenRanges,
1572 VarLocMap &VarLocIDs,
1573 InstToEntryLocMap &EntryValTransfers,
1574 RegDefToInstMap &RegSetInstrs) {
1578 if (
MI.isMetaInstruction())
1586 DefinedRegsSet DeadRegs;
1591 !(
MI.isCall() && MO.
getReg() == SP)) {
1596 RegSetInstrs.erase(MO.
getReg());
1597 RegSetInstrs.insert({MO.
getReg(), &
MI});
1606 if (!RegMasks.
empty()) {
1608 getUsedRegs(OpenRanges.getVarLocs(), UsedRegs);
1618 bool AnyRegMaskKillsReg =
1622 if (AnyRegMaskKillsReg)
1623 DeadRegs.insert(Reg);
1624 if (AnyRegMaskKillsReg) {
1625 RegSetInstrs.erase(Reg);
1626 RegSetInstrs.insert({
Reg, &
MI});
1631 if (DeadRegs.empty())
1634 VarLocsInRange KillSet;
1635 collectIDsForRegs(KillSet, DeadRegs, OpenRanges.getVarLocs(), VarLocIDs);
1636 OpenRanges.erase(KillSet, VarLocIDs, LocIndex::kUniversalLocation);
1640 if (
TM.Options.ShouldEmitDebugEntryValues())
1641 emitEntryValues(
MI, OpenRanges, VarLocIDs, EntryValTransfers, KillSet);
1646 OpenRangesSet &OpenRanges,
1647 VarLocMap &VarLocIDs) {
1657 VarLocsInRange KillSet;
1659 for (
uint64_t ID : OpenRanges.getWasmVarLocs()) {
1660 LocIndex
Idx = LocIndex::fromRawInteger(
ID);
1661 const VarLoc &VL = VarLocIDs[
Idx];
1662 assert(VL.containsWasmLocs() &&
"Broken VarLocSet?");
1663 if (VL.usesWasmLoc(Loc))
1666 OpenRanges.erase(KillSet, VarLocIDs, LocIndex::kWasmLocation);
1672 if (!
MI.hasOneMemOperand())
1675 if (!
MI.getSpillSize(
TII) && !
MI.getFoldedSpillSize(
TII))
1684 if (!isSpillInstruction(
MI, MF))
1699 if (isKilledReg(MO, Reg))
1705 auto NextI = std::next(
MI.getIterator());
1707 if (
MI.getParent()->end() == NextI)
1713 if (isKilledReg(MONext, RegNext) && RegNext == Reg)
1722std::optional<VarLocBasedLDV::VarLoc::SpillLoc>
1725 if (!
MI.hasOneMemOperand())
1726 return std::nullopt;
1730 if (
MI.getRestoreSize(
TII)) {
1731 Reg =
MI.getOperand(0).getReg();
1732 return extractSpillBaseRegAndOffset(
MI);
1734 return std::nullopt;
1745 OpenRangesSet &OpenRanges,
1746 VarLocMap &VarLocIDs,
1747 TransferMap &Transfers) {
1751 std::optional<VarLoc::SpillLoc> Loc;
1758 VarLocsInRange KillSet;
1759 if (isSpillInstruction(
MI, MF)) {
1760 Loc = extractSpillBaseRegAndOffset(
MI);
1761 for (
uint64_t ID : OpenRanges.getSpillVarLocs()) {
1762 LocIndex
Idx = LocIndex::fromRawInteger(
ID);
1763 const VarLoc &VL = VarLocIDs[
Idx];
1764 assert(VL.containsSpillLocs() &&
"Broken VarLocSet?");
1765 if (VL.usesSpillLoc(*Loc)) {
1777 unsigned SpillLocIdx = VL.getSpillLocIdx(*Loc);
1778 VarLoc::MachineLoc OldLoc = VL.Locs[SpillLocIdx];
1779 VarLoc UndefVL = VarLoc::CreateCopyLoc(VL, OldLoc, 0);
1780 LocIndices UndefLocIDs = VarLocIDs.insert(UndefVL);
1781 Transfers.push_back({&
MI, UndefLocIDs.back()});
1784 OpenRanges.erase(KillSet, VarLocIDs, LocIndex::kSpillLocation);
1789 if (isLocationSpill(
MI, MF, Reg)) {
1790 TKind = TransferKind::TransferSpill;
1795 if (!(Loc = isRestoreInstruction(
MI, MF, Reg)))
1797 TKind = TransferKind::TransferRestore;
1803 auto TransferCandidates = OpenRanges.getEmptyVarLocRange();
1804 if (TKind == TransferKind::TransferSpill)
1805 TransferCandidates = OpenRanges.getRegisterVarLocs(Reg);
1806 else if (TKind == TransferKind::TransferRestore)
1807 TransferCandidates = OpenRanges.getSpillVarLocs();
1809 LocIndex
Idx = LocIndex::fromRawInteger(
ID);
1810 const VarLoc &VL = VarLocIDs[
Idx];
1812 if (TKind == TransferKind::TransferSpill) {
1813 assert(VL.usesReg(Reg) &&
"Broken VarLocSet?");
1815 << VL.Var.getVariable()->getName() <<
")\n");
1816 LocIdx = VL.getRegIdx(Reg);
1818 assert(TKind == TransferKind::TransferRestore && VL.containsSpillLocs() &&
1819 "Broken VarLocSet?");
1820 if (!VL.usesSpillLoc(*Loc))
1824 << VL.Var.getVariable()->getName() <<
")\n");
1825 LocIdx = VL.getSpillLocIdx(*Loc);
1827 VarLoc::MachineLoc MLoc = VL.Locs[
LocIdx];
1828 insertTransferDebugPair(
MI, OpenRanges, Transfers, VarLocIDs,
Idx, TKind,
1840 OpenRangesSet &OpenRanges,
1841 VarLocMap &VarLocIDs,
1842 TransferMap &Transfers) {
1843 auto DestSrc =
TII->isCopyLikeInstr(
MI);
1850 if (!DestRegOp->
isDef())
1855 if (CalleeSavedRegs.
test(*RAI))
1868 if (!isCalleeSavedReg(DestReg))
1875 for (
uint64_t ID : OpenRanges.getEntryValueBackupVarLocs()) {
1876 LocIndex
Idx = LocIndex::fromRawInteger(
ID);
1877 const VarLoc &VL = VarLocIDs[
Idx];
1878 if (VL.isEntryValueBackupReg(SrcReg)) {
1880 VarLoc EntryValLocCopyBackup =
1881 VarLoc::CreateEntryCopyBackupLoc(VL.MI, VL.Expr, DestReg);
1883 OpenRanges.erase(VL);
1886 LocIndices EntryValCopyLocIDs = VarLocIDs.insert(EntryValLocCopyBackup);
1887 OpenRanges.insert(EntryValCopyLocIDs, EntryValLocCopyBackup);
1896 for (
uint64_t ID : OpenRanges.getRegisterVarLocs(SrcReg)) {
1897 LocIndex
Idx = LocIndex::fromRawInteger(
ID);
1898 assert(VarLocIDs[
Idx].usesReg(SrcReg) &&
"Broken VarLocSet?");
1899 VarLoc::MachineLocValue Loc;
1901 VarLoc::MachineLoc MLoc{VarLoc::MachineLocKind::RegisterKind, Loc};
1902 insertTransferDebugPair(
MI, OpenRanges, Transfers, VarLocIDs,
Idx,
1903 TransferKind::TransferCopy, MLoc, DestReg);
1912 OpenRangesSet &OpenRanges,
1913 VarLocInMBB &OutLocs,
1914 const VarLocMap &VarLocIDs) {
1915 bool Changed =
false;
1918 OpenRanges.getUniqueVarLocs(VarLocs, VarLocIDs);
1919 for (VarLoc &VL : VarLocs) {
1921 dbgs() <<
"Add to OutLocs in MBB #" << CurMBB->
getNumber() <<
": ";
1925 VarLocSet &VLS = getVarLocsInMBB(CurMBB, OutLocs);
1926 Changed = VLS != OpenRanges.getVarLocs();
1930 VLS = OpenRanges.getVarLocs();
1946 VarToFragments &SeenFragments,
1949 MI.getDebugLoc()->getInlinedAt());
1950 FragmentInfo ThisFragment = MIVar.getFragmentOrDefault();
1955 auto SeenIt = SeenFragments.find(MIVar.getVariable());
1956 if (SeenIt == SeenFragments.end()) {
1958 OneFragment.
insert(ThisFragment);
1959 SeenFragments.insert({MIVar.getVariable(), OneFragment});
1961 OverlappingFragments.
insert({{MIVar.getVariable(), ThisFragment}, {}});
1968 OverlappingFragments.
insert({{MIVar.getVariable(), ThisFragment}, {}});
1969 if (!IsInOLapMap.second)
1972 auto &ThisFragmentsOverlaps = IsInOLapMap.first->second;
1973 auto &AllSeenFragments = SeenIt->second;
1978 for (
const auto &ASeenFragment : AllSeenFragments) {
1982 ThisFragmentsOverlaps.push_back(ASeenFragment);
1985 auto ASeenFragmentsOverlaps =
1986 OverlappingFragments.
find({MIVar.getVariable(), ASeenFragment});
1987 assert(ASeenFragmentsOverlaps != OverlappingFragments.
end() &&
1988 "Previously seen var fragment has no vector of overlaps");
1989 ASeenFragmentsOverlaps->second.push_back(ThisFragment);
1993 AllSeenFragments.insert(ThisFragment);
1997void VarLocBasedLDV::process(
MachineInstr &
MI, OpenRangesSet &OpenRanges,
1998 VarLocMap &VarLocIDs, TransferMap &Transfers,
1999 InstToEntryLocMap &EntryValTransfers,
2000 RegDefToInstMap &RegSetInstrs) {
2001 if (!
MI.isDebugInstr())
2003 transferDebugValue(
MI, OpenRanges, VarLocIDs, EntryValTransfers,
2005 transferRegisterDef(
MI, OpenRanges, VarLocIDs, EntryValTransfers,
2007 transferWasmDef(
MI, OpenRanges, VarLocIDs);
2008 transferRegisterCopy(
MI, OpenRanges, VarLocIDs, Transfers);
2009 transferSpillOrRestoreInst(
MI, OpenRanges, VarLocIDs, Transfers);
2015bool VarLocBasedLDV::join(
2017 const VarLocMap &VarLocIDs,
2022 VarLocSet InLocsT(Alloc);
2033 if (!Visited.
count(p)) {
2034 LLVM_DEBUG(
dbgs() <<
" ignoring unvisited pred MBB: " <<
p->getNumber()
2038 auto OL = OutLocs.find(p);
2040 if (OL == OutLocs.end())
2045 VarLocSet &OutLocVLS = *OL->second;
2047 InLocsT = OutLocVLS;
2049 InLocsT &= OutLocVLS;
2052 if (!InLocsT.empty()) {
2054 collectAllVarLocs(VarLocs, InLocsT, VarLocIDs);
2055 for (const VarLoc &VL : VarLocs)
2056 dbgs() <<
" gathered candidate incoming var: "
2057 << VL.Var.getVariable()->getName() <<
"\n";
2065 VarLocSet KillSet(Alloc);
2066 bool IsArtificial = ArtificialBlocks.
count(&
MBB);
2067 if (!IsArtificial) {
2069 LocIndex
Idx = LocIndex::fromRawInteger(
ID);
2074 dbgs() <<
" killing " <<
Name <<
", it doesn't dominate MBB\n";
2079 InLocsT.intersectWithComplement(KillSet);
2085 "Should have processed at least one predecessor");
2087 VarLocSet &ILS = getVarLocsInMBB(&
MBB, InLocs);
2088 bool Changed =
false;
2089 if (ILS != InLocsT) {
2097void VarLocBasedLDV::flushPendingLocs(VarLocInMBB &PendingInLocs,
2098 VarLocMap &VarLocIDs) {
2101 for (
auto &Iter : PendingInLocs) {
2104 VarLocSet &Pending = *Iter.second;
2107 collectAllVarLocs(VarLocs, Pending, VarLocIDs);
2109 for (VarLoc DiffIt : VarLocs) {
2112 if (DiffIt.isEntryBackupLoc())
2123bool VarLocBasedLDV::isEntryValueCandidate(
2124 const MachineInstr &
MI,
const DefinedRegsSet &DefinedRegs)
const {
2125 assert(
MI.isDebugValue() &&
"This must be DBG_VALUE.");
2131 auto *DIVar =
MI.getDebugVariable();
2132 if (!DIVar->isParameter())
2136 if (
MI.getDebugLoc()->getInlinedAt())
2149 if (DefinedRegs.count(
MI.getDebugOperand(0).getReg()))
2167 Regs.insert(MO.
getReg());
2178 const DefinedRegsSet &DefinedRegs,
2179 OpenRangesSet &OpenRanges,
2180 VarLocMap &VarLocIDs) {
2183 if (!
TM.Options.ShouldEmitDebugEntryValues())
2188 MI.getDebugLoc()->getInlinedAt());
2190 if (!isEntryValueCandidate(
MI, DefinedRegs) ||
2191 OpenRanges.getEntryValueBackup(V))
2200 VarLoc EntryValLocAsBackup = VarLoc::CreateEntryBackupLoc(
MI,
NewExpr);
2201 LocIndices EntryValLocIDs = VarLocIDs.insert(EntryValLocAsBackup);
2202 OpenRanges.insert(EntryValLocIDs, EntryValLocAsBackup);
2210 unsigned InputDbgValLimit) {
2230 bool Changed =
false;
2231 bool OLChanged =
false;
2232 bool MBBJoined =
false;
2234 VarLocMap VarLocIDs;
2236 OpenRangesSet OpenRanges(Alloc, OverlapFragments);
2238 VarLocInMBB OutLocs;
2240 TransferMap Transfers;
2243 InstToEntryLocMap EntryValTransfers;
2245 RegDefToInstMap RegSetInstrs;
2247 VarToFragments SeenFragments;
2255 std::priority_queue<unsigned int, std::vector<unsigned int>,
2256 std::greater<unsigned int>>
2258 std::priority_queue<unsigned int, std::vector<unsigned int>,
2259 std::greater<unsigned int>>
2264 DefinedRegsSet DefinedRegs;
2269 for (
auto &
MI : First_MBB) {
2271 if (
MI.isDebugValue())
2272 recordEntryValue(
MI, DefinedRegs, OpenRanges, VarLocIDs);
2276 for (
auto &
MBB : MF)
2277 for (
auto &
MI :
MBB)
2278 if (
MI.isDebugValue())
2279 accumulateFragmentMap(
MI, SeenFragments, OverlapFragments);
2281 auto hasNonArtificialLocation = [](
const MachineInstr &
MI) ->
bool {
2283 return DL.getLine() != 0;
2286 for (
auto &
MBB : MF)
2290 LLVM_DEBUG(printVarLocInMBB(MF, OutLocs, VarLocIDs,
2291 "OutLocs after initialization",
dbgs()));
2294 unsigned int RPONumber = 0;
2296 OrderToBB[RPONumber] =
MBB;
2297 BBToOrder[
MBB] = RPONumber;
2298 Worklist.push(RPONumber);
2303 unsigned NumInputDbgValues = 0;
2304 for (
auto &
MBB : MF)
2305 for (
auto &
MI :
MBB)
2306 if (
MI.isDebugValue())
2307 ++NumInputDbgValues;
2308 if (NumInputDbgValues > InputDbgValLimit) {
2309 LLVM_DEBUG(
dbgs() <<
"Disabling VarLocBasedLDV: " << MF.getName()
2310 <<
" has " << RPONumber <<
" basic blocks and "
2311 << NumInputDbgValues
2312 <<
" input DBG_VALUEs, exceeding limits.\n");
2322 while (!Worklist.empty() || !Pending.empty()) {
2328 while (!Worklist.empty()) {
2331 MBBJoined = join(*
MBB, OutLocs, InLocs, VarLocIDs, Visited,
2333 MBBJoined |= Visited.
insert(
MBB).second;
2341 OpenRanges.insertFromLocSet(getVarLocsInMBB(
MBB, InLocs), VarLocIDs);
2342 LastNonDbgMI =
nullptr;
2343 RegSetInstrs.clear();
2344 for (
auto &
MI : *
MBB)
2345 process(
MI, OpenRanges, VarLocIDs, Transfers, EntryValTransfers,
2347 OLChanged |= transferTerminator(
MBB, OpenRanges, OutLocs, VarLocIDs);
2349 LLVM_DEBUG(printVarLocInMBB(MF, OutLocs, VarLocIDs,
2350 "OutLocs after propagating",
dbgs()));
2351 LLVM_DEBUG(printVarLocInMBB(MF, InLocs, VarLocIDs,
2352 "InLocs after propagating",
dbgs()));
2357 if (OnPending.
insert(s).second) {
2358 Pending.push(BBToOrder[s]);
2363 Worklist.swap(Pending);
2366 assert(Pending.empty() &&
"Pending should be empty");
2370 for (
auto &TR : Transfers) {
2371 assert(!TR.TransferInst->isTerminator() &&
2372 "Cannot insert DBG_VALUE after terminator");
2374 const VarLoc &VL = VarLocIDs[TR.LocationID];
2381 for (
auto &TR : EntryValTransfers) {
2384 "Cannot insert DBG_VALUE after terminator");
2386 const VarLoc &VL = VarLocIDs[TR.second];
2390 EntryValTransfers.clear();
2394 flushPendingLocs(InLocs, VarLocIDs);
2396 LLVM_DEBUG(printVarLocInMBB(MF, OutLocs, VarLocIDs,
"Final OutLocs",
dbgs()));
2397 LLVM_DEBUG(printVarLocInMBB(MF, InLocs, VarLocIDs,
"Final InLocs",
dbgs()));
2404 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.
static void clear(coro::Shape &Shape)
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...
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...
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.