#ifndef LLVM_CODEGEN_LIVEINTERVALUNION_H
#define LLVM_CODEGEN_LIVEINTERVALUNION_H
#include "llvm/ADT/IntervalMap.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/CodeGen/LiveInterval.h"
#include "llvm/CodeGen/SlotIndexes.h"
#include <cassert>
#include <limits>
namespace llvm {
class raw_ostream;
class TargetRegisterInfo;
#ifndef NDEBUG
template <unsigned Element> class SparseBitVector;
using LiveVirtRegBitSet = SparseBitVector<128>;
#endif
class LiveIntervalUnion {
using LiveSegments = IntervalMap<SlotIndex, LiveInterval*>;
public:
using SegmentIter = LiveSegments::iterator;
using ConstSegmentIter = LiveSegments::const_iterator;
using Allocator = LiveSegments::Allocator;
private:
unsigned Tag = 0;
LiveSegments Segments;
public:
explicit LiveIntervalUnion(Allocator &a) : Segments(a) {}
SegmentIter begin() { return Segments.begin(); }
SegmentIter end() { return Segments.end(); }
SegmentIter find(SlotIndex x) { return Segments.find(x); }
ConstSegmentIter begin() const { return Segments.begin(); }
ConstSegmentIter end() const { return Segments.end(); }
ConstSegmentIter find(SlotIndex x) const { return Segments.find(x); }
bool empty() const { return Segments.empty(); }
SlotIndex startIndex() const { return Segments.start(); }
using Map = LiveSegments;
const Map &getMap() const { return Segments; }
unsigned getTag() const { return Tag; }
bool changedSince(unsigned tag) const { return tag != Tag; }
void unify(LiveInterval &VirtReg, const LiveRange &Range);
void extract(LiveInterval &VirtReg, const LiveRange &Range);
void clear() { Segments.clear(); ++Tag; }
void print(raw_ostream &OS, const TargetRegisterInfo *TRI) const;
#ifndef NDEBUG
void verify(LiveVirtRegBitSet& VisitedVRegs);
#endif
class Query {
const LiveIntervalUnion *LiveUnion = nullptr;
const LiveRange *LR = nullptr;
LiveRange::const_iterator LRI;
ConstSegmentIter LiveUnionI;
SmallVector<LiveInterval*,4> InterferingVRegs;
bool CheckedFirstInterference = false;
bool SeenAllInterferences = false;
unsigned Tag = 0;
unsigned UserTag = 0;
void reset(unsigned NewUserTag, const LiveRange &NewLR,
const LiveIntervalUnion &NewLiveUnion) {
LiveUnion = &NewLiveUnion;
LR = &NewLR;
InterferingVRegs.clear();
CheckedFirstInterference = false;
SeenAllInterferences = false;
Tag = NewLiveUnion.getTag();
UserTag = NewUserTag;
}
public:
Query() = default;
Query(const LiveRange &LR, const LiveIntervalUnion &LIU):
LiveUnion(&LIU), LR(&LR) {}
Query(const Query &) = delete;
Query &operator=(const Query &) = delete;
void init(unsigned NewUserTag, const LiveRange &NewLR,
const LiveIntervalUnion &NewLiveUnion) {
if (UserTag == NewUserTag && LR == &NewLR && LiveUnion == &NewLiveUnion &&
!NewLiveUnion.changedSince(Tag)) {
return;
}
reset(NewUserTag, NewLR, NewLiveUnion);
}
bool checkInterference() { return collectInterferingVRegs(1); }
unsigned collectInterferingVRegs(
unsigned MaxInterferingRegs = std::numeric_limits<unsigned>::max());
bool isSeenInterference(LiveInterval *VirtReg) const;
bool seenAllInterferences() const { return SeenAllInterferences; }
const SmallVectorImpl<LiveInterval*> &interferingVRegs() const {
return InterferingVRegs;
}
};
class Array {
unsigned Size = 0;
LiveIntervalUnion *LIUs = nullptr;
public:
Array() = default;
~Array() { clear(); }
void init(LiveIntervalUnion::Allocator&, unsigned Size);
unsigned size() const { return Size; }
void clear();
LiveIntervalUnion& operator[](unsigned idx) {
assert(idx < Size && "idx out of bounds");
return LIUs[idx];
}
const LiveIntervalUnion& operator[](unsigned Idx) const {
assert(Idx < Size && "Idx out of bounds");
return LIUs[Idx];
}
};
};
}
#endif