137#include "llvm/Config/llvm-config.h"
159#define DEBUG_TYPE "livedebugvalues"
161STATISTIC(NumInserted,
"Number of DBG_VALUE instructions inserted");
205 using u32_location_t = uint32_t;
206 using u32_index_t = uint32_t;
208 u32_location_t Location;
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)
246 : Location(Location), Index(Index) {}
249 return (
static_cast<uint64_t>(Location) << 32) | 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) {
270 uint64_t End = LocIndex(Location + 1, 0).getAsRawInteger();
271 return Set.half_open_range(Start, End);
282class VarLocBasedLDV :
public LDVImpl {
284 const TargetRegisterInfo *TRI;
285 const TargetInstrInfo *TII;
286 const TargetFrameLowering *TFI;
287 bool ShouldEmitDebugEntryValues;
288 BitVector CalleeSavedRegs;
290 VarLocSet::Allocator Alloc;
292 const MachineInstr *LastNonDbgMI;
294 enum struct TransferKind { TransferCopy, TransferSpill, TransferRestore };
297 using OptFragmentInfo = std::optional<DIExpression::FragmentInfo>;
305 StackOffset SpillOffset;
307 return SpillBase ==
Other.SpillBase && SpillOffset ==
Other.SpillOffset;
310 return !(*
this ==
Other);
324 return Index ==
Other.Index && Offset ==
Other.Offset;
330 const GlobalValue *GV;
333 return GV ==
Other.GV && Offset ==
Other.Offset;
338 const DebugVariable Var;
341 const DIExpression *Expr;
345 const MachineInstr &MI;
347 enum class MachineLocKind {
356 enum class EntryValueLocKind {
357 NonEntryValueKind = 0,
359 EntryValueBackupKind,
360 EntryValueCopyBackupKind
361 } EVKind = EntryValueLocKind::NonEntryValueKind;
365 union MachineLocValue {
367 SpillLoc SpillLocation;
371 const ConstantInt *CImm;
372 WasmLoc WasmLocation;
373 GlobalAddr GlobalAddress;
374 MachineLocValue() : Hash(0) {}
383 MachineLocValue Value;
385 if (Kind !=
Other.Kind)
388 case MachineLocKind::SpillLocKind:
389 return Value.SpillLocation ==
Other.Value.SpillLocation;
390 case MachineLocKind::WasmLocKind:
391 return Value.WasmLocation ==
Other.Value.WasmLocation;
392 case MachineLocKind::GlobalAddrKind:
393 return Value.GlobalAddress ==
Other.Value.GlobalAddress;
394 case MachineLocKind::RegisterKind:
395 case MachineLocKind::ImmediateKind:
396 return Value.Hash ==
Other.Value.Hash;
405 if (Kind !=
Other.Kind)
406 return Kind <
Other.Kind;
408 case MachineLocKind::SpillLocKind:
409 return std::make_tuple(
410 Value.SpillLocation.SpillBase,
411 Value.SpillLocation.SpillOffset.getFixed(),
412 Value.SpillLocation.SpillOffset.getScalable()) <
414 Other.Value.SpillLocation.SpillBase,
415 Other.Value.SpillLocation.SpillOffset.getFixed(),
416 Other.Value.SpillLocation.SpillOffset.getScalable());
417 case MachineLocKind::WasmLocKind:
418 return std::tie(Value.WasmLocation.Index, Value.WasmLocation.Offset) <
419 std::tie(
Other.Value.WasmLocation.Index,
420 Other.Value.WasmLocation.Offset);
421 case MachineLocKind::GlobalAddrKind:
422 return std::tie(Value.GlobalAddress.GV, Value.GlobalAddress.Offset) <
423 std::tie(
Other.Value.GlobalAddress.GV,
424 Other.Value.GlobalAddress.Offset);
425 case MachineLocKind::RegisterKind:
426 case MachineLocKind::ImmediateKind:
427 return Value.Hash <
Other.Value.Hash;
442 SmallVector<unsigned, 8> OrigLocMap;
444 VarLoc(
const MachineInstr &MI)
445 : Var(MI.getDebugVariable(), MI.getDebugExpression(),
447 Expr(MI.getDebugExpression()), MI(MI) {
448 assert(MI.isDebugValue() &&
"not a DBG_VALUE");
449 assert((MI.isDebugValueList() || MI.getNumOperands() == 4) &&
450 "malformed DBG_VALUE");
451 for (
const MachineOperand &
Op : MI.debug_operands()) {
452 MachineLoc
ML = GetLocForOp(
Op);
454 if (It == Locs.end()) {
456 OrigLocMap.push_back(MI.getDebugOperandIndex(&
Op));
460 unsigned OpIdx = Locs.size();
461 unsigned DuplicatingIdx = std::distance(Locs.begin(), It);
468 assert(EVKind != EntryValueLocKind::EntryValueKind &&
469 !isEntryBackupLoc());
472 static MachineLoc GetLocForOp(
const MachineOperand &
Op) {
476 Kind = MachineLocKind::RegisterKind;
477 Loc.RegNo =
Op.getReg();
478 }
else if (
Op.isImm()) {
479 Kind = MachineLocKind::ImmediateKind;
480 Loc.Immediate =
Op.getImm();
481 }
else if (
Op.isFPImm()) {
482 Kind = MachineLocKind::ImmediateKind;
483 Loc.FPImm =
Op.getFPImm();
484 }
else if (
Op.isCImm()) {
485 Kind = MachineLocKind::ImmediateKind;
486 Loc.CImm =
Op.getCImm();
487 }
else if (
Op.isTargetIndex()) {
488 Kind = MachineLocKind::WasmLocKind;
489 Loc.WasmLocation = {
Op.getIndex(),
Op.getOffset()};
490 }
else if (
Op.isGlobal()) {
491 Kind = MachineLocKind::GlobalAddrKind;
492 Loc.GlobalAddress = {
Op.getGlobal(),
Op.getOffset()};
500 static VarLoc CreateEntryLoc(
const MachineInstr &MI,
503 assert(VL.Locs.size() == 1 &&
504 VL.Locs[0].Kind == MachineLocKind::RegisterKind);
505 VL.EVKind = EntryValueLocKind::EntryValueKind;
507 VL.Locs[0].Value.RegNo =
Reg;
515 static VarLoc CreateEntryBackupLoc(
const MachineInstr &MI,
516 const DIExpression *EntryExpr) {
518 assert(VL.Locs.size() == 1 &&
519 VL.Locs[0].Kind == MachineLocKind::RegisterKind);
520 VL.EVKind = EntryValueLocKind::EntryValueBackupKind;
528 static VarLoc CreateEntryCopyBackupLoc(
const MachineInstr &MI,
529 const DIExpression *EntryExpr,
532 assert(VL.Locs.size() == 1 &&
533 VL.Locs[0].Kind == MachineLocKind::RegisterKind);
534 VL.EVKind = EntryValueLocKind::EntryValueCopyBackupKind;
536 VL.Locs[0].Value.RegNo = NewReg;
542 static VarLoc CreateCopyLoc(
const VarLoc &OldVL,
const MachineLoc &OldML,
545 for (MachineLoc &
ML : VL.Locs)
547 ML.Kind = MachineLocKind::RegisterKind;
548 ML.Value.RegNo = NewReg;
556 static VarLoc CreateSpillLoc(
const VarLoc &OldVL,
const MachineLoc &OldML,
557 unsigned SpillBase, StackOffset SpillOffset) {
559 for (MachineLoc &
ML : VL.Locs)
561 ML.Kind = MachineLocKind::SpillLocKind;
562 ML.Value.SpillLocation = {SpillBase, SpillOffset};
573 assert(!isEntryBackupLoc() &&
574 "Tried to produce DBG_VALUE for backup VarLoc");
575 const DebugLoc &DbgLoc = MI.getDebugLoc();
576 bool Indirect = MI.isIndirectDebugValue();
577 const auto &IID = MI.getDesc();
578 const DILocalVariable *Var = MI.getDebugVariable();
581 const DIExpression *DIExpr = Expr;
583 for (
unsigned I = 0,
E = Locs.size();
I <
E; ++
I) {
584 MachineLocKind LocKind = Locs[
I].Kind;
585 MachineLocValue Loc = Locs[
I].Value;
586 const MachineOperand &Orig = MI.getDebugOperand(OrigLocMap[
I]);
588 case MachineLocKind::RegisterKind:
596 EVKind == EntryValueLocKind::EntryValueKind ? Orig.
getReg()
600 case MachineLocKind::SpillLocKind: {
605 unsigned Base = Loc.SpillLocation.SpillBase;
607 if (MI.isNonListDebugValue()) {
609 DIExpr =
TRI->prependOffsetExpression(
611 Loc.SpillLocation.SpillOffset);
614 SmallVector<uint64_t, 4>
Ops;
615 TRI->getOffsetOpcodes(Loc.SpillLocation.SpillOffset,
Ops);
616 Ops.push_back(dwarf::DW_OP_deref);
622 case MachineLocKind::ImmediateKind: {
626 case MachineLocKind::WasmLocKind:
627 case MachineLocKind::GlobalAddrKind: {
631 case MachineLocKind::InvalidKind:
635 return BuildMI(MF, DbgLoc, IID, Indirect, MOs, Var, DIExpr);
640 return Kind == MachineLocKind::ImmediateKind ||
641 Kind == MachineLocKind::GlobalAddrKind;
645 bool isEntryBackupLoc()
const {
646 return EVKind == EntryValueLocKind::EntryValueBackupKind ||
647 EVKind == EntryValueLocKind::EntryValueCopyBackupKind;
653 return EVKind == EntryValueLocKind::EntryValueBackupKind && usesReg(
Reg);
658 bool isEntryValueCopyBackupReg(
Register Reg)
const {
659 return EVKind == EntryValueLocKind::EntryValueCopyBackupKind &&
666 RegML.Kind = MachineLocKind::RegisterKind;
667 RegML.Value.RegNo =
Reg;
673 for (
unsigned Idx = 0; Idx < Locs.size(); ++Idx)
674 if (Locs[Idx].Kind == MachineLocKind::RegisterKind &&
675 Register{
static_cast<unsigned>(Locs[Idx].Value.RegNo)} ==
Reg)
682 bool getDescribingRegs(SmallVectorImpl<uint32_t> &Regs)
const {
683 bool AnyRegs =
false;
684 for (
const auto &Loc : Locs)
685 if (Loc.Kind == MachineLocKind::RegisterKind) {
692 bool containsSpillLocs()
const {
693 return any_of(Locs, [](VarLoc::MachineLoc
ML) {
694 return ML.Kind == VarLoc::MachineLocKind::SpillLocKind;
700 bool usesSpillLoc(SpillLoc SpillLocation)
const {
702 SpillML.Kind = MachineLocKind::SpillLocKind;
703 SpillML.Value.SpillLocation = SpillLocation;
709 unsigned getSpillLocIdx(SpillLoc SpillLocation)
const {
710 for (
unsigned Idx = 0; Idx < Locs.size(); ++Idx)
711 if (Locs[Idx].Kind == MachineLocKind::SpillLocKind &&
712 Locs[Idx].
Value.SpillLocation == SpillLocation)
717 bool containsWasmLocs()
const {
718 return any_of(Locs, [](VarLoc::MachineLoc
ML) {
719 return ML.Kind == VarLoc::MachineLocKind::WasmLocKind;
725 bool usesWasmLoc(WasmLoc WasmLocation)
const {
727 WasmML.Kind = MachineLocKind::WasmLocKind;
728 WasmML.Value.WasmLocation = WasmLocation;
734 bool dominates(LexicalScopes &LS, MachineBasicBlock &
MBB)
const {
735 return LS.dominates(MI.getDebugLoc().get(), &
MBB);
738#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
740 void dump(
const TargetRegisterInfo *
TRI,
const TargetInstrInfo *
TII,
741 raw_ostream &Out =
dbgs())
const {
743 for (
const MachineLoc &MLoc : Locs) {
744 if (Locs.begin() != &MLoc)
747 case MachineLocKind::RegisterKind:
750 case MachineLocKind::SpillLocKind:
752 Out <<
"[" << MLoc.Value.SpillLocation.SpillOffset.getFixed() <<
" + "
753 << MLoc.Value.SpillLocation.SpillOffset.getScalable()
757 case MachineLocKind::ImmediateKind:
758 Out << MLoc.Value.Immediate;
760 case MachineLocKind::GlobalAddrKind:
761 Out << MLoc.Value.GlobalAddress.GV->getName();
762 if (MLoc.Value.GlobalAddress.Offset)
763 Out <<
'+' << MLoc.Value.GlobalAddress.Offset;
765 case MachineLocKind::WasmLocKind: {
767 auto Indices =
TII->getSerializableTargetIndices();
769 find_if(Indices, [&](
const std::pair<int, const char *> &
I) {
770 return I.first == MLoc.Value.WasmLocation.Index;
772 assert(Found != Indices.end());
773 Out << Found->second;
774 if (MLoc.Value.WasmLocation.Offset > 0)
775 Out <<
" + " << MLoc.Value.WasmLocation.Offset;
781 case MachineLocKind::InvalidKind:
786 Out <<
", \"" << Var.getVariable()->getName() <<
"\", " << *Expr <<
", ";
787 if (Var.getInlinedAt())
788 Out <<
"!" << Var.getInlinedAt()->getMetadataID() <<
")\n";
792 if (isEntryBackupLoc())
793 Out <<
" (backup loc)\n";
800 return std::tie(EVKind, Var, Expr, Locs) ==
806 return std::tie(Var, EVKind, Locs, Expr) <
812 using VarVec = SmallVector<VarLoc, 32>;
822 std::map<VarLoc, LocIndices> Var2Indices;
826 SmallDenseMap<LocIndex::u32_location_t, std::vector<VarLoc>> Loc2Vars;
830 LocIndices insert(
const VarLoc &VL) {
831 LocIndices &Indices = Var2Indices[VL];
833 if (!Indices.empty())
841 if (VL.EVKind == VarLoc::EntryValueLocKind::NonEntryValueKind) {
842 VL.getDescribingRegs(Locations);
845 return (RegNo < LocIndex::kFirstInvalidRegLocation) ||
846 (LocIndex::kFirstVirtualRegLocation <= RegNo);
848 "Physical or virtual register out of range?");
849 if (VL.containsSpillLocs())
850 Locations.push_back(LocIndex::kSpillLocation);
851 if (VL.containsWasmLocs())
852 Locations.push_back(LocIndex::kWasmLocation);
853 }
else if (VL.EVKind != VarLoc::EntryValueLocKind::EntryValueKind) {
854 LocIndex::u32_location_t Loc = LocIndex::kEntryValueBackupLocation;
857 Locations.push_back(LocIndex::kUniversalLocation);
858 for (LocIndex::u32_location_t Location : Locations) {
861 {
Location,
static_cast<LocIndex::u32_index_t
>(Vars.size())});
867 LocIndices getAllIndices(
const VarLoc &VL)
const {
868 auto IndIt = Var2Indices.find(VL);
869 assert(IndIt != Var2Indices.end() &&
"VarLoc not tracked");
870 return IndIt->second;
874 const VarLoc &operator[](LocIndex ID)
const {
875 auto LocIt = Loc2Vars.find(
ID.Location);
876 assert(LocIt != Loc2Vars.end() &&
"Location not tracked");
877 return LocIt->second[
ID.Index];
882 SmallDenseMap<const MachineBasicBlock *, std::unique_ptr<VarLocSet>>;
883 struct TransferDebugPair {
884 MachineInstr *TransferInst;
887 using TransferMap = SmallVector<TransferDebugPair, 4>;
890 using InstToEntryLocMap = std::multimap<const MachineInstr *, LocIndex>;
891 using RegDefToInstMap = DenseMap<Register, MachineInstr *>;
896 using FragmentOfVar =
897 std::pair<const DILocalVariable *, DIExpression::FragmentInfo>;
899 DenseMap<FragmentOfVar, SmallVector<DIExpression::FragmentInfo, 1>>;
903 using VarToFragments =
904 DenseMap<const DILocalVariable *, SmallSet<FragmentInfo, 4>>;
908 static void collectAllVarLocs(SmallVectorImpl<VarLoc> &Collected,
909 const VarLocSet &CollectFrom,
910 const VarLocMap &VarLocIDs);
914 void getUsedRegs(
const VarLocSet &CollectFrom,
915 SmallVectorImpl<Register> &UsedRegs)
const;
926 class OpenRangesSet {
927 VarLocSet::Allocator &Alloc;
930 SmallDenseMap<DebugVariable, LocIndices, 8> Vars;
932 SmallDenseMap<DebugVariable, LocIndices, 8> EntryValuesBackupVars;
936 OpenRangesSet(VarLocSet::Allocator &Alloc,
OverlapMap &_OLapMap)
937 : Alloc(Alloc), VarLocs(Alloc), OverlappingFragments(_OLapMap) {}
939 const VarLocSet &getVarLocs()
const {
return VarLocs; }
946 void getUniqueVarLocs(SmallVectorImpl<VarLoc> &Collected,
947 const VarLocMap &VarLocIDs)
const {
948 collectAllVarLocs(Collected, VarLocs, VarLocIDs);
952 void erase(
const VarLoc &VL);
956 void erase(
const VarLocsInRange &KillSet,
const VarLocMap &VarLocIDs,
957 LocIndex::u32_location_t Location);
960 void insert(LocIndices VarLocIDs,
const VarLoc &VL);
963 void insertFromLocSet(
const VarLocSet &ToLoad,
const VarLocMap &Map);
965 std::optional<LocIndices> getEntryValueBackup(DebugVariable Var);
971 EntryValuesBackupVars.clear();
976 assert(Vars.empty() == EntryValuesBackupVars.empty() &&
977 Vars.empty() == VarLocs.empty() &&
978 "open ranges are inconsistent");
979 return VarLocs.empty();
983 auto getEmptyVarLocRange()
const {
990 return LocIndex::indexRangeForLocation(getVarLocs(),
Reg);
994 auto getSpillVarLocs()
const {
995 return LocIndex::indexRangeForLocation(getVarLocs(),
996 LocIndex::kSpillLocation);
1001 auto getEntryValueBackupVarLocs()
const {
1002 return LocIndex::indexRangeForLocation(
1003 getVarLocs(), LocIndex::kEntryValueBackupLocation);
1007 auto getWasmVarLocs()
const {
1008 return LocIndex::indexRangeForLocation(getVarLocs(),
1009 LocIndex::kWasmLocation);
1017 static void collectIDsForRegs(VarLocsInRange &Collected,
1019 const VarLocSet &CollectFrom,
1020 const VarLocMap &VarLocIDs);
1022 VarLocSet &getVarLocsInMBB(
const MachineBasicBlock *
MBB, VarLocInMBB &Locs) {
1023 std::unique_ptr<VarLocSet> &VLS = Locs[
MBB];
1025 VLS = std::make_unique<VarLocSet>(Alloc);
1029 const VarLocSet &getVarLocsInMBB(
const MachineBasicBlock *
MBB,
1030 const VarLocInMBB &Locs)
const {
1031 auto It = Locs.find(
MBB);
1032 assert(It != Locs.end() &&
"MBB not in map");
1053 bool isEntryValueCandidate(
const MachineInstr &
MI,
1054 const DefinedRegsSet &Regs)
const;
1058 std::optional<VarLoc::SpillLoc> isRestoreInstruction(
const MachineInstr &
MI,
1063 VarLoc::SpillLoc extractSpillBaseRegAndOffset(
const MachineInstr &
MI);
1064 void insertTransferDebugPair(MachineInstr &
MI, OpenRangesSet &OpenRanges,
1065 TransferMap &Transfers, VarLocMap &VarLocIDs,
1066 LocIndex OldVarID, TransferKind Kind,
1067 const VarLoc::MachineLoc &OldLoc,
1070 void transferDebugValue(
const MachineInstr &
MI, OpenRangesSet &OpenRanges,
1071 VarLocMap &VarLocIDs,
1072 InstToEntryLocMap &EntryValTransfers,
1073 RegDefToInstMap &RegSetInstrs);
1074 void transferSpillOrRestoreInst(MachineInstr &
MI, OpenRangesSet &OpenRanges,
1075 VarLocMap &VarLocIDs, TransferMap &Transfers);
1076 void cleanupEntryValueTransfers(
const MachineInstr *
MI,
1077 OpenRangesSet &OpenRanges,
1078 VarLocMap &VarLocIDs,
const VarLoc &EntryVL,
1079 InstToEntryLocMap &EntryValTransfers);
1080 void removeEntryValue(
const MachineInstr &
MI, OpenRangesSet &OpenRanges,
1081 VarLocMap &VarLocIDs,
const VarLoc &EntryVL,
1082 InstToEntryLocMap &EntryValTransfers,
1083 RegDefToInstMap &RegSetInstrs);
1084 void emitEntryValues(MachineInstr &
MI, OpenRangesSet &OpenRanges,
1085 VarLocMap &VarLocIDs,
1086 InstToEntryLocMap &EntryValTransfers,
1087 VarLocsInRange &KillSet);
1088 void recordEntryValue(
const MachineInstr &
MI,
1089 const DefinedRegsSet &DefinedRegs,
1090 OpenRangesSet &OpenRanges, VarLocMap &VarLocIDs);
1091 void transferRegisterCopy(MachineInstr &
MI, OpenRangesSet &OpenRanges,
1092 VarLocMap &VarLocIDs, TransferMap &Transfers);
1093 void transferRegisterDef(MachineInstr &
MI, OpenRangesSet &OpenRanges,
1094 VarLocMap &VarLocIDs,
1095 InstToEntryLocMap &EntryValTransfers,
1096 RegDefToInstMap &RegSetInstrs);
1097 void transferWasmDef(MachineInstr &
MI, OpenRangesSet &OpenRanges,
1098 VarLocMap &VarLocIDs);
1099 bool transferTerminator(MachineBasicBlock *
MBB, OpenRangesSet &OpenRanges,
1100 VarLocInMBB &OutLocs,
const VarLocMap &VarLocIDs);
1102 void process(MachineInstr &
MI, OpenRangesSet &OpenRanges,
1103 VarLocMap &VarLocIDs, TransferMap &Transfers,
1104 InstToEntryLocMap &EntryValTransfers,
1105 RegDefToInstMap &RegSetInstrs);
1107 void accumulateFragmentMap(MachineInstr &
MI, VarToFragments &SeenFragments,
1108 OverlapMap &OLapMap);
1110 bool join(MachineBasicBlock &
MBB, VarLocInMBB &OutLocs, VarLocInMBB &InLocs,
1111 const VarLocMap &VarLocIDs,
1112 SmallPtrSet<const MachineBasicBlock *, 16> &Visited,
1113 SmallPtrSetImpl<const MachineBasicBlock *> &ArtificialBlocks);
1117 void flushPendingLocs(VarLocInMBB &PendingInLocs, VarLocMap &VarLocIDs);
1120 bool ShouldEmitDebugEntryValues,
unsigned InputBBLimit,
1121 unsigned InputDbgValLimit)
override;
1127 ~VarLocBasedLDV()
override;
1130 void printVarLocInMBB(
const MachineFunction &MF,
const VarLocInMBB &V,
1131 const VarLocMap &VarLocIDs,
const char *msg,
1132 raw_ostream &Out)
const;
1141VarLocBasedLDV::VarLocBasedLDV() =
default;
1143VarLocBasedLDV::~VarLocBasedLDV() =
default;
1150void VarLocBasedLDV::OpenRangesSet::erase(
const VarLoc &VL) {
1152 auto DoErase = [&VL,
this](DebugVariable VarToErase) {
1153 auto *EraseFrom = VL.isEntryBackupLoc() ? &EntryValuesBackupVars : &Vars;
1154 auto It = EraseFrom->
find(VarToErase);
1155 if (It != EraseFrom->end()) {
1156 LocIndices IDs = It->second;
1157 for (LocIndex ID : IDs)
1158 VarLocs.reset(
ID.getAsRawInteger());
1159 EraseFrom->erase(It);
1163 DebugVariable Var = VL.Var;
1174 auto MapIt = OverlappingFragments.find({Var.
getVariable(), ThisFragment});
1175 if (MapIt != OverlappingFragments.end()) {
1176 for (
auto Fragment : MapIt->second) {
1177 VarLocBasedLDV::OptFragmentInfo FragmentHolder;
1179 FragmentHolder = VarLocBasedLDV::OptFragmentInfo(
Fragment);
1185void VarLocBasedLDV::OpenRangesSet::erase(
const VarLocsInRange &KillSet,
1186 const VarLocMap &VarLocIDs,
1187 LocIndex::u32_location_t Location) {
1188 VarLocSet RemoveSet(
Alloc);
1189 for (LocIndex::u32_index_t ID : KillSet) {
1190 const VarLoc &VL = VarLocIDs[LocIndex(Location, ID)];
1191 auto *EraseFrom = VL.isEntryBackupLoc() ? &EntryValuesBackupVars : &Vars;
1192 EraseFrom->
erase(VL.Var);
1193 LocIndices VLI = VarLocIDs.getAllIndices(VL);
1194 for (LocIndex ID : VLI)
1195 RemoveSet.set(
ID.getAsRawInteger());
1197 VarLocs.intersectWithComplement(RemoveSet);
1200void VarLocBasedLDV::OpenRangesSet::insertFromLocSet(
const VarLocSet &ToLoad,
1201 const VarLocMap &Map) {
1202 VarLocsInRange UniqueVarLocIDs;
1203 Register UniversalLoc = LocIndex::kUniversalLocation;
1204 collectIDsForRegs(UniqueVarLocIDs, UniversalLoc, ToLoad, Map);
1205 for (
uint64_t ID : UniqueVarLocIDs) {
1206 LocIndex Idx = LocIndex::fromRawInteger(ID);
1207 const VarLoc &VarL =
Map[Idx];
1208 const LocIndices Indices =
Map.getAllIndices(VarL);
1209 insert(Indices, VarL);
1213void VarLocBasedLDV::OpenRangesSet::insert(LocIndices VarLocIDs,
1215 auto *InsertInto = VL.isEntryBackupLoc() ? &EntryValuesBackupVars : &Vars;
1216 for (LocIndex ID : VarLocIDs)
1217 VarLocs.set(
ID.getAsRawInteger());
1218 InsertInto->
insert({VL.Var, VarLocIDs});
1223std::optional<LocIndices>
1224VarLocBasedLDV::OpenRangesSet::getEntryValueBackup(DebugVariable Var) {
1225 auto It = EntryValuesBackupVars.
find(Var);
1226 if (It != EntryValuesBackupVars.
end())
1229 return std::nullopt;
1232void VarLocBasedLDV::collectIDsForRegs(VarLocsInRange &Collected,
1234 const VarLocSet &CollectFrom,
1235 const VarLocMap &VarLocIDs) {
1241 auto It = CollectFrom.find(LocIndex::rawIndexForReg(SortedRegs.
front()));
1242 auto End = CollectFrom.end();
1247 uint64_t FirstIndexForReg = LocIndex::rawIndexForReg(
Reg);
1248 uint64_t FirstInvalidIndex = LocIndex::rawIndexForReg(
Reg + 1);
1249 It.advanceToLowerBound(FirstIndexForReg);
1252 for (; It != End && *It < FirstInvalidIndex; ++It) {
1253 LocIndex ItIdx = LocIndex::fromRawInteger(*It);
1254 const VarLoc &VL = VarLocIDs[ItIdx];
1255 LocIndices LI = VarLocIDs.getAllIndices(VL);
1257 assert(LI.back().Location == LocIndex::kUniversalLocation &&
1258 "Unexpected order of LocIndices for VarLoc; was it inserted into "
1259 "the VarLocMap correctly?");
1260 Collected.insert(LI.back().Index);
1268void VarLocBasedLDV::getUsedRegs(
const VarLocSet &CollectFrom,
1269 SmallVectorImpl<Register> &UsedRegs)
const {
1273 LocIndex::rawIndexForReg(LocIndex::kFirstRegLocation);
1275 LocIndex::rawIndexForReg(LocIndex::kFirstInvalidRegLocation);
1277 LocIndex::rawIndexForReg(LocIndex::kFirstVirtualRegLocation);
1278 auto doGetUsedRegs = [&](VarLocSet::const_iterator &It) {
1281 uint32_t FoundReg = LocIndex::fromRawInteger(*It).Location;
1283 "Duplicate used reg");
1289 uint64_t NextRegIndex = LocIndex::rawIndexForReg(FoundReg + 1);
1290 It.advanceToLowerBound(NextRegIndex);
1292 for (
auto It = CollectFrom.find(FirstRegIndex),
1293 End = CollectFrom.find(FirstInvalidIndex);
1297 for (
auto It = CollectFrom.find(FirstVirtualRegIndex),
1298 End = CollectFrom.end();
1310 const VarLocInMBB &V,
1311 const VarLocMap &VarLocIDs,
1313 raw_ostream &Out)
const {
1314 Out <<
'\n' << msg <<
'\n';
1315 for (
const MachineBasicBlock &BB : MF) {
1318 const VarLocSet &
L = getVarLocsInMBB(&BB, V);
1321 SmallVector<VarLoc, 32> VarLocs;
1322 collectAllVarLocs(VarLocs, L, VarLocIDs);
1323 Out <<
"MBB: " << BB.getNumber() <<
":\n";
1324 for (
const VarLoc &VL : VarLocs) {
1325 Out <<
" Var: " << VL.Var.getVariable()->getName();
1334VarLocBasedLDV::VarLoc::SpillLoc
1335VarLocBasedLDV::extractSpillBaseRegAndOffset(
const MachineInstr &
MI) {
1337 "Spill instruction does not have exactly one memory operand?");
1338 auto MMOI =
MI.memoperands_begin();
1339 const PseudoSourceValue *PVal = (*MMOI)->getPseudoValue();
1341 "Inconsistent memory operand in spill instruction");
1351void VarLocBasedLDV::cleanupEntryValueTransfers(
1352 const MachineInstr *TRInst, OpenRangesSet &OpenRanges, VarLocMap &VarLocIDs,
1353 const VarLoc &EntryVL, InstToEntryLocMap &EntryValTransfers) {
1354 if (EntryValTransfers.empty() || TRInst ==
nullptr)
1357 auto TransRange = EntryValTransfers.equal_range(TRInst);
1359 const VarLoc &EmittedEV = VarLocIDs[TDPair.second];
1360 if (std::tie(EntryVL.Var, EntryVL.Locs[0].Value.RegNo, EntryVL.Expr) ==
1361 std::tie(EmittedEV.Var, EmittedEV.Locs[0].Value.RegNo,
1363 OpenRanges.erase(EmittedEV);
1364 EntryValTransfers.erase(TRInst);
1374void VarLocBasedLDV::removeEntryValue(
const MachineInstr &
MI,
1375 OpenRangesSet &OpenRanges,
1376 VarLocMap &VarLocIDs,
1377 const VarLoc &EntryVL,
1378 InstToEntryLocMap &EntryValTransfers,
1379 RegDefToInstMap &RegSetInstrs) {
1381 if (&
MI == &EntryVL.MI)
1387 if (!
MI.getDebugOperand(0).isReg())
1392 const MachineInstr *TransferInst =
1396 if (!TransferInst && !LastNonDbgMI &&
MI.getParent()->isEntryBlock())
1402 if (
MI.getDebugExpression()->getNumElements() == 0 && TransferInst) {
1409 auto DestSrc =
TII->isCopyLikeInstr(*TransferInst);
1411 const MachineOperand *SrcRegOp, *DestRegOp;
1412 SrcRegOp = DestSrc->Source;
1413 DestRegOp = DestSrc->Destination;
1415 for (
uint64_t ID : OpenRanges.getEntryValueBackupVarLocs()) {
1416 const VarLoc &VL = VarLocIDs[LocIndex::fromRawInteger(ID)];
1417 if (VL.isEntryValueCopyBackupReg(
Reg) &&
1419 VL.MI.getDebugOperand(0).getReg() == SrcRegOp->
getReg())
1430 cleanupEntryValueTransfers(TransferInst, OpenRanges, VarLocIDs, EntryVL,
1432 OpenRanges.erase(EntryVL);
1437void VarLocBasedLDV::transferDebugValue(
const MachineInstr &
MI,
1438 OpenRangesSet &OpenRanges,
1439 VarLocMap &VarLocIDs,
1440 InstToEntryLocMap &EntryValTransfers,
1441 RegDefToInstMap &RegSetInstrs) {
1442 if (!
MI.isDebugValue())
1444 const DILocalVariable *Var =
MI.getDebugVariable();
1445 const DIExpression *Expr =
MI.getDebugExpression();
1446 const DILocation *
DebugLoc =
MI.getDebugLoc();
1447 const DILocation *InlinedAt =
DebugLoc->getInlinedAt();
1449 "Expected inlined-at fields to agree");
1451 DebugVariable
V(Var, Expr, InlinedAt);
1455 auto EntryValBackupID = OpenRanges.getEntryValueBackup(V);
1457 const VarLoc &EntryVL = VarLocIDs[EntryValBackupID->back()];
1458 removeEntryValue(
MI, OpenRanges, VarLocIDs, EntryVL, EntryValTransfers,
1462 if (
all_of(
MI.debug_operands(), [](
const MachineOperand &MO) {
1463 return (MO.isReg() && MO.getReg()) || MO.isImm() || MO.isFPImm() ||
1464 MO.isCImm() || MO.isTargetIndex() || MO.isGlobal();
1470 OpenRanges.erase(VL);
1472 LocIndices IDs = VarLocIDs.insert(VL);
1474 OpenRanges.insert(IDs, VL);
1475 }
else if (
MI.memoperands().size() > 0) {
1476 llvm_unreachable(
"DBG_VALUE with mem operand encountered after regalloc?");
1480 "Unexpected non-undef DBG_VALUE encountered");
1482 OpenRanges.erase(VL);
1487void VarLocBasedLDV::collectAllVarLocs(SmallVectorImpl<VarLoc> &Collected,
1488 const VarLocSet &CollectFrom,
1489 const VarLocMap &VarLocIDs) {
1493 uint64_t FirstIndex = LocIndex::rawIndexForReg(LocIndex::kUniversalLocation);
1495 LocIndex::rawIndexForReg(LocIndex::kUniversalLocation + 1);
1497 for (
auto It = CollectFrom.find(FirstIndex), End = CollectFrom.end();
1498 It != End && *It < FirstInvalidIndex; ++It) {
1499 LocIndex RegIdx = LocIndex::fromRawInteger(*It);
1505void VarLocBasedLDV::emitEntryValues(MachineInstr &
MI,
1506 OpenRangesSet &OpenRanges,
1507 VarLocMap &VarLocIDs,
1508 InstToEntryLocMap &EntryValTransfers,
1509 VarLocsInRange &KillSet) {
1511 if (
MI.isTerminator())
1514 for (uint32_t ID : KillSet) {
1516 LocIndex Idx = LocIndex(LocIndex::kUniversalLocation, ID);
1517 const VarLoc &VL = VarLocIDs[Idx];
1518 if (!VL.Var.getVariable()->isParameter())
1521 auto DebugVar = VL.Var;
1522 std::optional<LocIndices> EntryValBackupIDs =
1523 OpenRanges.getEntryValueBackup(DebugVar);
1527 if (!EntryValBackupIDs)
1530 const VarLoc &EntryVL = VarLocIDs[EntryValBackupIDs->back()];
1531 VarLoc EntryLoc = VarLoc::CreateEntryLoc(EntryVL.MI, EntryVL.Expr,
1532 EntryVL.Locs[0].Value.RegNo);
1533 LocIndices EntryValueIDs = VarLocIDs.insert(EntryLoc);
1534 assert(EntryValueIDs.size() == 1 &&
1535 "EntryValue loc should not be variadic");
1536 EntryValTransfers.insert({&
MI, EntryValueIDs.back()});
1537 OpenRanges.insert(EntryValueIDs, EntryLoc);
1546void VarLocBasedLDV::insertTransferDebugPair(
1547 MachineInstr &
MI, OpenRangesSet &OpenRanges, TransferMap &Transfers,
1548 VarLocMap &VarLocIDs, LocIndex OldVarID, TransferKind Kind,
1549 const VarLoc::MachineLoc &OldLoc,
Register NewReg) {
1550 const VarLoc &OldVarLoc = VarLocIDs[OldVarID];
1552 auto ProcessVarLoc = [&
MI, &OpenRanges, &Transfers, &VarLocIDs](VarLoc &VL) {
1553 LocIndices LocIds = VarLocIDs.insert(VL);
1556 OpenRanges.erase(VL);
1560 OpenRanges.insert(LocIds, VL);
1561 assert(!
MI.isTerminator() &&
"Cannot insert DBG_VALUE after terminator");
1562 TransferDebugPair MIP = {&
MI, LocIds.back()};
1563 Transfers.push_back(MIP);
1567 OpenRanges.erase(VarLocIDs[OldVarID]);
1569 case TransferKind::TransferCopy: {
1571 "No register supplied when handling a copy of a debug value");
1574 VarLoc VL = VarLoc::CreateCopyLoc(OldVarLoc, OldLoc, NewReg);
1577 dbgs() <<
"Creating VarLoc for register copy:";
1582 case TransferKind::TransferSpill: {
1585 VarLoc::SpillLoc SpillLocation = extractSpillBaseRegAndOffset(
MI);
1586 VarLoc VL = VarLoc::CreateSpillLoc(
1587 OldVarLoc, OldLoc, SpillLocation.SpillBase, SpillLocation.SpillOffset);
1590 dbgs() <<
"Creating VarLoc for spill:";
1595 case TransferKind::TransferRestore: {
1597 "No register supplied when handling a restore of a debug value");
1600 VarLoc VL = VarLoc::CreateCopyLoc(OldVarLoc, OldLoc, NewReg);
1603 dbgs() <<
"Creating VarLoc for restore:";
1613void VarLocBasedLDV::transferRegisterDef(MachineInstr &
MI,
1614 OpenRangesSet &OpenRanges,
1615 VarLocMap &VarLocIDs,
1616 InstToEntryLocMap &EntryValTransfers,
1617 RegDefToInstMap &RegSetInstrs) {
1621 if (
MI.isMetaInstruction())
1630 SmallVector<const uint32_t *, 4> RegMasks;
1631 for (
const MachineOperand &MO :
MI.operands()) {
1634 !(
MI.isCall() && MO.
getReg() == SP)) {
1636 for (MCRegAliasIterator RAI(MO.
getReg(),
TRI,
true); RAI.isValid(); ++RAI)
1638 RegSetInstrs.erase(MO.
getReg());
1639 RegSetInstrs.insert({MO.
getReg(), &
MI});
1648 if (!RegMasks.
empty()) {
1650 getUsedRegs(OpenRanges.getVarLocs(), UsedRegs);
1660 bool AnyRegMaskKillsReg =
1661 any_of(RegMasks, [
Reg](
const uint32_t *RegMask) {
1664 if (AnyRegMaskKillsReg)
1666 if (AnyRegMaskKillsReg) {
1667 RegSetInstrs.erase(
Reg);
1668 RegSetInstrs.insert({
Reg, &
MI});
1673 if (DeadRegs.
empty())
1676 VarLocsInRange KillSet;
1677 collectIDsForRegs(KillSet, DeadRegs, OpenRanges.getVarLocs(), VarLocIDs);
1678 OpenRanges.erase(KillSet, VarLocIDs, LocIndex::kUniversalLocation);
1680 if (ShouldEmitDebugEntryValues)
1681 emitEntryValues(
MI, OpenRanges, VarLocIDs, EntryValTransfers, KillSet);
1684void VarLocBasedLDV::transferWasmDef(MachineInstr &
MI,
1685 OpenRangesSet &OpenRanges,
1686 VarLocMap &VarLocIDs) {
1691 if (!
TII->isExplicitTargetIndexDef(
MI, Index,
Offset))
1696 VarLocsInRange KillSet;
1698 for (
uint64_t ID : OpenRanges.getWasmVarLocs()) {
1699 LocIndex Idx = LocIndex::fromRawInteger(ID);
1700 const VarLoc &VL = VarLocIDs[Idx];
1701 assert(VL.containsWasmLocs() &&
"Broken VarLocSet?");
1702 if (VL.usesWasmLoc(Loc))
1705 OpenRanges.erase(KillSet, VarLocIDs, LocIndex::kWasmLocation);
1708bool VarLocBasedLDV::isSpillInstruction(
const MachineInstr &
MI,
1711 if (!
MI.hasOneMemOperand())
1714 if (!
MI.getSpillSize(
TII) && !
MI.getFoldedSpillSize(
TII))
1721bool VarLocBasedLDV::isLocationSpill(
const MachineInstr &
MI,
1723 if (!isSpillInstruction(
MI, MF))
1726 auto isKilledReg = [&](
const MachineOperand MO,
Register &
Reg) {
1735 for (
const MachineOperand &MO :
MI.operands()) {
1738 if (isKilledReg(MO,
Reg))
1744 auto NextI = std::next(
MI.getIterator());
1746 if (
MI.getParent()->end() == NextI)
1749 for (
const MachineOperand &MONext : NextI->operands()) {
1752 if (isKilledReg(MONext, RegNext) && RegNext ==
Reg)
1761std::optional<VarLocBasedLDV::VarLoc::SpillLoc>
1762VarLocBasedLDV::isRestoreInstruction(
const MachineInstr &
MI,
1764 if (!
MI.hasOneMemOperand())
1765 return std::nullopt;
1769 if (
MI.getRestoreSize(
TII)) {
1770 Reg =
MI.getOperand(0).getReg();
1771 return extractSpillBaseRegAndOffset(
MI);
1773 return std::nullopt;
1783void VarLocBasedLDV::transferSpillOrRestoreInst(MachineInstr &
MI,
1784 OpenRangesSet &OpenRanges,
1785 VarLocMap &VarLocIDs,
1786 TransferMap &Transfers) {
1790 std::optional<VarLoc::SpillLoc> Loc;
1797 VarLocsInRange KillSet;
1798 if (isSpillInstruction(
MI, MF)) {
1799 Loc = extractSpillBaseRegAndOffset(
MI);
1800 for (
uint64_t ID : OpenRanges.getSpillVarLocs()) {
1801 LocIndex Idx = LocIndex::fromRawInteger(ID);
1802 const VarLoc &VL = VarLocIDs[Idx];
1803 assert(VL.containsSpillLocs() &&
"Broken VarLocSet?");
1804 if (VL.usesSpillLoc(*Loc)) {
1816 unsigned SpillLocIdx = VL.getSpillLocIdx(*Loc);
1817 VarLoc::MachineLoc OldLoc = VL.Locs[SpillLocIdx];
1818 VarLoc UndefVL = VarLoc::CreateCopyLoc(VL, OldLoc, 0);
1819 LocIndices UndefLocIDs = VarLocIDs.insert(UndefVL);
1820 Transfers.push_back({&
MI, UndefLocIDs.back()});
1823 OpenRanges.erase(KillSet, VarLocIDs, LocIndex::kSpillLocation);
1828 if (isLocationSpill(
MI, MF,
Reg)) {
1829 TKind = TransferKind::TransferSpill;
1834 if (!(Loc = isRestoreInstruction(
MI, MF,
Reg)))
1836 TKind = TransferKind::TransferRestore;
1842 auto TransferCandidates = OpenRanges.getEmptyVarLocRange();
1843 if (TKind == TransferKind::TransferSpill)
1844 TransferCandidates = OpenRanges.getRegisterVarLocs(
Reg);
1845 else if (TKind == TransferKind::TransferRestore)
1846 TransferCandidates = OpenRanges.getSpillVarLocs();
1847 for (
uint64_t ID : TransferCandidates) {
1848 LocIndex Idx = LocIndex::fromRawInteger(ID);
1849 const VarLoc &VL = VarLocIDs[Idx];
1851 if (TKind == TransferKind::TransferSpill) {
1852 assert(VL.usesReg(
Reg) &&
"Broken VarLocSet?");
1854 << VL.Var.getVariable()->getName() <<
")\n");
1855 LocIdx = VL.getRegIdx(
Reg);
1857 assert(TKind == TransferKind::TransferRestore && VL.containsSpillLocs() &&
1858 "Broken VarLocSet?");
1859 if (!VL.usesSpillLoc(*Loc))
1863 << VL.Var.getVariable()->getName() <<
")\n");
1864 LocIdx = VL.getSpillLocIdx(*Loc);
1866 VarLoc::MachineLoc MLoc = VL.Locs[LocIdx];
1867 insertTransferDebugPair(
MI, OpenRanges, Transfers, VarLocIDs, Idx, TKind,
1878void VarLocBasedLDV::transferRegisterCopy(MachineInstr &
MI,
1879 OpenRangesSet &OpenRanges,
1880 VarLocMap &VarLocIDs,
1881 TransferMap &Transfers) {
1882 auto DestSrc =
TII->isCopyLikeInstr(
MI);
1886 const MachineOperand *DestRegOp = DestSrc->Destination;
1887 const MachineOperand *SrcRegOp = DestSrc->Source;
1889 if (!DestRegOp->
isDef())
1893 for (MCRegAliasIterator RAI(
Reg,
TRI,
true); RAI.isValid(); ++RAI)
1894 if (CalleeSavedRegs.
test((*RAI).id()))
1907 if (!isCalleeSavedReg(DestReg))
1914 for (
uint64_t ID : OpenRanges.getEntryValueBackupVarLocs()) {
1915 LocIndex Idx = LocIndex::fromRawInteger(ID);
1916 const VarLoc &VL = VarLocIDs[Idx];
1917 if (VL.isEntryValueBackupReg(SrcReg)) {
1919 VarLoc EntryValLocCopyBackup =
1920 VarLoc::CreateEntryCopyBackupLoc(VL.MI, VL.Expr, DestReg);
1922 OpenRanges.erase(VL);
1925 LocIndices EntryValCopyLocIDs = VarLocIDs.insert(EntryValLocCopyBackup);
1926 OpenRanges.insert(EntryValCopyLocIDs, EntryValLocCopyBackup);
1935 for (
uint64_t ID : OpenRanges.getRegisterVarLocs(SrcReg)) {
1936 LocIndex Idx = LocIndex::fromRawInteger(ID);
1937 assert(VarLocIDs[Idx].usesReg(SrcReg) &&
"Broken VarLocSet?");
1938 VarLoc::MachineLocValue Loc;
1940 VarLoc::MachineLoc MLoc{VarLoc::MachineLocKind::RegisterKind, Loc};
1941 insertTransferDebugPair(
MI, OpenRanges, Transfers, VarLocIDs, Idx,
1942 TransferKind::TransferCopy, MLoc, DestReg);
1950bool VarLocBasedLDV::transferTerminator(MachineBasicBlock *CurMBB,
1951 OpenRangesSet &OpenRanges,
1952 VarLocInMBB &OutLocs,
1953 const VarLocMap &VarLocIDs) {
1957 OpenRanges.getUniqueVarLocs(VarLocs, VarLocIDs);
1958 for (VarLoc &VL : VarLocs) {
1960 dbgs() <<
"Add to OutLocs in MBB #" << CurMBB->
getNumber() <<
": ";
1964 VarLocSet &VLS = getVarLocsInMBB(CurMBB, OutLocs);
1965 Changed = VLS != OpenRanges.getVarLocs();
1969 VLS = OpenRanges.getVarLocs();
1984void VarLocBasedLDV::accumulateFragmentMap(MachineInstr &
MI,
1985 VarToFragments &SeenFragments,
1987 DebugVariable MIVar(
MI.getDebugVariable(),
MI.getDebugExpression(),
1988 MI.getDebugLoc()->getInlinedAt());
1989 FragmentInfo ThisFragment = MIVar.getFragmentOrDefault();
1994 auto [SeenIt,
Inserted] = SeenFragments.try_emplace(MIVar.getVariable());
1996 SeenIt->second.insert(ThisFragment);
1998 OverlappingFragments.insert({{MIVar.getVariable(), ThisFragment}, {}});
2005 OverlappingFragments.insert({{MIVar.getVariable(), ThisFragment}, {}});
2006 if (!IsInOLapMap.second)
2009 auto &ThisFragmentsOverlaps = IsInOLapMap.first->second;
2010 auto &AllSeenFragments = SeenIt->second;
2015 for (
const auto &ASeenFragment : AllSeenFragments) {
2019 ThisFragmentsOverlaps.push_back(ASeenFragment);
2022 auto ASeenFragmentsOverlaps =
2023 OverlappingFragments.find({MIVar.getVariable(), ASeenFragment});
2024 assert(ASeenFragmentsOverlaps != OverlappingFragments.end() &&
2025 "Previously seen var fragment has no vector of overlaps");
2026 ASeenFragmentsOverlaps->second.push_back(ThisFragment);
2030 AllSeenFragments.insert(ThisFragment);
2034void VarLocBasedLDV::process(MachineInstr &
MI, OpenRangesSet &OpenRanges,
2035 VarLocMap &VarLocIDs, TransferMap &Transfers,
2036 InstToEntryLocMap &EntryValTransfers,
2037 RegDefToInstMap &RegSetInstrs) {
2038 if (!
MI.isDebugInstr())
2040 transferDebugValue(
MI, OpenRanges, VarLocIDs, EntryValTransfers,
2042 transferRegisterDef(
MI, OpenRanges, VarLocIDs, EntryValTransfers,
2044 transferWasmDef(
MI, OpenRanges, VarLocIDs);
2045 transferRegisterCopy(
MI, OpenRanges, VarLocIDs, Transfers);
2046 transferSpillOrRestoreInst(
MI, OpenRanges, VarLocIDs, Transfers);
2052bool VarLocBasedLDV::join(
2053 MachineBasicBlock &
MBB, VarLocInMBB &OutLocs, VarLocInMBB &InLocs,
2054 const VarLocMap &VarLocIDs,
2055 SmallPtrSet<const MachineBasicBlock *, 16> &Visited,
2056 SmallPtrSetImpl<const MachineBasicBlock *> &ArtificialBlocks) {
2059 VarLocSet InLocsT(
Alloc);
2070 if (!Visited.
count(p)) {
2071 LLVM_DEBUG(
dbgs() <<
" ignoring unvisited pred MBB: " <<
p->getNumber()
2075 auto OL = OutLocs.find(p);
2077 if (OL == OutLocs.end())
2082 VarLocSet &OutLocVLS = *OL->second;
2084 InLocsT = OutLocVLS;
2086 InLocsT &= OutLocVLS;
2089 if (!InLocsT.empty()) {
2091 collectAllVarLocs(VarLocs, InLocsT, VarLocIDs);
2092 for (
const VarLoc &VL : VarLocs)
2093 dbgs() <<
" gathered candidate incoming var: "
2094 << VL.Var.getVariable()->getName() <<
"\n";
2102 VarLocSet KillSet(
Alloc);
2103 bool IsArtificial = ArtificialBlocks.
count(&
MBB);
2104 if (!IsArtificial) {
2106 LocIndex Idx = LocIndex::fromRawInteger(ID);
2110 auto Name = VarLocIDs[Idx].Var.getVariable()->getName();
2111 dbgs() <<
" killing " <<
Name <<
", it doesn't dominate MBB\n";
2116 InLocsT.intersectWithComplement(KillSet);
2122 "Should have processed at least one predecessor");
2124 VarLocSet &ILS = getVarLocsInMBB(&
MBB, InLocs);
2126 if (ILS != InLocsT) {
2134void VarLocBasedLDV::flushPendingLocs(VarLocInMBB &PendingInLocs,
2135 VarLocMap &VarLocIDs) {
2138 for (
auto &Iter : PendingInLocs) {
2140 auto &
MBB =
const_cast<MachineBasicBlock &
>(*Iter.first);
2141 VarLocSet &Pending = *Iter.second;
2143 SmallVector<VarLoc, 32> VarLocs;
2144 collectAllVarLocs(VarLocs, Pending, VarLocIDs);
2146 for (VarLoc DiffIt : VarLocs) {
2149 if (DiffIt.isEntryBackupLoc())
2160bool VarLocBasedLDV::isEntryValueCandidate(
2161 const MachineInstr &
MI,
const DefinedRegsSet &DefinedRegs)
const {
2162 assert(
MI.isDebugValue() &&
"This must be DBG_VALUE.");
2168 auto *DIVar =
MI.getDebugVariable();
2169 if (!DIVar->isParameter())
2173 if (
MI.getDebugLoc()->getInlinedAt())
2186 if (DefinedRegs.count(
MI.getDebugOperand(0).getReg()))
2192 const DIExpression *Expr =
MI.getDebugExpression();
2204 Regs.insert(MO.
getReg());
2214void VarLocBasedLDV::recordEntryValue(
const MachineInstr &
MI,
2215 const DefinedRegsSet &DefinedRegs,
2216 OpenRangesSet &OpenRanges,
2217 VarLocMap &VarLocIDs) {
2218 if (!ShouldEmitDebugEntryValues)
2221 DebugVariable
V(
MI.getDebugVariable(),
MI.getDebugExpression(),
2222 MI.getDebugLoc()->getInlinedAt());
2224 if (!isEntryValueCandidate(
MI, DefinedRegs) ||
2225 OpenRanges.getEntryValueBackup(V))
2232 DIExpression *NewExpr =
2234 VarLoc EntryValLocAsBackup = VarLoc::CreateEntryBackupLoc(
MI, NewExpr);
2235 LocIndices EntryValLocIDs = VarLocIDs.insert(EntryValLocAsBackup);
2236 OpenRanges.insert(EntryValLocIDs, EntryValLocAsBackup);
2242 MachineDominatorTree *DomTree,
2243 bool ShouldEmitDebugEntryValues,
2245 unsigned InputDbgValLimit) {
2262 this->ShouldEmitDebugEntryValues = ShouldEmitDebugEntryValues;
2264 LS.scanFunction(MF);
2267 bool OLChanged =
false;
2268 bool MBBJoined =
false;
2270 VarLocMap VarLocIDs;
2272 OpenRangesSet OpenRanges(
Alloc, OverlapFragments);
2274 VarLocInMBB OutLocs;
2276 TransferMap Transfers;
2279 InstToEntryLocMap EntryValTransfers;
2281 RegDefToInstMap RegSetInstrs;
2283 VarToFragments SeenFragments;
2287 SmallPtrSet<const MachineBasicBlock *, 16> ArtificialBlocks;
2289 DenseMap<unsigned int, MachineBasicBlock *> OrderToBB;
2290 DenseMap<MachineBasicBlock *, unsigned int> BBToOrder;
2291 std::priority_queue<unsigned int, std::vector<unsigned int>,
2292 std::greater<unsigned int>>
2294 std::priority_queue<unsigned int, std::vector<unsigned int>,
2295 std::greater<unsigned int>>
2300 DefinedRegsSet DefinedRegs;
2304 MachineBasicBlock &First_MBB = *(MF.
begin());
2305 for (
auto &
MI : First_MBB) {
2307 if (
MI.isDebugValue())
2308 recordEntryValue(
MI, DefinedRegs, OpenRanges, VarLocIDs);
2312 for (
auto &
MBB : MF)
2313 for (
auto &
MI :
MBB)
2314 if (
MI.isDebugValue())
2315 accumulateFragmentMap(
MI, SeenFragments, OverlapFragments);
2317 auto hasNonArtificialLocation = [](
const MachineInstr &
MI) ->
bool {
2319 return DL.getLine() != 0;
2322 for (
auto &
MBB : MF)
2326 LLVM_DEBUG(printVarLocInMBB(MF, OutLocs, VarLocIDs,
2327 "OutLocs after initialization",
dbgs()));
2329 ReversePostOrderTraversal<MachineFunction *> RPOT(&MF);
2330 unsigned int RPONumber = 0;
2331 for (MachineBasicBlock *
MBB : RPOT) {
2332 OrderToBB[RPONumber] =
MBB;
2333 BBToOrder[
MBB] = RPONumber;
2334 Worklist.push(RPONumber);
2339 unsigned NumInputDbgValues = 0;
2340 for (
auto &
MBB : MF)
2341 for (
auto &
MI :
MBB)
2342 if (
MI.isDebugValue())
2343 ++NumInputDbgValues;
2344 if (NumInputDbgValues > InputDbgValLimit) {
2345 LLVM_DEBUG(
dbgs() <<
"Disabling VarLocBasedLDV: " << MF.getName()
2346 <<
" has " << RPONumber <<
" basic blocks and "
2347 << NumInputDbgValues
2348 <<
" input DBG_VALUEs, exceeding limits.\n");
2357 SmallPtrSet<const MachineBasicBlock *, 16> Visited;
2358 while (!Worklist.empty() || !Pending.empty()) {
2362 SmallPtrSet<MachineBasicBlock *, 16> OnPending;
2364 while (!Worklist.empty()) {
2365 MachineBasicBlock *
MBB = OrderToBB[Worklist.top()];
2367 MBBJoined =
join(*
MBB, OutLocs, InLocs, VarLocIDs, Visited,
2369 MBBJoined |= Visited.
insert(
MBB).second;
2377 OpenRanges.insertFromLocSet(getVarLocsInMBB(
MBB, InLocs), VarLocIDs);
2378 LastNonDbgMI =
nullptr;
2379 RegSetInstrs.clear();
2386 bool PacketHasTerminator =
false;
2387 for (
auto BI = BStart; BI != BEnd; ++BI) {
2388 if (BI->isTerminator()) {
2389 PacketHasTerminator =
true;
2393 if (PacketHasTerminator) {
2400 auto FirstOp = (BStart->isBundle()) ? std::next(BStart) : BStart;
2401 for (
auto BI = FirstOp; BI != BEnd; ++BI) {
2402 if (BI->isTerminator())
2404 process(*BI, OpenRanges, VarLocIDs, Transfers, EntryValTransfers,
2409 OLChanged |= transferTerminator(
MBB, OpenRanges, OutLocs, VarLocIDs);
2411 LLVM_DEBUG(printVarLocInMBB(MF, OutLocs, VarLocIDs,
2412 "OutLocs after propagating",
dbgs()));
2413 LLVM_DEBUG(printVarLocInMBB(MF, InLocs, VarLocIDs,
2414 "InLocs after propagating",
dbgs()));
2419 if (OnPending.
insert(s).second) {
2420 Pending.push(BBToOrder[s]);
2425 Worklist.swap(Pending);
2428 assert(Pending.empty() &&
"Pending should be empty");
2432 for (
auto &TR : Transfers) {
2433 assert(!
TR.TransferInst->isTerminator() &&
2434 "Cannot insert DBG_VALUE after terminator");
2435 MachineBasicBlock *
MBB =
TR.TransferInst->getParent();
2436 const VarLoc &VL = VarLocIDs[
TR.LocationID];
2437 MachineInstr *
MI = VL.BuildDbgValue(MF);
2443 for (
auto &TR : EntryValTransfers) {
2444 MachineInstr *TRInst =
const_cast<MachineInstr *
>(
TR.first);
2446 "Cannot insert DBG_VALUE after terminator");
2448 const VarLoc &VL = VarLocIDs[
TR.second];
2449 MachineInstr *
MI = VL.BuildDbgValue(MF);
2452 EntryValTransfers.clear();
2456 flushPendingLocs(InLocs, VarLocIDs);
2458 LLVM_DEBUG(printVarLocInMBB(MF, OutLocs, VarLocIDs,
"Final OutLocs",
dbgs()));
2459 LLVM_DEBUG(printVarLocInMBB(MF, InLocs, VarLocIDs,
"Final InLocs",
dbgs()));
2466 return new VarLocBasedLDV();
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static bool isConstant(const MachineInstr &MI)
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
A bitvector that uses an IntervalMap to coalesce adjacent elements into intervals.
This file defines the DenseMap class.
This file contains constants used for implementing Dwarf debug support.
const HexagonInstrInfo * TII
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
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)
Register const TargetRegisterInfo * TRI
Promote Memory to Register
This file builds on the ADT/GraphTraits.h file to build a generic graph post order iterator.
static bool dominates(InstrPosIndexes &PosIndexes, const MachineInstr &A, const MachineInstr &B)
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.
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.
bool empty() const
Check if the array is empty.
bool test(unsigned Idx) const
Returns true if bit Idx is set.
A bitvector that, under the hood, relies on an IntervalMap to coalesce elements into intervals.
unsigned getNumElements() const
DbgVariableFragmentInfo FragmentInfo
static bool fragmentsOverlap(const FragmentInfo &A, const FragmentInfo &B)
Check if fragments overlap between a pair of FragmentInfos.
static LLVM_ABI DIExpression * appendOpsToArg(const DIExpression *Expr, ArrayRef< uint64_t > Ops, unsigned ArgNo, bool StackValue=false)
Create a copy of Expr by appending the given list of Ops to each instance of the operand DW_OP_LLVM_a...
LLVM_ABI bool isDeref() const
Return whether there is exactly one operator and it is a DW_OP_deref;.
static LLVM_ABI 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 LLVM_ABI DIExpression * prepend(const DIExpression *Expr, uint8_t Flags, int64_t Offset=0)
Prepend DIExpr with a deref and offset operation and optionally turn it into a stack value or/and an ...
bool isValidLocationForIntrinsic(const DILocation *DL) const
Check that a location is valid for this 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.
MCRegAliasIterator enumerates all registers aliasing Reg.
instr_iterator instr_begin()
LLVM_ABI instr_iterator insert(instr_iterator I, MachineInstr *M)
Insert MI into the instruction list before I, possibly inside a bundle.
int getNumber() const
MachineBasicBlocks are uniquely numbered at the function level, unless they're not in a MachineFuncti...
instr_iterator instr_end()
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,...
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)
Wrapper class representing virtual and physical registers.
constexpr bool isValid() const
constexpr unsigned id() const
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
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.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
iterator erase(const_iterator CI)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
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...
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...
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual const TargetFrameLowering * getFrameLowering() const
virtual const TargetInstrInfo * getInstrInfo() const
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
virtual const TargetLowering * getTargetLowering() const
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
DenseMap< FragmentOfVar, SmallVector< DIExpression::FragmentInfo, 1 > > OverlapMap
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.
MachineBasicBlock::instr_iterator getBundleStart(MachineBasicBlock::instr_iterator I)
Returns an iterator to the first instruction in the bundle containing I.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
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.
auto unique(Range &&R, Predicate P)
bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
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.
void sort(IteratorTy Start, IteratorTy End)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool none_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly.
MachineBasicBlock::instr_iterator getBundleEnd(MachineBasicBlock::instr_iterator I)
Returns an iterator pointing beyond the bundle containing I.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
LDVImpl * makeVarLocBasedLiveDebugValues()
iterator_range(Container &&) -> iterator_range< llvm::detail::IterOfRange< Container > >
std::string join(IteratorT Begin, IteratorT End, StringRef Separator)
Joins the strings in the range [Begin, End), adding Separator between the elements.
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
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.
LLVM_ABI 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.