diff options
Diffstat (limited to 'llvm/lib/Target/Hexagon/RDFLiveness.cpp')
| -rw-r--r-- | llvm/lib/Target/Hexagon/RDFLiveness.cpp | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/llvm/lib/Target/Hexagon/RDFLiveness.cpp b/llvm/lib/Target/Hexagon/RDFLiveness.cpp index 102388762a4..ebd5eaa778a 100644 --- a/llvm/lib/Target/Hexagon/RDFLiveness.cpp +++ b/llvm/lib/Target/Hexagon/RDFLiveness.cpp @@ -235,7 +235,93 @@ NodeList Liveness::getAllReachingDefs(NodeAddr<RefNode*> RefA) { } +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) { + const auto DA = DFG.addr<const DefNode*>(D); + if (!(DA.Addr->getFlags() & NodeAttrs::PhiRef)) + DefRRs.insert(DA.Addr->getRegRef()); + } + + auto 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) + TmpDefs.insert(R.Id); + + NodeSet Result = Defs; + + for (NodeAddr<DefNode*> DA : RDs) { + Result.insert(DA.Id); + if (!(DA.Addr->getFlags() & NodeAttrs::PhiRef)) + continue; + NodeAddr<PhiNode*> PA = DA.Addr->getOwner(DFG); + if (Visited.count(PA.Id)) + continue; + Visited.insert(PA.Id); + // Go over all phi uses and get the reaching defs for each use. + for (auto U : PA.Addr->members_if(DFG.IsRef<NodeAttrs::Use>, DFG)) { + const auto &T = getAllReachingDefsRec(RefRR, U, Visited, TmpDefs); + Result.insert(T.begin(), T.end()); + } + } + + return Result; +} + + +NodeSet Liveness::getAllReachedUses(RegisterRef RefRR, + NodeAddr<DefNode*> DefA, const RegisterSet &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)) + return Uses; + + // Add all directly reached uses. + NodeId U = DefA.Addr->getReachedUse(); + 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); + U = UA.Addr->getSibling(); + } + + // Traverse all reached defs. + 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(); + // 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)) + continue; + NodeSet T; + if (DA.Addr->getFlags() & NodeAttrs::Preserving) { + // If it is a preserving def, do not update the set of intervening defs. + T = getAllReachedUses(RefRR, DA, DefRRs); + } else { + RegisterSet NewDefRRs = DefRRs; + NewDefRRs.insert(DR); + T = getAllReachedUses(RefRR, DA, NewDefRRs); + } + Uses.insert(T.begin(), T.end()); + } + return Uses; +} + + void Liveness::computePhiInfo() { + RealUseMap.clear(); + NodeList Phis; NodeAddr<FuncNode*> FA = DFG.getFunc(); auto Blocks = FA.Addr->members(DFG); |

