mirror of
https://github.com/RPCSX/llvm.git
synced 2024-12-23 12:40:38 +00:00
[RDF] Switch RegisterAggr to a bit vector of register units
This avoids many complications related to the complex register aliasing schemes. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@300345 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
ec87df5c2d
commit
0e9e7d51d9
@ -259,7 +259,7 @@ void HexagonOptAddrMode::getAllRealUses(NodeAddr<StmtNode *> SA,
|
||||
<< Print<Liveness::RefMap>(phiUse, *DFG) << "\n");
|
||||
if (!phiUse.empty()) {
|
||||
for (auto I : phiUse) {
|
||||
if (DR.Reg != I.first)
|
||||
if (!DFG->getPRI().alias(RegisterRef(I.first), DR))
|
||||
continue;
|
||||
auto phiUseSet = I.second;
|
||||
for (auto phiUI : phiUseSet) {
|
||||
|
@ -913,10 +913,11 @@ void DataFlowGraph::build(unsigned Options) {
|
||||
}
|
||||
|
||||
// Add function-entry phi nodes for the live-in registers.
|
||||
for (std::pair<RegisterId,LaneBitmask> P : LiveIns) {
|
||||
//for (std::pair<RegisterId,LaneBitmask> P : LiveIns) {
|
||||
for (auto I = LiveIns.rr_begin(), E = LiveIns.rr_end(); I != E; ++I) {
|
||||
RegisterRef RR = *I;
|
||||
NodeAddr<PhiNode*> PA = newPhi(EA);
|
||||
uint16_t PhiFlags = NodeAttrs::PhiRef | NodeAttrs::Preserving;
|
||||
RegisterRef RR(P.first, P.second);
|
||||
NodeAddr<DefNode*> DA = newDef(PA, RR, PhiFlags);
|
||||
PA.Addr->addMember(DA, *this);
|
||||
}
|
||||
@ -993,9 +994,9 @@ RegisterRef DataFlowGraph::restrictRef(RegisterRef AR, RegisterRef BR) const {
|
||||
return M.any() ? RegisterRef(AR.Reg, M) : RegisterRef();
|
||||
}
|
||||
#ifndef NDEBUG
|
||||
RegisterRef NAR = PRI.normalize(AR);
|
||||
RegisterRef NBR = PRI.normalize(BR);
|
||||
assert(NAR.Reg != NBR.Reg);
|
||||
// RegisterRef NAR = PRI.normalize(AR);
|
||||
// RegisterRef NBR = PRI.normalize(BR);
|
||||
// assert(NAR.Reg != NBR.Reg);
|
||||
#endif
|
||||
// This isn't strictly correct, because the overlap may happen in the
|
||||
// part masked out.
|
||||
|
@ -797,19 +797,9 @@ void Liveness::computeLiveIns() {
|
||||
//dbgs() << "\tcomp = " << Print<RegisterAggr>(LiveMap[&B], DFG) << '\n';
|
||||
|
||||
LV.clear();
|
||||
for (std::pair<RegisterId,LaneBitmask> P : LiveMap[&B]) {
|
||||
MCSubRegIndexIterator S(P.first, &TRI);
|
||||
if (!S.isValid()) {
|
||||
LV.push_back(RegisterRef(P.first));
|
||||
continue;
|
||||
}
|
||||
do {
|
||||
LaneBitmask M = TRI.getSubRegIndexLaneMask(S.getSubRegIndex());
|
||||
if ((M & P.second).any())
|
||||
LV.push_back(RegisterRef(S.getSubReg()));
|
||||
++S;
|
||||
} while (S.isValid());
|
||||
}
|
||||
const RegisterAggr &LG = LiveMap[&B];
|
||||
for (auto I = LG.rr_begin(), E = LG.rr_end(); I != E; ++I)
|
||||
LV.push_back(*I);
|
||||
std::sort(LV.begin(), LV.end());
|
||||
dbgs() << "\tcomp = {";
|
||||
for (auto I : LV)
|
||||
@ -830,9 +820,10 @@ void Liveness::resetLiveIns() {
|
||||
for (auto I : T)
|
||||
B.removeLiveIn(I);
|
||||
// Add the newly computed live-ins.
|
||||
auto &LiveIns = LiveMap[&B];
|
||||
for (auto I : LiveIns) {
|
||||
B.addLiveIn({MCPhysReg(I.first), I.second});
|
||||
const RegisterAggr &LiveIns = LiveMap[&B];
|
||||
for (auto I = LiveIns.rr_begin(), E = LiveIns.rr_end(); I != E; ++I) {
|
||||
RegisterRef R = *I;
|
||||
B.addLiveIn({MCPhysReg(R.Reg), R.Mask});
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1032,10 +1023,9 @@ void Liveness::traverse(MachineBasicBlock *B, RefMap &LiveIn) {
|
||||
// registers are not covering LRef. The first def from the
|
||||
// upward chain will be live.
|
||||
// Subtract all accumulated defs (RRs) from LRef.
|
||||
RegisterAggr L(PRI);
|
||||
L.insert(LRef).clear(RRs);
|
||||
assert(!L.empty());
|
||||
NewDefs.insert({TA.Id,L.begin()->second});
|
||||
RegisterRef T = RRs.clearIn(LRef);
|
||||
assert(T);
|
||||
NewDefs.insert({TA.Id,T.Mask});
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -33,22 +33,33 @@ PhysicalRegisterInfo::PhysicalRegisterInfo(const TargetRegisterInfo &tri,
|
||||
}
|
||||
}
|
||||
|
||||
auto HasPartialOverlaps = [this] (uint32_t Reg) -> bool {
|
||||
for (MCRegAliasIterator A(Reg, &TRI, false); A.isValid(); ++A)
|
||||
if (!TRI.isSubRegister(Reg, *A) && !TRI.isSubRegister(*A, Reg))
|
||||
return true;
|
||||
return false;
|
||||
};
|
||||
UnitInfos.resize(TRI.getNumRegUnits());
|
||||
|
||||
for (MCPhysReg R = 1, NR = TRI.getNumRegs(); R != NR; ++R)
|
||||
RegInfos[R].Partial = HasPartialOverlaps(R);
|
||||
|
||||
for (MCPhysReg R = 1, NR = TRI.getNumRegs(); R != NR; ++R) {
|
||||
MCPhysReg SuperR = R;
|
||||
for (MCSuperRegIterator S(R, &TRI, false); S.isValid(); ++S)
|
||||
if (!RegInfos[*S].Partial)
|
||||
SuperR = *S;
|
||||
RegInfos[R].MaxSuper = SuperR;
|
||||
for (uint32_t U = 0, NU = TRI.getNumRegUnits(); U != NU; ++U) {
|
||||
if (UnitInfos[U].Reg != 0)
|
||||
continue;
|
||||
MCRegUnitRootIterator R(U, &TRI);
|
||||
assert(R.isValid());
|
||||
RegisterId F = *R;
|
||||
++R;
|
||||
if (R.isValid()) {
|
||||
UnitInfos[U].Mask = LaneBitmask::getAll();
|
||||
UnitInfos[U].Reg = F;
|
||||
} else {
|
||||
for (MCRegUnitMaskIterator I(F, &TRI); I.isValid(); ++I) {
|
||||
std::pair<uint32_t,LaneBitmask> P = *I;
|
||||
UnitInfo &UI = UnitInfos[P.first];
|
||||
UI.Reg = F;
|
||||
if (P.second.any()) {
|
||||
UI.Mask = P.second;
|
||||
} else {
|
||||
if (const TargetRegisterClass *RC = RegInfos[F].RegClass)
|
||||
UI.Mask = RC->LaneMask;
|
||||
else
|
||||
UI.Mask = LaneBitmask::getAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const uint32_t *RM : TRI.getRegMasks())
|
||||
@ -61,22 +72,7 @@ PhysicalRegisterInfo::PhysicalRegisterInfo(const TargetRegisterInfo &tri,
|
||||
}
|
||||
|
||||
RegisterRef PhysicalRegisterInfo::normalize(RegisterRef RR) const {
|
||||
if (PhysicalRegisterInfo::isRegMaskId(RR.Reg))
|
||||
return RR;
|
||||
RegisterId SuperReg = RegInfos[RR.Reg].MaxSuper;
|
||||
if (RR.Reg == SuperReg)
|
||||
return RR;
|
||||
|
||||
const TargetRegisterClass *RC = RegInfos[RR.Reg].RegClass;
|
||||
LaneBitmask RCMask = RC != nullptr ? RC->LaneMask : LaneBitmask(0x00000001);
|
||||
LaneBitmask Common = RR.Mask & RCMask;
|
||||
|
||||
// Ex: IP/EIP/RIP
|
||||
// assert(RC != nullptr || RR.Reg == SuperReg);
|
||||
uint32_t Sub = TRI.getSubRegIndex(SuperReg, RR.Reg);
|
||||
LaneBitmask SuperMask = TRI.composeSubRegIndexLaneMask(Sub, Common);
|
||||
assert(RR.Mask.none() || SuperMask.any());
|
||||
return RegisterRef(SuperReg, SuperMask);
|
||||
return RR;
|
||||
}
|
||||
|
||||
std::set<RegisterId> PhysicalRegisterInfo::getAliasSet(RegisterId Reg) const {
|
||||
@ -217,19 +213,11 @@ bool RegisterAggr::hasAliasOf(RegisterRef RR) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
RegisterRef NR = PRI.normalize(RR);
|
||||
auto F = Masks.find(NR.Reg);
|
||||
if (F != Masks.end()) {
|
||||
if ((F->second & NR.Mask).any())
|
||||
return true;
|
||||
}
|
||||
if (CheckUnits || PRI.hasPartialOverlaps(NR.Reg)) {
|
||||
for (MCRegUnitMaskIterator U(RR.Reg, &PRI.getTRI()); U.isValid(); ++U) {
|
||||
std::pair<RegisterId,LaneBitmask> P = *U;
|
||||
if (P.second.none() || (P.second & RR.Mask).any())
|
||||
if (ExpUnits.test(P.first))
|
||||
return true;
|
||||
}
|
||||
for (MCRegUnitMaskIterator U(RR.Reg, &PRI.getTRI()); U.isValid(); ++U) {
|
||||
std::pair<uint32_t,LaneBitmask> P = *U;
|
||||
if (P.second.none() || (P.second & RR.Mask).any())
|
||||
if (Units.test(P.first))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -247,25 +235,13 @@ bool RegisterAggr::hasCoverOf(RegisterRef RR) const {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Always have a cover for empty lane mask.
|
||||
RegisterRef NR = PRI.normalize(RR);
|
||||
if (NR.Mask.none())
|
||||
return true;
|
||||
auto F = Masks.find(NR.Reg);
|
||||
if (F != Masks.end()) {
|
||||
if ((NR.Mask & F->second) == NR.Mask)
|
||||
return true;
|
||||
for (MCRegUnitMaskIterator U(RR.Reg, &PRI.getTRI()); U.isValid(); ++U) {
|
||||
std::pair<uint32_t,LaneBitmask> P = *U;
|
||||
if (P.second.none() || (P.second & RR.Mask).any())
|
||||
if (!Units.test(P.first))
|
||||
return false;
|
||||
}
|
||||
if (CheckUnits || PRI.hasPartialOverlaps(NR.Reg)) {
|
||||
for (MCRegUnitMaskIterator U(RR.Reg, &PRI.getTRI()); U.isValid(); ++U) {
|
||||
std::pair<RegisterId,LaneBitmask> P = *U;
|
||||
if (P.second.none() || (P.second & RR.Mask).any())
|
||||
if (!ExpUnits.test(P.first))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
RegisterAggr &RegisterAggr::insert(RegisterRef RR) {
|
||||
@ -280,99 +256,34 @@ RegisterAggr &RegisterAggr::insert(RegisterRef RR) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
RegisterRef NR = PRI.normalize(RR);
|
||||
auto F = Masks.find(NR.Reg);
|
||||
if (F == Masks.end())
|
||||
Masks.insert({NR.Reg, NR.Mask});
|
||||
else
|
||||
F->second |= NR.Mask;
|
||||
|
||||
// If the register has any partial overlaps, the mask will not be sufficient
|
||||
// to accurately represent aliasing/covering information. Add all units to
|
||||
// the bit vector.
|
||||
if (PRI.hasPartialOverlaps(NR.Reg)) {
|
||||
for (MCRegUnitMaskIterator U(RR.Reg, &PRI.getTRI()); U.isValid(); ++U) {
|
||||
std::pair<RegisterId,LaneBitmask> P = *U;
|
||||
if (P.second.none() || (P.second & RR.Mask).none())
|
||||
continue;
|
||||
ExpUnits.set(P.first);
|
||||
CheckUnits = true;
|
||||
}
|
||||
for (MCRegUnitMaskIterator U(RR.Reg, &PRI.getTRI()); U.isValid(); ++U) {
|
||||
std::pair<uint32_t,LaneBitmask> P = *U;
|
||||
if (P.second.none() || (P.second & RR.Mask).any())
|
||||
Units.set(P.first);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
RegisterAggr &RegisterAggr::insert(const RegisterAggr &RG) {
|
||||
for (std::pair<RegisterId,LaneBitmask> P : RG.Masks)
|
||||
insert(RegisterRef(P.first, P.second));
|
||||
Units |= RG.Units;
|
||||
return *this;
|
||||
}
|
||||
|
||||
RegisterAggr &RegisterAggr::intersect(RegisterRef RR) {
|
||||
if (PhysicalRegisterInfo::isRegMaskId(RR.Reg))
|
||||
return intersect(RegisterAggr(PRI).insert(RR));
|
||||
|
||||
RegisterRef NR = PRI.normalize(RR);
|
||||
auto F = Masks.find(NR.Reg);
|
||||
LaneBitmask M;
|
||||
if (F != Masks.end())
|
||||
M = NR.Mask & F->second;
|
||||
Masks.clear();
|
||||
ExpUnits.clear();
|
||||
CheckUnits = false;
|
||||
if (M.any())
|
||||
insert(RegisterRef(NR.Reg, M));
|
||||
return *this;
|
||||
return intersect(RegisterAggr(PRI).insert(RR));
|
||||
}
|
||||
|
||||
RegisterAggr &RegisterAggr::intersect(const RegisterAggr &RG) {
|
||||
for (auto I = Masks.begin(); I != Masks.end(); ) {
|
||||
auto F = RG.Masks.find(I->first);
|
||||
if (F == RG.Masks.end()) {
|
||||
I = Masks.erase(I);
|
||||
} else {
|
||||
I->second &= F->second;
|
||||
++I;
|
||||
}
|
||||
}
|
||||
if (CheckUnits && RG.CheckUnits) {
|
||||
ExpUnits &= RG.ExpUnits;
|
||||
if (ExpUnits.empty())
|
||||
CheckUnits = false;
|
||||
} else {
|
||||
ExpUnits.clear();
|
||||
CheckUnits = false;
|
||||
}
|
||||
Units &= RG.Units;
|
||||
return *this;
|
||||
}
|
||||
|
||||
RegisterAggr &RegisterAggr::clear(RegisterRef RR) {
|
||||
if (PhysicalRegisterInfo::isRegMaskId(RR.Reg)) {
|
||||
// XXX SLOW
|
||||
const uint32_t *MB = PRI.getRegMaskBits(RR.Reg);
|
||||
for (unsigned i = 1, e = PRI.getTRI().getNumRegs(); i != e; ++i) {
|
||||
if (MB[i/32] & (1u << (i%32)))
|
||||
continue;
|
||||
clear(RegisterRef(i, LaneBitmask::getAll()));
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
RegisterRef NR = PRI.normalize(RR);
|
||||
auto F = Masks.find(NR.Reg);
|
||||
if (F == Masks.end())
|
||||
return *this;
|
||||
LaneBitmask NewM = F->second & ~NR.Mask;
|
||||
if (NewM.none())
|
||||
Masks.erase(F);
|
||||
else
|
||||
F->second = NewM;
|
||||
return *this;
|
||||
return clear(RegisterAggr(PRI).insert(RR));
|
||||
}
|
||||
|
||||
RegisterAggr &RegisterAggr::clear(const RegisterAggr &RG) {
|
||||
for (std::pair<RegisterId,LaneBitmask> P : RG.Masks)
|
||||
clear(RegisterRef(P.first, P.second));
|
||||
Units.reset(RG.Units);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -381,22 +292,75 @@ RegisterRef RegisterAggr::intersectWith(RegisterRef RR) const {
|
||||
T.insert(RR).intersect(*this);
|
||||
if (T.empty())
|
||||
return RegisterRef();
|
||||
return RegisterRef(T.begin()->first, T.begin()->second);
|
||||
RegisterRef NR = T.makeRegRef();
|
||||
assert(NR);
|
||||
return NR;
|
||||
}
|
||||
|
||||
RegisterRef RegisterAggr::clearIn(RegisterRef RR) const {
|
||||
RegisterAggr T(PRI);
|
||||
T.insert(RR).clear(*this);
|
||||
if (T.empty())
|
||||
return RegisterAggr(PRI).insert(RR).clear(*this).makeRegRef();
|
||||
}
|
||||
|
||||
RegisterRef RegisterAggr::makeRegRef() const {
|
||||
int U = Units.find_first();
|
||||
if (U < 0)
|
||||
return RegisterRef();
|
||||
return RegisterRef(T.begin()->first, T.begin()->second);
|
||||
|
||||
auto AliasedRegs = [this] (uint32_t Unit, BitVector &Regs) {
|
||||
for (MCRegUnitRootIterator R(Unit, &PRI.getTRI()); R.isValid(); ++R)
|
||||
for (MCSuperRegIterator S(*R, &PRI.getTRI(), true); S.isValid(); ++S)
|
||||
Regs.set(*S);
|
||||
};
|
||||
|
||||
// Find the set of all registers that are aliased to all the units
|
||||
// in this aggregate.
|
||||
|
||||
// Get all the registers aliased to the first unit in the bit vector.
|
||||
BitVector Regs(PRI.getTRI().getNumRegs());
|
||||
AliasedRegs(U, Regs);
|
||||
U = Units.find_next(U);
|
||||
|
||||
// For each other unit, intersect it with the set of all registers
|
||||
// aliased that unit.
|
||||
while (U >= 0) {
|
||||
BitVector AR(PRI.getTRI().getNumRegs());
|
||||
AliasedRegs(U, AR);
|
||||
Regs &= AR;
|
||||
U = Units.find_next(U);
|
||||
}
|
||||
|
||||
// If there is at least one register remaining, pick the first one,
|
||||
// and consolidate the masks of all of its units contained in this
|
||||
// aggregate.
|
||||
|
||||
int F = Regs.find_first();
|
||||
if (F <= 0)
|
||||
return RegisterRef();
|
||||
|
||||
LaneBitmask M;
|
||||
for (MCRegUnitMaskIterator I(F, &PRI.getTRI()); I.isValid(); ++I) {
|
||||
std::pair<uint32_t,LaneBitmask> P = *I;
|
||||
if (Units.test(P.first))
|
||||
M |= P.second.none() ? LaneBitmask::getAll() : P.second;
|
||||
}
|
||||
return RegisterRef(F, M);
|
||||
}
|
||||
|
||||
void RegisterAggr::print(raw_ostream &OS) const {
|
||||
OS << '{';
|
||||
for (auto I : Masks)
|
||||
OS << ' ' << PrintReg(I.first, &PRI.getTRI())
|
||||
<< PrintLaneMaskOpt(I.second);
|
||||
for (int U = Units.find_first(); U >= 0; U = Units.find_next(U))
|
||||
OS << ' ' << PrintRegUnit(U, &PRI.getTRI());
|
||||
OS << " }";
|
||||
}
|
||||
|
||||
RegisterAggr::rr_iterator::rr_iterator(const RegisterAggr &RG,
|
||||
bool End)
|
||||
: Owner(&RG) {
|
||||
for (int U = RG.Units.find_first(); U >= 0; U = RG.Units.find_next(U)) {
|
||||
RegisterRef R = RG.PRI.getRefForUnit(U);
|
||||
Masks[R.Reg] |= R.Mask;
|
||||
}
|
||||
Pos = End ? Masks.end() : Masks.begin();
|
||||
Index = End ? Masks.size() : 0;
|
||||
}
|
||||
|
||||
|
@ -103,21 +103,25 @@ namespace rdf {
|
||||
return !isRegMaskId(RB.Reg) ? aliasRM(RB, RA) : aliasMM(RA, RB);
|
||||
}
|
||||
std::set<RegisterId> getAliasSet(RegisterId Reg) const;
|
||||
bool hasPartialOverlaps(RegisterId Reg) const {
|
||||
return RegInfos[Reg].Partial;
|
||||
|
||||
RegisterRef getRefForUnit(uint32_t U) const {
|
||||
return RegisterRef(UnitInfos[U].Reg, UnitInfos[U].Mask);
|
||||
}
|
||||
|
||||
const TargetRegisterInfo &getTRI() const { return TRI; }
|
||||
|
||||
private:
|
||||
struct RegInfo {
|
||||
unsigned MaxSuper = 0;
|
||||
const TargetRegisterClass *RegClass = nullptr;
|
||||
bool Partial = false;
|
||||
};
|
||||
struct UnitInfo {
|
||||
RegisterId Reg = 0;
|
||||
LaneBitmask Mask;
|
||||
};
|
||||
|
||||
const TargetRegisterInfo &TRI;
|
||||
std::vector<RegInfo> RegInfos;
|
||||
std::vector<UnitInfo> UnitInfos;
|
||||
IndexedSet<const uint32_t*> RegMasks;
|
||||
|
||||
bool aliasRR(RegisterRef RA, RegisterRef RB) const;
|
||||
@ -128,10 +132,10 @@ namespace rdf {
|
||||
|
||||
struct RegisterAggr {
|
||||
RegisterAggr(const PhysicalRegisterInfo &pri)
|
||||
: ExpUnits(pri.getTRI().getNumRegUnits()), PRI(pri) {}
|
||||
: Units(pri.getTRI().getNumRegUnits()), PRI(pri) {}
|
||||
RegisterAggr(const RegisterAggr &RG) = default;
|
||||
|
||||
bool empty() const { return Masks.empty(); }
|
||||
bool empty() const { return Units.empty(); }
|
||||
bool hasAliasOf(RegisterRef RR) const;
|
||||
bool hasCoverOf(RegisterRef RR) const;
|
||||
static bool isCoverOf(RegisterRef RA, RegisterRef RB,
|
||||
@ -148,21 +152,45 @@ namespace rdf {
|
||||
|
||||
RegisterRef intersectWith(RegisterRef RR) const;
|
||||
RegisterRef clearIn(RegisterRef RR) const;
|
||||
RegisterRef makeRegRef() const;
|
||||
|
||||
void print(raw_ostream &OS) const;
|
||||
|
||||
private:
|
||||
typedef std::unordered_map<RegisterId, LaneBitmask> MapType;
|
||||
struct rr_iterator {
|
||||
typedef std::map<RegisterId,LaneBitmask> MapType;
|
||||
private:
|
||||
MapType Masks;
|
||||
MapType::iterator Pos;
|
||||
unsigned Index;
|
||||
const RegisterAggr *Owner;
|
||||
public:
|
||||
rr_iterator(const RegisterAggr &RG, bool End);
|
||||
RegisterRef operator*() const {
|
||||
return RegisterRef(Pos->first, Pos->second);
|
||||
}
|
||||
rr_iterator &operator++() {
|
||||
++Pos;
|
||||
++Index;
|
||||
return *this;
|
||||
}
|
||||
bool operator==(const rr_iterator &I) const {
|
||||
assert(Owner == I.Owner);
|
||||
return Index == I.Index;
|
||||
}
|
||||
bool operator!=(const rr_iterator &I) const {
|
||||
return !(*this == I);
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
typedef MapType::const_iterator iterator;
|
||||
iterator begin() const { return Masks.begin(); }
|
||||
iterator end() const { return Masks.end(); }
|
||||
rr_iterator rr_begin() const {
|
||||
return rr_iterator(*this, false);
|
||||
}
|
||||
rr_iterator rr_end() const {
|
||||
return rr_iterator(*this, true);
|
||||
}
|
||||
|
||||
private:
|
||||
MapType Masks;
|
||||
BitVector ExpUnits; // Register units for explicit checks.
|
||||
bool CheckUnits = false;
|
||||
BitVector Units;
|
||||
const PhysicalRegisterInfo &PRI;
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user