// phi use -> (map: reaching phi -> set of registers defined in between)
std::map<NodeId,std::map<NodeId,RegisterAggr>> PhiUp;
std::vector<NodeId> PhiUQ; // Work list of phis for upward propagation.
+ std::map<NodeId,RegisterAggr> PhiDRs; // Phi -> registers defined by it.
// Go over all phis.
for (NodeAddr<PhiNode*> PhiA : Phis) {
// For each def, add to the queue all reached (non-phi) defs.
SetVector<NodeId> DefQ;
NodeSet PhiDefs;
+ RegisterAggr DRs(PRI);
for (NodeAddr<RefNode*> R : PhiRefs) {
if (!DFG.IsRef<NodeAttrs::Def>(R))
continue;
+ DRs.insert(R.Addr->getRegRef(DFG));
DefQ.insert(R.Id);
PhiDefs.insert(R.Id);
}
+ PhiDRs.insert(std::make_pair(PhiA.Id, DRs));
// Collect the super-set of all possible reached uses. This set will
// contain all uses reached from this phi, either directly from the
// then add (R-MidDefs,U) to RealUseMap[P]
//
for (const std::pair<RegisterId,NodeRefSet> &T : RUM) {
- RegisterRef R = DFG.restrictRef(RegisterRef(T.first), UR);
- if (!R)
+ RegisterRef R(T.first);
+ // The current phi (PA) could be a phi for a regmask. It could
+ // reach a whole variety of uses that are not related to the
+ // specific upward phi (P.first).
+ const RegisterAggr &DRs = PhiDRs.at(P.first);
+ if (!DRs.hasAliasOf(R))
continue;
+ R = DRs.intersectWith(R);
for (std::pair<NodeId,LaneBitmask> V : T.second) {
- RegisterRef S = DFG.restrictRef(RegisterRef(R.Reg, V.second), R);
- if (!S)
+ LaneBitmask M = R.Mask & V.second;
+ if (M.none())
continue;
- if (RegisterRef SS = MidDefs.clearIn(S)) {
+ if (RegisterRef SS = MidDefs.clearIn(RegisterRef(R.Reg, M))) {
NodeRefSet &RS = RealUseMap[P.first][SS.Reg];
Changed |= RS.insert({V.first,SS.Mask}).second;
}
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;
+}
+
+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;
+ }
+ return *this;
+}
+
RegisterAggr &RegisterAggr::clear(RegisterRef RR) {
if (PhysicalRegisterInfo::isRegMaskId(RR.Reg)) {
// XXX SLOW
return *this;
}
+RegisterRef RegisterAggr::intersectWith(RegisterRef RR) const {
+ RegisterAggr T(PRI);
+ T.insert(RR).intersect(*this);
+ if (T.empty())
+ return RegisterRef();
+ return RegisterRef(T.begin()->first, T.begin()->second);
+}
+
RegisterRef RegisterAggr::clearIn(RegisterRef RR) const {
RegisterAggr T(PRI);
T.insert(RR).clear(*this);
RegisterAggr &insert(RegisterRef RR);
RegisterAggr &insert(const RegisterAggr &RG);
+ RegisterAggr &intersect(RegisterRef RR);
+ RegisterAggr &intersect(const RegisterAggr &RG);
RegisterAggr &clear(RegisterRef RR);
RegisterAggr &clear(const RegisterAggr &RG);
+ RegisterRef intersectWith(RegisterRef RR) const;
RegisterRef clearIn(RegisterRef RR) const;
void print(raw_ostream &OS) const;