From: Krzysztof Parzyszek Date: Mon, 3 Oct 2016 17:14:48 +0000 (+0000) Subject: [RDF] Replace RegisterAliasInfo with target-independent code using lane masks X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d1ed87a667069a0f730f8a22cce226a22e6e58b3;p=llvm [RDF] Replace RegisterAliasInfo with target-independent code using lane masks git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@283122 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Target/Hexagon/CMakeLists.txt b/lib/Target/Hexagon/CMakeLists.txt index 93d66539bed..759a75b6aa5 100644 --- a/lib/Target/Hexagon/CMakeLists.txt +++ b/lib/Target/Hexagon/CMakeLists.txt @@ -42,7 +42,6 @@ add_llvm_target(HexagonCodeGen HexagonOptAddrMode.cpp HexagonOptimizeSZextends.cpp HexagonPeephole.cpp - HexagonRDF.cpp HexagonRDFOpt.cpp HexagonRegisterInfo.cpp HexagonSelectionDAGInfo.cpp diff --git a/lib/Target/Hexagon/HexagonOptAddrMode.cpp b/lib/Target/Hexagon/HexagonOptAddrMode.cpp index 2ea7003bab4..ac362c65a4b 100644 --- a/lib/Target/Hexagon/HexagonOptAddrMode.cpp +++ b/lib/Target/Hexagon/HexagonOptAddrMode.cpp @@ -587,7 +587,7 @@ void HexagonOptAddrMode::updateMap(NodeAddr IA) { return; for (auto &R : RDefMap) { - auto F = DefM.find(R.first); + auto F = DefM.find(R.first.Reg); if (F == DefM.end() || F->second.empty()) continue; R.second[IA.Id] = F->second.top()->Id; @@ -622,8 +622,7 @@ bool HexagonOptAddrMode::runOnMachineFunction(MachineFunction &MF) { const auto &TRI = *MF.getSubtarget().getRegisterInfo(); const TargetOperandInfo TOI(*HII); - RegisterAliasInfo RAI(TRI); - DataFlowGraph G(MF, *HII, TRI, *MDT, MDF, RAI, TOI); + DataFlowGraph G(MF, *HII, TRI, *MDT, MDF, TOI); G.build(); DFG = &G; diff --git a/lib/Target/Hexagon/HexagonRDF.cpp b/lib/Target/Hexagon/HexagonRDF.cpp deleted file mode 100644 index ec4823da61f..00000000000 --- a/lib/Target/Hexagon/HexagonRDF.cpp +++ /dev/null @@ -1,64 +0,0 @@ -//===--- HexagonRDF.cpp ---------------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "HexagonRDF.h" -#include "HexagonInstrInfo.h" -#include "HexagonRegisterInfo.h" - -#include "llvm/CodeGen/MachineInstr.h" - -using namespace llvm; -using namespace rdf; - -bool HexagonRegisterAliasInfo::covers(RegisterRef RA, RegisterRef RB, - const DataFlowGraph &DFG) const { - if (RA == RB) - return true; - - if (TargetRegisterInfo::isVirtualRegister(RA.Reg) && - TargetRegisterInfo::isVirtualRegister(RB.Reg)) { - // Hexagon-specific cases. - if (RA.Reg == RB.Reg) { - if (RA.Sub == 0) - return true; - if (RB.Sub == 0) - return false; - } - } - - return RegisterAliasInfo::covers(RA, RB, DFG); -} - -bool HexagonRegisterAliasInfo::covers(const RegisterSet &RRs, RegisterRef RR, - const DataFlowGraph &DFG) const { - if (RRs.count(RR)) - return true; - - // 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 (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, DFG); -} diff --git a/lib/Target/Hexagon/HexagonRDF.h b/lib/Target/Hexagon/HexagonRDF.h deleted file mode 100644 index 7bcdbbaeb6d..00000000000 --- a/lib/Target/Hexagon/HexagonRDF.h +++ /dev/null @@ -1,30 +0,0 @@ -//===--- HexagonRDF.h -----------------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef HEXAGON_RDF_H -#define HEXAGON_RDF_H -#include "RDFGraph.h" - -namespace llvm { - class TargetRegisterInfo; - -namespace rdf { - struct HexagonRegisterAliasInfo : public RegisterAliasInfo { - HexagonRegisterAliasInfo(const TargetRegisterInfo &TRI) - : RegisterAliasInfo(TRI) {} - 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 - -#endif - diff --git a/lib/Target/Hexagon/HexagonRDFOpt.cpp b/lib/Target/Hexagon/HexagonRDFOpt.cpp index 2cd184dd622..1de281a5aef 100644 --- a/lib/Target/Hexagon/HexagonRDFOpt.cpp +++ b/lib/Target/Hexagon/HexagonRDFOpt.cpp @@ -8,7 +8,6 @@ //===----------------------------------------------------------------------===// #include "HexagonInstrInfo.h" -#include "HexagonRDF.h" #include "HexagonSubtarget.h" #include "RDFCopy.h" #include "RDFDeadCode.h" @@ -286,9 +285,8 @@ bool HexagonRDFOpt::runOnMachineFunction(MachineFunction &MF) { if (RDFDump) MF.print(dbgs() << "Before " << getPassName() << "\n", nullptr); - HexagonRegisterAliasInfo HAI(HRI); TargetOperandInfo TOI(HII); - DataFlowGraph G(MF, HII, HRI, *MDT, MDF, HAI, TOI); + DataFlowGraph G(MF, HII, HRI, *MDT, MDF, TOI); // Dead phi nodes are necessary for copy propagation: we can add a use // of a register in a block where it would need a phi node, but which // was dead (and removed) during the graph build time. diff --git a/lib/Target/Hexagon/RDFCopy.cpp b/lib/Target/Hexagon/RDFCopy.cpp index 61a83dada21..04e4bd83ff0 100644 --- a/lib/Target/Hexagon/RDFCopy.cpp +++ b/lib/Target/Hexagon/RDFCopy.cpp @@ -79,7 +79,7 @@ void CopyPropagation::recordCopy(NodeAddr SA, EqualityMap &EM) { Copies.push_back(SA.Id); for (auto I : EM) { - auto FS = DefM.find(I.second); + auto FS = DefM.find(I.second.Reg); if (FS == DefM.end() || FS->second.empty()) continue; // Undefined source RDefMap[I.second][SA.Id] = FS->second.top()->Id; @@ -106,7 +106,7 @@ void CopyPropagation::updateMap(NodeAddr IA) { for (auto &R : RDefMap) { if (!RRs.count(R.first)) continue; - auto F = DefM.find(R.first); + auto F = DefM.find(R.first.Reg); if (F == DefM.end() || F->second.empty()) continue; R.second[IA.Id] = F->second.top()->Id; diff --git a/lib/Target/Hexagon/RDFGraph.cpp b/lib/Target/Hexagon/RDFGraph.cpp index c180f99f219..7eb5cf86ba5 100644 --- a/lib/Target/Hexagon/RDFGraph.cpp +++ b/lib/Target/Hexagon/RDFGraph.cpp @@ -36,12 +36,9 @@ raw_ostream &operator<< (raw_ostream &OS, const Print &P) { OS << TRI.getName(P.Obj.Reg); else OS << '#' << P.Obj.Reg; - if (P.Obj.Sub > 0) { - OS << ':'; - if (P.Obj.Sub < TRI.getNumSubRegIndices()) - OS << TRI.getSubRegIndexName(P.Obj.Sub); - else - OS << '#' << P.Obj.Sub; + if (P.Obj.Sub != 0) { + LaneBitmask LM = P.G.getLMI().getLaneMaskForIndex(P.Obj.Sub); + OS << ":L" << PrintLaneMask(LM); } return OS; } @@ -305,6 +302,12 @@ raw_ostream &operator<< (raw_ostream &OS, const Print &P) { return OS; } +template<> +raw_ostream &operator<< (raw_ostream &OS, const Print &P) { + P.Obj.print(OS); + return OS; +} + template<> raw_ostream &operator<< (raw_ostream &OS, const Print &P) { @@ -581,152 +584,6 @@ NodeAddr FuncNode::getEntryBlock(const DataFlowGraph &G) { } -// Register aliasing information. -// - -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 DataFlowGraph &DFG) const { - if (RA == RB) - return true; - if (TargetRegisterInfo::isVirtualRegister(RA.Reg)) { - assert(TargetRegisterInfo::isVirtualRegister(RB.Reg)); - if (RA.Reg != RB.Reg) - return false; - if (RA.Sub == 0) - return true; - return TRI.composeSubRegIndices(RA.Sub, RB.Sub) == RA.Sub; - } - - assert(TargetRegisterInfo::isPhysicalRegister(RA.Reg) && - TargetRegisterInfo::isPhysicalRegister(RB.Reg)); - - 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 DataFlowGraph &DFG) const { - if (RRs.count(RR)) - return true; - - // For virtual registers, we cannot accurately determine covering based - // on subregisters. If RR itself is not present in RRs, but it has a sub- - // register reference, check for the super-register alone. Otherwise, - // assume non-covering. - if (TargetRegisterInfo::isVirtualRegister(RR.Reg)) { - if (RR.Sub != 0) - return RRs.count({RR.Reg, 0}); - return false; - } - - // If any super-register of RR is present, then RR is covered. - uint32_t Reg = RR.Sub == 0 ? RR.Reg : TRI.getSubReg(RR.Reg, RR.Sub); - for (MCSuperRegIterator SR(Reg, &TRI); SR.isValid(); ++SR) - if (RRs.count({*SR, 0})) - return true; - - return false; -} - -// 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. - std::vector AS; - if (TargetRegisterInfo::isVirtualRegister(RR.Reg)) - return AS; - assert(TargetRegisterInfo::isPhysicalRegister(RR.Reg)); - uint32_t R = RR.Reg; - if (RR.Sub) - R = TRI.getSubReg(RR.Reg, RR.Sub); - - for (MCRegAliasIterator AI(R, &TRI, false); AI.isValid(); ++AI) - AS.push_back(RegisterRef({*AI, 0})); - return AS; -} - -// Check whether RA and RB are aliased. -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 (IsVirtA) { - if (RA.Reg != RB.Reg) - return false; - // RA and RB refer to the same register. If any of them refer to the - // whole register, they must be aliased. - if (RA.Sub == 0 || RB.Sub == 0) - return true; - unsigned SA = TRI.getSubRegIdxSize(RA.Sub); - unsigned OA = TRI.getSubRegIdxOffset(RA.Sub); - unsigned SB = TRI.getSubRegIdxSize(RB.Sub); - unsigned OB = TRI.getSubRegIdxOffset(RB.Sub); - if (OA <= OB && OA+SA > OB) - return true; - if (OB <= OA && OB+SB > OA) - 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; -} - - // Target operand information. // @@ -778,16 +635,112 @@ bool TargetOperandInfo::isFixedReg(const MachineInstr &In, unsigned OpNum) } +uint32_t RegisterAggr::getLargestSuperReg(uint32_t Reg) const { + uint32_t SuperReg = Reg; + while (true) { + MCSuperRegIterator SR(SuperReg, &TRI, false); + if (!SR.isValid()) + return SuperReg; + SuperReg = *SR; + } + llvm_unreachable(nullptr); +} + +LaneBitmask RegisterAggr::composeMaskForReg(uint32_t Reg, LaneBitmask LM, + uint32_t SuperR) const { + uint32_t SubR = TRI.getSubRegIndex(SuperR, Reg); + const TargetRegisterClass &RC = *TRI.getMinimalPhysRegClass(Reg); + return TRI.composeSubRegIndexLaneMask(SubR, LM & RC.LaneMask); +} + +void RegisterAggr::setMaskRaw(uint32_t Reg, LaneBitmask LM) { + uint32_t SuperR = getLargestSuperReg(Reg); + LaneBitmask SuperM = composeMaskForReg(Reg, LM, SuperR); + auto F = Masks.find(SuperR); + if (F == Masks.end()) + Masks.insert({SuperR, SuperM}); + else + F->second |= SuperM; + + // 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(Reg, &TRI); U.isValid(); ++U) { + MCRegUnitRootIterator R(*U, &TRI); + ++R; + if (!R.isValid()) + continue; + ExpAliasUnits.set(*U); + CheckUnits = true; + } +} + +bool RegisterAggr::hasAliasOf(RegisterRef RR) const { + uint32_t SuperR = getLargestSuperReg(RR.Reg); + auto F = Masks.find(SuperR); + if (F != Masks.end()) { + LaneBitmask M = LMI.getLaneMaskForIndex(RR.Sub); + if (F->second & composeMaskForReg(RR.Reg, M, SuperR)) + 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 { + uint32_t SuperR = getLargestSuperReg(RR.Reg); + auto F = Masks.find(SuperR); + if (F == Masks.end()) + return false; + LaneBitmask M = LMI.getLaneMaskForIndex(RR.Sub); + LaneBitmask SuperM = composeMaskForReg(RR.Reg, M, SuperR); + return (SuperM & F->second) == SuperM; +} + +RegisterAggr &RegisterAggr::insert(RegisterRef RR) { + setMaskRaw(RR.Reg, LMI.getLaneMaskForIndex(RR.Sub)); + return *this; +} + +RegisterAggr &RegisterAggr::insert(const RegisterAggr &RG) { + for (auto P : RG.Masks) + setMaskRaw(P.first, P.second); + return *this; +} + +RegisterAggr &RegisterAggr::clear(RegisterRef RR) { + uint32_t SuperR = getLargestSuperReg(RR.Reg); + auto F = Masks.find(SuperR); + if (F == Masks.end()) + return *this; + LaneBitmask M = LMI.getLaneMaskForIndex(RR.Sub); + LaneBitmask NewM = F->second & ~composeMaskForReg(RR.Reg, M, SuperR); + if (NewM == LaneBitmask(0)) + Masks.erase(F); + else + F->second = NewM; + return *this; +} + +void RegisterAggr::print(raw_ostream &OS) const { + OS << '{'; + for (auto I : Masks) + OS << ' ' << PrintReg(I.first, &TRI) << ':' << PrintLaneMask(I.second); + OS << " }"; +} + + // // The data flow graph construction. // DataFlowGraph::DataFlowGraph(MachineFunction &mf, const TargetInstrInfo &tii, const TargetRegisterInfo &tri, const MachineDominatorTree &mdt, - const MachineDominanceFrontier &mdf, const RegisterAliasInfo &rai, - const TargetOperandInfo &toi) - : TimeG("rdf"), MF(mf), TII(tii), TRI(tri), MDT(mdt), MDF(mdf), RAI(rai), - TOI(toi) { + const MachineDominanceFrontier &mdf, const TargetOperandInfo &toi) + : TimeG("rdf"), MF(mf), TII(tii), TRI(tri), MDT(mdt), MDF(mdf), TOI(toi) { } @@ -879,16 +832,33 @@ unsigned DataFlowGraph::DefStack::nextDown(unsigned P) const { return P; } -std::vector DataFlowGraph::getLandingPadLiveIns() const { - std::vector LR; + +// Register information. + +// Get the list of references aliased to RR. Lane masks are ignored. +RegisterSet DataFlowGraph::getAliasSet(uint32_t Reg) const { + // Do not include RR in the alias set. For virtual registers return an + // empty set. + RegisterSet AS; + if (TargetRegisterInfo::isVirtualRegister(Reg)) + return AS; + assert(TargetRegisterInfo::isPhysicalRegister(Reg)); + + for (MCRegAliasIterator AI(Reg, &TRI, false); AI.isValid(); ++AI) + AS.insert({*AI,0}); + return AS; +} + +RegisterSet DataFlowGraph::getLandingPadLiveIns() const { + RegisterSet LR; const Function &F = *MF.getFunction(); const Constant *PF = F.hasPersonalityFn() ? F.getPersonalityFn() : nullptr; const TargetLowering &TLI = *MF.getSubtarget().getTargetLowering(); - if (uint32_t EPReg = TLI.getExceptionPointerRegister(PF)) - LR.push_back(EPReg); - if (uint32_t ESReg = TLI.getExceptionSelectorRegister(PF)) - LR.push_back(ESReg); + if (uint32_t R = TLI.getExceptionPointerRegister(PF)) + LR.insert({R,0}); + if (uint32_t R = TLI.getExceptionSelectorRegister(PF)) + LR.insert({R,0}); return LR; } @@ -1037,7 +1007,7 @@ void DataFlowGraph::build(unsigned Options) { // branches in the program, or fall-throughs from other blocks. They // are entered from the exception handling runtime and target's ABI // may define certain registers as defined on entry to such a block. - std::vector EHRegs = getLandingPadLiveIns(); + RegisterSet EHRegs = getLandingPadLiveIns(); if (!EHRegs.empty()) { for (NodeAddr BA : Blocks) { const MachineBasicBlock &B = *BA.Addr->getCode(); @@ -1050,15 +1020,15 @@ void DataFlowGraph::build(unsigned Options) { Preds.push_back(findBlock(PB)); // Build phi nodes for each live-in. - for (uint32_t R : EHRegs) { + for (RegisterRef RR : EHRegs) { NodeAddr PA = newPhi(BA); uint16_t PhiFlags = NodeAttrs::PhiRef | NodeAttrs::Preserving; // Add def: - NodeAddr DA = newDef(PA, {R,0}, PhiFlags); + NodeAddr DA = newDef(PA, RR, PhiFlags); PA.Addr->addMember(DA, *this); // Add uses (no reaching defs for phi uses): for (NodeAddr PBA : Preds) { - NodeAddr PUA = newPhiUse(PA, {R,0}, PBA); + NodeAddr PUA = newPhiUse(PA, RR, PBA); PA.Addr->addMember(PUA, *this); } } @@ -1130,9 +1100,9 @@ void DataFlowGraph::pushDefs(NodeAddr IA, DefStackMap &DefM) { for (NodeAddr DA : Defs) { if (Visited.count(DA.Id)) continue; + NodeList Rel = getRelatedRefs(IA, DA); NodeAddr PDA = Rel.front(); - // Push the definition on the stack for the register and all aliases. RegisterRef RR = PDA.Addr->getRegRef(); #ifndef NDEBUG // Assert if the register is defined in two or more unrelated defs. @@ -1145,13 +1115,16 @@ void DataFlowGraph::pushDefs(NodeAddr IA, DefStackMap &DefM) { llvm_unreachable(nullptr); } #endif - DefM[RR].push(DA); - for (auto A : RAI.getAliasSet(RR)) { + // Push the definition on the stack for the register and all aliases. + // The def stack traversal in linkNodeUp will check the exact aliasing. + DefM[RR.Reg].push(DA); + for (RegisterRef A : getAliasSet(RR.Reg /*FIXME? use RegisterRef*/)) { + // Check that we don't push the same def twice. assert(A != RR); - DefM[A].push(DA); + DefM[A.Reg].push(DA); } // Mark all the related defs as visited. - for (auto T : Rel) + for (NodeAddr T : Rel) Visited.insert(T.Id); } } @@ -1171,6 +1144,62 @@ NodeList DataFlowGraph::getRelatedRefs(NodeAddr IA, return Refs; } +// Return true if RA and RB overlap, false otherwise. +bool DataFlowGraph::alias(RegisterRef RA, RegisterRef RB) const { + // Handling of physical registers. + bool IsPhysA = TargetRegisterInfo::isPhysicalRegister(RA.Reg); + bool IsPhysB = TargetRegisterInfo::isPhysicalRegister(RB.Reg); + if (IsPhysA != IsPhysB) + return false; + if (IsPhysA) { + LaneBitmask LA = LMI.getLaneMaskForIndex(RA.Sub); + LaneBitmask LB = LMI.getLaneMaskForIndex(RB.Sub); + + 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 PA = *UMA; + std::pair PB = *UMB; + // If the returned lane mask is 0, it should be treated as ~0 + // (or the lane mask from the given register ref should be ignored). + // This can happen when a register has only one unit. + if (PA.first < PB.first || (PA.second && !(PA.second & LA))) + ++UMA; + else if (PB.first < PA.first || (PB.second && !(PB.second & LB))) + ++UMB; + else + return true; + } + return false; + } + + // Handling of virtual registers. + bool IsVirtA = TargetRegisterInfo::isVirtualRegister(RA.Reg); + bool IsVirtB = TargetRegisterInfo::isVirtualRegister(RB.Reg); + if (IsVirtA != IsVirtB) + return false; + if (IsVirtA) { + if (RA.Reg != RB.Reg) + return false; + // RA and RB refer to the same register. If any of them refer to the + // whole register, they must be aliased. + if (RA.Sub == 0 || RB.Sub == 0) + return true; + unsigned SA = TRI.getSubRegIdxSize(RA.Sub); + unsigned OA = TRI.getSubRegIdxOffset(RA.Sub); + unsigned SB = TRI.getSubRegIdxSize(RB.Sub); + unsigned OB = TRI.getSubRegIdxOffset(RB.Sub); + if (OA <= OB && OA+SA > OB) + return true; + if (OB <= OA && OB+SB > OA) + return true; + return false; + } + + return false; +} + // Clear all information in the graph. void DataFlowGraph::reset() { @@ -1301,7 +1330,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, *this)) + if (alias(DR, UR)) return false; } return true; @@ -1407,15 +1436,15 @@ void DataFlowGraph::buildStmt(NodeAddr BA, MachineInstr &In) { // that block, and from all blocks dominated by it. void DataFlowGraph::buildBlockRefs(NodeAddr BA, BlockRefsMap &RefM) { - auto &Refs = RefM[BA.Id]; + RegisterSet &Refs = RefM[BA.Id]; MachineDomTreeNode *N = MDT.getNode(BA.Addr->getCode()); assert(N); for (auto I : *N) { MachineBasicBlock *SB = I->getBlock(); - auto SBA = findBlock(SB); + NodeAddr SBA = findBlock(SB); buildBlockRefs(SBA, RefM); - const auto &SRs = RefM[SBA.Id]; - Refs.insert(SRs.begin(), SRs.end()); + const RegisterSet &RefsS = RefM[SBA.Id]; + Refs.insert(RefsS.begin(), RefsS.end()); } for (NodeAddr IA : BA.Addr->members(*this)) @@ -1451,8 +1480,7 @@ void DataFlowGraph::recordDefsForDF(BlockRefsMap &PhiM, BlockRefsMap &RefM, Defs.insert(RA.Addr->getRegRef()); } - // Finally, add the set of defs to each block in the iterated dominance - // frontier. + // Calculate the iterated dominance frontier of BB. const MachineDominanceFrontier::DomSetType &DF = DFLoc->second; SetVector IDF(DF.begin(), DF.end()); for (unsigned i = 0; i < IDF.size(); ++i) { @@ -1464,13 +1492,15 @@ void DataFlowGraph::recordDefsForDF(BlockRefsMap &PhiM, BlockRefsMap &RefM, // Get the register references that are reachable from this block. RegisterSet &Refs = RefM[BA.Id]; for (auto DB : IDF) { - auto DBA = findBlock(DB); - const auto &Rs = RefM[DBA.Id]; - Refs.insert(Rs.begin(), Rs.end()); + NodeAddr DBA = findBlock(DB); + const RegisterSet &RefsD = RefM[DBA.Id]; + Refs.insert(RefsD.begin(), RefsD.end()); } + // Finally, add the set of defs to each block in the iterated dominance + // frontier. for (auto DB : IDF) { - auto DBA = findBlock(DB); + NodeAddr DBA = findBlock(DB); PhiM[DBA.Id].insert(Defs.begin(), Defs.end()); } } @@ -1491,7 +1521,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, *this)) + if (I != RR && RegisterAggr::isCoverOf(I, RR, LMI, TRI)) RR = I; return RR; }; @@ -1518,18 +1548,16 @@ 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], *this)) + if (alias(RR, MaxRefs[I])) return true; return false; }; // Prepare a list of NodeIds of the block's predecessors. - std::vector PredList; + NodeList Preds; const MachineBasicBlock *MBB = BA.Addr->getCode(); - for (auto PB : MBB->predecessors()) { - auto B = findBlock(PB); - PredList.push_back(B.Id); - } + for (auto PB : MBB->predecessors()) + Preds.push_back(findBlock(PB)); while (!MaxRefs.empty()) { // Put the first element in the closure, and then add all subsequent @@ -1553,8 +1581,7 @@ void DataFlowGraph::buildPhis(BlockRefsMap &PhiM, BlockRefsMap &RefM, PA.Addr->addMember(DA, *this); } // Add phi uses. - for (auto P : PredList) { - auto PBA = addr(P); + for (NodeAddr PBA : Preds) { for (unsigned X = 0; X != CS; ++X) { RegisterRef RR = MaxRefs[ClosureIdx[X]]; NodeAddr PUA = newPhiUse(PA, RR, PBA); @@ -1632,21 +1659,21 @@ void DataFlowGraph::linkRefUp(NodeAddr IA, NodeAddr TA, NodeAddr TAP; // References from the def stack that have been examined so far. - RegisterSet Defs; + RegisterAggr Defs(LMI, TRI); 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, *this); - }; - 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)) { - if (PrecUp) + // seen. If this completes a cover of RR, stop the stack traversal. + bool Alias = Defs.hasAliasOf(QR); + bool Cover = Defs.insert(QR).hasCoverOf(RR); + if (Alias) { + if (Cover) break; continue; } + // The reaching def. NodeAddr RDA = *I; @@ -1662,27 +1689,29 @@ void DataFlowGraph::linkRefUp(NodeAddr IA, NodeAddr TA, // Create the link. TAP.Addr->linkToDef(TAP.Id, RDA); - if (PrecUp) + if (Cover) break; - Defs.insert(QR); } } // Create data-flow links for all reference nodes in the statement node SA. void DataFlowGraph::linkStmtRefs(DefStackMap &DefM, NodeAddr SA) { +#ifndef NDEBUG RegisterSet Defs; +#endif // Link all nodes (upwards in the data-flow) with their reaching defs. for (NodeAddr RA : SA.Addr->members(*this)) { uint16_t Kind = RA.Addr->getKind(); assert(Kind == NodeAttrs::Def || Kind == NodeAttrs::Use); RegisterRef RR = RA.Addr->getRegRef(); - // Do not process multiple defs of the same reference. - if (Kind == NodeAttrs::Def && Defs.count(RR)) - continue; +#ifndef NDEBUG + // Do not expect multiple defs of the same reference. + assert(Kind != NodeAttrs::Def || !Defs.count(RR)); Defs.insert(RR); +#endif - auto F = DefM.find(RR); + auto F = DefM.find(RR.Reg); if (F == DefM.end()) continue; DefStack &DS = F->second; @@ -1732,7 +1761,7 @@ void DataFlowGraph::linkBlockRefs(DefStackMap &DefM, NodeAddr BA) { return PUA.Addr->getPredecessor() == BA.Id; }; - std::vector EHLiveIns = getLandingPadLiveIns(); + RegisterSet EHLiveIns = getLandingPadLiveIns(); MachineBasicBlock *MBB = BA.Addr->getCode(); for (auto SB : MBB->successors()) { @@ -1744,14 +1773,14 @@ void DataFlowGraph::linkBlockRefs(DefStackMap &DefM, NodeAddr BA) { // Find what register this phi is for. NodeAddr RA = IA.Addr->getFirstMember(*this); assert(RA.Id != 0); - if (find(EHLiveIns, RA.Addr->getRegRef().Reg) != EHLiveIns.end()) + if (EHLiveIns.count(RA.Addr->getRegRef())) continue; } // Go over each phi use associated with MBB, and link it. for (auto U : IA.Addr->members_if(IsUseForBA, *this)) { NodeAddr PUA = U; RegisterRef RR = PUA.Addr->getRegRef(); - linkRefUp(IA, PUA, DefM[RR]); + linkRefUp(IA, PUA, DefM[RR.Reg]); } } } diff --git a/lib/Target/Hexagon/RDFGraph.h b/lib/Target/Hexagon/RDFGraph.h index 79ae8850ab9..a21ee2b914e 100644 --- a/lib/Target/Hexagon/RDFGraph.h +++ b/lib/Target/Hexagon/RDFGraph.h @@ -224,6 +224,7 @@ #ifndef RDF_GRAPH_H #define RDF_GRAPH_H +#include "llvm/ADT/BitVector.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" @@ -236,6 +237,11 @@ #include #include +// RDF uses uint32_t to refer to registers. This is to ensure that the type +// size remains specific. In other places, registers are often stored using +// unsigned. +static_assert(sizeof(uint32_t) == sizeof(unsigned), "Those should be equal"); + namespace llvm { class MachineBasicBlock; class MachineFunction; @@ -421,32 +427,6 @@ namespace rdf { }; typedef std::set RegisterSet; - struct RegisterAliasInfo { - RegisterAliasInfo(const TargetRegisterInfo &tri) : TRI(tri) {} - virtual ~RegisterAliasInfo() {} - - virtual std::vector getAliasSet(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 { TargetOperandInfo(const TargetInstrInfo &tii) : TII(tii) {} virtual ~TargetOperandInfo() {} @@ -463,7 +443,7 @@ namespace rdf { // as invalid and is never allocated. template struct IndexedSet { - IndexedSet() : Map(N) {} + IndexedSet() : Map() { Map.reserve(N); } const T get(uint32_t Idx) const { // Index Idx corresponds to Map[Idx-1]. assert(Idx != 0 && !Map.empty() && Idx-1 < Map.size()); @@ -473,7 +453,7 @@ namespace rdf { // Linear search. auto F = find(Map, Val); if (F != Map.end()) - return *F; + return F - Map.begin(); Map.push_back(Val); return Map.size(); // Return actual_index + 1. } @@ -482,6 +462,55 @@ namespace rdf { std::vector Map; }; + struct LaneMaskIndex : private IndexedSet { + LaneBitmask getLaneMaskForIndex(uint32_t K) const { + return K == 0 ? ~LaneBitmask(0) : get(K); + } + uint32_t getIndexForLaneMask(LaneBitmask LM) { + assert(LM != LaneBitmask(0)); + return LM == ~LaneBitmask(0) ? 0 : insert(LM); + } + }; + + struct RegisterAggr { + typedef std::pair ValueType; + + RegisterAggr(const LaneMaskIndex &m, const TargetRegisterInfo &tri) + : Masks(), ExpAliasUnits(tri.getNumRegUnits()), CheckUnits(false), + LMI(m), TRI(tri) {} + RegisterAggr(const RegisterAggr &RG) + : Masks(RG.Masks), ExpAliasUnits(RG.ExpAliasUnits), + CheckUnits(RG.CheckUnits), LMI(RG.LMI), TRI(RG.TRI) {} + + bool empty() const { return Masks.empty(); } + bool hasAliasOf(RegisterRef RR) const; + bool hasCoverOf(RegisterRef RR) const; + static bool isCoverOf(RegisterRef RefA, RegisterRef RefB, + const LaneMaskIndex &LMI, const TargetRegisterInfo &TRI) { + return RegisterAggr(LMI, TRI).insert(RefA).hasCoverOf(RefB); + } + + RegisterAggr &insert(RegisterRef RR); + RegisterAggr &insert(const RegisterAggr &RG); + RegisterAggr &clear(RegisterRef RR); + + void print(raw_ostream &OS) const; + + private: + typedef std::unordered_map MapType; + MapType Masks; + BitVector ExpAliasUnits; // Register units for explicit aliases. + bool CheckUnits; + const LaneMaskIndex &LMI; + const TargetRegisterInfo &TRI; + + uint32_t getLargestSuperReg(uint32_t Reg) const; + void setMaskRaw(uint32_t Reg, LaneBitmask LM); + LaneBitmask composeMaskForReg(uint32_t Reg, LaneBitmask LM, + uint32_t SuperR) const; + }; + struct NodeBase { public: @@ -669,8 +698,7 @@ namespace rdf { struct DataFlowGraph { DataFlowGraph(MachineFunction &mf, const TargetInstrInfo &tii, const TargetRegisterInfo &tri, const MachineDominatorTree &mdt, - const MachineDominanceFrontier &mdf, const RegisterAliasInfo &rai, - const TargetOperandInfo &toi); + const MachineDominanceFrontier &mdf, const TargetOperandInfo &toi); NodeBase *ptr(NodeId N) const; template T ptr(NodeId N) const { @@ -682,34 +710,14 @@ namespace rdf { return { ptr(N), N }; } - NodeAddr getFunc() const { - return Func; - } - MachineFunction &getMF() const { - return MF; - } - const TargetInstrInfo &getTII() const { - return TII; - } - const TargetRegisterInfo &getTRI() const { - return TRI; - } - const MachineDominatorTree &getDT() const { - return MDT; - } - const MachineDominanceFrontier &getDF() const { - return MDF; - } - const RegisterAliasInfo &getRAI() const { - return RAI; - } - - LaneBitmask getLaneMaskForIndex(uint32_t K) const { - return LMMap.get(K); - } - uint32_t getIndexForLaneMask(LaneBitmask LM) { - return LMMap.insert(LM); - } + NodeAddr getFunc() const { return Func; } + MachineFunction &getMF() const { return MF; } + LaneMaskIndex &getLMI() { return LMI; } + const LaneMaskIndex &getLMI() const { return LMI; } + const TargetInstrInfo &getTII() const { return TII; } + const TargetRegisterInfo &getTRI() const { return TRI; } + const MachineDominatorTree &getDT() const { return MDT; } + const MachineDominanceFrontier &getDF() const { return MDF; } struct DefStack { DefStack() = default; @@ -759,14 +767,9 @@ namespace rdf { StorageType Stack; }; - struct RegisterRefHasher { - unsigned operator() (RegisterRef RR) const { - return RR.Reg | (RR.Sub << 24); - } - }; // Make this std::unordered_map for speed of accessing elements. - typedef std::unordered_map - DefStackMap; + // Map: Register (physical or virtual) -> DefStack + typedef std::unordered_map DefStackMap; void build(unsigned Options = BuildOptions::None); void pushDefs(NodeAddr IA, DefStackMap &DM); @@ -826,10 +829,14 @@ namespace rdf { return (Flags & NodeAttrs::Preserving) && !(Flags & NodeAttrs::Undef); } + // Register aliasing. + bool alias(RegisterRef RA, RegisterRef RB) const; + private: void reset(); - std::vector getLandingPadLiveIns() const; + RegisterSet getAliasSet(uint32_t Reg) const; + RegisterSet getLandingPadLiveIns() const; NodeAddr newNode(uint16_t Attrs); NodeAddr cloneNode(const NodeAddr B); @@ -886,14 +893,13 @@ namespace rdf { // Local map: MachineBasicBlock -> NodeAddr std::map> BlockNodes; // Lane mask map. - IndexedSet LMMap; + LaneMaskIndex LMI; MachineFunction &MF; const TargetInstrInfo &TII; const TargetRegisterInfo &TRI; const MachineDominatorTree &MDT; const MachineDominanceFrontier &MDF; - const RegisterAliasInfo &RAI; const TargetOperandInfo &TOI; }; // struct DataFlowGraph diff --git a/lib/Target/Hexagon/RDFLiveness.cpp b/lib/Target/Hexagon/RDFLiveness.cpp index 7e1c39df9b8..efc45112518 100644 --- a/lib/Target/Hexagon/RDFLiveness.cpp +++ b/lib/Target/Hexagon/RDFLiveness.cpp @@ -85,7 +85,7 @@ namespace rdf { // the data-flow. NodeList Liveness::getAllReachingDefs(RegisterRef RefRR, - NodeAddr RefA, bool FullChain, const RegisterSet &DefRRs) { + NodeAddr RefA, bool FullChain, const RegisterAggr &DefRRs) { NodeList RDefs; // Return value. SetVector DefQ; SetVector Owners; @@ -118,8 +118,9 @@ 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, DFG)) - continue; + if (!DFG.IsPreservingDef(TA)) + if (RegisterAggr::isCoverOf(RR, RefRR, DFG.getLMI(), 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)) @@ -133,7 +134,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(), DFG)) + if (!IsPhi && !DFG.alias(RefRR, TA.Addr->getRegRef())) continue; Defs.insert(TA.Id); Owners.insert(TA.Addr->getOwner(DFG).Id); @@ -195,14 +196,14 @@ NodeList Liveness::getAllReachingDefs(RegisterRef RefRR, // covered if we added A first, and A would be covered // if we added B first. - RegisterSet RRs = DefRRs; + RegisterAggr RRs(DefRRs); auto DefInSet = [&Defs] (NodeAddr TA) -> bool { return TA.Addr->getKind() == NodeAttrs::Def && Defs.count(TA.Id); }; for (auto T : Tmp) { - if (!FullChain && RAI.covers(RRs, RefRR, DFG)) + if (!FullChain && RRs.hasCoverOf(RefRR)) break; auto TA = DFG.addr(T); bool IsPhi = DFG.IsCode(TA); @@ -217,7 +218,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, DFG)) + if (FullChain || IsPhi || !RRs.hasCoverOf(QR)) Ds.push_back(DA); } RDefs.insert(RDefs.end(), Ds.begin(), Ds.end()); @@ -240,19 +241,12 @@ NodeList Liveness::getAllReachingDefs(RegisterRef RefRR, } -static const RegisterSet NoRegs; - -NodeList Liveness::getAllReachingDefs(NodeAddr RefA) { - return getAllReachingDefs(RefA.Addr->getRegRef(), RefA, false, NoRegs); -} - - NodeSet Liveness::getAllReachingDefsRec(RegisterRef RefRR, NodeAddr 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(DFG.getLMI(), TRI); + for (NodeId D : Defs) { const auto DA = DFG.addr(D); if (!(DA.Addr->getFlags() & NodeAttrs::PhiRef)) DefRRs.insert(DA.Addr->getRegRef()); @@ -289,12 +283,12 @@ NodeSet Liveness::getAllReachingDefsRec(RegisterRef RefRR, NodeSet Liveness::getAllReachedUses(RegisterRef RefRR, - NodeAddr DefA, const RegisterSet &DefRRs) { + NodeAddr 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, DFG)) + if (DefRRs.hasCoverOf(RefRR)) return Uses; // Add all directly reached uses. @@ -305,7 +299,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, DFG) && !RAI.covers(DefRRs, UR, DFG)) + if (DFG.alias(RefRR, UR) && !DefRRs.hasCoverOf(UR)) Uses.insert(U); } U = UA.Addr->getSibling(); @@ -318,14 +312,14 @@ 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, DFG) || !RAI.alias(RefRR, DR, DFG)) + if (DefRRs.hasCoverOf(DR) || !DFG.alias(RefRR, DR)) continue; NodeSet T; 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); } @@ -347,21 +341,21 @@ void Liveness::computePhiInfo() { } // phi use -> (map: reaching phi -> set of registers defined in between) - std::map> PhiUp; + std::map> PhiUp; std::vector PhiUQ; // Work list of phis for upward propagation. // Go over all phis. for (NodeAddr 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 DefQ; NodeSet PhiDefs; - for (auto R : PhiRefs) { + for (NodeAddr R : PhiRefs) { if (!DFG.IsRef(R)) continue; DefQ.insert(R.Id); @@ -466,12 +460,17 @@ void Liveness::computePhiInfo() { for (NodeAddr VA : DFG.getRelatedRefs(PhiA, UA)) { SeenUses.insert(VA.Id); - RegisterSet DefRRs; + RegisterAggr DefRRs(DFG.getLMI(), TRI); for (NodeAddr 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; - PhiUp[FU][RP].insert(DefRRs.begin(), DefRRs.end()); + std::map &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()); } @@ -485,7 +484,7 @@ void Liveness::computePhiInfo() { dbgs() << "phi " << Print(I.first, DFG) << " -> {"; for (auto R : I.second) dbgs() << ' ' << Print(R.first, DFG) - << Print(R.second, DFG); + << Print(R.second, DFG); dbgs() << " }\n"; } } @@ -520,10 +519,10 @@ void Liveness::computePhiInfo() { for (auto U : PUs) { NodeAddr UA = U; - std::map &PUM = PhiUp[UA.Id]; - for (const std::pair &P : PUM) { + std::map &PUM = PhiUp[UA.Id]; + for (const std::pair &P : PUM) { bool Changed = false; - RegisterSet MidDefs = P.second; + const RegisterAggr &MidDefs = P.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 @@ -533,7 +532,7 @@ void Liveness::computePhiInfo() { RegisterRef R = T.first; if (!isRestrictedToRef(PA, UA, R)) R = getRestrictedRegRef(UA); - if (!RAI.covers(MidDefs, R, DFG)) + if (!MidDefs.hasCoverOf(R)) UpReached.insert(R); } if (UpReached.empty()) @@ -654,7 +653,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, DFG)) + if (!DFG.alias(R.first, RR)) continue; for (auto D : getAllReachingDefs(RR, UA)) LOX[RR].insert(D.Id); @@ -787,7 +786,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(), DFG)) + if (DFG.alias(RR, DFG.addr(RD).Addr->getRegRef())) return false; } return true; @@ -805,13 +804,6 @@ RegisterRef Liveness::getRestrictedRegRef(NodeAddr RA) const { } -unsigned Liveness::getPhysReg(RegisterRef RR) const { - if (!TargetRegisterInfo::isPhysicalRegister(RR.Reg)) - return 0; - return RR.Sub ? TRI.getSubReg(RR.Reg, RR.Sub) : RR.Reg; -} - - // Helper function to obtain the basic block containing the reaching def // of the given use. MachineBasicBlock *Liveness::getBlockWithRef(NodeId RN) const { @@ -899,13 +891,15 @@ 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, DFG); + bool Covering = RegisterAggr::isCoverOf(DDR, I.first, + DFG.getLMI(), TRI); 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, DFG); + Covering = RegisterAggr::isCoverOf(DA.Addr->getRegRef(), Q, + DFG.getLMI(), TRI); } U = DUA.Addr->getSibling(); } @@ -919,7 +913,7 @@ void Liveness::traverse(MachineBasicBlock *B, RefMap &LiveIn) { for (auto R : Rest) { auto DA = DFG.addr(R); RegisterRef DRR = DA.Addr->getRegRef(); - RegisterSet RRs; + RegisterAggr RRs(DFG.getLMI(), TRI); for (NodeAddr TA : getAllReachingDefs(DA)) { NodeAddr IA = TA.Addr->getOwner(DFG); NodeAddr BA = IA.Addr->getOwner(DFG); @@ -928,7 +922,7 @@ void Liveness::traverse(MachineBasicBlock *B, RefMap &LiveIn) { RRs.insert(TA.Addr->getRegRef()); if (BA.Addr->getCode() == B) continue; - if (RAI.covers(RRs, DRR, DFG)) + if (RRs.hasCoverOf(DRR)) break; Defs.insert(TA.Id); } diff --git a/lib/Target/Hexagon/RDFLiveness.h b/lib/Target/Hexagon/RDFLiveness.h index adfc74981a0..cc22c32e9c2 100644 --- a/lib/Target/Hexagon/RDFLiveness.h +++ b/lib/Target/Hexagon/RDFLiveness.h @@ -35,15 +35,24 @@ namespace rdf { Liveness(MachineRegisterInfo &mri, const DataFlowGraph &g) : DFG(g), TRI(g.getTRI()), MDT(g.getDT()), MDF(g.getDF()), - RAI(g.getRAI()), MRI(mri), Empty(), Trace(false) {} + MRI(mri), Empty(), NoRegs(g.getLMI(), g.getTRI()), + Trace(false) {} NodeList getAllReachingDefs(RegisterRef RefRR, NodeAddr RefA, - bool FullChain = false, const RegisterSet &DefRRs = RegisterSet()); - NodeList getAllReachingDefs(NodeAddr RefA); + bool FullChain, const RegisterAggr &DefRRs); + NodeList getAllReachingDefs(NodeAddr RefA) { + return getAllReachingDefs(RefA.Addr->getRegRef(), RefA, false, NoRegs); + } + NodeList getAllReachingDefs(RegisterRef RefRR, NodeAddr RefA) { + return getAllReachingDefs(RefRR, RefA, false, NoRegs); + } NodeSet getAllReachingDefsRec(RegisterRef RefRR, NodeAddr RefA, NodeSet &Visited, const NodeSet &Defs); NodeSet getAllReachedUses(RegisterRef RefRR, NodeAddr DefA, - const RegisterSet &DefRRs = RegisterSet()); + const RegisterAggr &DefRRs); + NodeSet getAllReachedUses(RegisterRef RefRR, NodeAddr DefA) { + return getAllReachedUses(RefRR, DefA, NoRegs); + } LiveMapType &getLiveMap() { return LiveMap; } const LiveMapType &getLiveMap() const { return LiveMap; } @@ -65,10 +74,10 @@ namespace rdf { const TargetRegisterInfo &TRI; const MachineDominatorTree &MDT; const MachineDominanceFrontier &MDF; - const RegisterAliasInfo &RAI; MachineRegisterInfo &MRI; LiveMapType LiveMap; const RefMap Empty; + const RegisterAggr NoRegs; bool Trace; // Cache of mapping from node ids (for RefNodes) to the containing @@ -99,7 +108,6 @@ namespace rdf { bool isRestrictedToRef(NodeAddr IA, NodeAddr RA, RegisterRef RR) const; RegisterRef getRestrictedRegRef(NodeAddr RA) const; - unsigned getPhysReg(RegisterRef RR) const; MachineBasicBlock *getBlockWithRef(NodeId RN) const; void traverse(MachineBasicBlock *B, RefMap &LiveIn); void emptify(RefMap &M);