[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:
Krzysztof Parzyszek 2017-04-14 17:25:13 +00:00
parent ec87df5c2d
commit 0e9e7d51d9
5 changed files with 168 additions and 185 deletions

View File

@ -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) {

View File

@ -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.

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
};