File indexing completed on 2026-05-10 08:43:29
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020 #ifndef LLVM_CODEGEN_LIVEINTERVAL_H
0021 #define LLVM_CODEGEN_LIVEINTERVAL_H
0022
0023 #include "llvm/ADT/ArrayRef.h"
0024 #include "llvm/ADT/IntEqClasses.h"
0025 #include "llvm/ADT/STLExtras.h"
0026 #include "llvm/ADT/SmallVector.h"
0027 #include "llvm/ADT/iterator_range.h"
0028 #include "llvm/CodeGen/Register.h"
0029 #include "llvm/CodeGen/SlotIndexes.h"
0030 #include "llvm/MC/LaneBitmask.h"
0031 #include "llvm/Support/Allocator.h"
0032 #include "llvm/Support/MathExtras.h"
0033 #include <algorithm>
0034 #include <cassert>
0035 #include <cstddef>
0036 #include <functional>
0037 #include <memory>
0038 #include <set>
0039 #include <tuple>
0040 #include <utility>
0041
0042 namespace llvm {
0043
0044 class CoalescerPair;
0045 class LiveIntervals;
0046 class MachineRegisterInfo;
0047 class raw_ostream;
0048
0049
0050
0051
0052
0053 class VNInfo {
0054 public:
0055 using Allocator = BumpPtrAllocator;
0056
0057
0058 unsigned id;
0059
0060
0061 SlotIndex def;
0062
0063
0064 VNInfo(unsigned i, SlotIndex d) : id(i), def(d) {}
0065
0066
0067 VNInfo(unsigned i, const VNInfo &orig) : id(i), def(orig.def) {}
0068
0069
0070 void copyFrom(VNInfo &src) {
0071 def = src.def;
0072 }
0073
0074
0075
0076
0077
0078 bool isPHIDef() const { return def.isBlock(); }
0079
0080
0081 bool isUnused() const { return !def.isValid(); }
0082
0083
0084 void markUnused() { def = SlotIndex(); }
0085 };
0086
0087
0088
0089
0090 class LiveQueryResult {
0091 VNInfo *const EarlyVal;
0092 VNInfo *const LateVal;
0093 const SlotIndex EndPoint;
0094 const bool Kill;
0095
0096 public:
0097 LiveQueryResult(VNInfo *EarlyVal, VNInfo *LateVal, SlotIndex EndPoint,
0098 bool Kill)
0099 : EarlyVal(EarlyVal), LateVal(LateVal), EndPoint(EndPoint), Kill(Kill)
0100 {}
0101
0102
0103
0104
0105 VNInfo *valueIn() const {
0106 return EarlyVal;
0107 }
0108
0109
0110
0111
0112 bool isKill() const {
0113 return Kill;
0114 }
0115
0116
0117 bool isDeadDef() const {
0118 return EndPoint.isDead();
0119 }
0120
0121
0122
0123 VNInfo *valueOut() const {
0124 return isDeadDef() ? nullptr : LateVal;
0125 }
0126
0127
0128
0129 VNInfo *valueOutOrDead() const {
0130 return LateVal;
0131 }
0132
0133
0134
0135 VNInfo *valueDefined() const {
0136 return EarlyVal == LateVal ? nullptr : LateVal;
0137 }
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147 SlotIndex endPoint() const {
0148 return EndPoint;
0149 }
0150 };
0151
0152
0153
0154
0155
0156
0157 class LiveRange {
0158 public:
0159
0160
0161
0162 struct Segment {
0163 SlotIndex start;
0164 SlotIndex end;
0165 VNInfo *valno = nullptr;
0166
0167
0168 Segment() = default;
0169
0170 Segment(SlotIndex S, SlotIndex E, VNInfo *V)
0171 : start(S), end(E), valno(V) {
0172 assert(S < E && "Cannot create empty or backwards segment");
0173 }
0174
0175
0176 bool contains(SlotIndex I) const {
0177 return start <= I && I < end;
0178 }
0179
0180
0181 bool containsInterval(SlotIndex S, SlotIndex E) const {
0182 assert((S < E) && "Backwards interval?");
0183 return (start <= S && S < end) && (start < E && E <= end);
0184 }
0185
0186 bool operator<(const Segment &Other) const {
0187 return std::tie(start, end) < std::tie(Other.start, Other.end);
0188 }
0189 bool operator==(const Segment &Other) const {
0190 return start == Other.start && end == Other.end;
0191 }
0192
0193 bool operator!=(const Segment &Other) const {
0194 return !(*this == Other);
0195 }
0196
0197 void dump() const;
0198 };
0199
0200 using Segments = SmallVector<Segment, 2>;
0201 using VNInfoList = SmallVector<VNInfo *, 2>;
0202
0203 Segments segments;
0204 VNInfoList valnos;
0205
0206
0207
0208
0209 using SegmentSet = std::set<Segment>;
0210 std::unique_ptr<SegmentSet> segmentSet;
0211
0212 using iterator = Segments::iterator;
0213 using const_iterator = Segments::const_iterator;
0214
0215 iterator begin() { return segments.begin(); }
0216 iterator end() { return segments.end(); }
0217
0218 const_iterator begin() const { return segments.begin(); }
0219 const_iterator end() const { return segments.end(); }
0220
0221 using vni_iterator = VNInfoList::iterator;
0222 using const_vni_iterator = VNInfoList::const_iterator;
0223
0224 vni_iterator vni_begin() { return valnos.begin(); }
0225 vni_iterator vni_end() { return valnos.end(); }
0226
0227 const_vni_iterator vni_begin() const { return valnos.begin(); }
0228 const_vni_iterator vni_end() const { return valnos.end(); }
0229
0230 iterator_range<vni_iterator> vnis() {
0231 return make_range(vni_begin(), vni_end());
0232 }
0233
0234 iterator_range<const_vni_iterator> vnis() const {
0235 return make_range(vni_begin(), vni_end());
0236 }
0237
0238
0239 LiveRange(bool UseSegmentSet = false)
0240 : segmentSet(UseSegmentSet ? std::make_unique<SegmentSet>()
0241 : nullptr) {}
0242
0243
0244
0245 LiveRange(const LiveRange &Other, BumpPtrAllocator &Allocator) {
0246 assert(Other.segmentSet == nullptr &&
0247 "Copying of LiveRanges with active SegmentSets is not supported");
0248 assign(Other, Allocator);
0249 }
0250
0251
0252 void assign(const LiveRange &Other, BumpPtrAllocator &Allocator) {
0253 if (this == &Other)
0254 return;
0255
0256 assert(Other.segmentSet == nullptr &&
0257 "Copying of LiveRanges with active SegmentSets is not supported");
0258
0259 for (const VNInfo *VNI : Other.valnos)
0260 createValueCopy(VNI, Allocator);
0261
0262 for (const Segment &S : Other.segments)
0263 segments.push_back(Segment(S.start, S.end, valnos[S.valno->id]));
0264 }
0265
0266
0267
0268
0269
0270
0271 iterator advanceTo(iterator I, SlotIndex Pos) {
0272 assert(I != end());
0273 if (Pos >= endIndex())
0274 return end();
0275 while (I->end <= Pos) ++I;
0276 return I;
0277 }
0278
0279 const_iterator advanceTo(const_iterator I, SlotIndex Pos) const {
0280 assert(I != end());
0281 if (Pos >= endIndex())
0282 return end();
0283 while (I->end <= Pos) ++I;
0284 return I;
0285 }
0286
0287
0288
0289
0290
0291
0292
0293
0294 iterator find(SlotIndex Pos);
0295
0296 const_iterator find(SlotIndex Pos) const {
0297 return const_cast<LiveRange*>(this)->find(Pos);
0298 }
0299
0300 void clear() {
0301 valnos.clear();
0302 segments.clear();
0303 }
0304
0305 size_t size() const {
0306 return segments.size();
0307 }
0308
0309 bool hasAtLeastOneValue() const { return !valnos.empty(); }
0310
0311 bool containsOneValue() const { return valnos.size() == 1; }
0312
0313 unsigned getNumValNums() const { return (unsigned)valnos.size(); }
0314
0315
0316
0317 inline VNInfo *getValNumInfo(unsigned ValNo) {
0318 return valnos[ValNo];
0319 }
0320 inline const VNInfo *getValNumInfo(unsigned ValNo) const {
0321 return valnos[ValNo];
0322 }
0323
0324
0325 bool containsValue(const VNInfo *VNI) const {
0326 return VNI && VNI->id < getNumValNums() && VNI == getValNumInfo(VNI->id);
0327 }
0328
0329
0330
0331 VNInfo *getNextValue(SlotIndex Def, VNInfo::Allocator &VNInfoAllocator) {
0332 VNInfo *VNI =
0333 new (VNInfoAllocator) VNInfo((unsigned)valnos.size(), Def);
0334 valnos.push_back(VNI);
0335 return VNI;
0336 }
0337
0338
0339
0340
0341 VNInfo *createDeadDef(SlotIndex Def, VNInfo::Allocator &VNIAlloc);
0342
0343
0344
0345 VNInfo *createDeadDef(VNInfo *VNI);
0346
0347
0348
0349 VNInfo *createValueCopy(const VNInfo *orig,
0350 VNInfo::Allocator &VNInfoAllocator) {
0351 VNInfo *VNI =
0352 new (VNInfoAllocator) VNInfo((unsigned)valnos.size(), *orig);
0353 valnos.push_back(VNI);
0354 return VNI;
0355 }
0356
0357
0358
0359 void RenumberValues();
0360
0361
0362
0363
0364
0365 VNInfo* MergeValueNumberInto(VNInfo *V1, VNInfo *V2);
0366
0367
0368
0369
0370
0371
0372 void MergeSegmentsInAsValue(const LiveRange &RHS, VNInfo *LHSValNo);
0373
0374
0375
0376
0377
0378
0379 void MergeValueInAsValue(const LiveRange &RHS,
0380 const VNInfo *RHSValNo, VNInfo *LHSValNo);
0381
0382 bool empty() const { return segments.empty(); }
0383
0384
0385 SlotIndex beginIndex() const {
0386 assert(!empty() && "Call to beginIndex() on empty range.");
0387 return segments.front().start;
0388 }
0389
0390
0391
0392 SlotIndex endIndex() const {
0393 assert(!empty() && "Call to endIndex() on empty range.");
0394 return segments.back().end;
0395 }
0396
0397 bool expiredAt(SlotIndex index) const {
0398 return index >= endIndex();
0399 }
0400
0401 bool liveAt(SlotIndex index) const {
0402 const_iterator r = find(index);
0403 return r != end() && r->start <= index;
0404 }
0405
0406
0407
0408 const Segment *getSegmentContaining(SlotIndex Idx) const {
0409 const_iterator I = FindSegmentContaining(Idx);
0410 return I == end() ? nullptr : &*I;
0411 }
0412
0413
0414
0415 Segment *getSegmentContaining(SlotIndex Idx) {
0416 iterator I = FindSegmentContaining(Idx);
0417 return I == end() ? nullptr : &*I;
0418 }
0419
0420
0421 VNInfo *getVNInfoAt(SlotIndex Idx) const {
0422 const_iterator I = FindSegmentContaining(Idx);
0423 return I == end() ? nullptr : I->valno;
0424 }
0425
0426
0427
0428
0429 VNInfo *getVNInfoBefore(SlotIndex Idx) const {
0430 const_iterator I = FindSegmentContaining(Idx.getPrevSlot());
0431 return I == end() ? nullptr : I->valno;
0432 }
0433
0434
0435
0436 iterator FindSegmentContaining(SlotIndex Idx) {
0437 iterator I = find(Idx);
0438 return I != end() && I->start <= Idx ? I : end();
0439 }
0440
0441 const_iterator FindSegmentContaining(SlotIndex Idx) const {
0442 const_iterator I = find(Idx);
0443 return I != end() && I->start <= Idx ? I : end();
0444 }
0445
0446
0447
0448 bool overlaps(const LiveRange &other) const {
0449 if (other.empty())
0450 return false;
0451 return overlapsFrom(other, other.begin());
0452 }
0453
0454
0455
0456
0457
0458
0459 bool overlaps(const LiveRange &Other, const CoalescerPair &CP,
0460 const SlotIndexes&) const;
0461
0462
0463
0464 bool overlaps(SlotIndex Start, SlotIndex End) const;
0465
0466
0467
0468
0469 bool overlapsFrom(const LiveRange &Other, const_iterator StartPos) const;
0470
0471
0472
0473
0474
0475 bool covers(const LiveRange &Other) const;
0476
0477
0478
0479
0480 iterator addSegment(Segment S);
0481
0482
0483
0484
0485
0486
0487
0488
0489
0490
0491
0492
0493
0494
0495
0496 std::pair<VNInfo*,bool> extendInBlock(ArrayRef<SlotIndex> Undefs,
0497 SlotIndex StartIdx, SlotIndex Kill);
0498
0499
0500
0501
0502
0503
0504 VNInfo *extendInBlock(SlotIndex StartIdx, SlotIndex Kill);
0505
0506
0507
0508
0509 void join(LiveRange &Other,
0510 const int *ValNoAssignments,
0511 const int *RHSValNoAssignments,
0512 SmallVectorImpl<VNInfo *> &NewVNInfo);
0513
0514
0515
0516
0517
0518 bool isLocal(SlotIndex Start, SlotIndex End) const {
0519 return beginIndex() > Start.getBaseIndex() &&
0520 endIndex() < End.getBoundaryIndex();
0521 }
0522
0523
0524
0525
0526 void removeSegment(SlotIndex Start, SlotIndex End,
0527 bool RemoveDeadValNo = false);
0528
0529 void removeSegment(Segment S, bool RemoveDeadValNo = false) {
0530 removeSegment(S.start, S.end, RemoveDeadValNo);
0531 }
0532
0533
0534 iterator removeSegment(iterator I, bool RemoveDeadValNo = false);
0535
0536
0537 void removeValNoIfDead(VNInfo *ValNo);
0538
0539
0540
0541
0542 LiveQueryResult Query(SlotIndex Idx) const {
0543
0544 const_iterator I = find(Idx.getBaseIndex());
0545 const_iterator E = end();
0546 if (I == E)
0547 return LiveQueryResult(nullptr, nullptr, SlotIndex(), false);
0548
0549
0550
0551
0552 VNInfo *EarlyVal = nullptr;
0553 VNInfo *LateVal = nullptr;
0554 SlotIndex EndPoint;
0555 bool Kill = false;
0556 if (I->start <= Idx.getBaseIndex()) {
0557 EarlyVal = I->valno;
0558 EndPoint = I->end;
0559
0560 if (SlotIndex::isSameInstr(Idx, I->end)) {
0561 Kill = true;
0562 if (++I == E)
0563 return LiveQueryResult(EarlyVal, LateVal, EndPoint, Kill);
0564 }
0565
0566
0567
0568
0569 if (EarlyVal->def == Idx.getBaseIndex())
0570 EarlyVal = nullptr;
0571 }
0572
0573
0574 if (!SlotIndex::isEarlierInstr(Idx, I->start)) {
0575 LateVal = I->valno;
0576 EndPoint = I->end;
0577 }
0578 return LiveQueryResult(EarlyVal, LateVal, EndPoint, Kill);
0579 }
0580
0581
0582
0583 void removeValNo(VNInfo *ValNo);
0584
0585
0586
0587 bool isZeroLength(SlotIndexes *Indexes) const {
0588 for (const Segment &S : segments)
0589 if (Indexes->getNextNonNullIndex(S.start).getBaseIndex() <
0590 S.end.getBaseIndex())
0591 return false;
0592 return true;
0593 }
0594
0595
0596
0597
0598 bool isLiveAtIndexes(ArrayRef<SlotIndex> Slots) const;
0599
0600 bool operator<(const LiveRange& other) const {
0601 const SlotIndex &thisIndex = beginIndex();
0602 const SlotIndex &otherIndex = other.beginIndex();
0603 return thisIndex < otherIndex;
0604 }
0605
0606
0607
0608 bool isUndefIn(ArrayRef<SlotIndex> Undefs, SlotIndex Begin,
0609 SlotIndex End) const {
0610 return llvm::any_of(Undefs, [Begin, End](SlotIndex Idx) -> bool {
0611 return Begin <= Idx && Idx < End;
0612 });
0613 }
0614
0615
0616
0617
0618
0619 void flushSegmentSet();
0620
0621
0622
0623
0624
0625
0626
0627 template <typename Range, typename OutputIt>
0628 bool findIndexesLiveAt(Range &&R, OutputIt O) const {
0629 assert(llvm::is_sorted(R));
0630 auto Idx = R.begin(), EndIdx = R.end();
0631 auto Seg = segments.begin(), EndSeg = segments.end();
0632 bool Found = false;
0633 while (Idx != EndIdx && Seg != EndSeg) {
0634
0635
0636 if (Seg->end <= *Idx) {
0637 Seg =
0638 std::upper_bound(++Seg, EndSeg, *Idx, [=](auto V, const auto &S) {
0639 return V < S.end;
0640 });
0641 if (Seg == EndSeg)
0642 break;
0643 }
0644 auto NotLessStart = std::lower_bound(Idx, EndIdx, Seg->start);
0645 if (NotLessStart == EndIdx)
0646 break;
0647 auto NotLessEnd = std::lower_bound(NotLessStart, EndIdx, Seg->end);
0648 if (NotLessEnd != NotLessStart) {
0649 Found = true;
0650 O = std::copy(NotLessStart, NotLessEnd, O);
0651 }
0652 Idx = NotLessEnd;
0653 ++Seg;
0654 }
0655 return Found;
0656 }
0657
0658 void print(raw_ostream &OS) const;
0659 void dump() const;
0660
0661
0662
0663
0664 #ifdef NDEBUG
0665 [[nodiscard]] bool verify() const { return true; }
0666 #else
0667 [[nodiscard]] bool verify() const;
0668 #endif
0669
0670 protected:
0671
0672 void append(const LiveRange::Segment S);
0673
0674 private:
0675 friend class LiveRangeUpdater;
0676 void addSegmentToSet(Segment S);
0677 void markValNoForDeletion(VNInfo *V);
0678 };
0679
0680 inline raw_ostream &operator<<(raw_ostream &OS, const LiveRange &LR) {
0681 LR.print(OS);
0682 return OS;
0683 }
0684
0685
0686
0687 class LiveInterval : public LiveRange {
0688 public:
0689 using super = LiveRange;
0690
0691
0692
0693
0694 class SubRange : public LiveRange {
0695 public:
0696 SubRange *Next = nullptr;
0697 LaneBitmask LaneMask;
0698
0699
0700 SubRange(LaneBitmask LaneMask) : LaneMask(LaneMask) {}
0701
0702
0703 SubRange(LaneBitmask LaneMask, const LiveRange &Other,
0704 BumpPtrAllocator &Allocator)
0705 : LiveRange(Other, Allocator), LaneMask(LaneMask) {}
0706
0707 void print(raw_ostream &OS) const;
0708 void dump() const;
0709 };
0710
0711 private:
0712 SubRange *SubRanges = nullptr;
0713
0714 const Register Reg;
0715 float Weight = 0.0;
0716
0717 public:
0718 Register reg() const { return Reg; }
0719 float weight() const { return Weight; }
0720 void incrementWeight(float Inc) { Weight += Inc; }
0721 void setWeight(float Value) { Weight = Value; }
0722
0723 LiveInterval(unsigned Reg, float Weight) : Reg(Reg), Weight(Weight) {}
0724
0725 ~LiveInterval() {
0726 clearSubRanges();
0727 }
0728
0729 template<typename T>
0730 class SingleLinkedListIterator {
0731 T *P;
0732
0733 public:
0734 using difference_type = ptrdiff_t;
0735 using value_type = T;
0736 using pointer = T *;
0737 using reference = T &;
0738 using iterator_category = std::forward_iterator_tag;
0739
0740 SingleLinkedListIterator(T *P) : P(P) {}
0741
0742 SingleLinkedListIterator<T> &operator++() {
0743 P = P->Next;
0744 return *this;
0745 }
0746 SingleLinkedListIterator<T> operator++(int) {
0747 SingleLinkedListIterator res = *this;
0748 ++*this;
0749 return res;
0750 }
0751 bool operator!=(const SingleLinkedListIterator<T> &Other) const {
0752 return P != Other.operator->();
0753 }
0754 bool operator==(const SingleLinkedListIterator<T> &Other) const {
0755 return P == Other.operator->();
0756 }
0757 T &operator*() const {
0758 return *P;
0759 }
0760 T *operator->() const {
0761 return P;
0762 }
0763 };
0764
0765 using subrange_iterator = SingleLinkedListIterator<SubRange>;
0766 using const_subrange_iterator = SingleLinkedListIterator<const SubRange>;
0767
0768 subrange_iterator subrange_begin() {
0769 return subrange_iterator(SubRanges);
0770 }
0771 subrange_iterator subrange_end() {
0772 return subrange_iterator(nullptr);
0773 }
0774
0775 const_subrange_iterator subrange_begin() const {
0776 return const_subrange_iterator(SubRanges);
0777 }
0778 const_subrange_iterator subrange_end() const {
0779 return const_subrange_iterator(nullptr);
0780 }
0781
0782 iterator_range<subrange_iterator> subranges() {
0783 return make_range(subrange_begin(), subrange_end());
0784 }
0785
0786 iterator_range<const_subrange_iterator> subranges() const {
0787 return make_range(subrange_begin(), subrange_end());
0788 }
0789
0790
0791
0792 SubRange *createSubRange(BumpPtrAllocator &Allocator,
0793 LaneBitmask LaneMask) {
0794 SubRange *Range = new (Allocator) SubRange(LaneMask);
0795 appendSubRange(Range);
0796 return Range;
0797 }
0798
0799
0800
0801 SubRange *createSubRangeFrom(BumpPtrAllocator &Allocator,
0802 LaneBitmask LaneMask,
0803 const LiveRange &CopyFrom) {
0804 SubRange *Range = new (Allocator) SubRange(LaneMask, CopyFrom, Allocator);
0805 appendSubRange(Range);
0806 return Range;
0807 }
0808
0809
0810 bool hasSubRanges() const {
0811 return SubRanges != nullptr;
0812 }
0813
0814
0815 void clearSubRanges();
0816
0817
0818
0819 void removeEmptySubRanges();
0820
0821
0822
0823 unsigned getSize() const;
0824
0825
0826 bool isSpillable() const { return Weight != huge_valf; }
0827
0828
0829 void markNotSpillable() { Weight = huge_valf; }
0830
0831
0832
0833 void computeSubRangeUndefs(SmallVectorImpl<SlotIndex> &Undefs,
0834 LaneBitmask LaneMask,
0835 const MachineRegisterInfo &MRI,
0836 const SlotIndexes &Indexes) const;
0837
0838
0839
0840
0841
0842
0843
0844
0845
0846
0847
0848
0849
0850
0851
0852
0853
0854
0855
0856
0857
0858
0859
0860
0861
0862
0863
0864
0865
0866
0867
0868
0869
0870
0871
0872
0873
0874
0875
0876
0877 void refineSubRanges(BumpPtrAllocator &Allocator, LaneBitmask LaneMask,
0878 std::function<void(LiveInterval::SubRange &)> Apply,
0879 const SlotIndexes &Indexes,
0880 const TargetRegisterInfo &TRI,
0881 unsigned ComposeSubRegIdx = 0);
0882
0883 bool operator<(const LiveInterval& other) const {
0884 const SlotIndex &thisIndex = beginIndex();
0885 const SlotIndex &otherIndex = other.beginIndex();
0886 return std::tie(thisIndex, Reg) < std::tie(otherIndex, other.Reg);
0887 }
0888
0889 void print(raw_ostream &OS) const;
0890 void dump() const;
0891
0892
0893
0894
0895 #ifdef NDEBUG
0896 [[nodiscard]] bool verify(const MachineRegisterInfo *MRI = nullptr) const {
0897 return true;
0898 }
0899 #else
0900 [[nodiscard]] bool verify(const MachineRegisterInfo *MRI = nullptr) const;
0901 #endif
0902
0903 private:
0904
0905 void appendSubRange(SubRange *Range) {
0906 Range->Next = SubRanges;
0907 SubRanges = Range;
0908 }
0909
0910
0911 void freeSubRange(SubRange *S);
0912 };
0913
0914 inline raw_ostream &operator<<(raw_ostream &OS,
0915 const LiveInterval::SubRange &SR) {
0916 SR.print(OS);
0917 return OS;
0918 }
0919
0920 inline raw_ostream &operator<<(raw_ostream &OS, const LiveInterval &LI) {
0921 LI.print(OS);
0922 return OS;
0923 }
0924
0925 raw_ostream &operator<<(raw_ostream &OS, const LiveRange::Segment &S);
0926
0927 inline bool operator<(SlotIndex V, const LiveRange::Segment &S) {
0928 return V < S.start;
0929 }
0930
0931 inline bool operator<(const LiveRange::Segment &S, SlotIndex V) {
0932 return S.start < V;
0933 }
0934
0935
0936
0937
0938
0939
0940
0941
0942
0943 class LiveRangeUpdater {
0944 LiveRange *LR;
0945 SlotIndex LastStart;
0946 LiveRange::iterator WriteI;
0947 LiveRange::iterator ReadI;
0948 SmallVector<LiveRange::Segment, 16> Spills;
0949 void mergeSpills();
0950
0951 public:
0952
0953
0954 LiveRangeUpdater(LiveRange *lr = nullptr) : LR(lr) {}
0955
0956 ~LiveRangeUpdater() { flush(); }
0957
0958
0959
0960
0961 void add(LiveRange::Segment);
0962
0963 void add(SlotIndex Start, SlotIndex End, VNInfo *VNI) {
0964 add(LiveRange::Segment(Start, End, VNI));
0965 }
0966
0967
0968
0969 bool isDirty() const { return LastStart.isValid(); }
0970
0971
0972
0973 void flush();
0974
0975
0976 void setDest(LiveRange *lr) {
0977 if (LR != lr && isDirty())
0978 flush();
0979 LR = lr;
0980 }
0981
0982
0983 LiveRange *getDest() const { return LR; }
0984
0985 void dump() const;
0986 void print(raw_ostream&) const;
0987 };
0988
0989 inline raw_ostream &operator<<(raw_ostream &OS, const LiveRangeUpdater &X) {
0990 X.print(OS);
0991 return OS;
0992 }
0993
0994
0995
0996
0997
0998
0999
1000
1001
1002
1003
1004
1005
1006
1007 class ConnectedVNInfoEqClasses {
1008 LiveIntervals &LIS;
1009 IntEqClasses EqClass;
1010
1011 public:
1012 explicit ConnectedVNInfoEqClasses(LiveIntervals &lis) : LIS(lis) {}
1013
1014
1015
1016 unsigned Classify(const LiveRange &LR);
1017
1018
1019
1020 unsigned getEqClass(const VNInfo *VNI) const { return EqClass[VNI->id]; }
1021
1022
1023
1024
1025
1026 void Distribute(LiveInterval &LI, LiveInterval *LIV[],
1027 MachineRegisterInfo &MRI);
1028 };
1029
1030 }
1031
1032 #endif