summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/lib/Target/Hexagon/RDFLiveness.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/lib/Target/Hexagon/RDFLiveness.cpp')
-rw-r--r--contrib/llvm/lib/Target/Hexagon/RDFLiveness.cpp538
1 files changed, 314 insertions, 224 deletions
diff --git a/contrib/llvm/lib/Target/Hexagon/RDFLiveness.cpp b/contrib/llvm/lib/Target/Hexagon/RDFLiveness.cpp
index 641f014..e74c4bf 100644
--- a/contrib/llvm/lib/Target/Hexagon/RDFLiveness.cpp
+++ b/contrib/llvm/lib/Target/Hexagon/RDFLiveness.cpp
@@ -41,10 +41,10 @@ namespace rdf {
template<>
raw_ostream &operator<< (raw_ostream &OS, const Print<Liveness::RefMap> &P) {
OS << '{';
- for (auto I : P.Obj) {
- OS << ' ' << Print<RegisterRef>(I.first, P.G) << '{';
+ for (auto &I : P.Obj) {
+ OS << ' ' << PrintReg(I.first, &P.G.getTRI()) << '{';
for (auto J = I.second.begin(), E = I.second.end(); J != E; ) {
- OS << Print<NodeId>(*J, P.G);
+ OS << Print<NodeId>(J->first, P.G) << PrintLaneMaskOpt(J->second);
if (++J != E)
OS << ',';
}
@@ -85,10 +85,19 @@ namespace rdf {
// the data-flow.
NodeList Liveness::getAllReachingDefs(RegisterRef RefRR,
- NodeAddr<RefNode*> RefA, bool FullChain, const RegisterSet &DefRRs) {
+ NodeAddr<RefNode*> RefA, bool FullChain, const RegisterAggr &DefRRs) {
+ NodeList RDefs; // Return value.
SetVector<NodeId> DefQ;
SetVector<NodeId> Owners;
+ // Dead defs will be treated as if they were live, since they are actually
+ // on the data-flow path. They cannot be ignored because even though they
+ // do not generate meaningful values, they still modify registers.
+
+ // If the reference is undefined, there is nothing to do.
+ if (RefA.Addr->getFlags() & NodeAttrs::Undef)
+ return RDefs;
+
// The initial queue should not have reaching defs for shadows. The
// whole point of a shadow is that it will have a reaching def that
// is not aliased to the reaching defs of the related shadows.
@@ -108,26 +117,24 @@ NodeList Liveness::getAllReachingDefs(RegisterRef RefRR,
if (TA.Addr->getFlags() & NodeAttrs::PhiRef)
continue;
// Stop at the covering/overwriting def of the initial register reference.
- RegisterRef RR = TA.Addr->getRegRef();
- if (RAI.covers(RR, RefRR)) {
- uint16_t Flags = TA.Addr->getFlags();
- if (!(Flags & NodeAttrs::Preserving))
+ RegisterRef RR = TA.Addr->getRegRef(DFG);
+ if (!DFG.IsPreservingDef(TA))
+ if (RegisterAggr::isCoverOf(RR, RefRR, TRI))
continue;
- }
// Get the next level of reaching defs. This will include multiple
// reaching defs for shadows.
for (auto S : DFG.getRelatedRefs(TA.Addr->getOwner(DFG), TA))
- if (auto RD = NodeAddr<RefNode*>(S).Addr->getReachingDef())
+ if (NodeId RD = NodeAddr<RefNode*>(S).Addr->getReachingDef())
DefQ.insert(RD);
}
// Remove all non-phi defs that are not aliased to RefRR, and collect
// the owners of the remaining defs.
SetVector<NodeId> Defs;
- for (auto N : DefQ) {
+ for (NodeId N : DefQ) {
auto TA = DFG.addr<DefNode*>(N);
bool IsPhi = TA.Addr->getFlags() & NodeAttrs::PhiRef;
- if (!IsPhi && !RAI.alias(RefRR, TA.Addr->getRegRef()))
+ if (!IsPhi && !DFG.alias(RefRR, TA.Addr->getRegRef(DFG)))
continue;
Defs.insert(TA.Id);
Owners.insert(TA.Addr->getOwner(DFG).Id);
@@ -156,8 +163,8 @@ NodeList Liveness::getAllReachingDefs(RegisterRef RefRR,
if (StmtA) {
if (!StmtB) // OB is a phi and phis dominate statements.
return true;
- auto CA = NodeAddr<StmtNode*>(OA).Addr->getCode();
- auto CB = NodeAddr<StmtNode*>(OB).Addr->getCode();
+ MachineInstr *CA = NodeAddr<StmtNode*>(OA).Addr->getCode();
+ MachineInstr *CB = NodeAddr<StmtNode*>(OB).Addr->getCode();
// The order must be linear, so tie-break such equalities.
if (CA == CB)
return A < B;
@@ -189,21 +196,20 @@ NodeList Liveness::getAllReachingDefs(RegisterRef RefRR,
// covered if we added A first, and A would be covered
// if we added B first.
- NodeList RDefs;
- RegisterSet RRs = DefRRs;
+ RegisterAggr RRs(DefRRs);
auto DefInSet = [&Defs] (NodeAddr<RefNode*> TA) -> bool {
return TA.Addr->getKind() == NodeAttrs::Def &&
Defs.count(TA.Id);
};
- for (auto T : Tmp) {
- if (!FullChain && RAI.covers(RRs, RefRR))
+ for (NodeId T : Tmp) {
+ if (!FullChain && RRs.hasCoverOf(RefRR))
break;
auto TA = DFG.addr<InstrNode*>(T);
bool IsPhi = DFG.IsCode<NodeAttrs::Phi>(TA);
NodeList Ds;
for (NodeAddr<DefNode*> DA : TA.Addr->members_if(DefInSet, DFG)) {
- auto QR = DA.Addr->getRegRef();
+ RegisterRef QR = DA.Addr->getRegRef(DFG);
// Add phi defs even if they are covered by subsequent defs. This is
// for cases where the reached use is not covered by any of the defs
// encountered so far: the phi def is needed to expose the liveness
@@ -212,7 +218,7 @@ NodeList Liveness::getAllReachingDefs(RegisterRef RefRR,
// phi d1<R3>(,d2,), ... Phi def d1 is covered by d2.
// d2<R3>(d1,,u3), ...
// ..., u3<D1>(d2) This use needs to be live on entry.
- if (FullChain || IsPhi || !RAI.covers(RRs, QR))
+ if (FullChain || IsPhi || !RRs.hasCoverOf(QR))
Ds.push_back(DA);
}
RDefs.insert(RDefs.end(), Ds.begin(), Ds.end());
@@ -221,19 +227,17 @@ NodeList Liveness::getAllReachingDefs(RegisterRef RefRR,
// defs to actually define a register.
uint16_t Flags = DA.Addr->getFlags();
if (!FullChain || !(Flags & NodeAttrs::PhiRef))
- if (!(Flags & NodeAttrs::Preserving))
- RRs.insert(DA.Addr->getRegRef());
+ if (!(Flags & NodeAttrs::Preserving)) // Don't care about Undef here.
+ RRs.insert(DA.Addr->getRegRef(DFG));
}
}
- return RDefs;
-}
-
-
-static const RegisterSet NoRegs;
+ auto DeadP = [](const NodeAddr<DefNode*> DA) -> bool {
+ return DA.Addr->getFlags() & NodeAttrs::Dead;
+ };
+ RDefs.resize(std::distance(RDefs.begin(), remove_if(RDefs, DeadP)));
-NodeList Liveness::getAllReachingDefs(NodeAddr<RefNode*> RefA) {
- return getAllReachingDefs(RefA.Addr->getRegRef(), RefA, false, NoRegs);
+ return RDefs;
}
@@ -241,20 +245,20 @@ NodeSet Liveness::getAllReachingDefsRec(RegisterRef RefRR,
NodeAddr<RefNode*> RefA, NodeSet &Visited, const NodeSet &Defs) {
// Collect all defined registers. Do not consider phis to be defining
// anything, only collect "real" definitions.
- RegisterSet DefRRs;
- for (const auto D : Defs) {
+ RegisterAggr DefRRs(TRI);
+ for (NodeId D : Defs) {
const auto DA = DFG.addr<const DefNode*>(D);
if (!(DA.Addr->getFlags() & NodeAttrs::PhiRef))
- DefRRs.insert(DA.Addr->getRegRef());
+ DefRRs.insert(DA.Addr->getRegRef(DFG));
}
- auto RDs = getAllReachingDefs(RefRR, RefA, true, DefRRs);
+ NodeList RDs = getAllReachingDefs(RefRR, RefA, true, DefRRs);
if (RDs.empty())
return Defs;
// Make a copy of the preexisting definitions and add the newly found ones.
NodeSet TmpDefs = Defs;
- for (auto R : RDs)
+ for (NodeAddr<NodeBase*> R : RDs)
TmpDefs.insert(R.Id);
NodeSet Result = Defs;
@@ -279,39 +283,43 @@ NodeSet Liveness::getAllReachingDefsRec(RegisterRef RefRR,
NodeSet Liveness::getAllReachedUses(RegisterRef RefRR,
- NodeAddr<DefNode*> DefA, const RegisterSet &DefRRs) {
+ NodeAddr<DefNode*> DefA, const RegisterAggr &DefRRs) {
NodeSet Uses;
// If the original register is already covered by all the intervening
// defs, no more uses can be reached.
- if (RAI.covers(DefRRs, RefRR))
+ if (DefRRs.hasCoverOf(RefRR))
return Uses;
// Add all directly reached uses.
- NodeId U = DefA.Addr->getReachedUse();
+ // If the def is dead, it does not provide a value for any use.
+ bool IsDead = DefA.Addr->getFlags() & NodeAttrs::Dead;
+ NodeId U = !IsDead ? DefA.Addr->getReachedUse() : 0;
while (U != 0) {
auto UA = DFG.addr<UseNode*>(U);
- auto UR = UA.Addr->getRegRef();
- if (RAI.alias(RefRR, UR) && !RAI.covers(DefRRs, UR))
- Uses.insert(U);
+ if (!(UA.Addr->getFlags() & NodeAttrs::Undef)) {
+ RegisterRef UR = UA.Addr->getRegRef(DFG);
+ if (DFG.alias(RefRR, UR) && !DefRRs.hasCoverOf(UR))
+ Uses.insert(U);
+ }
U = UA.Addr->getSibling();
}
- // Traverse all reached defs.
+ // Traverse all reached defs. This time dead defs cannot be ignored.
for (NodeId D = DefA.Addr->getReachedDef(), NextD; D != 0; D = NextD) {
auto DA = DFG.addr<DefNode*>(D);
NextD = DA.Addr->getSibling();
- auto DR = DA.Addr->getRegRef();
+ RegisterRef DR = DA.Addr->getRegRef(DFG);
// If this def is already covered, it cannot reach anything new.
// Similarly, skip it if it is not aliased to the interesting register.
- if (RAI.covers(DefRRs, DR) || !RAI.alias(RefRR, DR))
+ if (DefRRs.hasCoverOf(DR) || !DFG.alias(RefRR, DR))
continue;
NodeSet T;
- if (DA.Addr->getFlags() & NodeAttrs::Preserving) {
+ if (DFG.IsPreservingDef(DA)) {
// If it is a preserving def, do not update the set of intervening defs.
T = getAllReachedUses(RefRR, DA, DefRRs);
} else {
- RegisterSet NewDefRRs = DefRRs;
+ RegisterAggr NewDefRRs = DefRRs;
NewDefRRs.insert(DR);
T = getAllReachedUses(RefRR, DA, NewDefRRs);
}
@@ -326,42 +334,57 @@ void Liveness::computePhiInfo() {
NodeList Phis;
NodeAddr<FuncNode*> FA = DFG.getFunc();
- auto Blocks = FA.Addr->members(DFG);
+ NodeList Blocks = FA.Addr->members(DFG);
for (NodeAddr<BlockNode*> BA : Blocks) {
auto Ps = BA.Addr->members_if(DFG.IsCode<NodeAttrs::Phi>, DFG);
Phis.insert(Phis.end(), Ps.begin(), Ps.end());
}
// phi use -> (map: reaching phi -> set of registers defined in between)
- std::map<NodeId,std::map<NodeId,RegisterSet>> PhiUp;
+ std::map<NodeId,std::map<NodeId,RegisterAggr>> PhiUp;
std::vector<NodeId> PhiUQ; // Work list of phis for upward propagation.
// Go over all phis.
for (NodeAddr<PhiNode*> PhiA : Phis) {
// Go over all defs and collect the reached uses that are non-phi uses
// (i.e. the "real uses").
- auto &RealUses = RealUseMap[PhiA.Id];
- auto PhiRefs = PhiA.Addr->members(DFG);
+ RefMap &RealUses = RealUseMap[PhiA.Id];
+ NodeList PhiRefs = PhiA.Addr->members(DFG);
// Have a work queue of defs whose reached uses need to be found.
// For each def, add to the queue all reached (non-phi) defs.
SetVector<NodeId> DefQ;
NodeSet PhiDefs;
- for (auto R : PhiRefs) {
+ for (NodeAddr<RefNode*> R : PhiRefs) {
if (!DFG.IsRef<NodeAttrs::Def>(R))
continue;
DefQ.insert(R.Id);
PhiDefs.insert(R.Id);
}
+
+ // Collect the super-set of all possible reached uses. This set will
+ // contain all uses reached from this phi, either directly from the
+ // phi defs, or (recursively) via non-phi defs reached by the phi defs.
+ // This set of uses will later be trimmed to only contain these uses that
+ // are actually reached by the phi defs.
for (unsigned i = 0; i < DefQ.size(); ++i) {
NodeAddr<DefNode*> DA = DFG.addr<DefNode*>(DefQ[i]);
- NodeId UN = DA.Addr->getReachedUse();
+ // Visit all reached uses. Phi defs should not really have the "dead"
+ // flag set, but check it anyway for consistency.
+ bool IsDead = DA.Addr->getFlags() & NodeAttrs::Dead;
+ NodeId UN = !IsDead ? DA.Addr->getReachedUse() : 0;
while (UN != 0) {
NodeAddr<UseNode*> A = DFG.addr<UseNode*>(UN);
- if (!(A.Addr->getFlags() & NodeAttrs::PhiRef))
- RealUses[getRestrictedRegRef(A)].insert(A.Id);
+ uint16_t F = A.Addr->getFlags();
+ if ((F & (NodeAttrs::Undef | NodeAttrs::PhiRef)) == 0) {
+ RegisterRef R = DFG.normalizeRef(getRestrictedRegRef(A));
+ RealUses[R.Reg].insert({A.Id,R.Mask});
+ }
UN = A.Addr->getSibling();
}
+ // Visit all reached defs, and add them to the queue. These defs may
+ // override some of the uses collected here, but that will be handled
+ // later.
NodeId DN = DA.Addr->getReachedDef();
while (DN != 0) {
NodeAddr<DefNode*> A = DFG.addr<DefNode*>(DN);
@@ -388,7 +411,7 @@ void Liveness::computePhiInfo() {
// = R1:0 u6 Not reached by d1 (covered collectively
// by d3 and d5), but following reached
// defs and uses from d1 will lead here.
- auto HasDef = [&PhiDefs] (NodeAddr<DefNode*> DA) -> bool {
+ auto InPhiDefs = [&PhiDefs] (NodeAddr<DefNode*> DA) -> bool {
return PhiDefs.count(DA.Id);
};
for (auto UI = RealUses.begin(), UE = RealUses.end(); UI != UE; ) {
@@ -396,11 +419,14 @@ void Liveness::computePhiInfo() {
// uses of it. For each such use, check if it is reached by this phi,
// i.e. check if the set of its reaching uses intersects the set of
// this phi's defs.
- auto &Uses = UI->second;
+ NodeRefSet &Uses = UI->second;
for (auto I = Uses.begin(), E = Uses.end(); I != E; ) {
- auto UA = DFG.addr<UseNode*>(*I);
- NodeList RDs = getAllReachingDefs(UI->first, UA);
- if (std::any_of(RDs.begin(), RDs.end(), HasDef))
+ auto UA = DFG.addr<UseNode*>(I->first);
+ // Undef flag is checked above.
+ assert((UA.Addr->getFlags() & NodeAttrs::Undef) == 0);
+ RegisterRef R(UI->first, I->second);
+ NodeList RDs = getAllReachingDefs(R, UA);
+ if (any_of(RDs, InPhiDefs))
++I;
else
I = Uses.erase(I);
@@ -418,31 +444,50 @@ void Liveness::computePhiInfo() {
// Go over all phi uses and check if the reaching def is another phi.
// Collect the phis that are among the reaching defs of these uses.
- // While traversing the list of reaching defs for each phi use, collect
- // the set of registers defined between this phi (Phi) and the owner phi
+ // While traversing the list of reaching defs for each phi use, accumulate
+ // the set of registers defined between this phi (PhiA) and the owner phi
// of the reaching def.
+ NodeSet SeenUses;
+
for (auto I : PhiRefs) {
- if (!DFG.IsRef<NodeAttrs::Use>(I))
+ if (!DFG.IsRef<NodeAttrs::Use>(I) || SeenUses.count(I.Id))
continue;
NodeAddr<UseNode*> UA = I;
- auto &UpMap = PhiUp[UA.Id];
- RegisterSet DefRRs;
- for (NodeAddr<DefNode*> DA : getAllReachingDefs(UA)) {
- if (DA.Addr->getFlags() & NodeAttrs::PhiRef)
- UpMap[DA.Addr->getOwner(DFG).Id] = DefRRs;
- else
- DefRRs.insert(DA.Addr->getRegRef());
+
+ // Given a phi use UA, traverse all related phi uses (including UA).
+ // The related phi uses may reach different phi nodes or may reach the
+ // same phi node. If multiple uses reach the same phi P, the intervening
+ // defs must be accumulated for all such uses. To group all such uses
+ // into one set, map their node ids to the first use id that reaches P.
+ std::map<NodeId,NodeId> FirstUse; // Phi reached up -> first phi use.
+
+ for (NodeAddr<UseNode*> VA : DFG.getRelatedRefs(PhiA, UA)) {
+ SeenUses.insert(VA.Id);
+ RegisterAggr DefRRs(TRI);
+ for (NodeAddr<DefNode*> DA : getAllReachingDefs(VA)) {
+ if (DA.Addr->getFlags() & NodeAttrs::PhiRef) {
+ NodeId RP = DA.Addr->getOwner(DFG).Id;
+ NodeId FU = FirstUse.insert({RP,VA.Id}).first->second;
+ std::map<NodeId,RegisterAggr> &M = PhiUp[FU];
+ auto F = M.find(RP);
+ if (F == M.end())
+ M.insert(std::make_pair(RP, DefRRs));
+ else
+ F->second.insert(DefRRs);
+ }
+ DefRRs.insert(DA.Addr->getRegRef(DFG));
+ }
}
}
}
if (Trace) {
- dbgs() << "Phi-up-to-phi map:\n";
+ dbgs() << "Phi-up-to-phi map with intervening defs:\n";
for (auto I : PhiUp) {
dbgs() << "phi " << Print<NodeId>(I.first, DFG) << " -> {";
for (auto R : I.second)
dbgs() << ' ' << Print<NodeId>(R.first, DFG)
- << Print<RegisterSet>(R.second, DFG);
+ << Print<RegisterAggr>(R.second, DFG);
dbgs() << " }\n";
}
}
@@ -467,40 +512,50 @@ void Liveness::computePhiInfo() {
//
// When propagating uses up the phi chains, get the all reaching defs
// for a given phi use, and traverse the list until the propagated ref
- // is covered, or until or until reaching the final phi. Only assume
- // that the reference reaches the phi in the latter case.
+ // is covered, or until reaching the final phi. Only assume that the
+ // reference reaches the phi in the latter case.
for (unsigned i = 0; i < PhiUQ.size(); ++i) {
auto PA = DFG.addr<PhiNode*>(PhiUQ[i]);
- auto &RealUses = RealUseMap[PA.Id];
- for (auto U : PA.Addr->members_if(DFG.IsRef<NodeAttrs::Use>, DFG)) {
- NodeAddr<UseNode*> UA = U;
- auto &UpPhis = PhiUp[UA.Id];
- for (auto UP : UpPhis) {
+ NodeList PUs = PA.Addr->members_if(DFG.IsRef<NodeAttrs::Use>, DFG);
+ RefMap &RUM = RealUseMap[PA.Id];
+
+ for (NodeAddr<UseNode*> UA : PUs) {
+ std::map<NodeId,RegisterAggr> &PUM = PhiUp[UA.Id];
+ RegisterRef UR = DFG.normalizeRef(getRestrictedRegRef(UA));
+ for (const std::pair<NodeId,RegisterAggr> &P : PUM) {
bool Changed = false;
- auto &MidDefs = UP.second;
- // Collect the set UpReached of uses that are reached by the current
- // phi PA, and are not covered by any intervening def between PA and
- // the upward phi UP.
- RegisterSet UpReached;
- for (auto T : RealUses) {
- if (!isRestricted(PA, UA, T.first))
- continue;
- if (!RAI.covers(MidDefs, T.first))
- UpReached.insert(T.first);
- }
- if (UpReached.empty())
+ const RegisterAggr &MidDefs = P.second;
+
+ // Collect the set PropUp of uses that are reached by the current
+ // phi PA, and are not covered by any intervening def between the
+ // currently visited use UA and the the upward phi P.
+
+ if (MidDefs.hasCoverOf(UR))
continue;
- // Update the set PRUs of real uses reached by the upward phi UP with
- // the actual set of uses (UpReached) that the UP phi reaches.
- auto &PRUs = RealUseMap[UP.first];
- for (auto R : UpReached) {
- unsigned Z = PRUs[R].size();
- PRUs[R].insert(RealUses[R].begin(), RealUses[R].end());
- Changed |= (PRUs[R].size() != Z);
+
+ // General algorithm:
+ // for each (R,U) : U is use node of R, U is reached by PA
+ // if MidDefs does not cover (R,U)
+ // 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)
+ continue;
+ for (std::pair<NodeId,LaneBitmask> V : T.second) {
+ RegisterRef S = DFG.restrictRef(RegisterRef(R.Reg, V.second), R);
+ if (!S)
+ continue;
+ if (RegisterRef SS = MidDefs.clearIn(S)) {
+ NodeRefSet &RS = RealUseMap[P.first][SS.Reg];
+ Changed |= RS.insert({V.first,SS.Mask}).second;
+ }
+ }
}
+
if (Changed)
- PhiUQ.push_back(UP.first);
+ PhiUQ.push_back(P.first);
}
}
}
@@ -512,7 +567,7 @@ void Liveness::computePhiInfo() {
NodeAddr<PhiNode*> PA = DFG.addr<PhiNode*>(I.first);
NodeList Ds = PA.Addr->members_if(DFG.IsRef<NodeAttrs::Def>, DFG);
if (!Ds.empty()) {
- RegisterRef RR = NodeAddr<DefNode*>(Ds[0]).Addr->getRegRef();
+ RegisterRef RR = NodeAddr<DefNode*>(Ds[0]).Addr->getRegRef(DFG);
dbgs() << '<' << Print<RegisterRef>(RR, DFG) << '>';
} else {
dbgs() << "<noreg>";
@@ -540,7 +595,7 @@ void Liveness::computeLiveIns() {
// Compute IDF first, then the inverse.
decltype(IIDF) IDF;
- for (auto &B : MF) {
+ for (MachineBasicBlock &B : MF) {
auto F1 = MDF.find(&B);
if (F1 == MDF.end())
continue;
@@ -562,20 +617,20 @@ void Liveness::computeLiveIns() {
computePhiInfo();
NodeAddr<FuncNode*> FA = DFG.getFunc();
- auto Blocks = FA.Addr->members(DFG);
+ NodeList Blocks = FA.Addr->members(DFG);
// Build the phi live-on-entry map.
for (NodeAddr<BlockNode*> BA : Blocks) {
MachineBasicBlock *MB = BA.Addr->getCode();
- auto &LON = PhiLON[MB];
+ RefMap &LON = PhiLON[MB];
for (auto P : BA.Addr->members_if(DFG.IsCode<NodeAttrs::Phi>, DFG))
- for (auto S : RealUseMap[P.Id])
+ for (const RefMap::value_type &S : RealUseMap[P.Id])
LON[S.first].insert(S.second.begin(), S.second.end());
}
if (Trace) {
dbgs() << "Phi live-on-entry map:\n";
- for (auto I : PhiLON)
+ for (auto &I : PhiLON)
dbgs() << "block #" << I.first->getNumber() << " -> "
<< Print<RefMap>(I.second, DFG) << '\n';
}
@@ -584,33 +639,35 @@ void Liveness::computeLiveIns() {
// "real" uses. Propagate this set backwards into the block predecessors
// through the reaching defs of the corresponding phi uses.
for (NodeAddr<BlockNode*> BA : Blocks) {
- auto Phis = BA.Addr->members_if(DFG.IsCode<NodeAttrs::Phi>, DFG);
+ NodeList Phis = BA.Addr->members_if(DFG.IsCode<NodeAttrs::Phi>, DFG);
for (NodeAddr<PhiNode*> PA : Phis) {
- auto &RUs = RealUseMap[PA.Id];
+ RefMap &RUs = RealUseMap[PA.Id];
if (RUs.empty())
continue;
for (auto U : PA.Addr->members_if(DFG.IsRef<NodeAttrs::Use>, DFG)) {
- NodeAddr<PhiUseNode*> UA = U;
- if (UA.Addr->getReachingDef() == 0)
+ NodeAddr<PhiUseNode*> PUA = U;
+ if (PUA.Addr->getReachingDef() == 0)
continue;
// Mark all reached "real" uses of P as live on exit in the
// predecessor.
// Remap all the RUs so that they have a correct reaching def.
- auto PrA = DFG.addr<BlockNode*>(UA.Addr->getPredecessor());
- auto &LOX = PhiLOX[PrA.Addr->getCode()];
- for (auto R : RUs) {
- RegisterRef RR = R.first;
- if (!isRestricted(PA, UA, RR))
- RR = getRestrictedRegRef(UA);
- // The restricted ref may be different from the ref that was
- // accessed in the "real use". This means that this phi use
- // is not the one that carries this reference, so skip it.
- if (!RAI.alias(R.first, RR))
+ auto PrA = DFG.addr<BlockNode*>(PUA.Addr->getPredecessor());
+ RefMap &LOX = PhiLOX[PrA.Addr->getCode()];
+
+ RegisterRef UR = DFG.normalizeRef(getRestrictedRegRef(PUA));
+ for (const std::pair<RegisterId,NodeRefSet> &T : RUs) {
+ // Check if T.first aliases UR?
+ LaneBitmask M;
+ for (std::pair<NodeId,LaneBitmask> P : T.second)
+ M |= P.second;
+
+ RegisterRef S = DFG.restrictRef(RegisterRef(T.first, M), UR);
+ if (!S)
continue;
- for (auto D : getAllReachingDefs(RR, UA))
- LOX[RR].insert(D.Id);
+ for (NodeAddr<DefNode*> D : getAllReachingDefs(S, PUA))
+ LOX[S.Reg].insert({D.Id, S.Mask});
}
} // for U : phi uses
} // for P : Phis
@@ -618,7 +675,7 @@ void Liveness::computeLiveIns() {
if (Trace) {
dbgs() << "Phi live-on-exit map:\n";
- for (auto I : PhiLOX)
+ for (auto &I : PhiLOX)
dbgs() << "block #" << I.first->getNumber() << " -> "
<< Print<RefMap>(I.second, DFG) << '\n';
}
@@ -629,19 +686,41 @@ void Liveness::computeLiveIns() {
// Add function live-ins to the live-in set of the function entry block.
auto &EntryIn = LiveMap[&MF.front()];
for (auto I = MRI.livein_begin(), E = MRI.livein_end(); I != E; ++I)
- EntryIn.insert({I->first,0});
+ EntryIn.insert(RegisterRef(I->first));
if (Trace) {
// Dump the liveness map
- for (auto &B : MF) {
- BitVector LV(TRI.getNumRegs());
+ for (MachineBasicBlock &B : MF) {
+ std::vector<RegisterRef> LV;
for (auto I = B.livein_begin(), E = B.livein_end(); I != E; ++I)
- LV.set(I->PhysReg);
+ LV.push_back(RegisterRef(I->PhysReg, I->LaneMask));
+ std::sort(LV.begin(), LV.end());
dbgs() << "BB#" << B.getNumber() << "\t rec = {";
- for (int x = LV.find_first(); x >= 0; x = LV.find_next(x))
- dbgs() << ' ' << Print<RegisterRef>({unsigned(x),0}, DFG);
+ for (auto I : LV)
+ dbgs() << ' ' << Print<RegisterRef>(I, DFG);
dbgs() << " }\n";
- dbgs() << "\tcomp = " << Print<RegisterSet>(LiveMap[&B], DFG) << '\n';
+ //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());
+ }
+ std::sort(LV.begin(), LV.end());
+ dbgs() << "\tcomp = {";
+ for (auto I : LV)
+ dbgs() << ' ' << Print<RegisterRef>(I, DFG);
+ dbgs() << " }\n";
+
}
}
}
@@ -658,8 +737,7 @@ void Liveness::resetLiveIns() {
// Add the newly computed live-ins.
auto &LiveIns = LiveMap[&B];
for (auto I : LiveIns) {
- assert(I.Sub == 0);
- B.addLiveIn(I.Reg);
+ B.addLiveIn({MCPhysReg(I.first), I.second});
}
}
}
@@ -672,9 +750,20 @@ void Liveness::resetKills() {
void Liveness::resetKills(MachineBasicBlock *B) {
- auto CopyLiveIns = [] (MachineBasicBlock *B, BitVector &LV) -> void {
- for (auto I = B->livein_begin(), E = B->livein_end(); I != E; ++I)
- LV.set(I->PhysReg);
+ auto CopyLiveIns = [this] (MachineBasicBlock *B, BitVector &LV) -> void {
+ for (auto I : B->liveins()) {
+ MCSubRegIndexIterator S(I.PhysReg, &TRI);
+ if (!S.isValid()) {
+ LV.set(I.PhysReg);
+ continue;
+ }
+ do {
+ LaneBitmask M = TRI.getSubRegIndexLaneMask(S.getSubRegIndex());
+ if ((M & I.LaneMask).any())
+ LV.set(S.getSubReg());
+ ++S;
+ } while (S.isValid());
+ }
};
BitVector LiveIn(TRI.getNumRegs()), Live(TRI.getNumRegs());
@@ -724,26 +813,6 @@ void Liveness::resetKills(MachineBasicBlock *B) {
}
-// For shadows, determine if RR is aliased to a reaching def of any other
-// shadow associated with RA. If it is not, then RR is "restricted" to RA,
-// and so it can be considered a value specific to RA. This is important
-// for accurately determining values associated with phi uses.
-// For non-shadows, this function returns "true".
-bool Liveness::isRestricted(NodeAddr<InstrNode*> IA, NodeAddr<RefNode*> RA,
- RegisterRef RR) const {
- NodeId Start = RA.Id;
- for (NodeAddr<RefNode*> TA = DFG.getNextShadow(IA, RA);
- TA.Id != 0 && TA.Id != Start; TA = DFG.getNextShadow(IA, TA)) {
- NodeId RD = TA.Addr->getReachingDef();
- if (RD == 0)
- continue;
- if (RAI.alias(RR, DFG.addr<DefNode*>(RD).Addr->getRegRef()))
- return false;
- }
- return true;
-}
-
-
RegisterRef Liveness::getRestrictedRegRef(NodeAddr<RefNode*> RA) const {
assert(DFG.IsRef<NodeAttrs::Use>(RA));
if (RA.Addr->getFlags() & NodeAttrs::Shadow) {
@@ -751,14 +820,7 @@ RegisterRef Liveness::getRestrictedRegRef(NodeAddr<RefNode*> RA) const {
assert(RD);
RA = DFG.addr<DefNode*>(RD);
}
- return RA.Addr->getRegRef();
-}
-
-
-unsigned Liveness::getPhysReg(RegisterRef RR) const {
- if (!TargetRegisterInfo::isPhysicalRegister(RR.Reg))
- return 0;
- return RR.Sub ? TRI.getSubReg(RR.Reg, RR.Sub) : RR.Reg;
+ return RA.Addr->getRegRef(DFG);
}
@@ -808,77 +870,99 @@ void Liveness::traverse(MachineBasicBlock *B, RefMap &LiveIn) {
}
if (Trace) {
- dbgs() << LLVM_FUNCTION_NAME << " in BB#" << B->getNumber()
- << " after recursion into";
+ dbgs() << "\n-- BB#" << B->getNumber() << ": " << __func__
+ << " after recursion into: {";
for (auto I : *N)
dbgs() << ' ' << I->getBlock()->getNumber();
- dbgs() << "\n LiveIn: " << Print<RefMap>(LiveIn, DFG);
- dbgs() << "\n Local: " << Print<RegisterSet>(LiveMap[B], DFG) << '\n';
+ dbgs() << " }\n";
+ dbgs() << " LiveIn: " << Print<RefMap>(LiveIn, DFG) << '\n';
+ dbgs() << " Local: " << Print<RegisterAggr>(LiveMap[B], DFG) << '\n';
}
- // Add phi uses that are live on exit from this block.
+ // Add reaching defs of phi uses that are live on exit from this block.
RefMap &PUs = PhiLOX[B];
- for (auto S : PUs)
+ for (auto &S : PUs)
LiveIn[S.first].insert(S.second.begin(), S.second.end());
if (Trace) {
dbgs() << "after LOX\n";
dbgs() << " LiveIn: " << Print<RefMap>(LiveIn, DFG) << '\n';
- dbgs() << " Local: " << Print<RegisterSet>(LiveMap[B], DFG) << '\n';
+ dbgs() << " Local: " << Print<RegisterAggr>(LiveMap[B], DFG) << '\n';
}
- // Stop tracking all uses defined in this block: erase those records
- // where the reaching def is located in B and which cover all reached
- // uses.
- auto Copy = LiveIn;
+ // The LiveIn map at this point has all defs that are live-on-exit from B,
+ // as if they were live-on-entry to B. First, we need to filter out all
+ // defs that are present in this block. Then we will add reaching defs of
+ // all upward-exposed uses.
+
+ // To filter out the defs, first make a copy of LiveIn, and then re-populate
+ // LiveIn with the defs that should remain.
+ RefMap LiveInCopy = LiveIn;
LiveIn.clear();
- for (auto I : Copy) {
- auto &Defs = LiveIn[I.first];
- NodeSet Rest;
- for (auto R : I.second) {
- auto DA = DFG.addr<DefNode*>(R);
- RegisterRef DDR = DA.Addr->getRegRef();
+ for (const std::pair<RegisterId,NodeRefSet> &LE : LiveInCopy) {
+ RegisterRef LRef(LE.first);
+ NodeRefSet &NewDefs = LiveIn[LRef.Reg]; // To be filled.
+ const NodeRefSet &OldDefs = LE.second;
+ for (NodeRef OR : OldDefs) {
+ // R is a def node that was live-on-exit
+ auto DA = DFG.addr<DefNode*>(OR.first);
NodeAddr<InstrNode*> IA = DA.Addr->getOwner(DFG);
NodeAddr<BlockNode*> BA = IA.Addr->getOwner(DFG);
- // Defs from a different block need to be preserved. Defs from this
- // block will need to be processed further, except for phi defs, the
- // liveness of which is handled through the PhiLON/PhiLOX maps.
- if (B != BA.Addr->getCode())
- Defs.insert(R);
- else {
- bool IsPreserving = DA.Addr->getFlags() & NodeAttrs::Preserving;
- if (IA.Addr->getKind() != NodeAttrs::Phi && !IsPreserving) {
- bool Covering = RAI.covers(DDR, I.first);
- NodeId U = DA.Addr->getReachedUse();
- while (U && Covering) {
- auto DUA = DFG.addr<UseNode*>(U);
- RegisterRef Q = DUA.Addr->getRegRef();
- Covering = RAI.covers(DA.Addr->getRegRef(), Q);
- U = DUA.Addr->getSibling();
- }
- if (!Covering)
- Rest.insert(R);
- }
+ if (B != BA.Addr->getCode()) {
+ // Defs from a different block need to be preserved. Defs from this
+ // block will need to be processed further, except for phi defs, the
+ // liveness of which is handled through the PhiLON/PhiLOX maps.
+ NewDefs.insert(OR);
+ continue;
+ }
+
+ // Defs from this block need to stop the liveness from being
+ // propagated upwards. This only applies to non-preserving defs,
+ // and to the parts of the register actually covered by those defs.
+ // (Note that phi defs should always be preserving.)
+ RegisterAggr RRs(TRI);
+ LRef.Mask = OR.second;
+
+ if (!DFG.IsPreservingDef(DA)) {
+ assert(!(IA.Addr->getFlags() & NodeAttrs::Phi));
+ // DA is a non-phi def that is live-on-exit from this block, and
+ // that is also located in this block. LRef is a register ref
+ // whose use this def reaches. If DA covers LRef, then no part
+ // of LRef is exposed upwards.A
+ if (RRs.insert(DA.Addr->getRegRef(DFG)).hasCoverOf(LRef))
+ continue;
}
- }
- // Non-covering defs from B.
- for (auto R : Rest) {
- auto DA = DFG.addr<DefNode*>(R);
- RegisterRef DRR = DA.Addr->getRegRef();
- RegisterSet RRs;
+ // DA itself was not sufficient to cover LRef. In general, it is
+ // the last in a chain of aliased defs before the exit from this block.
+ // There could be other defs in this block that are a part of that
+ // chain. Check that now: accumulate the registers from these defs,
+ // and if they all together cover LRef, it is not live-on-entry.
for (NodeAddr<DefNode*> TA : getAllReachingDefs(DA)) {
- NodeAddr<InstrNode*> IA = TA.Addr->getOwner(DFG);
- NodeAddr<BlockNode*> BA = IA.Addr->getOwner(DFG);
- // Preserving defs do not count towards covering.
+ // DefNode -> InstrNode -> BlockNode.
+ NodeAddr<InstrNode*> ITA = TA.Addr->getOwner(DFG);
+ NodeAddr<BlockNode*> BTA = ITA.Addr->getOwner(DFG);
+ // Reaching defs are ordered in the upward direction.
+ if (BTA.Addr->getCode() != B) {
+ // We have reached past the beginning of B, and the accumulated
+ // registers are not covering LRef. The first def from the
+ // upward chain will be live.
+ // Subtract all accumulated defs (RRs) from LRef.
+ RegisterAggr L(TRI);
+ L.insert(LRef).clear(RRs);
+ assert(!L.empty());
+ NewDefs.insert({TA.Id,L.begin()->second});
+ break;
+ }
+
+ // TA is in B. Only add this def to the accumulated cover if it is
+ // not preserving.
if (!(TA.Addr->getFlags() & NodeAttrs::Preserving))
- RRs.insert(TA.Addr->getRegRef());
- if (BA.Addr->getCode() == B)
- continue;
- if (RAI.covers(RRs, DRR))
+ RRs.insert(TA.Addr->getRegRef(DFG));
+ // If this is enough to cover LRef, then stop.
+ if (RRs.hasCoverOf(LRef))
break;
- Defs.insert(TA.Id);
}
}
}
@@ -888,7 +972,7 @@ void Liveness::traverse(MachineBasicBlock *B, RefMap &LiveIn) {
if (Trace) {
dbgs() << "after defs in block\n";
dbgs() << " LiveIn: " << Print<RefMap>(LiveIn, DFG) << '\n';
- dbgs() << " Local: " << Print<RegisterSet>(LiveMap[B], DFG) << '\n';
+ dbgs() << " Local: " << Print<RegisterAggr>(LiveMap[B], DFG) << '\n';
}
// Scan the block for upward-exposed uses and add them to the tracking set.
@@ -897,38 +981,44 @@ void Liveness::traverse(MachineBasicBlock *B, RefMap &LiveIn) {
if (IA.Addr->getKind() != NodeAttrs::Stmt)
continue;
for (NodeAddr<UseNode*> UA : IA.Addr->members_if(DFG.IsUse, DFG)) {
- RegisterRef RR = UA.Addr->getRegRef();
- for (auto D : getAllReachingDefs(UA))
+ if (UA.Addr->getFlags() & NodeAttrs::Undef)
+ continue;
+ RegisterRef RR = DFG.normalizeRef(UA.Addr->getRegRef(DFG));
+ for (NodeAddr<DefNode*> D : getAllReachingDefs(UA))
if (getBlockWithRef(D.Id) != B)
- LiveIn[RR].insert(D.Id);
+ LiveIn[RR.Reg].insert({D.Id,RR.Mask});
}
}
if (Trace) {
dbgs() << "after uses in block\n";
dbgs() << " LiveIn: " << Print<RefMap>(LiveIn, DFG) << '\n';
- dbgs() << " Local: " << Print<RegisterSet>(LiveMap[B], DFG) << '\n';
+ dbgs() << " Local: " << Print<RegisterAggr>(LiveMap[B], DFG) << '\n';
}
// Phi uses should not be propagated up the dominator tree, since they
// are not dominated by their corresponding reaching defs.
- auto &Local = LiveMap[B];
- auto &LON = PhiLON[B];
- for (auto R : LON)
- Local.insert(R.first);
+ RegisterAggr &Local = LiveMap[B];
+ RefMap &LON = PhiLON[B];
+ for (auto &R : LON) {
+ LaneBitmask M;
+ for (auto P : R.second)
+ M |= P.second;
+ Local.insert(RegisterRef(R.first,M));
+ }
if (Trace) {
dbgs() << "after phi uses in block\n";
dbgs() << " LiveIn: " << Print<RefMap>(LiveIn, DFG) << '\n';
- dbgs() << " Local: " << Print<RegisterSet>(Local, DFG) << '\n';
+ dbgs() << " Local: " << Print<RegisterAggr>(Local, DFG) << '\n';
}
for (auto C : IIDF[B]) {
- auto &LiveC = LiveMap[C];
- for (auto S : LiveIn)
+ RegisterAggr &LiveC = LiveMap[C];
+ for (const std::pair<RegisterId,NodeRefSet> &S : LiveIn)
for (auto R : S.second)
- if (MDT.properlyDominates(getBlockWithRef(R), C))
- LiveC.insert(S.first);
+ if (MDT.properlyDominates(getBlockWithRef(R.first), C))
+ LiveC.insert(RegisterRef(S.first, R.second));
}
}
OpenPOWER on IntegriCloud