From: Krzysztof Parzyszek Date: Thu, 22 Sep 2016 21:01:24 +0000 (+0000) Subject: [RDF] Add initial support for lane masks in the DFG X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=319d69e0f2b9dcc1487d359e05fe01844fc040d1;p=llvm [RDF] Add initial support for lane masks in the DFG Use lane masks for calculating covering and aliasing of register references. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@282194 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Target/Hexagon/HexagonRDF.cpp b/lib/Target/Hexagon/HexagonRDF.cpp index 06719cddf4b..ec4823da61f 100644 --- a/lib/Target/Hexagon/HexagonRDF.cpp +++ b/lib/Target/Hexagon/HexagonRDF.cpp @@ -16,7 +16,8 @@ using namespace llvm; using namespace rdf; -bool HexagonRegisterAliasInfo::covers(RegisterRef RA, RegisterRef RB) const { +bool HexagonRegisterAliasInfo::covers(RegisterRef RA, RegisterRef RB, + const DataFlowGraph &DFG) const { if (RA == RB) return true; @@ -31,30 +32,33 @@ bool HexagonRegisterAliasInfo::covers(RegisterRef RA, RegisterRef RB) const { } } - return RegisterAliasInfo::covers(RA, RB); + return RegisterAliasInfo::covers(RA, RB, DFG); } -bool HexagonRegisterAliasInfo::covers(const RegisterSet &RRs, RegisterRef RR) - const { +bool HexagonRegisterAliasInfo::covers(const RegisterSet &RRs, RegisterRef RR, + const DataFlowGraph &DFG) const { if (RRs.count(RR)) return true; - if (!TargetRegisterInfo::isPhysicalRegister(RR.Reg)) { - assert(TargetRegisterInfo::isVirtualRegister(RR.Reg)); - // Check if both covering subregisters are present. + // The exact reference RR is not in the set. + + if (TargetRegisterInfo::isVirtualRegister(RR.Reg)) { + // Check if the there are references in RRs of the same register, + // with both covering subregisters. bool HasLo = RRs.count({RR.Reg, Hexagon::subreg_loreg}); bool HasHi = RRs.count({RR.Reg, Hexagon::subreg_hireg}); if (HasLo && HasHi) return true; } - if (RR.Sub == 0) { - // Check if both covering subregisters are present. + if (TargetRegisterInfo::isPhysicalRegister(RR.Reg)) { + // Check if both covering subregisters are present with full + // lane masks. unsigned Lo = TRI.getSubReg(RR.Reg, Hexagon::subreg_loreg); unsigned Hi = TRI.getSubReg(RR.Reg, Hexagon::subreg_hireg); if (RRs.count({Lo, 0}) && RRs.count({Hi, 0})) return true; } - return RegisterAliasInfo::covers(RRs, RR); + return RegisterAliasInfo::covers(RRs, RR, DFG); } diff --git a/lib/Target/Hexagon/HexagonRDF.h b/lib/Target/Hexagon/HexagonRDF.h index 9a63150c377..7bcdbbaeb6d 100644 --- a/lib/Target/Hexagon/HexagonRDF.h +++ b/lib/Target/Hexagon/HexagonRDF.h @@ -18,8 +18,10 @@ namespace rdf { struct HexagonRegisterAliasInfo : public RegisterAliasInfo { HexagonRegisterAliasInfo(const TargetRegisterInfo &TRI) : RegisterAliasInfo(TRI) {} - bool covers(RegisterRef RA, RegisterRef RR) const override; - bool covers(const RegisterSet &RRs, RegisterRef RR) const override; + bool covers(RegisterRef RA, RegisterRef RR, + const DataFlowGraph &DFG) const override; + bool covers(const RegisterSet &RRs, RegisterRef RR, + const DataFlowGraph &DFG) const override; }; } // namespace rdf } // namespace llvm diff --git a/lib/Target/Hexagon/RDFGraph.cpp b/lib/Target/Hexagon/RDFGraph.cpp index bea9a837127..dd39dcfdb1c 100644 --- a/lib/Target/Hexagon/RDFGraph.cpp +++ b/lib/Target/Hexagon/RDFGraph.cpp @@ -580,14 +580,47 @@ NodeAddr FuncNode::getEntryBlock(const DataFlowGraph &G) { // Register aliasing information. // -// In theory, the lane information could be used to determine register -// covering (and aliasing), but depending on the sub-register structure, -// the lane mask information may be missing. The covering information -// must be available for this framework to work, so relying solely on -// the lane data is not sufficient. + +LaneBitmask RegisterAliasInfo::getLaneMask(RegisterRef RR, + const DataFlowGraph &DFG) const { + assert(TargetRegisterInfo::isPhysicalRegister(RR.Reg)); + const TargetRegisterClass *RC = TRI.getMinimalPhysRegClass(RR.Reg); + return (RR.Sub != 0) ? DFG.getLaneMaskForIndex(RR.Sub) : RC->LaneMask; +} + +RegisterAliasInfo::CommonRegister::CommonRegister( + unsigned RegA, LaneBitmask LA, unsigned RegB, LaneBitmask LB, + const TargetRegisterInfo &TRI) { + if (RegA == RegB) { + SuperReg = RegA; + MaskA = LA; + MaskB = LB; + return; + } + + // Find a common super-register. + SuperReg = 0; + for (MCSuperRegIterator SA(RegA, &TRI, true); SA.isValid(); ++SA) { + if (!TRI.isSubRegisterEq(*SA, RegB)) + continue; + SuperReg = *SA; + break; + } + if (SuperReg == 0) + return; + + if (unsigned SubA = TRI.getSubRegIndex(SuperReg, RegA)) + LA = TRI.composeSubRegIndexLaneMask(SubA, LA); + if (unsigned SubB = TRI.getSubRegIndex(SuperReg, RegB)) + LB = TRI.composeSubRegIndexLaneMask(SubB, LB); + + MaskA = LA; + MaskB = LB; +} // Determine whether RA covers RB. -bool RegisterAliasInfo::covers(RegisterRef RA, RegisterRef RB) const { +bool RegisterAliasInfo::covers(RegisterRef RA, RegisterRef RB, + const DataFlowGraph &DFG) const { if (RA == RB) return true; if (TargetRegisterInfo::isVirtualRegister(RA.Reg)) { @@ -601,13 +634,17 @@ bool RegisterAliasInfo::covers(RegisterRef RA, RegisterRef RB) const { assert(TargetRegisterInfo::isPhysicalRegister(RA.Reg) && TargetRegisterInfo::isPhysicalRegister(RB.Reg)); - uint32_t A = RA.Sub != 0 ? TRI.getSubReg(RA.Reg, RA.Sub) : RA.Reg; - uint32_t B = RB.Sub != 0 ? TRI.getSubReg(RB.Reg, RB.Sub) : RB.Reg; - return TRI.isSubRegister(A, B); + + CommonRegister CR(RA.Reg, getLaneMask(RA, DFG), + RB.Reg, getLaneMask(RB, DFG), TRI); + if (CR.SuperReg == 0) + return false; + return (CR.MaskA & CR.MaskB) == CR.MaskB; } // Determine whether RR is covered by the set of references RRs. -bool RegisterAliasInfo::covers(const RegisterSet &RRs, RegisterRef RR) const { +bool RegisterAliasInfo::covers(const RegisterSet &RRs, RegisterRef RR, + const DataFlowGraph &DFG) const { if (RRs.count(RR)) return true; @@ -630,7 +667,7 @@ bool RegisterAliasInfo::covers(const RegisterSet &RRs, RegisterRef RR) const { return false; } -// Get the list of references aliased to RR. +// Get the list of references aliased to RR. Lane masks are ignored. std::vector RegisterAliasInfo::getAliasSet(RegisterRef RR) const { // Do not include RR in the alias set. For virtual registers return an // empty set. @@ -648,16 +685,17 @@ std::vector RegisterAliasInfo::getAliasSet(RegisterRef RR) const { } // Check whether RA and RB are aliased. -bool RegisterAliasInfo::alias(RegisterRef RA, RegisterRef RB) const { - bool VirtA = TargetRegisterInfo::isVirtualRegister(RA.Reg); - bool VirtB = TargetRegisterInfo::isVirtualRegister(RB.Reg); - bool PhysA = TargetRegisterInfo::isPhysicalRegister(RA.Reg); - bool PhysB = TargetRegisterInfo::isPhysicalRegister(RB.Reg); - - if (VirtA != VirtB) +bool RegisterAliasInfo::alias(RegisterRef RA, RegisterRef RB, + const DataFlowGraph &DFG) const { + bool IsVirtA = TargetRegisterInfo::isVirtualRegister(RA.Reg); + bool IsVirtB = TargetRegisterInfo::isVirtualRegister(RB.Reg); + bool IsPhysA = TargetRegisterInfo::isPhysicalRegister(RA.Reg); + bool IsPhysB = TargetRegisterInfo::isPhysicalRegister(RB.Reg); + + if (IsVirtA != IsVirtB) return false; - if (VirtA) { + if (IsVirtA) { if (RA.Reg != RB.Reg) return false; // RA and RB refer to the same register. If any of them refer to the @@ -675,14 +713,14 @@ bool RegisterAliasInfo::alias(RegisterRef RA, RegisterRef RB) const { return false; } - assert(PhysA && PhysB); - (void)PhysA, (void)PhysB; - uint32_t A = RA.Sub ? TRI.getSubReg(RA.Reg, RA.Sub) : RA.Reg; - uint32_t B = RB.Sub ? TRI.getSubReg(RB.Reg, RB.Sub) : RB.Reg; - for (MCRegAliasIterator I(A, &TRI, true); I.isValid(); ++I) - if (B == *I) - return true; - return false; + assert(IsPhysA && IsPhysB); + (void)IsPhysA, (void)IsPhysB; + + CommonRegister CR(RA.Reg, getLaneMask(RA, DFG), + RB.Reg, getLaneMask(RB, DFG), TRI); + if (CR.SuperReg == 0) + return false; + return (CR.MaskA & CR.MaskB) != 0; } @@ -1213,7 +1251,7 @@ void DataFlowGraph::buildStmt(NodeAddr BA, MachineInstr &In) { if (!UseOp.isReg() || !UseOp.isUse() || UseOp.isUndef()) continue; RegisterRef UR = { UseOp.getReg(), UseOp.getSubReg() }; - if (RAI.alias(DR, UR)) + if (RAI.alias(DR, UR, *this)) return false; } return true; @@ -1398,7 +1436,7 @@ void DataFlowGraph::buildPhis(BlockRefsMap &PhiM, BlockRefsMap &RefM, auto MaxCoverIn = [this] (RegisterRef RR, RegisterSet &RRs) -> RegisterRef { for (auto I : RRs) - if (I != RR && RAI.covers(I, RR)) + if (I != RR && RAI.covers(I, RR, *this)) RR = I; return RR; }; @@ -1425,7 +1463,7 @@ void DataFlowGraph::buildPhis(BlockRefsMap &PhiM, BlockRefsMap &RefM, auto Aliased = [this,&MaxRefs](RegisterRef RR, std::vector &Closure) -> bool { for (auto I : Closure) - if (RAI.alias(RR, MaxRefs[I])) + if (RAI.alias(RR, MaxRefs[I], *this)) return true; return false; }; @@ -1544,9 +1582,9 @@ void DataFlowGraph::linkRefUp(NodeAddr IA, NodeAddr TA, for (auto I = DS.top(), E = DS.bottom(); I != E; I.down()) { RegisterRef QR = I->Addr->getRegRef(); auto AliasQR = [QR,this] (RegisterRef RR) -> bool { - return RAI.alias(QR, RR); + return RAI.alias(QR, RR, *this); }; - bool PrecUp = RAI.covers(QR, RR); + bool PrecUp = RAI.covers(QR, RR, *this); // Skip all defs that are aliased to any of the defs that we have already // seen. If we encounter a covering def, stop the stack traversal early. if (any_of(Defs, AliasQR)) { diff --git a/lib/Target/Hexagon/RDFGraph.h b/lib/Target/Hexagon/RDFGraph.h index 876fe241f72..3403b649d56 100644 --- a/lib/Target/Hexagon/RDFGraph.h +++ b/lib/Target/Hexagon/RDFGraph.h @@ -221,6 +221,7 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/Timer.h" +#include "llvm/Target/TargetRegisterInfo.h" #include #include @@ -236,11 +237,12 @@ namespace llvm { class MachineDominanceFrontier; class MachineDominatorTree; class TargetInstrInfo; - class TargetRegisterInfo; namespace rdf { typedef uint32_t NodeId; + struct DataFlowGraph; + struct NodeAttrs { enum : uint16_t { None = 0x0000, // Nothing @@ -384,6 +386,15 @@ namespace rdf { }; struct RegisterRef { + // For virtual registers, Reg and Sub have the usual meanings. + // + // Physical registers are assumed not to have any subregisters, and for + // them, Sub is the key of the LaneBitmask in the lane mask map in DFG. + // The case of Sub = 0 is treated as 'all lanes', i.e. lane mask of ~0. + // Use an key/map to access lane masks, since we only have uint32_t + // for it, and the LaneBitmask type can grow in the future. + // + // The case when Reg = 0 and Sub = 0 is reserved to mean "no register". uint32_t Reg, Sub; // No non-trivial constructors, since this will be a member of a union. @@ -407,11 +418,25 @@ namespace rdf { virtual ~RegisterAliasInfo() {} virtual std::vector getAliasSet(RegisterRef RR) const; - virtual bool alias(RegisterRef RA, RegisterRef RB) const; - virtual bool covers(RegisterRef RA, RegisterRef RB) const; - virtual bool covers(const RegisterSet &RRs, RegisterRef RR) const; + virtual bool alias(RegisterRef RA, RegisterRef RB, + const DataFlowGraph &DFG) const; + virtual bool covers(RegisterRef RA, RegisterRef RB, + const DataFlowGraph &DFG) const; + virtual bool covers(const RegisterSet &RRs, RegisterRef RR, + const DataFlowGraph &DFG) const; const TargetRegisterInfo &TRI; + + protected: + LaneBitmask getLaneMask(RegisterRef RR, const DataFlowGraph &DFG) const; + + struct CommonRegister { + CommonRegister(unsigned RegA, LaneBitmask LA, + unsigned RegB, LaneBitmask LB, + const TargetRegisterInfo &TRI); + unsigned SuperReg; + LaneBitmask MaskA, MaskB; + }; }; struct TargetOperandInfo { @@ -424,8 +449,31 @@ namespace rdf { const TargetInstrInfo &TII; }; + // Template class for a map translating uint32_t into arbitrary types. + // The map will act like an indexed set: upon insertion of a new object, + // it will automatically assign a new index to it. Index of 0 is treated + // as invalid and is never allocated. + template + struct IndexedSet { + IndexedSet() : Map(N) {} + const T get(uint32_t Idx) const { + // Index Idx corresponds to Map[Idx-1]. + assert(Idx != 0 && !Map.empty() && Idx-1 < Map.size()); + return Map[Idx-1]; + } + uint32_t insert(T Val) { + // Linear search. + auto F = find(Map, Val); + if (F != Map.end()) + return *F; + Map.push_back(Val); + return Map.size(); // Return actual_index + 1. + } + + private: + std::vector Map; + }; - struct DataFlowGraph; struct NodeBase { public: @@ -648,6 +696,13 @@ namespace rdf { return RAI; } + LaneBitmask getLaneMaskForIndex(uint32_t K) const { + return LMMap.get(K); + } + uint32_t getIndexForLaneMask(LaneBitmask LM) { + return LMMap.insert(LM); + } + struct DefStack { DefStack() = default; bool empty() const { return Stack.empty() || top() == bottom(); } @@ -820,6 +875,8 @@ namespace rdf { NodeAllocator Memory; // Local map: MachineBasicBlock -> NodeAddr std::map> BlockNodes; + // Lane mask map. + IndexedSet LMMap; MachineFunction &MF; const TargetInstrInfo &TII; diff --git a/lib/Target/Hexagon/RDFLiveness.cpp b/lib/Target/Hexagon/RDFLiveness.cpp index 3dfa7683c1c..48de9a6dbea 100644 --- a/lib/Target/Hexagon/RDFLiveness.cpp +++ b/lib/Target/Hexagon/RDFLiveness.cpp @@ -109,7 +109,7 @@ NodeList Liveness::getAllReachingDefs(RegisterRef RefRR, continue; // Stop at the covering/overwriting def of the initial register reference. RegisterRef RR = TA.Addr->getRegRef(); - if (!DFG.IsPreservingDef(TA) && RAI.covers(RR, RefRR)) + if (!DFG.IsPreservingDef(TA) && RAI.covers(RR, RefRR, DFG)) continue; // Get the next level of reaching defs. This will include multiple // reaching defs for shadows. @@ -124,7 +124,7 @@ NodeList Liveness::getAllReachingDefs(RegisterRef RefRR, for (auto N : DefQ) { auto TA = DFG.addr(N); bool IsPhi = TA.Addr->getFlags() & NodeAttrs::PhiRef; - if (!IsPhi && !RAI.alias(RefRR, TA.Addr->getRegRef())) + if (!IsPhi && !RAI.alias(RefRR, TA.Addr->getRegRef(), DFG)) continue; Defs.insert(TA.Id); Owners.insert(TA.Addr->getOwner(DFG).Id); @@ -194,7 +194,7 @@ NodeList Liveness::getAllReachingDefs(RegisterRef RefRR, Defs.count(TA.Id); }; for (auto T : Tmp) { - if (!FullChain && RAI.covers(RRs, RefRR)) + if (!FullChain && RAI.covers(RRs, RefRR, DFG)) break; auto TA = DFG.addr(T); bool IsPhi = DFG.IsCode(TA); @@ -209,7 +209,7 @@ NodeList Liveness::getAllReachingDefs(RegisterRef RefRR, // phi d1(,d2,), ... Phi def d1 is covered by d2. // d2(d1,,u3), ... // ..., u3(d2) This use needs to be live on entry. - if (FullChain || IsPhi || !RAI.covers(RRs, QR)) + if (FullChain || IsPhi || !RAI.covers(RRs, QR, DFG)) Ds.push_back(DA); } RDefs.insert(RDefs.end(), Ds.begin(), Ds.end()); @@ -281,7 +281,7 @@ NodeSet Liveness::getAllReachedUses(RegisterRef RefRR, // If the original register is already covered by all the intervening // defs, no more uses can be reached. - if (RAI.covers(DefRRs, RefRR)) + if (RAI.covers(DefRRs, RefRR, DFG)) return Uses; // Add all directly reached uses. @@ -290,7 +290,7 @@ NodeSet Liveness::getAllReachedUses(RegisterRef RefRR, auto UA = DFG.addr(U); if (!(UA.Addr->getFlags() & NodeAttrs::Undef)) { auto UR = UA.Addr->getRegRef(); - if (RAI.alias(RefRR, UR) && !RAI.covers(DefRRs, UR)) + if (RAI.alias(RefRR, UR, DFG) && !RAI.covers(DefRRs, UR, DFG)) Uses.insert(U); } U = UA.Addr->getSibling(); @@ -303,7 +303,7 @@ NodeSet Liveness::getAllReachedUses(RegisterRef RefRR, 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)) + if (RAI.covers(DefRRs, DR, DFG) || !RAI.alias(RefRR, DR, DFG)) continue; NodeSet T; if (DFG.IsPreservingDef(DA)) { @@ -514,7 +514,7 @@ void Liveness::computePhiInfo() { RegisterRef R = T.first; if (!isRestrictedToRef(PA, UA, R)) R = getRestrictedRegRef(UA); - if (!RAI.covers(MidDefs, R)) + if (!RAI.covers(MidDefs, R, DFG)) UpReached.insert(R); } if (UpReached.empty()) @@ -635,7 +635,7 @@ void Liveness::computeLiveIns() { // 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)) + if (!RAI.alias(R.first, RR, DFG)) continue; for (auto D : getAllReachingDefs(RR, UA)) LOX[RR].insert(D.Id); @@ -768,7 +768,7 @@ bool Liveness::isRestrictedToRef(NodeAddr IA, NodeAddr RA, NodeId RD = TA.Addr->getReachingDef(); if (RD == 0) continue; - if (RAI.alias(RR, DFG.addr(RD).Addr->getRegRef())) + if (RAI.alias(RR, DFG.addr(RD).Addr->getRegRef(), DFG)) return false; } return true; @@ -880,13 +880,13 @@ void Liveness::traverse(MachineBasicBlock *B, RefMap &LiveIn) { else { bool IsPreserving = DFG.IsPreservingDef(DA); if (IA.Addr->getKind() != NodeAttrs::Phi && !IsPreserving) { - bool Covering = RAI.covers(DDR, I.first); + bool Covering = RAI.covers(DDR, I.first, DFG); NodeId U = DA.Addr->getReachedUse(); while (U && Covering) { auto DUA = DFG.addr(U); if (!(DUA.Addr->getFlags() & NodeAttrs::Undef)) { RegisterRef Q = DUA.Addr->getRegRef(); - Covering = RAI.covers(DA.Addr->getRegRef(), Q); + Covering = RAI.covers(DA.Addr->getRegRef(), Q, DFG); } U = DUA.Addr->getSibling(); } @@ -909,7 +909,7 @@ void Liveness::traverse(MachineBasicBlock *B, RefMap &LiveIn) { RRs.insert(TA.Addr->getRegRef()); if (BA.Addr->getCode() == B) continue; - if (RAI.covers(RRs, DRR)) + if (RAI.covers(RRs, DRR, DFG)) break; Defs.insert(TA.Id); }