diff --git a/llvm/include/llvm/ADT/CoalescingBitVector.h b/llvm/include/llvm/ADT/CoalescingBitVector.h --- a/llvm/include/llvm/ADT/CoalescingBitVector.h +++ b/llvm/include/llvm/ADT/CoalescingBitVector.h @@ -16,6 +16,7 @@ #include "llvm/ADT/IntervalMap.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" @@ -352,6 +353,19 @@ return It; } + /// Return a range iterator which iterates over all of the set bits in the + /// half-open range [Start, End). + iterator_range half_open_range(IndexT Start, + IndexT End) const { + assert(Start < End && "Not a valid range"); + auto StartIt = find(Start); + if (StartIt == end() || *StartIt >= End) + return {end(), end()}; + auto EndIt = StartIt; + EndIt.advanceToLowerBound(End); + return {StartIt, EndIt}; + } + void print(raw_ostream &OS) const { OS << "{"; for (auto It = Intervals.begin(), End = Intervals.end(); It != End; diff --git a/llvm/lib/CodeGen/LiveDebugValues.cpp b/llvm/lib/CodeGen/LiveDebugValues.cpp --- a/llvm/lib/CodeGen/LiveDebugValues.cpp +++ b/llvm/lib/CodeGen/LiveDebugValues.cpp @@ -135,6 +135,9 @@ // to encode non-register locations. uint32_t Index; + /// A special location reserved for VarLocKind::EntryValueCopyBackupKind. + static constexpr uint32_t kEntryValueCopyBackupLocation = (1 << 30); + LocIndex(uint32_t Location, uint32_t Index) : Location(Location), Index(Index) {} @@ -154,6 +157,14 @@ static uint64_t rawIndexForReg(uint32_t Reg) { return LocIndex(Reg, 0).getAsRawInteger(); } + + /// Return a range covering all set indices in the half-open interval + /// reserved for \p Location in \p Set. + static auto indexRangeForLocation(const VarLocSet &Set, uint32_t Location) { + uint64_t Start = LocIndex(Location, 0).getAsRawInteger(); + uint64_t End = LocIndex(Location + 1, 0).getAsRawInteger(); + return Set.half_open_range(Start, End); + } }; class LiveDebugValues : public MachineFunctionPass { @@ -465,10 +476,24 @@ /// location. SmallDenseMap> Loc2Vars; + /// Determine the 32-bit location reserved for \p VL, based on its kind + /// and register number. + static uint32_t getLocationForVar(const VarLoc &VL) { + switch (VL.Kind) { + case VarLoc::RegisterKind: + assert((VL.Loc.RegNo < (1 << 30)) && "Physreg out of range?"); + return VL.Loc.RegNo; + case VarLoc::EntryValueCopyBackupKind: + return LocIndex::kEntryValueCopyBackupLocation; + default: + return 0; + } + } + public: /// Retrieve a unique LocIndex for \p VL. LocIndex insert(const VarLoc &VL) { - uint32_t Location = VL.isDescribedByReg(); + uint32_t Location = getLocationForVar(VL); uint32_t &Index = Var2Index[VL]; if (!Index) { auto &Vars = Loc2Vars[Location]; @@ -565,6 +590,12 @@ "open ranges are inconsistent"); return VarLocs.empty(); } + + /// Get all set IDs for VarLocs of kind EntryValueCopyBackupKind. + auto getEntryValueCopyBackupLocs() const { + return LocIndex::indexRangeForLocation( + getVarLocs(), LocIndex::kEntryValueCopyBackupLocation); + } }; /// Collect all VarLoc IDs from \p CollectFrom for VarLocs of kind @@ -809,7 +840,9 @@ // All register-based VarLocs are assigned indices greater than or equal to // FirstRegIndex. uint64_t FirstRegIndex = LocIndex::rawIndexForReg(1); - for (auto It = CollectFrom.find(FirstRegIndex), End = CollectFrom.end(); + uint64_t FirstInvalidIndex = LocIndex::rawIndexForReg(1 << 30); + for (auto It = CollectFrom.find(FirstRegIndex), + End = CollectFrom.find(FirstInvalidIndex); It != End;) { // We found a VarLoc ID for a VarLoc that lives in a register. Figure out // which register and add it to UsedRegs. @@ -912,11 +945,8 @@ } if (TrySalvageEntryValue) { - for (uint64_t ID : OpenRanges.getVarLocs()) { + for (uint64_t ID : OpenRanges.getEntryValueCopyBackupLocs()) { const VarLoc &VL = VarLocIDs[LocIndex::fromRawInteger(ID)]; - if (!VL.isEntryBackupLoc()) - continue; - if (VL.getEntryValueCopyBackupReg() == Reg && VL.MI.getOperand(0).getReg() == SrcRegOp->getReg()) return false; diff --git a/llvm/unittests/ADT/CoalescingBitVectorTest.cpp b/llvm/unittests/ADT/CoalescingBitVectorTest.cpp --- a/llvm/unittests/ADT/CoalescingBitVectorTest.cpp +++ b/llvm/unittests/ADT/CoalescingBitVectorTest.cpp @@ -31,6 +31,11 @@ return true; } +bool rangesMatch(iterator_range R, + std::initializer_list List) { + return std::equal(R.begin(), R.end(), List.begin(), List.end()); +} + TEST(CoalescingBitVectorTest, Set) { UBitVec::Allocator Alloc; UBitVec BV1(Alloc); @@ -486,6 +491,35 @@ EXPECT_TRUE(It == BV.end()); } +TEST(CoalescingBitVectorTest, HalfOpenRange) { + UBitVec::Allocator Alloc; + + { + UBitVec BV(Alloc); + BV.set({1, 2, 3}); + + EXPECT_TRUE(rangesMatch(BV.half_open_range(0, 5), {1, 2, 3})); + EXPECT_TRUE(rangesMatch(BV.half_open_range(1, 4), {1, 2, 3})); + EXPECT_TRUE(rangesMatch(BV.half_open_range(1, 3), {1, 2})); + EXPECT_TRUE(rangesMatch(BV.half_open_range(2, 3), {2})); + EXPECT_TRUE(rangesMatch(BV.half_open_range(2, 4), {2, 3})); + } + + { + UBitVec BV(Alloc); + BV.set({1, 2, 11, 12}); + + EXPECT_TRUE(rangesMatch(BV.half_open_range(0, 15), {1, 2, 11, 12})); + EXPECT_TRUE(rangesMatch(BV.half_open_range(1, 13), {1, 2, 11, 12})); + EXPECT_TRUE(rangesMatch(BV.half_open_range(1, 12), {1, 2, 11})); + + EXPECT_TRUE(rangesMatch(BV.half_open_range(0, 5), {1, 2})); + EXPECT_TRUE(rangesMatch(BV.half_open_range(1, 5), {1, 2})); + EXPECT_TRUE(rangesMatch(BV.half_open_range(2, 5), {2})); + EXPECT_TRUE(rangesMatch(BV.half_open_range(1, 2), {1})); + } +} + TEST(CoalescingBitVectorTest, Print) { std::string S; {