137#include "llvm/Config/llvm-config.h"
159#define DEBUG_TYPE "live-debug-values"
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 &&
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) {
1237 if (CollectFrom.empty())
1243 auto It = CollectFrom.find(LocIndex::rawIndexForReg(SortedRegs.
front()));
1244 auto End = CollectFrom.end();
1249 uint64_t FirstIndexForReg = LocIndex::rawIndexForReg(
Reg);
1250 uint64_t FirstInvalidIndex = LocIndex::rawIndexForReg(
Reg + 1);
1251 It.advanceToLowerBound(FirstIndexForReg);
1254 for (; It !=
End && *It < FirstInvalidIndex; ++It) {
1255 LocIndex ItIdx = LocIndex::fromRawInteger(*It);
1256 const VarLoc &VL = VarLocIDs[ItIdx];
1257 LocIndices LI = VarLocIDs.getAllIndices(VL);
1259 assert(LI.back().Location == LocIndex::kUniversalLocation &&
1260 "Unexpected order of LocIndices for VarLoc; was it inserted into "
1261 "the VarLocMap correctly?");
1262 Collected.insert(LI.back().Index);
1270void VarLocBasedLDV::getUsedRegs(
const VarLocSet &CollectFrom,
1271 SmallVectorImpl<Register> &UsedRegs)
const {
1275 LocIndex::rawIndexForReg(LocIndex::kFirstRegLocation);
1277 LocIndex::rawIndexForReg(LocIndex::kFirstInvalidRegLocation);
1279 LocIndex::rawIndexForReg(LocIndex::kFirstVirtualRegLocation);
1280 auto doGetUsedRegs = [&](VarLocSet::const_iterator &It) {
1283 uint32_t FoundReg = LocIndex::fromRawInteger(*It).Location;
1285 "Duplicate used reg");
1291 uint64_t NextRegIndex = LocIndex::rawIndexForReg(FoundReg + 1);
1292 It.advanceToLowerBound(NextRegIndex);
1294 for (
auto It = CollectFrom.find(FirstRegIndex),
1295 End = CollectFrom.find(FirstInvalidIndex);
1299 for (
auto It = CollectFrom.find(FirstVirtualRegIndex),
1300 End = CollectFrom.end();
1312 const VarLocInMBB &V,
1313 const VarLocMap &VarLocIDs,
1315 raw_ostream &Out)
const {
1316 Out <<
'\n' << msg <<
'\n';
1317 for (
const MachineBasicBlock &BB : MF) {
1320 const VarLocSet &
L = getVarLocsInMBB(&BB, V);
1323 SmallVector<VarLoc, 32> VarLocs;
1324 collectAllVarLocs(VarLocs, L, VarLocIDs);
1325 Out <<
"MBB: " << BB.getNumber() <<
":\n";
1326 for (
const VarLoc &VL : VarLocs) {
1327 Out <<
" Var: " << VL.Var.getVariable()->getName();
1336VarLocBasedLDV::VarLoc::SpillLoc
1337VarLocBasedLDV::extractSpillBaseRegAndOffset(
const MachineInstr &
MI) {
1339 "Spill instruction does not have exactly one memory operand?");
1340 auto MMOI =
MI.memoperands_begin();
1341 const PseudoSourceValue *PVal = (*MMOI)->getPseudoValue();
1343 "Inconsistent memory operand in spill instruction");
1353void VarLocBasedLDV::cleanupEntryValueTransfers(
1354 const MachineInstr *TRInst, OpenRangesSet &OpenRanges, VarLocMap &VarLocIDs,
1355 const VarLoc &EntryVL, InstToEntryLocMap &EntryValTransfers) {
1356 if (EntryValTransfers.empty() || TRInst ==
nullptr)
1359 auto TransRange = EntryValTransfers.equal_range(TRInst);
1361 const VarLoc &EmittedEV = VarLocIDs[TDPair.second];
1362 if (std::tie(EntryVL.Var, EntryVL.Locs[0].Value.RegNo, EntryVL.Expr) ==
1363 std::tie(EmittedEV.Var, EmittedEV.Locs[0].Value.RegNo,
1365 OpenRanges.erase(EmittedEV);
1366 EntryValTransfers.erase(TRInst);
1376void VarLocBasedLDV::removeEntryValue(
const MachineInstr &
MI,
1377 OpenRangesSet &OpenRanges,
1378 VarLocMap &VarLocIDs,
1379 const VarLoc &EntryVL,
1380 InstToEntryLocMap &EntryValTransfers,
1381 RegDefToInstMap &RegSetInstrs) {
1383 if (&
MI == &EntryVL.MI)
1389 if (!
MI.getDebugOperand(0).isReg())
1394 const MachineInstr *TransferInst =
1398 if (!TransferInst && !LastNonDbgMI &&
MI.getParent()->isEntryBlock())
1404 if (
MI.getDebugExpression()->getNumElements() == 0 && TransferInst) {
1411 auto DestSrc =
TII->isCopyLikeInstr(*TransferInst);
1413 const MachineOperand *SrcRegOp, *DestRegOp;
1414 SrcRegOp = DestSrc->Source;
1415 DestRegOp = DestSrc->Destination;
1417 for (
uint64_t ID : OpenRanges.getEntryValueBackupVarLocs()) {
1418 const VarLoc &VL = VarLocIDs[LocIndex::fromRawInteger(ID)];
1419 if (VL.isEntryValueCopyBackupReg(
Reg) &&
1421 VL.MI.getDebugOperand(0).getReg() == SrcRegOp->
getReg())
1432 cleanupEntryValueTransfers(TransferInst, OpenRanges, VarLocIDs, EntryVL,
1434 OpenRanges.erase(EntryVL);
1439void VarLocBasedLDV::transferDebugValue(
const MachineInstr &
MI,
1440 OpenRangesSet &OpenRanges,
1441 VarLocMap &VarLocIDs,
1442 InstToEntryLocMap &EntryValTransfers,
1443 RegDefToInstMap &RegSetInstrs) {
1444 if (!
MI.isDebugValue())
1446 const DILocalVariable *Var =
MI.getDebugVariable();
1447 const DIExpression *Expr =
MI.getDebugExpression();
1448 const DILocation *
DebugLoc =
MI.getDebugLoc();
1449 const DILocation *InlinedAt =
DebugLoc->getInlinedAt();
1451 "Expected inlined-at fields to agree");
1453 DebugVariable
V(Var, Expr, InlinedAt);
1457 auto EntryValBackupID = OpenRanges.getEntryValueBackup(V);
1459 const VarLoc &EntryVL = VarLocIDs[EntryValBackupID->back()];
1460 removeEntryValue(
MI, OpenRanges, VarLocIDs, EntryVL, EntryValTransfers,
1464 if (
all_of(
MI.debug_operands(), [](
const MachineOperand &MO) {
1465 return (MO.isReg() && MO.getReg()) || MO.isImm() || MO.isFPImm() ||
1466 MO.isCImm() || MO.isTargetIndex() || MO.isGlobal();
1472 OpenRanges.erase(VL);
1474 LocIndices IDs = VarLocIDs.insert(VL);
1476 OpenRanges.insert(IDs, VL);
1477 }
else if (
MI.memoperands().size() > 0) {
1478 llvm_unreachable(
"DBG_VALUE with mem operand encountered after regalloc?");
1482 "Unexpected non-undef DBG_VALUE encountered");
1484 OpenRanges.erase(VL);
1489void VarLocBasedLDV::collectAllVarLocs(SmallVectorImpl<VarLoc> &Collected,
1490 const VarLocSet &CollectFrom,
1491 const VarLocMap &VarLocIDs) {
1495 uint64_t FirstIndex = LocIndex::rawIndexForReg(LocIndex::kUniversalLocation);
1497 LocIndex::rawIndexForReg(LocIndex::kUniversalLocation + 1);
1499 for (
auto It = CollectFrom.find(FirstIndex),
End = CollectFrom.end();
1500 It !=
End && *It < FirstInvalidIndex; ++It) {
1501 LocIndex RegIdx = LocIndex::fromRawInteger(*It);
1507void VarLocBasedLDV::emitEntryValues(MachineInstr &
MI,
1508 OpenRangesSet &OpenRanges,
1509 VarLocMap &VarLocIDs,
1510 InstToEntryLocMap &EntryValTransfers,
1511 VarLocsInRange &KillSet) {
1513 if (
MI.isTerminator())
1516 for (uint32_t ID : KillSet) {
1518 LocIndex
Idx = LocIndex(LocIndex::kUniversalLocation, ID);
1519 const VarLoc &VL = VarLocIDs[
Idx];
1520 if (!VL.Var.getVariable()->isParameter())
1523 auto DebugVar = VL.Var;
1524 std::optional<LocIndices> EntryValBackupIDs =
1525 OpenRanges.getEntryValueBackup(DebugVar);
1529 if (!EntryValBackupIDs)
1532 const VarLoc &EntryVL = VarLocIDs[EntryValBackupIDs->back()];
1533 VarLoc EntryLoc = VarLoc::CreateEntryLoc(EntryVL.MI, EntryVL.Expr,
1534 EntryVL.Locs[0].Value.RegNo);
1535 LocIndices EntryValueIDs = VarLocIDs.insert(EntryLoc);
1536 assert(EntryValueIDs.size() == 1 &&
1537 "EntryValue loc should not be variadic");
1538 EntryValTransfers.insert({&
MI, EntryValueIDs.back()});
1539 OpenRanges.insert(EntryValueIDs, EntryLoc);
1548void VarLocBasedLDV::insertTransferDebugPair(
1549 MachineInstr &
MI, OpenRangesSet &OpenRanges, TransferMap &Transfers,
1550 VarLocMap &VarLocIDs, LocIndex OldVarID, TransferKind Kind,
1551 const VarLoc::MachineLoc &OldLoc,
Register NewReg) {
1552 const VarLoc &OldVarLoc = VarLocIDs[OldVarID];
1554 auto ProcessVarLoc = [&
MI, &OpenRanges, &Transfers, &VarLocIDs](VarLoc &VL) {
1555 LocIndices LocIds = VarLocIDs.insert(VL);
1558 OpenRanges.erase(VL);
1562 OpenRanges.insert(LocIds, VL);
1563 assert(!
MI.isTerminator() &&
"Cannot insert DBG_VALUE after terminator");
1564 TransferDebugPair MIP = {&
MI, LocIds.back()};
1565 Transfers.push_back(MIP);
1569 OpenRanges.erase(VarLocIDs[OldVarID]);
1571 case TransferKind::TransferCopy: {
1573 "No register supplied when handling a copy of a debug value");
1576 VarLoc VL = VarLoc::CreateCopyLoc(OldVarLoc, OldLoc, NewReg);
1579 dbgs() <<
"Creating VarLoc for register copy:";
1584 case TransferKind::TransferSpill: {
1587 VarLoc::SpillLoc SpillLocation = extractSpillBaseRegAndOffset(
MI);
1588 VarLoc VL = VarLoc::CreateSpillLoc(
1589 OldVarLoc, OldLoc, SpillLocation.SpillBase, SpillLocation.SpillOffset);
1592 dbgs() <<
"Creating VarLoc for spill:";
1597 case TransferKind::TransferRestore: {
1599 "No register supplied when handling a restore of a debug value");
1602 VarLoc VL = VarLoc::CreateCopyLoc(OldVarLoc, OldLoc, NewReg);
1605 dbgs() <<
"Creating VarLoc for restore:";
1615void VarLocBasedLDV::transferRegisterDef(MachineInstr &
MI,
1616 OpenRangesSet &OpenRanges,
1617 VarLocMap &VarLocIDs,
1618 InstToEntryLocMap &EntryValTransfers,
1619 RegDefToInstMap &RegSetInstrs) {
1623 if (
MI.isMetaInstruction())
1632 SmallVector<const uint32_t *, 4> RegMasks;
1633 for (
const MachineOperand &MO :
MI.operands()) {
1636 !(
MI.isCall() && MO.
getReg() == SP)) {
1638 for (MCRegAliasIterator RAI(MO.
getReg(),
TRI,
true); RAI.isValid(); ++RAI)
1640 RegSetInstrs.erase(MO.
getReg());
1641 RegSetInstrs.insert({MO.
getReg(), &
MI});
1650 if (!RegMasks.
empty()) {
1652 getUsedRegs(OpenRanges.getVarLocs(), UsedRegs);
1662 bool AnyRegMaskKillsReg =
1663 any_of(RegMasks, [
Reg](
const uint32_t *RegMask) {
1666 if (AnyRegMaskKillsReg)
1668 if (AnyRegMaskKillsReg) {
1669 RegSetInstrs.erase(
Reg);
1670 RegSetInstrs.insert({
Reg, &
MI});
1675 if (DeadRegs.
empty())
1678 VarLocsInRange KillSet;
1679 collectIDsForRegs(KillSet, DeadRegs, OpenRanges.getVarLocs(), VarLocIDs);
1680 OpenRanges.erase(KillSet, VarLocIDs, LocIndex::kUniversalLocation);
1682 if (ShouldEmitDebugEntryValues)
1683 emitEntryValues(
MI, OpenRanges, VarLocIDs, EntryValTransfers, KillSet);
1686void VarLocBasedLDV::transferWasmDef(MachineInstr &
MI,
1687 OpenRangesSet &OpenRanges,
1688 VarLocMap &VarLocIDs) {
1693 if (!
TII->isExplicitTargetIndexDef(
MI, Index,
Offset))
1698 VarLocsInRange KillSet;
1700 for (
uint64_t ID : OpenRanges.getWasmVarLocs()) {
1701 LocIndex
Idx = LocIndex::fromRawInteger(ID);
1702 const VarLoc &VL = VarLocIDs[
Idx];
1703 assert(VL.containsWasmLocs() &&
"Broken VarLocSet?");
1704 if (VL.usesWasmLoc(Loc))
1707 OpenRanges.erase(KillSet, VarLocIDs, LocIndex::kWasmLocation);
1710bool VarLocBasedLDV::isSpillInstruction(
const MachineInstr &
MI,
1713 if (!
MI.hasOneMemOperand())
1716 if (!
MI.getSpillSize(
TII) && !
MI.getFoldedSpillSize(
TII))
1723bool VarLocBasedLDV::isLocationSpill(
const MachineInstr &
MI,
1725 if (!isSpillInstruction(
MI, MF))
1728 auto isKilledReg = [&](
const MachineOperand MO,
Register &
Reg) {
1737 for (
const MachineOperand &MO :
MI.operands()) {
1740 if (isKilledReg(MO,
Reg))
1746 auto NextI = std::next(
MI.getIterator());
1748 if (
MI.getParent()->end() == NextI)
1751 for (
const MachineOperand &MONext : NextI->operands()) {
1754 if (isKilledReg(MONext, RegNext) && RegNext ==
Reg)
1763std::optional<VarLocBasedLDV::VarLoc::SpillLoc>
1764VarLocBasedLDV::isRestoreInstruction(
const MachineInstr &
MI,
1766 if (!
MI.hasOneMemOperand())
1767 return std::nullopt;
1771 if (
MI.getRestoreSize(
TII)) {
1772 Reg =
MI.getOperand(0).getReg();
1773 return extractSpillBaseRegAndOffset(
MI);
1775 return std::nullopt;
1785void VarLocBasedLDV::transferSpillOrRestoreInst(MachineInstr &
MI,
1786 OpenRangesSet &OpenRanges,
1787 VarLocMap &VarLocIDs,
1788 TransferMap &Transfers) {
1792 std::optional<VarLoc::SpillLoc> Loc;
1799 VarLocsInRange KillSet;
1800 if (isSpillInstruction(
MI, MF)) {
1801 Loc = extractSpillBaseRegAndOffset(
MI);
1802 for (
uint64_t ID : OpenRanges.getSpillVarLocs()) {
1803 LocIndex
Idx = LocIndex::fromRawInteger(ID);
1804 const VarLoc &VL = VarLocIDs[
Idx];
1805 assert(VL.containsSpillLocs() &&
"Broken VarLocSet?");
1806 if (VL.usesSpillLoc(*Loc)) {
1818 unsigned SpillLocIdx = VL.getSpillLocIdx(*Loc);
1819 VarLoc::MachineLoc OldLoc = VL.Locs[SpillLocIdx];
1820 VarLoc UndefVL = VarLoc::CreateCopyLoc(VL, OldLoc, 0);
1821 LocIndices UndefLocIDs = VarLocIDs.insert(UndefVL);
1822 Transfers.push_back({&
MI, UndefLocIDs.back()});
1825 OpenRanges.erase(KillSet, VarLocIDs, LocIndex::kSpillLocation);
1830 if (isLocationSpill(
MI, MF,
Reg)) {
1831 TKind = TransferKind::TransferSpill;
1836 if (!(Loc = isRestoreInstruction(
MI, MF,
Reg)))
1838 TKind = TransferKind::TransferRestore;
1844 auto TransferCandidates = OpenRanges.getEmptyVarLocRange();
1845 if (TKind == TransferKind::TransferSpill)
1846 TransferCandidates = OpenRanges.getRegisterVarLocs(
Reg);
1847 else if (TKind == TransferKind::TransferRestore)
1848 TransferCandidates = OpenRanges.getSpillVarLocs();
1849 for (
uint64_t ID : TransferCandidates) {
1850 LocIndex
Idx = LocIndex::fromRawInteger(ID);
1851 const VarLoc &VL = VarLocIDs[
Idx];
1853 if (TKind == TransferKind::TransferSpill) {
1854 assert(VL.usesReg(
Reg) &&
"Broken VarLocSet?");
1856 << VL.Var.getVariable()->getName() <<
")\n");
1857 LocIdx = VL.getRegIdx(
Reg);
1859 assert(TKind == TransferKind::TransferRestore && VL.containsSpillLocs() &&
1860 "Broken VarLocSet?");
1861 if (!VL.usesSpillLoc(*Loc))
1865 << VL.Var.getVariable()->getName() <<
")\n");
1866 LocIdx = VL.getSpillLocIdx(*Loc);
1868 VarLoc::MachineLoc MLoc = VL.Locs[LocIdx];
1869 insertTransferDebugPair(
MI, OpenRanges, Transfers, VarLocIDs, Idx, TKind,
1880void VarLocBasedLDV::transferRegisterCopy(MachineInstr &
MI,
1881 OpenRangesSet &OpenRanges,
1882 VarLocMap &VarLocIDs,
1883 TransferMap &Transfers) {
1884 auto DestSrc =
TII->isCopyLikeInstr(
MI);
1888 const MachineOperand *DestRegOp = DestSrc->Destination;
1889 const MachineOperand *SrcRegOp = DestSrc->Source;
1891 if (!DestRegOp->
isDef())
1895 for (MCRegAliasIterator RAI(
Reg,
TRI,
true); RAI.isValid(); ++RAI)
1896 if (CalleeSavedRegs.
test((*RAI).id()))
1909 if (!isCalleeSavedReg(DestReg))
1916 for (
uint64_t ID : OpenRanges.getEntryValueBackupVarLocs()) {
1917 LocIndex
Idx = LocIndex::fromRawInteger(ID);
1918 const VarLoc &VL = VarLocIDs[
Idx];
1919 if (VL.isEntryValueBackupReg(SrcReg)) {
1921 VarLoc EntryValLocCopyBackup =
1922 VarLoc::CreateEntryCopyBackupLoc(VL.MI, VL.Expr, DestReg);
1924 OpenRanges.erase(VL);
1927 LocIndices EntryValCopyLocIDs = VarLocIDs.insert(EntryValLocCopyBackup);
1928 OpenRanges.insert(EntryValCopyLocIDs, EntryValLocCopyBackup);
1937 for (
uint64_t ID : OpenRanges.getRegisterVarLocs(SrcReg)) {
1938 LocIndex
Idx = LocIndex::fromRawInteger(ID);
1939 assert(VarLocIDs[Idx].usesReg(SrcReg) &&
"Broken VarLocSet?");
1940 VarLoc::MachineLocValue Loc;
1942 VarLoc::MachineLoc MLoc{VarLoc::MachineLocKind::RegisterKind, Loc};
1943 insertTransferDebugPair(
MI, OpenRanges, Transfers, VarLocIDs, Idx,
1944 TransferKind::TransferCopy, MLoc, DestReg);
1952bool VarLocBasedLDV::transferTerminator(MachineBasicBlock *CurMBB,
1953 OpenRangesSet &OpenRanges,
1954 VarLocInMBB &OutLocs,
1955 const VarLocMap &VarLocIDs) {
1959 OpenRanges.getUniqueVarLocs(VarLocs, VarLocIDs);
1960 for (VarLoc &VL : VarLocs) {
1962 dbgs() <<
"Add to OutLocs in MBB #" << CurMBB->
getNumber() <<
": ";
1966 VarLocSet &VLS = getVarLocsInMBB(CurMBB, OutLocs);
1967 Changed = VLS != OpenRanges.getVarLocs();
1971 VLS = OpenRanges.getVarLocs();
1986void VarLocBasedLDV::accumulateFragmentMap(MachineInstr &
MI,
1987 VarToFragments &SeenFragments,
1989 DebugVariable MIVar(
MI.getDebugVariable(),
MI.getDebugExpression(),
1990 MI.getDebugLoc()->getInlinedAt());
1991 FragmentInfo ThisFragment = MIVar.getFragmentOrDefault();
1996 auto [SeenIt,
Inserted] = SeenFragments.try_emplace(MIVar.getVariable());
1998 SeenIt->second.insert(ThisFragment);
2000 OverlappingFragments.insert({{MIVar.getVariable(), ThisFragment}, {}});
2007 OverlappingFragments.insert({{MIVar.getVariable(), ThisFragment}, {}});
2008 if (!IsInOLapMap.second)
2011 auto &ThisFragmentsOverlaps = IsInOLapMap.first->second;
2012 auto &AllSeenFragments = SeenIt->second;
2017 for (
const auto &ASeenFragment : AllSeenFragments) {
2021 ThisFragmentsOverlaps.push_back(ASeenFragment);
2024 auto ASeenFragmentsOverlaps =
2025 OverlappingFragments.find({MIVar.getVariable(), ASeenFragment});
2026 assert(ASeenFragmentsOverlaps != OverlappingFragments.end() &&
2027 "Previously seen var fragment has no vector of overlaps");
2028 ASeenFragmentsOverlaps->second.push_back(ThisFragment);
2032 AllSeenFragments.insert(ThisFragment);
2036void VarLocBasedLDV::process(MachineInstr &
MI, OpenRangesSet &OpenRanges,
2037 VarLocMap &VarLocIDs, TransferMap &Transfers,
2038 InstToEntryLocMap &EntryValTransfers,
2039 RegDefToInstMap &RegSetInstrs) {
2040 if (!
MI.isDebugInstr())
2042 transferDebugValue(
MI, OpenRanges, VarLocIDs, EntryValTransfers,
2044 transferRegisterDef(
MI, OpenRanges, VarLocIDs, EntryValTransfers,
2046 transferWasmDef(
MI, OpenRanges, VarLocIDs);
2047 transferRegisterCopy(
MI, OpenRanges, VarLocIDs, Transfers);
2048 transferSpillOrRestoreInst(
MI, OpenRanges, VarLocIDs, Transfers);
2054bool VarLocBasedLDV::join(
2055 MachineBasicBlock &
MBB, VarLocInMBB &OutLocs, VarLocInMBB &InLocs,
2056 const VarLocMap &VarLocIDs,
2057 SmallPtrSet<const MachineBasicBlock *, 16> &Visited,
2058 SmallPtrSetImpl<const MachineBasicBlock *> &ArtificialBlocks) {
2061 VarLocSet InLocsT(
Alloc);
2072 if (!Visited.
count(p)) {
2073 LLVM_DEBUG(
dbgs() <<
" ignoring unvisited pred MBB: " <<
p->getNumber()
2077 auto OL = OutLocs.find(p);
2079 if (OL == OutLocs.end())
2084 VarLocSet &OutLocVLS = *OL->second;
2086 InLocsT = OutLocVLS;
2088 InLocsT &= OutLocVLS;
2091 if (!InLocsT.empty()) {
2093 collectAllVarLocs(VarLocs, InLocsT, VarLocIDs);
2094 for (
const VarLoc &VL : VarLocs)
2095 dbgs() <<
" gathered candidate incoming var: "
2096 << VL.Var.getVariable()->getName() <<
"\n";
2104 VarLocSet KillSet(
Alloc);
2105 bool IsArtificial = ArtificialBlocks.
count(&
MBB);
2106 if (!IsArtificial) {
2108 LocIndex
Idx = LocIndex::fromRawInteger(ID);
2112 auto Name = VarLocIDs[
Idx].Var.getVariable()->getName();
2113 dbgs() <<
" killing " <<
Name <<
", it doesn't dominate MBB\n";
2118 InLocsT.intersectWithComplement(KillSet);
2124 "Should have processed at least one predecessor");
2126 VarLocSet &ILS = getVarLocsInMBB(&
MBB, InLocs);
2128 if (ILS != InLocsT) {
2136void VarLocBasedLDV::flushPendingLocs(VarLocInMBB &PendingInLocs,
2137 VarLocMap &VarLocIDs) {
2140 for (
auto &Iter : PendingInLocs) {
2142 auto &
MBB =
const_cast<MachineBasicBlock &
>(*Iter.first);
2143 VarLocSet &Pending = *Iter.second;
2145 SmallVector<VarLoc, 32> VarLocs;
2146 collectAllVarLocs(VarLocs, Pending, VarLocIDs);
2148 for (VarLoc DiffIt : VarLocs) {
2151 if (DiffIt.isEntryBackupLoc())
2162bool VarLocBasedLDV::isEntryValueCandidate(
2163 const MachineInstr &
MI,
const DefinedRegsSet &DefinedRegs)
const {
2164 assert(
MI.isDebugValue() &&
"This must be DBG_VALUE.");
2170 auto *DIVar =
MI.getDebugVariable();
2171 if (!DIVar->isParameter())
2175 if (
MI.getDebugLoc()->getInlinedAt())
2188 if (DefinedRegs.count(
MI.getDebugOperand(0).getReg()))
2194 const DIExpression *Expr =
MI.getDebugExpression();
2206 Regs.insert(MO.
getReg());
2216void VarLocBasedLDV::recordEntryValue(
const MachineInstr &
MI,
2217 const DefinedRegsSet &DefinedRegs,
2218 OpenRangesSet &OpenRanges,
2219 VarLocMap &VarLocIDs) {
2220 if (!ShouldEmitDebugEntryValues)
2223 DebugVariable
V(
MI.getDebugVariable(),
MI.getDebugExpression(),
2224 MI.getDebugLoc()->getInlinedAt());
2226 if (!isEntryValueCandidate(
MI, DefinedRegs) ||
2227 OpenRanges.getEntryValueBackup(V))
2234 DIExpression *NewExpr =
2236 VarLoc EntryValLocAsBackup = VarLoc::CreateEntryBackupLoc(
MI, NewExpr);
2237 LocIndices EntryValLocIDs = VarLocIDs.insert(EntryValLocAsBackup);
2238 OpenRanges.insert(EntryValLocIDs, EntryValLocAsBackup);
2244 MachineDominatorTree *DomTree,
2245 bool ShouldEmitDebugEntryValues,
2247 unsigned InputDbgValLimit) {
2264 this->ShouldEmitDebugEntryValues = ShouldEmitDebugEntryValues;
2266 LS.scanFunction(MF);
2269 bool OLChanged =
false;
2270 bool MBBJoined =
false;
2272 VarLocMap VarLocIDs;
2274 OpenRangesSet OpenRanges(
Alloc, OverlapFragments);
2276 VarLocInMBB OutLocs;
2278 TransferMap Transfers;
2281 InstToEntryLocMap EntryValTransfers;
2283 RegDefToInstMap RegSetInstrs;
2285 VarToFragments SeenFragments;
2289 SmallPtrSet<const MachineBasicBlock *, 16> ArtificialBlocks;
2291 DenseMap<unsigned int, MachineBasicBlock *> OrderToBB;
2292 DenseMap<MachineBasicBlock *, unsigned int> BBToOrder;
2293 std::priority_queue<unsigned int, std::vector<unsigned int>,
2294 std::greater<unsigned int>>
2296 std::priority_queue<unsigned int, std::vector<unsigned int>,
2297 std::greater<unsigned int>>
2302 DefinedRegsSet DefinedRegs;
2306 MachineBasicBlock &First_MBB = *(MF.
begin());
2307 for (
auto &
MI : First_MBB) {
2309 if (
MI.isDebugValue())
2310 recordEntryValue(
MI, DefinedRegs, OpenRanges, VarLocIDs);
2314 for (
auto &
MBB : MF)
2315 for (
auto &
MI :
MBB)
2316 if (
MI.isDebugValue())
2317 accumulateFragmentMap(
MI, SeenFragments, OverlapFragments);
2319 auto hasNonArtificialLocation = [](
const MachineInstr &
MI) ->
bool {
2321 return DL.getLine() != 0;
2324 for (
auto &
MBB : MF)
2328 LLVM_DEBUG(printVarLocInMBB(MF, OutLocs, VarLocIDs,
2329 "OutLocs after initialization",
dbgs()));
2331 ReversePostOrderTraversal<MachineFunction *> RPOT(&MF);
2332 unsigned int RPONumber = 0;
2333 for (MachineBasicBlock *
MBB : RPOT) {
2334 OrderToBB[RPONumber] =
MBB;
2335 BBToOrder[
MBB] = RPONumber;
2336 Worklist.push(RPONumber);
2341 unsigned NumInputDbgValues = 0;
2342 for (
auto &
MBB : MF)
2343 for (
auto &
MI :
MBB)
2344 if (
MI.isDebugValue())
2345 ++NumInputDbgValues;
2346 if (NumInputDbgValues > InputDbgValLimit) {
2347 LLVM_DEBUG(
dbgs() <<
"Disabling VarLocBasedLDV: " << MF.getName()
2348 <<
" has " << RPONumber <<
" basic blocks and "
2349 << NumInputDbgValues
2350 <<
" input DBG_VALUEs, exceeding limits.\n");
2359 SmallPtrSet<const MachineBasicBlock *, 16> Visited;
2360 while (!Worklist.empty() || !Pending.empty()) {
2364 SmallPtrSet<MachineBasicBlock *, 16> OnPending;
2366 while (!Worklist.empty()) {
2367 MachineBasicBlock *
MBB = OrderToBB[Worklist.top()];
2369 MBBJoined =
join(*
MBB, OutLocs, InLocs, VarLocIDs, Visited,
2371 MBBJoined |= Visited.
insert(
MBB).second;
2379 OpenRanges.insertFromLocSet(getVarLocsInMBB(
MBB, InLocs), VarLocIDs);
2380 LastNonDbgMI =
nullptr;
2381 RegSetInstrs.clear();
2388 bool PacketHasTerminator =
false;
2389 for (
auto BI = BStart; BI != BEnd; ++BI) {
2390 if (BI->isTerminator()) {
2391 PacketHasTerminator =
true;
2395 if (PacketHasTerminator) {
2402 auto FirstOp = (BStart->isBundle()) ? std::next(BStart) : BStart;
2403 for (
auto BI = FirstOp; BI != BEnd; ++BI) {
2404 if (BI->isTerminator())
2406 process(*BI, OpenRanges, VarLocIDs, Transfers, EntryValTransfers,
2411 OLChanged |= transferTerminator(
MBB, OpenRanges, OutLocs, VarLocIDs);
2413 LLVM_DEBUG(printVarLocInMBB(MF, OutLocs, VarLocIDs,
2414 "OutLocs after propagating",
dbgs()));
2415 LLVM_DEBUG(printVarLocInMBB(MF, InLocs, VarLocIDs,
2416 "InLocs after propagating",
dbgs()));
2421 if (OnPending.
insert(s).second) {
2422 Pending.push(BBToOrder[s]);
2427 Worklist.swap(Pending);
2430 assert(Pending.empty() &&
"Pending should be empty");
2434 for (
auto &TR : Transfers) {
2435 assert(!
TR.TransferInst->isTerminator() &&
2436 "Cannot insert DBG_VALUE after terminator");
2437 MachineBasicBlock *
MBB =
TR.TransferInst->getParent();
2438 const VarLoc &VL = VarLocIDs[
TR.LocationID];
2439 MachineInstr *
MI = VL.BuildDbgValue(MF);
2445 for (
auto &TR : EntryValTransfers) {
2446 MachineInstr *TRInst =
const_cast<MachineInstr *
>(
TR.first);
2448 "Cannot insert DBG_VALUE after terminator");
2450 const VarLoc &VL = VarLocIDs[
TR.second];
2451 MachineInstr *
MI = VL.BuildDbgValue(MF);
2454 EntryValTransfers.clear();
2458 flushPendingLocs(InLocs, VarLocIDs);
2460 LLVM_DEBUG(printVarLocInMBB(MF, OutLocs, VarLocIDs,
"Final OutLocs",
dbgs()));
2461 LLVM_DEBUG(printVarLocInMBB(MF, InLocs, VarLocIDs,
"Final InLocs",
dbgs()));
2468 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.
@ End
Run the machine verifier once, at the end of the pipeline.
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.