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) {}
248 uint64_t getAsRawInteger()
const {
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) {
269 uint64_t
Start = LocIndex(Location, 0).getAsRawInteger();
270 uint64_t End = LocIndex(Location + 1, 0).getAsRawInteger();
271 return Set.half_open_range(Start, End);
282class VarLocBasedLDV :
public LDVImpl {
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 DebugVariable Var;
333 const DIExpression *Expr;
337 const MachineInstr &MI;
339 enum class MachineLocKind {
347 enum class EntryValueLocKind {
348 NonEntryValueKind = 0,
350 EntryValueBackupKind,
351 EntryValueCopyBackupKind
352 } EVKind = EntryValueLocKind::NonEntryValueKind;
356 union MachineLocValue {
358 SpillLoc SpillLocation;
362 const ConstantInt *CImm;
363 WasmLoc WasmLocation;
364 MachineLocValue() : Hash(0) {}
373 MachineLocValue Value;
375 if (Kind !=
Other.Kind)
378 case MachineLocKind::SpillLocKind:
379 return Value.SpillLocation ==
Other.Value.SpillLocation;
380 case MachineLocKind::WasmLocKind:
381 return Value.WasmLocation ==
Other.Value.WasmLocation;
382 case MachineLocKind::RegisterKind:
383 case MachineLocKind::ImmediateKind:
384 return Value.Hash ==
Other.Value.Hash;
391 case MachineLocKind::SpillLocKind:
392 return std::make_tuple(
393 Kind, Value.SpillLocation.SpillBase,
394 Value.SpillLocation.SpillOffset.getFixed(),
395 Value.SpillLocation.SpillOffset.getScalable()) <
397 Other.Kind,
Other.Value.SpillLocation.SpillBase,
398 Other.Value.SpillLocation.SpillOffset.getFixed(),
399 Other.Value.SpillLocation.SpillOffset.getScalable());
400 case MachineLocKind::WasmLocKind:
401 return std::make_tuple(Kind, Value.WasmLocation.Index,
402 Value.WasmLocation.Offset) <
403 std::make_tuple(
Other.Kind,
Other.Value.WasmLocation.Index,
404 Other.Value.WasmLocation.Offset);
405 case MachineLocKind::RegisterKind:
406 case MachineLocKind::ImmediateKind:
407 return std::tie(Kind, Value.Hash) <
423 SmallVector<unsigned, 8> OrigLocMap;
425 VarLoc(
const MachineInstr &MI)
426 : Var(MI.getDebugVariable(), MI.getDebugExpression(),
428 Expr(MI.getDebugExpression()), MI(MI) {
429 assert(MI.isDebugValue() &&
"not a DBG_VALUE");
430 assert((MI.isDebugValueList() || MI.getNumOperands() == 4) &&
431 "malformed DBG_VALUE");
432 for (
const MachineOperand &
Op : MI.debug_operands()) {
433 MachineLoc
ML = GetLocForOp(
Op);
435 if (It == Locs.end()) {
437 OrigLocMap.push_back(MI.getDebugOperandIndex(&
Op));
441 unsigned OpIdx = Locs.size();
442 unsigned DuplicatingIdx = std::distance(Locs.begin(), It);
449 assert(EVKind != EntryValueLocKind::EntryValueKind &&
450 !isEntryBackupLoc());
453 static MachineLoc GetLocForOp(
const MachineOperand &
Op) {
457 Kind = MachineLocKind::RegisterKind;
458 Loc.RegNo =
Op.getReg();
459 }
else if (
Op.isImm()) {
460 Kind = MachineLocKind::ImmediateKind;
461 Loc.Immediate =
Op.getImm();
462 }
else if (
Op.isFPImm()) {
463 Kind = MachineLocKind::ImmediateKind;
464 Loc.FPImm =
Op.getFPImm();
465 }
else if (
Op.isCImm()) {
466 Kind = MachineLocKind::ImmediateKind;
467 Loc.CImm =
Op.getCImm();
468 }
else if (
Op.isTargetIndex()) {
469 Kind = MachineLocKind::WasmLocKind;
470 Loc.WasmLocation = {
Op.getIndex(),
Op.getOffset()};
478 static VarLoc CreateEntryLoc(
const MachineInstr &MI,
481 assert(VL.Locs.size() == 1 &&
482 VL.Locs[0].Kind == MachineLocKind::RegisterKind);
483 VL.EVKind = EntryValueLocKind::EntryValueKind;
485 VL.Locs[0].Value.RegNo =
Reg;
493 static VarLoc CreateEntryBackupLoc(
const MachineInstr &MI,
494 const DIExpression *EntryExpr) {
496 assert(VL.Locs.size() == 1 &&
497 VL.Locs[0].Kind == MachineLocKind::RegisterKind);
498 VL.EVKind = EntryValueLocKind::EntryValueBackupKind;
506 static VarLoc CreateEntryCopyBackupLoc(
const MachineInstr &MI,
507 const DIExpression *EntryExpr,
510 assert(VL.Locs.size() == 1 &&
511 VL.Locs[0].Kind == MachineLocKind::RegisterKind);
512 VL.EVKind = EntryValueLocKind::EntryValueCopyBackupKind;
514 VL.Locs[0].Value.RegNo = NewReg;
520 static VarLoc CreateCopyLoc(
const VarLoc &OldVL,
const MachineLoc &OldML,
523 for (MachineLoc &
ML : VL.Locs)
525 ML.Kind = MachineLocKind::RegisterKind;
526 ML.Value.RegNo = NewReg;
534 static VarLoc CreateSpillLoc(
const VarLoc &OldVL,
const MachineLoc &OldML,
535 unsigned SpillBase, StackOffset SpillOffset) {
537 for (MachineLoc &
ML : VL.Locs)
539 ML.Kind = MachineLocKind::SpillLocKind;
540 ML.Value.SpillLocation = {SpillBase, SpillOffset};
550 MachineInstr *BuildDbgValue(MachineFunction &MF)
const {
551 assert(!isEntryBackupLoc() &&
552 "Tried to produce DBG_VALUE for backup VarLoc");
553 const DebugLoc &DbgLoc = MI.getDebugLoc();
554 bool Indirect = MI.isIndirectDebugValue();
555 const auto &IID = MI.getDesc();
556 const DILocalVariable *Var = MI.getDebugVariable();
559 const DIExpression *DIExpr = Expr;
561 for (
unsigned I = 0,
E = Locs.size();
I <
E; ++
I) {
562 MachineLocKind LocKind = Locs[
I].Kind;
563 MachineLocValue Loc = Locs[
I].Value;
564 const MachineOperand &Orig = MI.getDebugOperand(OrigLocMap[
I]);
566 case MachineLocKind::RegisterKind:
574 EVKind == EntryValueLocKind::EntryValueKind ? Orig.
getReg()
578 case MachineLocKind::SpillLocKind: {
583 unsigned Base = Loc.SpillLocation.SpillBase;
585 if (MI.isNonListDebugValue()) {
587 DIExpr =
TRI->prependOffsetExpression(
589 Loc.SpillLocation.SpillOffset);
592 SmallVector<uint64_t, 4>
Ops;
593 TRI->getOffsetOpcodes(Loc.SpillLocation.SpillOffset,
Ops);
594 Ops.push_back(dwarf::DW_OP_deref);
600 case MachineLocKind::ImmediateKind: {
604 case MachineLocKind::WasmLocKind: {
608 case MachineLocKind::InvalidKind:
612 return BuildMI(MF, DbgLoc, IID, Indirect, MOs, Var, DIExpr);
617 return Kind == MachineLocKind::ImmediateKind;
621 bool isEntryBackupLoc()
const {
622 return EVKind == EntryValueLocKind::EntryValueBackupKind ||
623 EVKind == EntryValueLocKind::EntryValueCopyBackupKind;
629 return EVKind == EntryValueLocKind::EntryValueBackupKind && usesReg(
Reg);
634 bool isEntryValueCopyBackupReg(
Register Reg)
const {
635 return EVKind == EntryValueLocKind::EntryValueCopyBackupKind &&
642 RegML.Kind = MachineLocKind::RegisterKind;
643 RegML.Value.RegNo =
Reg;
649 for (
unsigned Idx = 0; Idx < Locs.size(); ++Idx)
650 if (Locs[Idx].Kind == MachineLocKind::RegisterKind &&
651 Register{
static_cast<unsigned>(Locs[Idx].Value.RegNo)} ==
Reg)
658 bool getDescribingRegs(SmallVectorImpl<uint32_t> &Regs)
const {
659 bool AnyRegs =
false;
660 for (
const auto &Loc : Locs)
661 if (Loc.Kind == MachineLocKind::RegisterKind) {
668 bool containsSpillLocs()
const {
669 return any_of(Locs, [](VarLoc::MachineLoc
ML) {
670 return ML.Kind == VarLoc::MachineLocKind::SpillLocKind;
676 bool usesSpillLoc(SpillLoc SpillLocation)
const {
678 SpillML.Kind = MachineLocKind::SpillLocKind;
679 SpillML.Value.SpillLocation = SpillLocation;
685 unsigned getSpillLocIdx(SpillLoc SpillLocation)
const {
686 for (
unsigned Idx = 0; Idx < Locs.size(); ++Idx)
687 if (Locs[Idx].Kind == MachineLocKind::SpillLocKind &&
688 Locs[Idx].
Value.SpillLocation == SpillLocation)
693 bool containsWasmLocs()
const {
694 return any_of(Locs, [](VarLoc::MachineLoc
ML) {
695 return ML.Kind == VarLoc::MachineLocKind::WasmLocKind;
701 bool usesWasmLoc(WasmLoc WasmLocation)
const {
703 WasmML.Kind = MachineLocKind::WasmLocKind;
704 WasmML.Value.WasmLocation = WasmLocation;
710 bool dominates(LexicalScopes &LS, MachineBasicBlock &
MBB)
const {
711 return LS.dominates(MI.getDebugLoc().get(), &
MBB);
714#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
716 void dump(
const TargetRegisterInfo *
TRI,
const TargetInstrInfo *
TII,
717 raw_ostream &Out =
dbgs())
const {
719 for (
const MachineLoc &MLoc : Locs) {
720 if (Locs.begin() != &MLoc)
723 case MachineLocKind::RegisterKind:
726 case MachineLocKind::SpillLocKind:
727 Out <<
printReg(MLoc.Value.SpillLocation.SpillBase,
TRI);
728 Out <<
"[" << MLoc.Value.SpillLocation.SpillOffset.getFixed() <<
" + "
729 << MLoc.Value.SpillLocation.SpillOffset.getScalable()
733 case MachineLocKind::ImmediateKind:
734 Out << MLoc.Value.Immediate;
736 case MachineLocKind::WasmLocKind: {
738 auto Indices =
TII->getSerializableTargetIndices();
740 find_if(Indices, [&](
const std::pair<int, const char *> &
I) {
741 return I.first == MLoc.Value.WasmLocation.Index;
743 assert(Found != Indices.end());
744 Out << Found->second;
745 if (MLoc.Value.WasmLocation.Offset > 0)
746 Out <<
" + " << MLoc.Value.WasmLocation.Offset;
752 case MachineLocKind::InvalidKind:
757 Out <<
", \"" << Var.getVariable()->getName() <<
"\", " << *Expr <<
", ";
758 if (Var.getInlinedAt())
759 Out <<
"!" << Var.getInlinedAt()->getMetadataID() <<
")\n";
763 if (isEntryBackupLoc())
764 Out <<
" (backup loc)\n";
771 return std::tie(EVKind, Var, Expr, Locs) ==
777 return std::tie(Var, EVKind, Locs, Expr) <
783 using VarVec = SmallVector<VarLoc, 32>;
793 std::map<VarLoc, LocIndices> Var2Indices;
797 SmallDenseMap<LocIndex::u32_location_t, std::vector<VarLoc>> Loc2Vars;
801 LocIndices insert(
const VarLoc &VL) {
802 LocIndices &Indices = Var2Indices[VL];
804 if (!Indices.empty())
812 if (VL.EVKind == VarLoc::EntryValueLocKind::NonEntryValueKind) {
813 VL.getDescribingRegs(Locations);
816 return (RegNo < LocIndex::kFirstInvalidRegLocation) ||
817 (LocIndex::kFirstVirtualRegLocation <= RegNo);
819 "Physical or virtual register out of range?");
820 if (VL.containsSpillLocs())
821 Locations.push_back(LocIndex::kSpillLocation);
822 if (VL.containsWasmLocs())
823 Locations.push_back(LocIndex::kWasmLocation);
824 }
else if (VL.EVKind != VarLoc::EntryValueLocKind::EntryValueKind) {
825 LocIndex::u32_location_t Loc = LocIndex::kEntryValueBackupLocation;
828 Locations.push_back(LocIndex::kUniversalLocation);
829 for (LocIndex::u32_location_t Location : Locations) {
832 {
Location,
static_cast<LocIndex::u32_index_t
>(Vars.size())});
838 LocIndices getAllIndices(
const VarLoc &VL)
const {
839 auto IndIt = Var2Indices.find(VL);
840 assert(IndIt != Var2Indices.end() &&
"VarLoc not tracked");
841 return IndIt->second;
845 const VarLoc &operator[](LocIndex
ID)
const {
846 auto LocIt = Loc2Vars.find(
ID.Location);
847 assert(LocIt != Loc2Vars.end() &&
"Location not tracked");
848 return LocIt->second[
ID.Index];
853 SmallDenseMap<const MachineBasicBlock *, std::unique_ptr<VarLocSet>>;
854 struct TransferDebugPair {
855 MachineInstr *TransferInst;
858 using TransferMap = SmallVector<TransferDebugPair, 4>;
861 using InstToEntryLocMap = std::multimap<const MachineInstr *, LocIndex>;
862 using RegDefToInstMap = DenseMap<Register, MachineInstr *>;
867 using FragmentOfVar =
868 std::pair<const DILocalVariable *, DIExpression::FragmentInfo>;
870 DenseMap<FragmentOfVar, SmallVector<DIExpression::FragmentInfo, 1>>;
874 using VarToFragments =
875 DenseMap<const DILocalVariable *, SmallSet<FragmentInfo, 4>>;
879 static void collectAllVarLocs(SmallVectorImpl<VarLoc> &Collected,
880 const VarLocSet &CollectFrom,
881 const VarLocMap &VarLocIDs);
885 void getUsedRegs(
const VarLocSet &CollectFrom,
886 SmallVectorImpl<Register> &UsedRegs)
const;
897 class OpenRangesSet {
898 VarLocSet::Allocator &Alloc;
901 SmallDenseMap<DebugVariable, LocIndices, 8> Vars;
903 SmallDenseMap<DebugVariable, LocIndices, 8> EntryValuesBackupVars;
907 OpenRangesSet(VarLocSet::Allocator &Alloc,
OverlapMap &_OLapMap)
908 : Alloc(Alloc), VarLocs(Alloc), OverlappingFragments(_OLapMap) {}
910 const VarLocSet &getVarLocs()
const {
return VarLocs; }
917 void getUniqueVarLocs(SmallVectorImpl<VarLoc> &Collected,
918 const VarLocMap &VarLocIDs)
const {
919 collectAllVarLocs(Collected, VarLocs, VarLocIDs);
923 void erase(
const VarLoc &VL);
927 void erase(
const VarLocsInRange &KillSet,
const VarLocMap &VarLocIDs,
928 LocIndex::u32_location_t Location);
931 void insert(LocIndices VarLocIDs,
const VarLoc &VL);
934 void insertFromLocSet(
const VarLocSet &ToLoad,
const VarLocMap &Map);
936 std::optional<LocIndices> getEntryValueBackup(DebugVariable Var);
942 EntryValuesBackupVars.clear();
947 assert(Vars.empty() == EntryValuesBackupVars.empty() &&
948 Vars.empty() == VarLocs.empty() &&
949 "open ranges are inconsistent");
950 return VarLocs.empty();
954 auto getEmptyVarLocRange()
const {
961 return LocIndex::indexRangeForLocation(getVarLocs(),
Reg);
965 auto getSpillVarLocs()
const {
966 return LocIndex::indexRangeForLocation(getVarLocs(),
967 LocIndex::kSpillLocation);
972 auto getEntryValueBackupVarLocs()
const {
973 return LocIndex::indexRangeForLocation(
974 getVarLocs(), LocIndex::kEntryValueBackupLocation);
978 auto getWasmVarLocs()
const {
979 return LocIndex::indexRangeForLocation(getVarLocs(),
980 LocIndex::kWasmLocation);
988 static void collectIDsForRegs(VarLocsInRange &Collected,
989 const DefinedRegsSet &Regs,
990 const VarLocSet &CollectFrom,
991 const VarLocMap &VarLocIDs);
993 VarLocSet &getVarLocsInMBB(
const MachineBasicBlock *
MBB, VarLocInMBB &Locs) {
994 std::unique_ptr<VarLocSet> &VLS = Locs[
MBB];
996 VLS = std::make_unique<VarLocSet>(Alloc);
1000 const VarLocSet &getVarLocsInMBB(
const MachineBasicBlock *
MBB,
1001 const VarLocInMBB &Locs)
const {
1002 auto It = Locs.find(
MBB);
1003 assert(It != Locs.end() &&
"MBB not in map");
1008 bool isSpillInstruction(
const MachineInstr &
MI, MachineFunction *MF);
1016 bool isLocationSpill(
const MachineInstr &
MI, MachineFunction *MF,
1024 bool isEntryValueCandidate(
const MachineInstr &
MI,
1025 const DefinedRegsSet &Regs)
const;
1029 std::optional<VarLoc::SpillLoc> isRestoreInstruction(
const MachineInstr &
MI,
1030 MachineFunction *MF,
1034 VarLoc::SpillLoc extractSpillBaseRegAndOffset(
const MachineInstr &
MI);
1035 void insertTransferDebugPair(MachineInstr &
MI, OpenRangesSet &OpenRanges,
1036 TransferMap &Transfers, VarLocMap &VarLocIDs,
1037 LocIndex OldVarID, TransferKind Kind,
1038 const VarLoc::MachineLoc &OldLoc,
1041 void transferDebugValue(
const MachineInstr &
MI, OpenRangesSet &OpenRanges,
1042 VarLocMap &VarLocIDs,
1043 InstToEntryLocMap &EntryValTransfers,
1044 RegDefToInstMap &RegSetInstrs);
1045 void transferSpillOrRestoreInst(MachineInstr &
MI, OpenRangesSet &OpenRanges,
1046 VarLocMap &VarLocIDs, TransferMap &Transfers);
1047 void cleanupEntryValueTransfers(
const MachineInstr *
MI,
1048 OpenRangesSet &OpenRanges,
1049 VarLocMap &VarLocIDs,
const VarLoc &EntryVL,
1050 InstToEntryLocMap &EntryValTransfers);
1051 void removeEntryValue(
const MachineInstr &
MI, OpenRangesSet &OpenRanges,
1052 VarLocMap &VarLocIDs,
const VarLoc &EntryVL,
1053 InstToEntryLocMap &EntryValTransfers,
1054 RegDefToInstMap &RegSetInstrs);
1055 void emitEntryValues(MachineInstr &
MI, OpenRangesSet &OpenRanges,
1056 VarLocMap &VarLocIDs,
1057 InstToEntryLocMap &EntryValTransfers,
1058 VarLocsInRange &KillSet);
1059 void recordEntryValue(
const MachineInstr &
MI,
1060 const DefinedRegsSet &DefinedRegs,
1061 OpenRangesSet &OpenRanges, VarLocMap &VarLocIDs);
1062 void transferRegisterCopy(MachineInstr &
MI, OpenRangesSet &OpenRanges,
1063 VarLocMap &VarLocIDs, TransferMap &Transfers);
1064 void transferRegisterDef(MachineInstr &
MI, OpenRangesSet &OpenRanges,
1065 VarLocMap &VarLocIDs,
1066 InstToEntryLocMap &EntryValTransfers,
1067 RegDefToInstMap &RegSetInstrs);
1068 void transferWasmDef(MachineInstr &
MI, OpenRangesSet &OpenRanges,
1069 VarLocMap &VarLocIDs);
1070 bool transferTerminator(MachineBasicBlock *
MBB, OpenRangesSet &OpenRanges,
1071 VarLocInMBB &OutLocs,
const VarLocMap &VarLocIDs);
1073 void process(MachineInstr &
MI, OpenRangesSet &OpenRanges,
1074 VarLocMap &VarLocIDs, TransferMap &Transfers,
1075 InstToEntryLocMap &EntryValTransfers,
1076 RegDefToInstMap &RegSetInstrs);
1078 void accumulateFragmentMap(MachineInstr &
MI, VarToFragments &SeenFragments,
1079 OverlapMap &OLapMap);
1081 bool join(MachineBasicBlock &
MBB, VarLocInMBB &OutLocs, VarLocInMBB &InLocs,
1082 const VarLocMap &VarLocIDs,
1083 SmallPtrSet<const MachineBasicBlock *, 16> &Visited,
1084 SmallPtrSetImpl<const MachineBasicBlock *> &ArtificialBlocks);
1088 void flushPendingLocs(VarLocInMBB &PendingInLocs, VarLocMap &VarLocIDs);
1090 bool ExtendRanges(MachineFunction &MF, MachineDominatorTree *DomTree,
1091 bool ShouldEmitDebugEntryValues,
unsigned InputBBLimit,
1092 unsigned InputDbgValLimit)
override;
1098 ~VarLocBasedLDV()
override;
1101 void printVarLocInMBB(
const MachineFunction &MF,
const VarLocInMBB &V,
1102 const VarLocMap &VarLocIDs,
const char *msg,
1103 raw_ostream &Out)
const;
1112VarLocBasedLDV::VarLocBasedLDV() =
default;
1114VarLocBasedLDV::~VarLocBasedLDV() =
default;
1121void VarLocBasedLDV::OpenRangesSet::erase(
const VarLoc &VL) {
1123 auto DoErase = [&VL,
this](DebugVariable VarToErase) {
1124 auto *EraseFrom = VL.isEntryBackupLoc() ? &EntryValuesBackupVars : &Vars;
1125 auto It = EraseFrom->
find(VarToErase);
1126 if (It != EraseFrom->end()) {
1127 LocIndices IDs = It->second;
1128 for (LocIndex
ID : IDs)
1129 VarLocs.reset(
ID.getAsRawInteger());
1130 EraseFrom->erase(It);
1134 DebugVariable Var = VL.Var;
1145 auto MapIt = OverlappingFragments.find({Var.
getVariable(), ThisFragment});
1146 if (MapIt != OverlappingFragments.end()) {
1147 for (
auto Fragment : MapIt->second) {
1148 VarLocBasedLDV::OptFragmentInfo FragmentHolder;
1150 FragmentHolder = VarLocBasedLDV::OptFragmentInfo(Fragment);
1156void VarLocBasedLDV::OpenRangesSet::erase(
const VarLocsInRange &KillSet,
1157 const VarLocMap &VarLocIDs,
1158 LocIndex::u32_location_t Location) {
1159 VarLocSet RemoveSet(
Alloc);
1160 for (LocIndex::u32_index_t
ID : KillSet) {
1161 const VarLoc &VL = VarLocIDs[LocIndex(Location,
ID)];
1162 auto *EraseFrom = VL.isEntryBackupLoc() ? &EntryValuesBackupVars : &Vars;
1163 EraseFrom->
erase(VL.Var);
1164 LocIndices VLI = VarLocIDs.getAllIndices(VL);
1165 for (LocIndex
ID : VLI)
1166 RemoveSet.set(
ID.getAsRawInteger());
1168 VarLocs.intersectWithComplement(RemoveSet);
1171void VarLocBasedLDV::OpenRangesSet::insertFromLocSet(
const VarLocSet &ToLoad,
1172 const VarLocMap &Map) {
1173 VarLocsInRange UniqueVarLocIDs;
1174 DefinedRegsSet Regs;
1175 Regs.
insert(LocIndex::kUniversalLocation);
1176 collectIDsForRegs(UniqueVarLocIDs, Regs, ToLoad, Map);
1177 for (uint64_t
ID : UniqueVarLocIDs) {
1178 LocIndex Idx = LocIndex::fromRawInteger(
ID);
1179 const VarLoc &VarL =
Map[Idx];
1180 const LocIndices Indices =
Map.getAllIndices(VarL);
1181 insert(Indices, VarL);
1185void VarLocBasedLDV::OpenRangesSet::insert(LocIndices VarLocIDs,
1187 auto *InsertInto = VL.isEntryBackupLoc() ? &EntryValuesBackupVars : &Vars;
1188 for (LocIndex
ID : VarLocIDs)
1189 VarLocs.set(
ID.getAsRawInteger());
1190 InsertInto->
insert({VL.Var, VarLocIDs});
1195std::optional<LocIndices>
1196VarLocBasedLDV::OpenRangesSet::getEntryValueBackup(DebugVariable Var) {
1197 auto It = EntryValuesBackupVars.
find(Var);
1198 if (It != EntryValuesBackupVars.
end())
1201 return std::nullopt;
1204void VarLocBasedLDV::collectIDsForRegs(VarLocsInRange &Collected,
1205 const DefinedRegsSet &Regs,
1206 const VarLocSet &CollectFrom,
1207 const VarLocMap &VarLocIDs) {
1208 assert(!Regs.empty() &&
"Nothing to collect");
1212 auto It = CollectFrom.find(LocIndex::rawIndexForReg(SortedRegs.
front()));
1213 auto End = CollectFrom.end();
1218 uint64_t FirstIndexForReg = LocIndex::rawIndexForReg(
Reg);
1219 uint64_t FirstInvalidIndex = LocIndex::rawIndexForReg(
Reg + 1);
1220 It.advanceToLowerBound(FirstIndexForReg);
1223 for (; It != End && *It < FirstInvalidIndex; ++It) {
1224 LocIndex ItIdx = LocIndex::fromRawInteger(*It);
1225 const VarLoc &VL = VarLocIDs[ItIdx];
1226 LocIndices LI = VarLocIDs.getAllIndices(VL);
1228 assert(LI.back().Location == LocIndex::kUniversalLocation &&
1229 "Unexpected order of LocIndices for VarLoc; was it inserted into "
1230 "the VarLocMap correctly?");
1231 Collected.insert(LI.back().Index);
1239void VarLocBasedLDV::getUsedRegs(
const VarLocSet &CollectFrom,
1240 SmallVectorImpl<Register> &UsedRegs)
const {
1243 uint64_t FirstRegIndex =
1244 LocIndex::rawIndexForReg(LocIndex::kFirstRegLocation);
1245 uint64_t FirstInvalidIndex =
1246 LocIndex::rawIndexForReg(LocIndex::kFirstInvalidRegLocation);
1247 uint64_t FirstVirtualRegIndex =
1248 LocIndex::rawIndexForReg(LocIndex::kFirstVirtualRegLocation);
1249 auto doGetUsedRegs = [&](VarLocSet::const_iterator &It) {
1252 uint32_t FoundReg = LocIndex::fromRawInteger(*It).Location;
1254 "Duplicate used reg");
1260 uint64_t NextRegIndex = LocIndex::rawIndexForReg(FoundReg + 1);
1261 It.advanceToLowerBound(NextRegIndex);
1263 for (
auto It = CollectFrom.find(FirstRegIndex),
1264 End = CollectFrom.find(FirstInvalidIndex);
1268 for (
auto It = CollectFrom.find(FirstVirtualRegIndex),
1269 End = CollectFrom.end();
1280void VarLocBasedLDV::printVarLocInMBB(
const MachineFunction &MF,
1281 const VarLocInMBB &V,
1282 const VarLocMap &VarLocIDs,
1284 raw_ostream &Out)
const {
1285 Out <<
'\n' << msg <<
'\n';
1286 for (
const MachineBasicBlock &BB : MF) {
1289 const VarLocSet &
L = getVarLocsInMBB(&BB, V);
1292 SmallVector<VarLoc, 32> VarLocs;
1293 collectAllVarLocs(VarLocs, L, VarLocIDs);
1294 Out <<
"MBB: " << BB.getNumber() <<
":\n";
1295 for (
const VarLoc &VL : VarLocs) {
1296 Out <<
" Var: " << VL.Var.getVariable()->getName();
1305VarLocBasedLDV::VarLoc::SpillLoc
1306VarLocBasedLDV::extractSpillBaseRegAndOffset(
const MachineInstr &
MI) {
1308 "Spill instruction does not have exactly one memory operand?");
1309 auto MMOI =
MI.memoperands_begin();
1310 const PseudoSourceValue *PVal = (*MMOI)->getPseudoValue();
1312 "Inconsistent memory operand in spill instruction");
1314 const MachineBasicBlock *
MBB =
MI.getParent();
1322void VarLocBasedLDV::cleanupEntryValueTransfers(
1323 const MachineInstr *TRInst, OpenRangesSet &OpenRanges, VarLocMap &VarLocIDs,
1324 const VarLoc &EntryVL, InstToEntryLocMap &EntryValTransfers) {
1325 if (EntryValTransfers.empty() || TRInst ==
nullptr)
1328 auto TransRange = EntryValTransfers.equal_range(TRInst);
1330 const VarLoc &EmittedEV = VarLocIDs[TDPair.second];
1331 if (std::tie(EntryVL.Var, EntryVL.Locs[0].Value.RegNo, EntryVL.Expr) ==
1332 std::tie(EmittedEV.Var, EmittedEV.Locs[0].Value.RegNo,
1334 OpenRanges.erase(EmittedEV);
1335 EntryValTransfers.erase(TRInst);
1345void VarLocBasedLDV::removeEntryValue(
const MachineInstr &
MI,
1346 OpenRangesSet &OpenRanges,
1347 VarLocMap &VarLocIDs,
1348 const VarLoc &EntryVL,
1349 InstToEntryLocMap &EntryValTransfers,
1350 RegDefToInstMap &RegSetInstrs) {
1352 if (&
MI == &EntryVL.MI)
1358 if (!
MI.getDebugOperand(0).isReg())
1363 const MachineInstr *TransferInst =
1367 if (!TransferInst && !LastNonDbgMI &&
MI.getParent()->isEntryBlock())
1373 if (
MI.getDebugExpression()->getNumElements() == 0 && TransferInst) {
1380 auto DestSrc =
TII->isCopyLikeInstr(*TransferInst);
1382 const MachineOperand *SrcRegOp, *DestRegOp;
1383 SrcRegOp = DestSrc->Source;
1384 DestRegOp = DestSrc->Destination;
1386 for (uint64_t
ID : OpenRanges.getEntryValueBackupVarLocs()) {
1387 const VarLoc &VL = VarLocIDs[LocIndex::fromRawInteger(
ID)];
1388 if (VL.isEntryValueCopyBackupReg(
Reg) &&
1390 VL.MI.getDebugOperand(0).getReg() == SrcRegOp->
getReg())
1401 cleanupEntryValueTransfers(TransferInst, OpenRanges, VarLocIDs, EntryVL,
1403 OpenRanges.erase(EntryVL);
1408void VarLocBasedLDV::transferDebugValue(
const MachineInstr &
MI,
1409 OpenRangesSet &OpenRanges,
1410 VarLocMap &VarLocIDs,
1411 InstToEntryLocMap &EntryValTransfers,
1412 RegDefToInstMap &RegSetInstrs) {
1413 if (!
MI.isDebugValue())
1415 const DILocalVariable *Var =
MI.getDebugVariable();
1416 const DIExpression *Expr =
MI.getDebugExpression();
1417 const DILocation *
DebugLoc =
MI.getDebugLoc();
1418 const DILocation *InlinedAt =
DebugLoc->getInlinedAt();
1420 "Expected inlined-at fields to agree");
1422 DebugVariable
V(Var, Expr, InlinedAt);
1426 auto EntryValBackupID = OpenRanges.getEntryValueBackup(V);
1428 const VarLoc &EntryVL = VarLocIDs[EntryValBackupID->back()];
1429 removeEntryValue(
MI, OpenRanges, VarLocIDs, EntryVL, EntryValTransfers,
1433 if (
all_of(
MI.debug_operands(), [](
const MachineOperand &MO) {
1434 return (MO.isReg() && MO.getReg()) || MO.isImm() || MO.isFPImm() ||
1435 MO.isCImm() || MO.isTargetIndex();
1440 OpenRanges.erase(VL);
1442 LocIndices IDs = VarLocIDs.insert(VL);
1444 OpenRanges.insert(IDs, VL);
1445 }
else if (
MI.memoperands().size() > 0) {
1446 llvm_unreachable(
"DBG_VALUE with mem operand encountered after regalloc?");
1450 "Unexpected non-undef DBG_VALUE encountered");
1452 OpenRanges.erase(VL);
1457void VarLocBasedLDV::collectAllVarLocs(SmallVectorImpl<VarLoc> &Collected,
1458 const VarLocSet &CollectFrom,
1459 const VarLocMap &VarLocIDs) {
1463 uint64_t FirstIndex = LocIndex::rawIndexForReg(LocIndex::kUniversalLocation);
1464 uint64_t FirstInvalidIndex =
1465 LocIndex::rawIndexForReg(LocIndex::kUniversalLocation + 1);
1467 for (
auto It = CollectFrom.find(FirstIndex), End = CollectFrom.end();
1468 It != End && *It < FirstInvalidIndex; ++It) {
1469 LocIndex RegIdx = LocIndex::fromRawInteger(*It);
1475void VarLocBasedLDV::emitEntryValues(MachineInstr &
MI,
1476 OpenRangesSet &OpenRanges,
1477 VarLocMap &VarLocIDs,
1478 InstToEntryLocMap &EntryValTransfers,
1479 VarLocsInRange &KillSet) {
1481 if (
MI.isTerminator())
1484 for (uint32_t
ID : KillSet) {
1486 LocIndex Idx = LocIndex(LocIndex::kUniversalLocation,
ID);
1487 const VarLoc &VL = VarLocIDs[Idx];
1488 if (!VL.Var.getVariable()->isParameter())
1491 auto DebugVar = VL.Var;
1492 std::optional<LocIndices> EntryValBackupIDs =
1493 OpenRanges.getEntryValueBackup(DebugVar);
1497 if (!EntryValBackupIDs)
1500 const VarLoc &EntryVL = VarLocIDs[EntryValBackupIDs->back()];
1501 VarLoc EntryLoc = VarLoc::CreateEntryLoc(EntryVL.MI, EntryVL.Expr,
1502 EntryVL.Locs[0].Value.RegNo);
1503 LocIndices EntryValueIDs = VarLocIDs.insert(EntryLoc);
1504 assert(EntryValueIDs.size() == 1 &&
1505 "EntryValue loc should not be variadic");
1506 EntryValTransfers.insert({&
MI, EntryValueIDs.back()});
1507 OpenRanges.insert(EntryValueIDs, EntryLoc);
1516void VarLocBasedLDV::insertTransferDebugPair(
1517 MachineInstr &
MI, OpenRangesSet &OpenRanges, TransferMap &Transfers,
1518 VarLocMap &VarLocIDs, LocIndex OldVarID, TransferKind Kind,
1519 const VarLoc::MachineLoc &OldLoc,
Register NewReg) {
1520 const VarLoc &OldVarLoc = VarLocIDs[OldVarID];
1522 auto ProcessVarLoc = [&
MI, &OpenRanges, &Transfers, &VarLocIDs](VarLoc &VL) {
1523 LocIndices LocIds = VarLocIDs.insert(VL);
1526 OpenRanges.erase(VL);
1530 OpenRanges.insert(LocIds, VL);
1531 assert(!
MI.isTerminator() &&
"Cannot insert DBG_VALUE after terminator");
1532 TransferDebugPair MIP = {&
MI, LocIds.back()};
1533 Transfers.push_back(MIP);
1537 OpenRanges.erase(VarLocIDs[OldVarID]);
1539 case TransferKind::TransferCopy: {
1541 "No register supplied when handling a copy of a debug value");
1544 VarLoc VL = VarLoc::CreateCopyLoc(OldVarLoc, OldLoc, NewReg);
1547 dbgs() <<
"Creating VarLoc for register copy:";
1552 case TransferKind::TransferSpill: {
1555 VarLoc::SpillLoc SpillLocation = extractSpillBaseRegAndOffset(
MI);
1556 VarLoc VL = VarLoc::CreateSpillLoc(
1557 OldVarLoc, OldLoc, SpillLocation.SpillBase, SpillLocation.SpillOffset);
1560 dbgs() <<
"Creating VarLoc for spill:";
1565 case TransferKind::TransferRestore: {
1567 "No register supplied when handling a restore of a debug value");
1570 VarLoc VL = VarLoc::CreateCopyLoc(OldVarLoc, OldLoc, NewReg);
1573 dbgs() <<
"Creating VarLoc for restore:";
1583void VarLocBasedLDV::transferRegisterDef(MachineInstr &
MI,
1584 OpenRangesSet &OpenRanges,
1585 VarLocMap &VarLocIDs,
1586 InstToEntryLocMap &EntryValTransfers,
1587 RegDefToInstMap &RegSetInstrs) {
1591 if (
MI.isMetaInstruction())
1594 MachineFunction *MF =
MI.getMF();
1599 DefinedRegsSet DeadRegs;
1600 SmallVector<const uint32_t *, 4> RegMasks;
1601 for (
const MachineOperand &MO :
MI.operands()) {
1604 !(
MI.isCall() && MO.
getReg() == SP)) {
1606 for (MCRegAliasIterator RAI(MO.
getReg(),
TRI,
true); RAI.isValid(); ++RAI)
1608 DeadRegs.insert((*RAI).id());
1609 RegSetInstrs.erase(MO.
getReg());
1610 RegSetInstrs.insert({MO.
getReg(), &
MI});
1619 if (!RegMasks.
empty()) {
1621 getUsedRegs(OpenRanges.getVarLocs(), UsedRegs);
1631 bool AnyRegMaskKillsReg =
1632 any_of(RegMasks, [
Reg](
const uint32_t *RegMask) {
1635 if (AnyRegMaskKillsReg)
1636 DeadRegs.insert(
Reg);
1637 if (AnyRegMaskKillsReg) {
1638 RegSetInstrs.erase(
Reg);
1639 RegSetInstrs.insert({
Reg, &
MI});
1644 if (DeadRegs.empty())
1647 VarLocsInRange KillSet;
1648 collectIDsForRegs(KillSet, DeadRegs, OpenRanges.getVarLocs(), VarLocIDs);
1649 OpenRanges.erase(KillSet, VarLocIDs, LocIndex::kUniversalLocation);
1651 if (ShouldEmitDebugEntryValues)
1652 emitEntryValues(
MI, OpenRanges, VarLocIDs, EntryValTransfers, KillSet);
1655void VarLocBasedLDV::transferWasmDef(MachineInstr &
MI,
1656 OpenRangesSet &OpenRanges,
1657 VarLocMap &VarLocIDs) {
1662 if (!
TII->isExplicitTargetIndexDef(
MI, Index,
Offset))
1667 VarLocsInRange KillSet;
1669 for (uint64_t
ID : OpenRanges.getWasmVarLocs()) {
1670 LocIndex Idx = LocIndex::fromRawInteger(
ID);
1671 const VarLoc &VL = VarLocIDs[Idx];
1672 assert(VL.containsWasmLocs() &&
"Broken VarLocSet?");
1673 if (VL.usesWasmLoc(Loc))
1676 OpenRanges.erase(KillSet, VarLocIDs, LocIndex::kWasmLocation);
1679bool VarLocBasedLDV::isSpillInstruction(
const MachineInstr &
MI,
1680 MachineFunction *MF) {
1682 if (!
MI.hasOneMemOperand())
1685 if (!
MI.getSpillSize(
TII) && !
MI.getFoldedSpillSize(
TII))
1692bool VarLocBasedLDV::isLocationSpill(
const MachineInstr &
MI,
1694 if (!isSpillInstruction(
MI, MF))
1697 auto isKilledReg = [&](
const MachineOperand MO,
Register &
Reg) {
1706 for (
const MachineOperand &MO :
MI.operands()) {
1709 if (isKilledReg(MO,
Reg))
1715 auto NextI = std::next(
MI.getIterator());
1717 if (
MI.getParent()->end() == NextI)
1720 for (
const MachineOperand &MONext : NextI->operands()) {
1723 if (isKilledReg(MONext, RegNext) && RegNext ==
Reg)
1732std::optional<VarLocBasedLDV::VarLoc::SpillLoc>
1733VarLocBasedLDV::isRestoreInstruction(
const MachineInstr &
MI,
1735 if (!
MI.hasOneMemOperand())
1736 return std::nullopt;
1740 if (
MI.getRestoreSize(
TII)) {
1741 Reg =
MI.getOperand(0).getReg();
1742 return extractSpillBaseRegAndOffset(
MI);
1744 return std::nullopt;
1754void VarLocBasedLDV::transferSpillOrRestoreInst(MachineInstr &
MI,
1755 OpenRangesSet &OpenRanges,
1756 VarLocMap &VarLocIDs,
1757 TransferMap &Transfers) {
1758 MachineFunction *MF =
MI.getMF();
1761 std::optional<VarLoc::SpillLoc> Loc;
1768 VarLocsInRange KillSet;
1769 if (isSpillInstruction(
MI, MF)) {
1770 Loc = extractSpillBaseRegAndOffset(
MI);
1771 for (uint64_t
ID : OpenRanges.getSpillVarLocs()) {
1772 LocIndex Idx = LocIndex::fromRawInteger(
ID);
1773 const VarLoc &VL = VarLocIDs[Idx];
1774 assert(VL.containsSpillLocs() &&
"Broken VarLocSet?");
1775 if (VL.usesSpillLoc(*Loc)) {
1787 unsigned SpillLocIdx = VL.getSpillLocIdx(*Loc);
1788 VarLoc::MachineLoc OldLoc = VL.Locs[SpillLocIdx];
1789 VarLoc UndefVL = VarLoc::CreateCopyLoc(VL, OldLoc, 0);
1790 LocIndices UndefLocIDs = VarLocIDs.insert(UndefVL);
1791 Transfers.push_back({&
MI, UndefLocIDs.back()});
1794 OpenRanges.erase(KillSet, VarLocIDs, LocIndex::kSpillLocation);
1799 if (isLocationSpill(
MI, MF,
Reg)) {
1800 TKind = TransferKind::TransferSpill;
1805 if (!(Loc = isRestoreInstruction(
MI, MF,
Reg)))
1807 TKind = TransferKind::TransferRestore;
1813 auto TransferCandidates = OpenRanges.getEmptyVarLocRange();
1814 if (TKind == TransferKind::TransferSpill)
1815 TransferCandidates = OpenRanges.getRegisterVarLocs(
Reg);
1816 else if (TKind == TransferKind::TransferRestore)
1817 TransferCandidates = OpenRanges.getSpillVarLocs();
1818 for (uint64_t
ID : TransferCandidates) {
1819 LocIndex Idx = LocIndex::fromRawInteger(
ID);
1820 const VarLoc &VL = VarLocIDs[Idx];
1822 if (TKind == TransferKind::TransferSpill) {
1823 assert(VL.usesReg(
Reg) &&
"Broken VarLocSet?");
1825 << VL.Var.getVariable()->getName() <<
")\n");
1826 LocIdx = VL.getRegIdx(
Reg);
1828 assert(TKind == TransferKind::TransferRestore && VL.containsSpillLocs() &&
1829 "Broken VarLocSet?");
1830 if (!VL.usesSpillLoc(*Loc))
1834 << VL.Var.getVariable()->getName() <<
")\n");
1835 LocIdx = VL.getSpillLocIdx(*Loc);
1837 VarLoc::MachineLoc MLoc = VL.Locs[LocIdx];
1838 insertTransferDebugPair(
MI, OpenRanges, Transfers, VarLocIDs, Idx, TKind,
1849void VarLocBasedLDV::transferRegisterCopy(MachineInstr &
MI,
1850 OpenRangesSet &OpenRanges,
1851 VarLocMap &VarLocIDs,
1852 TransferMap &Transfers) {
1853 auto DestSrc =
TII->isCopyLikeInstr(
MI);
1857 const MachineOperand *DestRegOp = DestSrc->Destination;
1858 const MachineOperand *SrcRegOp = DestSrc->Source;
1860 if (!DestRegOp->
isDef())
1864 for (MCRegAliasIterator RAI(
Reg,
TRI,
true); RAI.isValid(); ++RAI)
1865 if (CalleeSavedRegs.
test((*RAI).id()))
1878 if (!isCalleeSavedReg(DestReg))
1885 for (uint64_t
ID : OpenRanges.getEntryValueBackupVarLocs()) {
1886 LocIndex Idx = LocIndex::fromRawInteger(
ID);
1887 const VarLoc &VL = VarLocIDs[Idx];
1888 if (VL.isEntryValueBackupReg(SrcReg)) {
1890 VarLoc EntryValLocCopyBackup =
1891 VarLoc::CreateEntryCopyBackupLoc(VL.MI, VL.Expr, DestReg);
1893 OpenRanges.erase(VL);
1896 LocIndices EntryValCopyLocIDs = VarLocIDs.insert(EntryValLocCopyBackup);
1897 OpenRanges.insert(EntryValCopyLocIDs, EntryValLocCopyBackup);
1906 for (uint64_t
ID : OpenRanges.getRegisterVarLocs(SrcReg)) {
1907 LocIndex Idx = LocIndex::fromRawInteger(
ID);
1908 assert(VarLocIDs[Idx].usesReg(SrcReg) &&
"Broken VarLocSet?");
1909 VarLoc::MachineLocValue Loc;
1911 VarLoc::MachineLoc MLoc{VarLoc::MachineLocKind::RegisterKind, Loc};
1912 insertTransferDebugPair(
MI, OpenRanges, Transfers, VarLocIDs, Idx,
1913 TransferKind::TransferCopy, MLoc, DestReg);
1921bool VarLocBasedLDV::transferTerminator(MachineBasicBlock *CurMBB,
1922 OpenRangesSet &OpenRanges,
1923 VarLocInMBB &OutLocs,
1924 const VarLocMap &VarLocIDs) {
1928 OpenRanges.getUniqueVarLocs(VarLocs, VarLocIDs);
1929 for (VarLoc &VL : VarLocs) {
1931 dbgs() <<
"Add to OutLocs in MBB #" << CurMBB->
getNumber() <<
": ";
1935 VarLocSet &VLS = getVarLocsInMBB(CurMBB, OutLocs);
1936 Changed = VLS != OpenRanges.getVarLocs();
1940 VLS = OpenRanges.getVarLocs();
1955void VarLocBasedLDV::accumulateFragmentMap(MachineInstr &
MI,
1956 VarToFragments &SeenFragments,
1958 DebugVariable MIVar(
MI.getDebugVariable(),
MI.getDebugExpression(),
1959 MI.getDebugLoc()->getInlinedAt());
1960 FragmentInfo ThisFragment = MIVar.getFragmentOrDefault();
1965 auto [SeenIt,
Inserted] = SeenFragments.try_emplace(MIVar.getVariable());
1967 SeenIt->second.insert(ThisFragment);
1969 OverlappingFragments.insert({{MIVar.getVariable(), ThisFragment}, {}});
1976 OverlappingFragments.insert({{MIVar.getVariable(), ThisFragment}, {}});
1977 if (!IsInOLapMap.second)
1980 auto &ThisFragmentsOverlaps = IsInOLapMap.first->second;
1981 auto &AllSeenFragments = SeenIt->second;
1986 for (
const auto &ASeenFragment : AllSeenFragments) {
1990 ThisFragmentsOverlaps.push_back(ASeenFragment);
1993 auto ASeenFragmentsOverlaps =
1994 OverlappingFragments.find({MIVar.getVariable(), ASeenFragment});
1995 assert(ASeenFragmentsOverlaps != OverlappingFragments.end() &&
1996 "Previously seen var fragment has no vector of overlaps");
1997 ASeenFragmentsOverlaps->second.push_back(ThisFragment);
2001 AllSeenFragments.insert(ThisFragment);
2005void VarLocBasedLDV::process(MachineInstr &
MI, OpenRangesSet &OpenRanges,
2006 VarLocMap &VarLocIDs, TransferMap &Transfers,
2007 InstToEntryLocMap &EntryValTransfers,
2008 RegDefToInstMap &RegSetInstrs) {
2009 if (!
MI.isDebugInstr())
2011 transferDebugValue(
MI, OpenRanges, VarLocIDs, EntryValTransfers,
2013 transferRegisterDef(
MI, OpenRanges, VarLocIDs, EntryValTransfers,
2015 transferWasmDef(
MI, OpenRanges, VarLocIDs);
2016 transferRegisterCopy(
MI, OpenRanges, VarLocIDs, Transfers);
2017 transferSpillOrRestoreInst(
MI, OpenRanges, VarLocIDs, Transfers);
2023bool VarLocBasedLDV::join(
2024 MachineBasicBlock &
MBB, VarLocInMBB &OutLocs, VarLocInMBB &InLocs,
2025 const VarLocMap &VarLocIDs,
2026 SmallPtrSet<const MachineBasicBlock *, 16> &Visited,
2027 SmallPtrSetImpl<const MachineBasicBlock *> &ArtificialBlocks) {
2030 VarLocSet InLocsT(
Alloc);
2041 if (!Visited.
count(p)) {
2042 LLVM_DEBUG(
dbgs() <<
" ignoring unvisited pred MBB: " <<
p->getNumber()
2046 auto OL = OutLocs.find(p);
2048 if (OL == OutLocs.end())
2053 VarLocSet &OutLocVLS = *OL->second;
2055 InLocsT = OutLocVLS;
2057 InLocsT &= OutLocVLS;
2060 if (!InLocsT.empty()) {
2062 collectAllVarLocs(VarLocs, InLocsT, VarLocIDs);
2063 for (
const VarLoc &VL : VarLocs)
2064 dbgs() <<
" gathered candidate incoming var: "
2065 << VL.Var.getVariable()->getName() <<
"\n";
2073 VarLocSet KillSet(
Alloc);
2074 bool IsArtificial = ArtificialBlocks.
count(&
MBB);
2075 if (!IsArtificial) {
2076 for (uint64_t
ID : InLocsT) {
2077 LocIndex Idx = LocIndex::fromRawInteger(
ID);
2081 auto Name = VarLocIDs[Idx].Var.getVariable()->getName();
2082 dbgs() <<
" killing " <<
Name <<
", it doesn't dominate MBB\n";
2087 InLocsT.intersectWithComplement(KillSet);
2093 "Should have processed at least one predecessor");
2095 VarLocSet &ILS = getVarLocsInMBB(&
MBB, InLocs);
2097 if (ILS != InLocsT) {
2105void VarLocBasedLDV::flushPendingLocs(VarLocInMBB &PendingInLocs,
2106 VarLocMap &VarLocIDs) {
2109 for (
auto &Iter : PendingInLocs) {
2111 auto &
MBB =
const_cast<MachineBasicBlock &
>(*Iter.first);
2112 VarLocSet &Pending = *Iter.second;
2114 SmallVector<VarLoc, 32> VarLocs;
2115 collectAllVarLocs(VarLocs, Pending, VarLocIDs);
2117 for (VarLoc DiffIt : VarLocs) {
2120 if (DiffIt.isEntryBackupLoc())
2131bool VarLocBasedLDV::isEntryValueCandidate(
2132 const MachineInstr &
MI,
const DefinedRegsSet &DefinedRegs)
const {
2133 assert(
MI.isDebugValue() &&
"This must be DBG_VALUE.");
2139 auto *DIVar =
MI.getDebugVariable();
2140 if (!DIVar->isParameter())
2144 if (
MI.getDebugLoc()->getInlinedAt())
2157 if (DefinedRegs.count(
MI.getDebugOperand(0).getReg()))
2163 const DIExpression *Expr =
MI.getDebugExpression();
2175 Regs.insert(MO.
getReg());
2185void VarLocBasedLDV::recordEntryValue(
const MachineInstr &
MI,
2186 const DefinedRegsSet &DefinedRegs,
2187 OpenRangesSet &OpenRanges,
2188 VarLocMap &VarLocIDs) {
2189 if (!ShouldEmitDebugEntryValues)
2192 DebugVariable
V(
MI.getDebugVariable(),
MI.getDebugExpression(),
2193 MI.getDebugLoc()->getInlinedAt());
2195 if (!isEntryValueCandidate(
MI, DefinedRegs) ||
2196 OpenRanges.getEntryValueBackup(V))
2203 DIExpression *NewExpr =
2205 VarLoc EntryValLocAsBackup = VarLoc::CreateEntryBackupLoc(
MI, NewExpr);
2206 LocIndices EntryValLocIDs = VarLocIDs.insert(EntryValLocAsBackup);
2207 OpenRanges.insert(EntryValLocIDs, EntryValLocAsBackup);
2212bool VarLocBasedLDV::ExtendRanges(MachineFunction &MF,
2213 MachineDominatorTree *DomTree,
2214 bool ShouldEmitDebugEntryValues,
2216 unsigned InputDbgValLimit) {
2233 this->ShouldEmitDebugEntryValues = ShouldEmitDebugEntryValues;
2235 LS.scanFunction(MF);
2238 bool OLChanged =
false;
2239 bool MBBJoined =
false;
2241 VarLocMap VarLocIDs;
2243 OpenRangesSet OpenRanges(
Alloc, OverlapFragments);
2245 VarLocInMBB OutLocs;
2247 TransferMap Transfers;
2250 InstToEntryLocMap EntryValTransfers;
2252 RegDefToInstMap RegSetInstrs;
2254 VarToFragments SeenFragments;
2258 SmallPtrSet<const MachineBasicBlock *, 16> ArtificialBlocks;
2260 DenseMap<unsigned int, MachineBasicBlock *> OrderToBB;
2261 DenseMap<MachineBasicBlock *, unsigned int> BBToOrder;
2262 std::priority_queue<unsigned int, std::vector<unsigned int>,
2263 std::greater<unsigned int>>
2265 std::priority_queue<unsigned int, std::vector<unsigned int>,
2266 std::greater<unsigned int>>
2271 DefinedRegsSet DefinedRegs;
2275 MachineBasicBlock &First_MBB = *(MF.
begin());
2276 for (
auto &
MI : First_MBB) {
2278 if (
MI.isDebugValue())
2279 recordEntryValue(
MI, DefinedRegs, OpenRanges, VarLocIDs);
2283 for (
auto &
MBB : MF)
2284 for (
auto &
MI :
MBB)
2285 if (
MI.isDebugValue())
2286 accumulateFragmentMap(
MI, SeenFragments, OverlapFragments);
2288 auto hasNonArtificialLocation = [](
const MachineInstr &
MI) ->
bool {
2290 return DL.getLine() != 0;
2293 for (
auto &
MBB : MF)
2297 LLVM_DEBUG(printVarLocInMBB(MF, OutLocs, VarLocIDs,
2298 "OutLocs after initialization",
dbgs()));
2300 ReversePostOrderTraversal<MachineFunction *> RPOT(&MF);
2301 unsigned int RPONumber = 0;
2302 for (MachineBasicBlock *
MBB : RPOT) {
2303 OrderToBB[RPONumber] =
MBB;
2304 BBToOrder[
MBB] = RPONumber;
2305 Worklist.push(RPONumber);
2310 unsigned NumInputDbgValues = 0;
2311 for (
auto &
MBB : MF)
2312 for (
auto &
MI :
MBB)
2313 if (
MI.isDebugValue())
2314 ++NumInputDbgValues;
2315 if (NumInputDbgValues > InputDbgValLimit) {
2316 LLVM_DEBUG(
dbgs() <<
"Disabling VarLocBasedLDV: " << MF.getName()
2317 <<
" has " << RPONumber <<
" basic blocks and "
2318 << NumInputDbgValues
2319 <<
" input DBG_VALUEs, exceeding limits.\n");
2328 SmallPtrSet<const MachineBasicBlock *, 16> Visited;
2329 while (!Worklist.empty() || !Pending.empty()) {
2333 SmallPtrSet<MachineBasicBlock *, 16> OnPending;
2335 while (!Worklist.empty()) {
2336 MachineBasicBlock *
MBB = OrderToBB[Worklist.top()];
2338 MBBJoined =
join(*
MBB, OutLocs, InLocs, VarLocIDs, Visited,
2340 MBBJoined |= Visited.
insert(
MBB).second;
2348 OpenRanges.insertFromLocSet(getVarLocsInMBB(
MBB, InLocs), VarLocIDs);
2349 LastNonDbgMI =
nullptr;
2350 RegSetInstrs.clear();
2357 bool PacketHasTerminator =
false;
2358 for (
auto BI = BStart; BI != BEnd; ++BI) {
2359 if (BI->isTerminator()) {
2360 PacketHasTerminator =
true;
2364 if (PacketHasTerminator) {
2371 auto FirstOp = (BStart->isBundle()) ? std::next(BStart) : BStart;
2372 for (
auto BI = FirstOp; BI != BEnd; ++BI) {
2373 if (BI->isTerminator())
2375 process(*BI, OpenRanges, VarLocIDs, Transfers, EntryValTransfers,
2380 OLChanged |= transferTerminator(
MBB, OpenRanges, OutLocs, VarLocIDs);
2382 LLVM_DEBUG(printVarLocInMBB(MF, OutLocs, VarLocIDs,
2383 "OutLocs after propagating",
dbgs()));
2384 LLVM_DEBUG(printVarLocInMBB(MF, InLocs, VarLocIDs,
2385 "InLocs after propagating",
dbgs()));
2390 if (OnPending.
insert(s).second) {
2391 Pending.push(BBToOrder[s]);
2396 Worklist.swap(Pending);
2399 assert(Pending.empty() &&
"Pending should be empty");
2403 for (
auto &TR : Transfers) {
2404 assert(!TR.TransferInst->isTerminator() &&
2405 "Cannot insert DBG_VALUE after terminator");
2407 const VarLoc &VL = VarLocIDs[TR.LocationID];
2408 MachineInstr *
MI = VL.BuildDbgValue(MF);
2414 for (
auto &TR : EntryValTransfers) {
2415 MachineInstr *TRInst =
const_cast<MachineInstr *
>(TR.first);
2417 "Cannot insert DBG_VALUE after terminator");
2419 const VarLoc &VL = VarLocIDs[TR.second];
2420 MachineInstr *
MI = VL.BuildDbgValue(MF);
2423 EntryValTransfers.clear();
2427 flushPendingLocs(InLocs, VarLocIDs);
2429 LLVM_DEBUG(printVarLocInMBB(MF, OutLocs, VarLocIDs,
"Final OutLocs",
dbgs()));
2430 LLVM_DEBUG(printVarLocInMBB(MF, InLocs, VarLocIDs,
"Final InLocs",
dbgs()));
2437 return new VarLocBasedLDV();
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static bool isConstant(const MachineInstr &MI)
AMDGPU Prepare AGPR Alloc
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)
static DebugLoc getDebugLoc(MachineBasicBlock::instr_iterator FirstMI, MachineBasicBlock::instr_iterator LastMI)
Return the first DebugLoc that has line number information, given a range of instructions.
Register const TargetRegisterInfo * TRI
Promote Memory to Register
MachineInstr unsigned OpIdx
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 test(unsigned Idx) const
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)
virtual void print(raw_ostream &OS, const Module *M) const
print - Print out the internal state of the pass.
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 insert(iterator I, T &&Elt)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
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
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
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)
FunctionAddr VTableAddr Value
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.
bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)
void erase(Container &C, ValueType V)
Wrapper function to remove a value from a container:
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
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
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.
void array_pod_sort(IteratorTy Start, IteratorTy End)
array_pod_sort - This sorts an array with the specified start and end extent.
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.