diff options
-rw-r--r-- | llvm/lib/Target/Hexagon/CMakeLists.txt | 1 | ||||
-rw-r--r-- | llvm/lib/Target/Hexagon/RDFGraph.cpp | 167 | ||||
-rw-r--r-- | llvm/lib/Target/Hexagon/RDFGraph.h | 94 | ||||
-rw-r--r-- | llvm/lib/Target/Hexagon/RDFLiveness.cpp | 16 | ||||
-rw-r--r-- | llvm/lib/Target/Hexagon/RDFLiveness.h | 9 | ||||
-rw-r--r-- | llvm/lib/Target/Hexagon/RDFRegisters.cpp | 196 | ||||
-rw-r--r-- | llvm/lib/Target/Hexagon/RDFRegisters.h | 115 |
7 files changed, 344 insertions, 254 deletions
diff --git a/llvm/lib/Target/Hexagon/CMakeLists.txt b/llvm/lib/Target/Hexagon/CMakeLists.txt index de4ed45577c..3e2a8229797 100644 --- a/llvm/lib/Target/Hexagon/CMakeLists.txt +++ b/llvm/lib/Target/Hexagon/CMakeLists.txt @@ -59,6 +59,7 @@ add_llvm_target(HexagonCodeGen RDFDeadCode.cpp RDFGraph.cpp RDFLiveness.cpp + RDFRegisters.cpp ) add_subdirectory(AsmParser) diff --git a/llvm/lib/Target/Hexagon/RDFGraph.cpp b/llvm/lib/Target/Hexagon/RDFGraph.cpp index e5cfc7a96b4..98744d5c8de 100644 --- a/llvm/lib/Target/Hexagon/RDFGraph.cpp +++ b/llvm/lib/Target/Hexagon/RDFGraph.cpp @@ -654,109 +654,6 @@ bool TargetOperandInfo::isFixedReg(const MachineInstr &In, unsigned OpNum) return false; } -RegisterRef RegisterAggr::normalize(RegisterRef RR) const { - RegisterId SuperReg = RR.Reg; - while (true) { - MCSuperRegIterator SR(SuperReg, &TRI, false); - if (!SR.isValid()) - break; - SuperReg = *SR; - } - - const TargetRegisterClass &RC = *TRI.getMinimalPhysRegClass(RR.Reg); - LaneBitmask Common = RR.Mask & RC.LaneMask; - uint32_t Sub = TRI.getSubRegIndex(SuperReg, RR.Reg); - LaneBitmask SuperMask = TRI.composeSubRegIndexLaneMask(Sub, Common); - return RegisterRef(SuperReg, SuperMask); -} - -bool RegisterAggr::hasAliasOf(RegisterRef RR) const { - RegisterRef NR = normalize(RR); - auto F = Masks.find(NR.Reg); - if (F != Masks.end()) { - if ((F->second & NR.Mask).any()) - return true; - } - if (CheckUnits) { - for (MCRegUnitIterator U(RR.Reg, &TRI); U.isValid(); ++U) - if (ExpAliasUnits.test(*U)) - return true; - } - return false; -} - -bool RegisterAggr::hasCoverOf(RegisterRef RR) const { - // Always have a cover for empty lane mask. - RegisterRef NR = normalize(RR); - if (NR.Mask.none()) - return true; - auto F = Masks.find(NR.Reg); - if (F == Masks.end()) - return false; - return (NR.Mask & F->second) == NR.Mask; -} - -RegisterAggr &RegisterAggr::insert(RegisterRef RR) { - RegisterRef NR = normalize(RR); - auto F = Masks.find(NR.Reg); - if (F == Masks.end()) - Masks.insert({NR.Reg, NR.Mask}); - else - F->second |= NR.Mask; - - // Visit all register units to see if there are any that were created - // by explicit aliases. Add those that were to the bit vector. - for (MCRegUnitIterator U(RR.Reg, &TRI); U.isValid(); ++U) { - MCRegUnitRootIterator R(*U, &TRI); - ++R; - if (!R.isValid()) - continue; - ExpAliasUnits.set(*U); - CheckUnits = true; - } - return *this; -} - -RegisterAggr &RegisterAggr::insert(const RegisterAggr &RG) { - for (std::pair<RegisterId,LaneBitmask> P : RG.Masks) - insert(RegisterRef(P.first, P.second)); - return *this; -} - -RegisterAggr &RegisterAggr::clear(RegisterRef RR) { - RegisterRef NR = 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; -} - -RegisterAggr &RegisterAggr::clear(const RegisterAggr &RG) { - for (std::pair<RegisterId,LaneBitmask> P : RG.Masks) - clear(RegisterRef(P.first, P.second)); - return *this; -} - -RegisterRef RegisterAggr::clearIn(RegisterRef RR) const { - RegisterAggr T(TRI); - T.insert(RR).clear(*this); - if (T.empty()) - return RegisterRef(); - return RegisterRef(T.begin()->first, T.begin()->second); -} - -void RegisterAggr::print(raw_ostream &OS) const { - OS << '{'; - for (auto I : Masks) - OS << ' ' << PrintReg(I.first, &TRI) << PrintLaneMaskOpt(I.second); - OS << " }"; -} - // // The data flow graph construction. // @@ -764,7 +661,8 @@ void RegisterAggr::print(raw_ostream &OS) const { DataFlowGraph::DataFlowGraph(MachineFunction &mf, const TargetInstrInfo &tii, const TargetRegisterInfo &tri, const MachineDominatorTree &mdt, const MachineDominanceFrontier &mdf, const TargetOperandInfo &toi) - : MF(mf), TII(tii), TRI(tri), MDT(mdt), MDF(mdf), TOI(toi), LiveIns(TRI) { + : MF(mf), TII(tii), TRI(tri), PRI(tri, mf), MDT(mdt), MDF(mdf), TOI(toi), + LiveIns(PRI) { } // The implementation of the definition stack. @@ -1211,59 +1109,6 @@ NodeList DataFlowGraph::getRelatedRefs(NodeAddr<InstrNode*> IA, return Refs; } -// Return true if RA and RB overlap, false otherwise. -bool DataFlowGraph::alias(RegisterRef RA, RegisterRef RB) const { - assert(TargetRegisterInfo::isPhysicalRegister(RA.Reg)); - assert(TargetRegisterInfo::isPhysicalRegister(RB.Reg)); - - MCRegUnitMaskIterator UMA(RA.Reg, &TRI); - MCRegUnitMaskIterator UMB(RB.Reg, &TRI); - // Reg units are returned in the numerical order. - while (UMA.isValid() && UMB.isValid()) { - std::pair<uint32_t,LaneBitmask> PA = *UMA; - std::pair<uint32_t,LaneBitmask> PB = *UMB; - if (PA.first == PB.first) { - // Lane mask of 0 (given by the iterator) should be treated as "full". - // This can happen when the register has only one unit, or when the - // unit corresponds to explicit aliasing. In such cases, the lane mask - // from RegisterRef should be ignored. - if (PA.second.none() || PB.second.none()) - return true; - - // At this point the common unit corresponds to a subregister. The lane - // masks correspond to the lane mask of that unit within the original - // register, for example assuming register quadruple q0 = r3:0, and - // a register pair d1 = r3:2, the lane mask of r2 in q0 may be 0b0100, - // while the lane mask of r2 in d1 may be 0b0001. - LaneBitmask LA = PA.second & RA.Mask; - LaneBitmask LB = PB.second & RB.Mask; - if (LA.any() && LB.any()) { - unsigned Root = *MCRegUnitRootIterator(PA.first, &TRI); - // If register units were guaranteed to only have 1 bit in any lane - // mask, the code below would not be necessary. This is because LA - // and LB would have at most 1 bit set each, and that bit would be - // guaranteed to correspond to the given register unit. - uint32_t SubA = TRI.getSubRegIndex(RA.Reg, Root); - uint32_t SubB = TRI.getSubRegIndex(RB.Reg, Root); - const TargetRegisterClass &RC = *TRI.getMinimalPhysRegClass(Root); - LaneBitmask MaskA = TRI.reverseComposeSubRegIndexLaneMask(SubA, LA); - LaneBitmask MaskB = TRI.reverseComposeSubRegIndexLaneMask(SubB, LB); - if ((MaskA & MaskB & RC.LaneMask).any()) - return true; - } - - ++UMA; - ++UMB; - continue; - } - if (PA.first < PB.first) - ++UMA; - else if (PB.first < PA.first) - ++UMB; - } - return false; -} - // Clear all information in the graph. void DataFlowGraph::reset() { Memory.clear(); @@ -1392,7 +1237,7 @@ void DataFlowGraph::buildStmt(NodeAddr<BlockNode*> BA, MachineInstr &In) { if (!UseOp.isReg() || !UseOp.isUse() || UseOp.isUndef()) continue; RegisterRef UR = makeRegRef(UseOp.getReg(), UseOp.getSubReg()); - if (alias(DR, UR)) + if (PRI.alias(DR, UR)) return false; } return true; @@ -1578,7 +1423,7 @@ void DataFlowGraph::buildPhis(BlockRefsMap &PhiM, BlockRefsMap &RefM, auto MaxCoverIn = [this] (RegisterRef RR, RegisterSet &RRs) -> RegisterRef { for (RegisterRef I : RRs) - if (I != RR && RegisterAggr::isCoverOf(I, RR, TRI)) + if (I != RR && RegisterAggr::isCoverOf(I, RR, PRI)) RR = I; return RR; }; @@ -1605,7 +1450,7 @@ void DataFlowGraph::buildPhis(BlockRefsMap &PhiM, BlockRefsMap &RefM, auto Aliased = [this,&MaxRefs](RegisterRef RR, std::vector<unsigned> &Closure) -> bool { for (unsigned I : Closure) - if (alias(RR, MaxRefs[I])) + if (PRI.alias(RR, MaxRefs[I])) return true; return false; }; @@ -1716,7 +1561,7 @@ void DataFlowGraph::linkRefUp(NodeAddr<InstrNode*> IA, NodeAddr<T> TA, NodeAddr<T> TAP; // References from the def stack that have been examined so far. - RegisterAggr Defs(TRI); + RegisterAggr Defs(PRI); for (auto I = DS.top(), E = DS.bottom(); I != E; I.down()) { RegisterRef QR = I->Addr->getRegRef(*this); diff --git a/llvm/lib/Target/Hexagon/RDFGraph.h b/llvm/lib/Target/Hexagon/RDFGraph.h index b3132f69bf2..eae742016a6 100644 --- a/llvm/lib/Target/Hexagon/RDFGraph.h +++ b/llvm/lib/Target/Hexagon/RDFGraph.h @@ -225,6 +225,7 @@ #ifndef LLVM_LIB_TARGET_HEXAGON_RDFGRAPH_H #define LLVM_LIB_TARGET_HEXAGON_RDFGRAPH_H +#include "RDFRegisters.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/STLExtras.h" #include "llvm/MC/LaneBitmask.h" @@ -260,7 +261,6 @@ namespace llvm { namespace rdf { typedef uint32_t NodeId; - typedef uint32_t RegisterId; struct DataFlowGraph; @@ -412,25 +412,6 @@ namespace rdf { AllocatorTy MemPool; }; - struct RegisterRef { - RegisterId Reg; - LaneBitmask Mask; - - RegisterRef() : RegisterRef(0) {} - explicit RegisterRef(RegisterId R, LaneBitmask M = LaneBitmask::getAll()) - : Reg(R), Mask(R != 0 ? M : LaneBitmask::getNone()) {} - - operator bool() const { return Reg != 0 && Mask.any(); } - bool operator== (const RegisterRef &RR) const { - return Reg == RR.Reg && Mask == RR.Mask; - } - bool operator!= (const RegisterRef &RR) const { - return !operator==(RR); - } - bool operator< (const RegisterRef &RR) const { - return Reg < RR.Reg || (Reg == RR.Reg && Mask < RR.Mask); - } - }; typedef std::set<RegisterRef> RegisterSet; struct TargetOperandInfo { @@ -497,55 +478,6 @@ namespace rdf { assert(LM.any()); return LM.all() ? 0 : find(LM); } - - PackedRegisterRef pack(RegisterRef RR) { - return { RR.Reg, getIndexForLaneMask(RR.Mask) }; - } - PackedRegisterRef pack(RegisterRef RR) const { - return { RR.Reg, getIndexForLaneMask(RR.Mask) }; - } - - RegisterRef unpack(PackedRegisterRef PR) const { - return RegisterRef(PR.Reg, getLaneMaskForIndex(PR.MaskId)); - } - }; - - struct RegisterAggr { - RegisterAggr(const TargetRegisterInfo &tri) - : ExpAliasUnits(tri.getNumRegUnits()), CheckUnits(false), TRI(tri) {} - RegisterAggr(const RegisterAggr &RG) = default; - - bool empty() const { return Masks.empty(); } - bool hasAliasOf(RegisterRef RR) const; - bool hasCoverOf(RegisterRef RR) const; - static bool isCoverOf(RegisterRef RA, RegisterRef RB, - const TargetRegisterInfo &TRI) { - return RegisterAggr(TRI).insert(RA).hasCoverOf(RB); - } - - RegisterAggr &insert(RegisterRef RR); - RegisterAggr &insert(const RegisterAggr &RG); - RegisterAggr &clear(RegisterRef RR); - RegisterAggr &clear(const RegisterAggr &RG); - - RegisterRef clearIn(RegisterRef RR) const; - - void print(raw_ostream &OS) const; - - private: - typedef std::unordered_map<RegisterId, LaneBitmask> MapType; - - public: - typedef MapType::const_iterator iterator; - iterator begin() const { return Masks.begin(); } - iterator end() const { return Masks.end(); } - RegisterRef normalize(RegisterRef RR) const; - - private: - MapType Masks; - BitVector ExpAliasUnits; // Register units for explicit aliases. - bool CheckUnits; - const TargetRegisterInfo &TRI; }; struct NodeBase { @@ -761,6 +693,7 @@ namespace rdf { MachineFunction &getMF() const { return MF; } const TargetInstrInfo &getTII() const { return TII; } const TargetRegisterInfo &getTRI() const { return TRI; } + const PhysicalRegisterInfo &getPRI() const { return PRI; } const MachineDominatorTree &getDT() const { return MDT; } const MachineDominanceFrontier &getDF() const { return MDF; } const RegisterAggr &getLiveIns() const { return LiveIns; } @@ -833,9 +766,16 @@ namespace rdf { void markBlock(NodeId B, DefStackMap &DefM); void releaseBlock(NodeId B, DefStackMap &DefM); - PackedRegisterRef pack(RegisterRef RR) { return LMI.pack(RR); } - PackedRegisterRef pack(RegisterRef RR) const { return LMI.pack(RR); } - RegisterRef unpack(PackedRegisterRef PR) const { return LMI.unpack(PR); } + PackedRegisterRef pack(RegisterRef RR) { + return { RR.Reg, LMI.getIndexForLaneMask(RR.Mask) }; + } + PackedRegisterRef pack(RegisterRef RR) const { + return { RR.Reg, LMI.getIndexForLaneMask(RR.Mask) }; + } + RegisterRef unpack(PackedRegisterRef PR) const { + return RegisterRef(PR.Reg, LMI.getLaneMaskForIndex(PR.MaskId)); + } + RegisterRef makeRegRef(unsigned Reg, unsigned Sub) const; RegisterRef normalizeRef(RegisterRef RR) const; RegisterRef restrictRef(RegisterRef AR, RegisterRef BR) const; @@ -899,9 +839,6 @@ namespace rdf { return (Flags & NodeAttrs::Preserving) && !(Flags & NodeAttrs::Undef); } - // Register aliasing. - bool alias(RegisterRef RA, RegisterRef RB) const; - private: void reset(); @@ -961,6 +898,7 @@ namespace rdf { MachineFunction &MF; const TargetInstrInfo &TII; const TargetRegisterInfo &TRI; + const PhysicalRegisterInfo PRI; const MachineDominatorTree &MDT; const MachineDominanceFrontier &MDF; const TargetOperandInfo &TOI; @@ -1015,12 +953,6 @@ namespace rdf { return MM; } - // Optionally print the lane mask, if it is not ~0. - struct PrintLaneMaskOpt { - PrintLaneMaskOpt(LaneBitmask M) : Mask(M) {} - LaneBitmask Mask; - }; - raw_ostream &operator<< (raw_ostream &OS, const PrintLaneMaskOpt &P); template <typename T> struct Print; template <typename T> diff --git a/llvm/lib/Target/Hexagon/RDFLiveness.cpp b/llvm/lib/Target/Hexagon/RDFLiveness.cpp index 4b9dea08173..0dab15e9a69 100644 --- a/llvm/lib/Target/Hexagon/RDFLiveness.cpp +++ b/llvm/lib/Target/Hexagon/RDFLiveness.cpp @@ -119,7 +119,7 @@ NodeList Liveness::getAllReachingDefs(RegisterRef RefRR, // Stop at the covering/overwriting def of the initial register reference. RegisterRef RR = TA.Addr->getRegRef(DFG); if (!DFG.IsPreservingDef(TA)) - if (RegisterAggr::isCoverOf(RR, RefRR, TRI)) + if (RegisterAggr::isCoverOf(RR, RefRR, PRI)) continue; // Get the next level of reaching defs. This will include multiple // reaching defs for shadows. @@ -134,7 +134,7 @@ NodeList Liveness::getAllReachingDefs(RegisterRef RefRR, for (NodeId N : DefQ) { auto TA = DFG.addr<DefNode*>(N); bool IsPhi = TA.Addr->getFlags() & NodeAttrs::PhiRef; - if (!IsPhi && !DFG.alias(RefRR, TA.Addr->getRegRef(DFG))) + if (!IsPhi && !PRI.alias(RefRR, TA.Addr->getRegRef(DFG))) continue; Defs.insert(TA.Id); Owners.insert(TA.Addr->getOwner(DFG).Id); @@ -245,7 +245,7 @@ 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. - RegisterAggr DefRRs(TRI); + RegisterAggr DefRRs(PRI); for (NodeId D : Defs) { const auto DA = DFG.addr<const DefNode*>(D); if (!(DA.Addr->getFlags() & NodeAttrs::PhiRef)) @@ -299,7 +299,7 @@ NodeSet Liveness::getAllReachedUses(RegisterRef RefRR, auto UA = DFG.addr<UseNode*>(U); if (!(UA.Addr->getFlags() & NodeAttrs::Undef)) { RegisterRef UR = UA.Addr->getRegRef(DFG); - if (DFG.alias(RefRR, UR) && !DefRRs.hasCoverOf(UR)) + if (PRI.alias(RefRR, UR) && !DefRRs.hasCoverOf(UR)) Uses.insert(U); } U = UA.Addr->getSibling(); @@ -312,7 +312,7 @@ NodeSet Liveness::getAllReachedUses(RegisterRef RefRR, 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 (DefRRs.hasCoverOf(DR) || !DFG.alias(RefRR, DR)) + if (DefRRs.hasCoverOf(DR) || !PRI.alias(RefRR, DR)) continue; NodeSet T; if (DFG.IsPreservingDef(DA)) { @@ -463,7 +463,7 @@ void Liveness::computePhiInfo() { for (NodeAddr<UseNode*> VA : DFG.getRelatedRefs(PhiA, UA)) { SeenUses.insert(VA.Id); - RegisterAggr DefRRs(TRI); + RegisterAggr DefRRs(PRI); for (NodeAddr<DefNode*> DA : getAllReachingDefs(VA)) { if (DA.Addr->getFlags() & NodeAttrs::PhiRef) { NodeId RP = DA.Addr->getOwner(DFG).Id; @@ -918,7 +918,7 @@ void Liveness::traverse(MachineBasicBlock *B, RefMap &LiveIn) { // 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); + RegisterAggr RRs(PRI); LRef.Mask = OR.second; if (!DFG.IsPreservingDef(DA)) { @@ -946,7 +946,7 @@ 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(TRI); + RegisterAggr L(PRI); L.insert(LRef).clear(RRs); assert(!L.empty()); NewDefs.insert({TA.Id,L.begin()->second}); diff --git a/llvm/lib/Target/Hexagon/RDFLiveness.h b/llvm/lib/Target/Hexagon/RDFLiveness.h index c88396f36bb..756977fb386 100644 --- a/llvm/lib/Target/Hexagon/RDFLiveness.h +++ b/llvm/lib/Target/Hexagon/RDFLiveness.h @@ -33,7 +33,7 @@ namespace rdf { // This is really a std::map, except that it provides a non-trivial // default constructor to the element accessed via []. struct LiveMapType { - LiveMapType(const TargetRegisterInfo &tri) : Empty(tri) {} + LiveMapType(const PhysicalRegisterInfo &pri) : Empty(pri) {} RegisterAggr &operator[] (MachineBasicBlock *B) { return Map.emplace(B, Empty).first->second; @@ -49,9 +49,9 @@ namespace rdf { typedef std::map<RegisterId,NodeRefSet> RefMap; Liveness(MachineRegisterInfo &mri, const DataFlowGraph &g) - : DFG(g), TRI(g.getTRI()), MDT(g.getDT()), MDF(g.getDF()), - MRI(mri), LiveMap(g.getTRI()), Empty(), NoRegs(g.getTRI()), - Trace(false) {} + : DFG(g), TRI(g.getTRI()), PRI(g.getPRI()), MDT(g.getDT()), + MDF(g.getDF()), MRI(mri), LiveMap(g.getPRI()), Empty(), + NoRegs(g.getPRI()), Trace(false) {} NodeList getAllReachingDefs(RegisterRef RefRR, NodeAddr<RefNode*> RefA, bool FullChain, const RegisterAggr &DefRRs); @@ -87,6 +87,7 @@ namespace rdf { private: const DataFlowGraph &DFG; const TargetRegisterInfo &TRI; + const PhysicalRegisterInfo &PRI; const MachineDominatorTree &MDT; const MachineDominanceFrontier &MDF; MachineRegisterInfo &MRI; diff --git a/llvm/lib/Target/Hexagon/RDFRegisters.cpp b/llvm/lib/Target/Hexagon/RDFRegisters.cpp new file mode 100644 index 00000000000..5cb8f9a12d4 --- /dev/null +++ b/llvm/lib/Target/Hexagon/RDFRegisters.cpp @@ -0,0 +1,196 @@ +//===--- RDFRegisters.cpp ---------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "RDFRegisters.h" +#include "llvm/CodeGen/MachineFunction.h" + +using namespace llvm; +using namespace rdf; + +PhysicalRegisterInfo::PhysicalRegisterInfo(const TargetRegisterInfo &tri, + const MachineFunction &mf) + : TRI(tri) { + RegInfos.resize(TRI.getNumRegs()); + + BitVector BadRC(TRI.getNumRegs()); + for (const TargetRegisterClass *RC : TRI.regclasses()) { + for (MCPhysReg R : *RC) { + RegInfo &RI = RegInfos[R]; + if (RI.RegClass != nullptr && !BadRC[R]) { + if (RC->LaneMask != RI.RegClass->LaneMask) { + BadRC.set(R); + RI.RegClass = nullptr; + } + } else + RI.RegClass = RC; + } + } + + for (MCPhysReg R = 1, NR = TRI.getNumRegs(); R != NR; ++R) { + MCPhysReg SuperR = R; + for (MCSuperRegIterator S(R, &TRI, false); S.isValid(); ++S) + SuperR = *S; + RegInfos[R].MaxSuper = SuperR; + } +} + +bool PhysicalRegisterInfo::alias(RegisterRef RA, RegisterRef RB) const { + assert(TargetRegisterInfo::isPhysicalRegister(RA.Reg)); + assert(TargetRegisterInfo::isPhysicalRegister(RB.Reg)); + MCRegUnitMaskIterator UMA(RA.Reg, &TRI); + MCRegUnitMaskIterator UMB(RB.Reg, &TRI); + // Reg units are returned in the numerical order. + while (UMA.isValid() && UMB.isValid()) { + std::pair<uint32_t,LaneBitmask> PA = *UMA; + std::pair<uint32_t,LaneBitmask> PB = *UMB; + if (PA.first == PB.first) { + // Lane mask of 0 (given by the iterator) should be treated as "full". + // This can happen when the register has only one unit, or when the + // unit corresponds to explicit aliasing. In such cases, the lane mask + // from RegisterRef should be ignored. + if (PA.second.none() || PB.second.none()) + return true; + + // At this point the common unit corresponds to a subregister. The lane + // masks correspond to the lane mask of that unit within the original + // register, for example assuming register quadruple q0 = r3:0, and + // a register pair d1 = r3:2, the lane mask of r2 in q0 may be 0b0100, + // while the lane mask of r2 in d1 may be 0b0001. + LaneBitmask LA = PA.second & RA.Mask; + LaneBitmask LB = PB.second & RB.Mask; + if (LA.any() && LB.any()) { + unsigned Root = *MCRegUnitRootIterator(PA.first, &TRI); + // If register units were guaranteed to only have 1 bit in any lane + // mask, the code below would not be necessary. This is because LA + // and LB would have at most 1 bit set each, and that bit would be + // guaranteed to correspond to the given register unit. + uint32_t SubA = TRI.getSubRegIndex(RA.Reg, Root); + uint32_t SubB = TRI.getSubRegIndex(RB.Reg, Root); + const TargetRegisterClass *RC = RegInfos[Root].RegClass; + LaneBitmask RCMask = RC != nullptr ? RC->LaneMask : LaneBitmask(0x1); + LaneBitmask MaskA = TRI.reverseComposeSubRegIndexLaneMask(SubA, LA); + LaneBitmask MaskB = TRI.reverseComposeSubRegIndexLaneMask(SubB, LB); + if ((MaskA & MaskB & RCMask).any()) + return true; + } + + ++UMA; + ++UMB; + continue; + } + if (PA.first < PB.first) + ++UMA; + else if (PB.first < PA.first) + ++UMB; + } + return false; +} + +RegisterRef RegisterAggr::normalize(RegisterRef RR) const { + const TargetRegisterClass *RC = PRI.RegInfos[RR.Reg].RegClass; + LaneBitmask RCMask = RC != nullptr ? RC->LaneMask : LaneBitmask(0x00000001); + LaneBitmask Common = RR.Mask & RCMask; + + RegisterId SuperReg = PRI.RegInfos[RR.Reg].MaxSuper; +// Ex: IP/EIP/RIP +// assert(RC != nullptr || RR.Reg == SuperReg); + uint32_t Sub = PRI.getTRI().getSubRegIndex(SuperReg, RR.Reg); + LaneBitmask SuperMask = PRI.getTRI().composeSubRegIndexLaneMask(Sub, Common); + return RegisterRef(SuperReg, SuperMask); +} + +bool RegisterAggr::hasAliasOf(RegisterRef RR) const { + RegisterRef NR = normalize(RR); + auto F = Masks.find(NR.Reg); + if (F != Masks.end()) { + if ((F->second & NR.Mask).any()) + return true; + } + if (CheckUnits) { + for (MCRegUnitIterator U(RR.Reg, &PRI.getTRI()); U.isValid(); ++U) + if (ExpAliasUnits.test(*U)) + return true; + } + return false; +} + +bool RegisterAggr::hasCoverOf(RegisterRef RR) const { + // Always have a cover for empty lane mask. + RegisterRef NR = normalize(RR); + if (NR.Mask.none()) + return true; + auto F = Masks.find(NR.Reg); + if (F == Masks.end()) + return false; + return (NR.Mask & F->second) == NR.Mask; +} + +RegisterAggr &RegisterAggr::insert(RegisterRef RR) { + RegisterRef NR = normalize(RR); + auto F = Masks.find(NR.Reg); + if (F == Masks.end()) + Masks.insert({NR.Reg, NR.Mask}); + else + F->second |= NR.Mask; + + // Visit all register units to see if there are any that were created + // by explicit aliases. Add those that were to the bit vector. + const TargetRegisterInfo &TRI = PRI.getTRI(); + for (MCRegUnitIterator U(RR.Reg, &TRI); U.isValid(); ++U) { + MCRegUnitRootIterator R(*U, &TRI); + ++R; + if (!R.isValid()) + continue; + ExpAliasUnits.set(*U); + CheckUnits = true; + } + return *this; +} + +RegisterAggr &RegisterAggr::insert(const RegisterAggr &RG) { + for (std::pair<RegisterId,LaneBitmask> P : RG.Masks) + insert(RegisterRef(P.first, P.second)); + return *this; +} + +RegisterAggr &RegisterAggr::clear(RegisterRef RR) { + RegisterRef NR = 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; +} + +RegisterAggr &RegisterAggr::clear(const RegisterAggr &RG) { + for (std::pair<RegisterId,LaneBitmask> P : RG.Masks) + clear(RegisterRef(P.first, P.second)); + return *this; +} + +RegisterRef RegisterAggr::clearIn(RegisterRef RR) const { + RegisterAggr T(PRI); + T.insert(RR).clear(*this); + if (T.empty()) + return RegisterRef(); + return RegisterRef(T.begin()->first, T.begin()->second); +} + +void RegisterAggr::print(raw_ostream &OS) const { + OS << '{'; + for (auto I : Masks) + OS << ' ' << PrintReg(I.first, &PRI.getTRI()) + << PrintLaneMaskOpt(I.second); + OS << " }"; +} + diff --git a/llvm/lib/Target/Hexagon/RDFRegisters.h b/llvm/lib/Target/Hexagon/RDFRegisters.h new file mode 100644 index 00000000000..fbeea2150b6 --- /dev/null +++ b/llvm/lib/Target/Hexagon/RDFRegisters.h @@ -0,0 +1,115 @@ +//===--- RDFRegisters.h -----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_HEXAGON_RDFREGISTERS_H +#define LLVM_LIB_TARGET_HEXAGON_RDFREGISTERS_H + +#include "llvm/ADT/BitVector.h" +#include "llvm/Target/TargetRegisterInfo.h" + +#include <unordered_map> +#include <vector> + +namespace llvm { +namespace rdf { + + typedef uint32_t RegisterId; + + struct RegisterRef { + RegisterId Reg = 0; + LaneBitmask Mask = LaneBitmask::getNone(); + + RegisterRef() = default; + explicit RegisterRef(RegisterId R, LaneBitmask M = LaneBitmask::getAll()) + : Reg(R), Mask(R != 0 ? M : LaneBitmask::getNone()) {} + + operator bool() const { + return Reg != 0 && Mask.any(); + } + bool operator== (const RegisterRef &RR) const { + return Reg == RR.Reg && Mask == RR.Mask; + } + bool operator!= (const RegisterRef &RR) const { + return !operator==(RR); + } + bool operator< (const RegisterRef &RR) const { + return Reg < RR.Reg || (Reg == RR.Reg && Mask < RR.Mask); + } + }; + + + struct PhysicalRegisterInfo { + PhysicalRegisterInfo(const TargetRegisterInfo &tri, + const MachineFunction &mf); + + bool alias(RegisterRef RA, RegisterRef RB) const; + + const TargetRegisterInfo &getTRI() const { return TRI; } + +// private: + struct RegInfo { + unsigned MaxSuper = 0; + const TargetRegisterClass *RegClass = nullptr; + }; + + const TargetRegisterInfo &TRI; + std::vector<RegInfo> RegInfos; + }; + + + struct RegisterAggr { + RegisterAggr(const PhysicalRegisterInfo &pri) + : ExpAliasUnits(pri.getTRI().getNumRegUnits()), PRI(pri) {} + RegisterAggr(const RegisterAggr &RG) = default; + + bool empty() const { return Masks.empty(); } + bool hasAliasOf(RegisterRef RR) const; + bool hasCoverOf(RegisterRef RR) const; + static bool isCoverOf(RegisterRef RA, RegisterRef RB, + const PhysicalRegisterInfo &PRI) { + return RegisterAggr(PRI).insert(RA).hasCoverOf(RB); + } + + RegisterAggr &insert(RegisterRef RR); + RegisterAggr &insert(const RegisterAggr &RG); + RegisterAggr &clear(RegisterRef RR); + RegisterAggr &clear(const RegisterAggr &RG); + + RegisterRef clearIn(RegisterRef RR) const; + + void print(raw_ostream &OS) const; + + private: + typedef std::unordered_map<RegisterId, LaneBitmask> MapType; + + public: + typedef MapType::const_iterator iterator; + iterator begin() const { return Masks.begin(); } + iterator end() const { return Masks.end(); } + RegisterRef normalize(RegisterRef RR) const; + + private: + MapType Masks; + BitVector ExpAliasUnits; // Register units for explicit aliases. + bool CheckUnits = false; + const PhysicalRegisterInfo &PRI; + }; + + // Optionally print the lane mask, if it is not ~0. + struct PrintLaneMaskOpt { + PrintLaneMaskOpt(LaneBitmask M) : Mask(M) {} + LaneBitmask Mask; + }; + raw_ostream &operator<< (raw_ostream &OS, const PrintLaneMaskOpt &P); + +} // namespace rdf +} // namespace llvm + +#endif + |