diff options
-rw-r--r-- | llvm/lib/Target/Hexagon/HexagonOptAddrMode.cpp | 7 | ||||
-rw-r--r-- | llvm/lib/Target/Hexagon/RDFGraph.cpp | 59 | ||||
-rw-r--r-- | llvm/lib/Target/Hexagon/RDFGraph.h | 15 | ||||
-rw-r--r-- | llvm/lib/Target/Hexagon/RDFLiveness.cpp | 199 | ||||
-rw-r--r-- | llvm/lib/Target/Hexagon/RDFLiveness.h | 22 | ||||
-rw-r--r-- | llvm/test/CodeGen/Hexagon/rdf-phi-up.ll | 60 |
6 files changed, 278 insertions, 84 deletions
diff --git a/llvm/lib/Target/Hexagon/HexagonOptAddrMode.cpp b/llvm/lib/Target/Hexagon/HexagonOptAddrMode.cpp index 0d899ebe986..148a07070d5 100644 --- a/llvm/lib/Target/Hexagon/HexagonOptAddrMode.cpp +++ b/llvm/lib/Target/Hexagon/HexagonOptAddrMode.cpp @@ -215,7 +215,8 @@ void HexagonOptAddrMode::getAllRealUses(NodeAddr<StmtNode *> SA, for (NodeAddr<DefNode *> DA : SA.Addr->members_if(DFG->IsDef, *DFG)) { DEBUG(dbgs() << "\t\t[DefNode]: " << Print<NodeAddr<DefNode *>>(DA, *DFG) << "\n"); - RegisterRef DR = DA.Addr->getRegRef(*DFG); + RegisterRef DR = DFG->normalizeRef(DA.Addr->getRegRef(*DFG)); + auto UseSet = LV->getAllReachedUses(DR, DA); for (auto UI : UseSet) { @@ -234,11 +235,11 @@ void HexagonOptAddrMode::getAllRealUses(NodeAddr<StmtNode *> SA, << Print<Liveness::RefMap>(phiUse, *DFG) << "\n"); if (phiUse.size() > 0) { for (auto I : phiUse) { - if (DR != I.first) + if (DR.Reg != I.first) continue; auto phiUseSet = I.second; for (auto phiUI : phiUseSet) { - NodeAddr<UseNode *> phiUA = DFG->addr<UseNode *>(phiUI); + NodeAddr<UseNode *> phiUA = DFG->addr<UseNode *>(phiUI.first); UNodeList.push_back(phiUA); } } diff --git a/llvm/lib/Target/Hexagon/RDFGraph.cpp b/llvm/lib/Target/Hexagon/RDFGraph.cpp index f25fcf72065..3d0777af9cd 100644 --- a/llvm/lib/Target/Hexagon/RDFGraph.cpp +++ b/llvm/lib/Target/Hexagon/RDFGraph.cpp @@ -29,6 +29,12 @@ using namespace rdf; namespace llvm { namespace rdf { +raw_ostream &operator<< (raw_ostream &OS, const PrintLaneMaskOpt &P) { + if (P.Mask != ~LaneBitmask(0)) + OS << ':' << PrintLaneMask(P.Mask); + return OS; +} + template<> raw_ostream &operator<< (raw_ostream &OS, const Print<RegisterRef> &P) { auto &TRI = P.G.getTRI(); @@ -36,8 +42,7 @@ raw_ostream &operator<< (raw_ostream &OS, const Print<RegisterRef> &P) { OS << TRI.getName(P.Obj.Reg); else OS << '#' << P.Obj.Reg; - if (P.Obj.Mask != ~LaneBitmask(0)) - OS << ":" << PrintLaneMask(P.Obj.Mask); + OS << PrintLaneMaskOpt(P.Obj.Mask); return OS; } @@ -719,10 +724,24 @@ RegisterAggr &RegisterAggr::clear(RegisterRef RR) { return *this; } +RegisterAggr &RegisterAggr::clear(const RegisterAggr &RG) { + for (std::pair<uint32_t,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) << ':' << PrintLaneMask(I.second); + OS << ' ' << PrintReg(I.first, &TRI) << PrintLaneMaskOpt(I.second); OS << " }"; } @@ -1051,6 +1070,40 @@ RegisterRef DataFlowGraph::makeRegRef(unsigned Reg, unsigned Sub) const { return RegisterRef(Reg); } +RegisterRef DataFlowGraph::normalizeRef(RegisterRef RR) const { + // FIXME copied from RegisterAggr + uint32_t SuperReg = RR.Reg; + while (true) { + MCSuperRegIterator SR(SuperReg, &TRI, false); + if (!SR.isValid()) + break; + SuperReg = *SR; + } + + uint32_t Sub = TRI.getSubRegIndex(SuperReg, RR.Reg); + const TargetRegisterClass &RC = *TRI.getMinimalPhysRegClass(RR.Reg); + LaneBitmask SuperMask = RR.Mask & + TRI.composeSubRegIndexLaneMask(Sub, RC.LaneMask); + return RegisterRef(SuperReg, SuperMask); +} + +RegisterRef DataFlowGraph::restrictRef(RegisterRef AR, RegisterRef BR) const { + if (AR.Reg == BR.Reg) { + LaneBitmask M = AR.Mask & BR.Mask; + return M ? RegisterRef(AR.Reg, M) : RegisterRef(); + } +#ifndef NDEBUG + RegisterRef NAR = normalizeRef(AR); + RegisterRef NBR = normalizeRef(BR); + assert(NAR.Reg != NBR.Reg); +#endif + // This isn't strictly correct, because the overlap may happen in the + // part masked out. + if (TRI.regsOverlap(AR.Reg, BR.Reg)) + return AR; + return RegisterRef(); +} + // For each stack in the map DefM, push the delimiter for block B on it. void DataFlowGraph::markBlock(NodeId B, DefStackMap &DefM) { // Push block delimiters. diff --git a/llvm/lib/Target/Hexagon/RDFGraph.h b/llvm/lib/Target/Hexagon/RDFGraph.h index 00b6f79f4ed..8fece7f99f2 100644 --- a/llvm/lib/Target/Hexagon/RDFGraph.h +++ b/llvm/lib/Target/Hexagon/RDFGraph.h @@ -406,9 +406,10 @@ namespace rdf { RegisterRef() : RegisterRef(0) {} explicit RegisterRef(RegisterId R, LaneBitmask M = ~LaneBitmask(0)) - : Reg(R), Mask(M) {} + : Reg(R), Mask(R != 0 ? M : 0) {} RegisterRef(const RegisterRef &RR) = default; RegisterRef &operator= (const RegisterRef &RR) = default; + operator bool() const { return Reg != 0 && Mask != LaneBitmask(0); } bool operator== (const RegisterRef &RR) const { return Reg == RR.Reg && Mask == RR.Mask; } @@ -511,6 +512,9 @@ namespace rdf { 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; @@ -797,6 +801,8 @@ namespace rdf { PackedRegisterRef pack(RegisterRef RR) const { return LMI.pack(RR); } RegisterRef unpack(PackedRegisterRef PR) const { return LMI.unpack(PR); } RegisterRef makeRegRef(unsigned Reg, unsigned Sub) const; + RegisterRef normalizeRef(RegisterRef RR) const; + RegisterRef restrictRef(RegisterRef AR, RegisterRef BR) const; NodeAddr<RefNode*> getNextRelated(NodeAddr<InstrNode*> IA, NodeAddr<RefNode*> RA) const; @@ -967,6 +973,13 @@ namespace rdf { } + // 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> raw_ostream &operator<< (raw_ostream &OS, const Print<T> &P); diff --git a/llvm/lib/Target/Hexagon/RDFLiveness.cpp b/llvm/lib/Target/Hexagon/RDFLiveness.cpp index 73c00ec0e90..258b8e867fd 100644 --- a/llvm/lib/Target/Hexagon/RDFLiveness.cpp +++ b/llvm/lib/Target/Hexagon/RDFLiveness.cpp @@ -42,9 +42,9 @@ namespace rdf { raw_ostream &operator<< (raw_ostream &OS, const Print<Liveness::RefMap> &P) { OS << '{'; for (auto &I : P.Obj) { - OS << ' ' << Print<RegisterRef>(I.first, P.G) << '{'; + OS << ' ' << PrintReg(I.first, &P.G.getTRI()) << '{'; for (auto J = I.second.begin(), E = I.second.end(); J != E; ) { - OS << Print<NodeId>(*J, P.G); + OS << Print<NodeId>(J->first, P.G) << PrintLaneMaskOpt(J->second); if (++J != E) OS << ','; } @@ -376,8 +376,10 @@ void Liveness::computePhiInfo() { while (UN != 0) { NodeAddr<UseNode*> A = DFG.addr<UseNode*>(UN); uint16_t F = A.Addr->getFlags(); - if ((F & (NodeAttrs::Undef | NodeAttrs::PhiRef)) == 0) - RealUses[getRestrictedRegRef(A)].insert(A.Id); + if ((F & (NodeAttrs::Undef | NodeAttrs::PhiRef)) == 0) { + RegisterRef R = DFG.normalizeRef(getRestrictedRegRef(A)); + RealUses[R.Reg].insert({A.Id,R.Mask}); + } UN = A.Addr->getSibling(); } // Visit all reached defs, and add them to the queue. These defs may @@ -417,12 +419,13 @@ void Liveness::computePhiInfo() { // uses of it. For each such use, check if it is reached by this phi, // i.e. check if the set of its reaching uses intersects the set of // this phi's defs. - NodeSet &Uses = UI->second; + NodeRefSet &Uses = UI->second; for (auto I = Uses.begin(), E = Uses.end(); I != E; ) { - auto UA = DFG.addr<UseNode*>(*I); + auto UA = DFG.addr<UseNode*>(I->first); // Undef flag is checked above. assert((UA.Addr->getFlags() & NodeAttrs::Undef) == 0); - NodeList RDs = getAllReachingDefs(UI->first, UA); + RegisterRef R(UI->first, I->second); + NodeList RDs = getAllReachingDefs(R, UA); if (any_of(RDs, InPhiDefs)) ++I; else @@ -519,31 +522,38 @@ void Liveness::computePhiInfo() { for (NodeAddr<UseNode*> UA : PUs) { std::map<NodeId,RegisterAggr> &PUM = PhiUp[UA.Id]; + RegisterRef UR = DFG.normalizeRef(getRestrictedRegRef(UA)); for (const std::pair<NodeId,RegisterAggr> &P : PUM) { bool Changed = false; 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 - // the upward phi P. - RegisterSet UpReached; - for (const std::pair<RegisterRef,NodeSet> &T : RUM) { - RegisterRef R = T.first; - if (UA.Addr->getFlags() & NodeAttrs::Shadow) - R = getRestrictedRegRef(UA); - if (!MidDefs.hasCoverOf(R)) - UpReached.insert(R); - } - if (UpReached.empty()) + // Collect the set PropUp of uses that are reached by the current + // phi PA, and are not covered by any intervening def between the + // currently visited use UA and the the upward phi P. + + if (MidDefs.hasCoverOf(UR)) continue; - // Update the set PRUs of real uses reached by the upward phi P with - // the actual set of uses (UpReached) that the P phi reaches. - RefMap &PRUs = RealUseMap[P.first]; - for (RegisterRef R : UpReached) { - unsigned Z = PRUs[R].size(); - PRUs[R].insert(RUM[R].begin(), RUM[R].end()); - Changed |= (PRUs[R].size() != Z); + + // General algorithm: + // for each (R,U) : U is use node of R, U is reached by PA + // if MidDefs does not cover (R,U) + // then add (R-MidDefs,U) to RealUseMap[P] + // + for (const std::pair<RegisterId,NodeRefSet> &T : RUM) { + RegisterRef R = DFG.restrictRef(RegisterRef(T.first), UR); + if (!R) + continue; + for (std::pair<NodeId,LaneBitmask> V : T.second) { + RegisterRef S = DFG.restrictRef(RegisterRef(R.Reg, V.second), R); + if (!S) + continue; + if (RegisterRef SS = MidDefs.clearIn(S)) { + NodeRefSet &RS = RealUseMap[P.first][SS.Reg]; + Changed |= RS.insert({V.first,SS.Mask}).second; + } + } } + if (Changed) PhiUQ.push_back(P.first); } @@ -636,26 +646,28 @@ void Liveness::computeLiveIns() { continue; for (auto U : PA.Addr->members_if(DFG.IsRef<NodeAttrs::Use>, DFG)) { - NodeAddr<PhiUseNode*> UA = U; - if (UA.Addr->getReachingDef() == 0) + NodeAddr<PhiUseNode*> PUA = U; + if (PUA.Addr->getReachingDef() == 0) continue; // Mark all reached "real" uses of P as live on exit in the // predecessor. // Remap all the RUs so that they have a correct reaching def. - auto PrA = DFG.addr<BlockNode*>(UA.Addr->getPredecessor()); + auto PrA = DFG.addr<BlockNode*>(PUA.Addr->getPredecessor()); RefMap &LOX = PhiLOX[PrA.Addr->getCode()]; - for (const RefMap::value_type &R : RUs) { - RegisterRef RR = R.first; - if (UA.Addr->getFlags() & NodeAttrs::Shadow) - RR = getRestrictedRegRef(UA); - // The restricted ref may be different from the ref that was - // accessed in the "real use". This means that this phi use - // is not the one that carries this reference, so skip it. - if (!DFG.alias(R.first, RR)) + + RegisterRef UR = DFG.normalizeRef(getRestrictedRegRef(PUA)); + for (const std::pair<RegisterId,NodeRefSet> &T : RUs) { + // Check if T.first aliases UR? + LaneBitmask M = 0; + for (std::pair<NodeId,LaneBitmask> P : T.second) + M |= P.second; + + RegisterRef S = DFG.restrictRef(RegisterRef(T.first, M), UR); + if (!S) continue; - for (NodeAddr<DefNode*> D : getAllReachingDefs(RR, UA)) - LOX[RR].insert(D.Id); + for (NodeAddr<DefNode*> D : getAllReachingDefs(S, PUA)) + LOX[S.Reg].insert({D.Id, S.Mask}); } } // for U : phi uses } // for P : Phis @@ -679,14 +691,36 @@ void Liveness::computeLiveIns() { if (Trace) { // Dump the liveness map for (MachineBasicBlock &B : MF) { - BitVector LV(TRI.getNumRegs()); + std::vector<RegisterRef> LV; for (auto I = B.livein_begin(), E = B.livein_end(); I != E; ++I) - LV.set(I->PhysReg); + LV.push_back(RegisterRef(I->PhysReg, I->LaneMask)); + std::sort(LV.begin(), LV.end()); dbgs() << "BB#" << B.getNumber() << "\t rec = {"; - for (int x = LV.find_first(); x >= 0; x = LV.find_next(x)) - dbgs() << ' ' << Print<RegisterRef>(RegisterRef(x), DFG); + for (auto I : LV) + dbgs() << ' ' << Print<RegisterRef>(I, DFG); + dbgs() << " }\n"; + //dbgs() << "\tcomp = " << Print<RegisterAggr>(LiveMap[&B], DFG) << '\n'; + + LV.clear(); + for (std::pair<RegisterId,LaneBitmask> P : LiveMap[&B]) { + MCSubRegIndexIterator S(P.first, &TRI); + if (!S.isValid()) { + LV.push_back(RegisterRef(P.first)); + continue; + } + do { + LaneBitmask M = TRI.getSubRegIndexLaneMask(S.getSubRegIndex()); + if (M & P.second) + LV.push_back(RegisterRef(S.getSubReg())); + ++S; + } while (S.isValid()); + } + std::sort(LV.begin(), LV.end()); + dbgs() << "\tcomp = {"; + for (auto I : LV) + dbgs() << ' ' << Print<RegisterRef>(I, DFG); dbgs() << " }\n"; - dbgs() << "\tcomp = " << Print<RegisterSet>(LiveMap[&B], DFG) << '\n'; + } } } @@ -703,7 +737,7 @@ void Liveness::resetLiveIns() { // Add the newly computed live-ins. auto &LiveIns = LiveMap[&B]; for (auto I : LiveIns) { - B.addLiveIn({MCPhysReg(I.Reg), I.Mask}); + B.addLiveIn({MCPhysReg(I.first), I.second}); } } } @@ -716,9 +750,20 @@ void Liveness::resetKills() { void Liveness::resetKills(MachineBasicBlock *B) { - auto CopyLiveIns = [] (MachineBasicBlock *B, BitVector &LV) -> void { - for (auto I = B->livein_begin(), E = B->livein_end(); I != E; ++I) - LV.set(I->PhysReg); + auto CopyLiveIns = [this] (MachineBasicBlock *B, BitVector &LV) -> void { + for (auto I : B->liveins()) { + MCSubRegIndexIterator S(I.PhysReg, &TRI); + if (!S.isValid()) { + LV.set(I.PhysReg); + continue; + } + do { + LaneBitmask M = TRI.getSubRegIndexLaneMask(S.getSubRegIndex()); + if (M & I.LaneMask) + LV.set(S.getSubReg()); + ++S; + } while (S.isValid()); + } }; BitVector LiveIn(TRI.getNumRegs()), Live(TRI.getNumRegs()); @@ -831,7 +876,7 @@ void Liveness::traverse(MachineBasicBlock *B, RefMap &LiveIn) { dbgs() << ' ' << I->getBlock()->getNumber(); dbgs() << " }\n"; dbgs() << " LiveIn: " << Print<RefMap>(LiveIn, DFG) << '\n'; - dbgs() << " Local: " << Print<RegisterSet>(LiveMap[B], DFG) << '\n'; + dbgs() << " Local: " << Print<RegisterAggr>(LiveMap[B], DFG) << '\n'; } // Add reaching defs of phi uses that are live on exit from this block. @@ -842,7 +887,7 @@ void Liveness::traverse(MachineBasicBlock *B, RefMap &LiveIn) { if (Trace) { dbgs() << "after LOX\n"; dbgs() << " LiveIn: " << Print<RefMap>(LiveIn, DFG) << '\n'; - dbgs() << " Local: " << Print<RegisterSet>(LiveMap[B], DFG) << '\n'; + dbgs() << " Local: " << Print<RegisterAggr>(LiveMap[B], DFG) << '\n'; } // The LiveIn map at this point has all defs that are live-on-exit from B, @@ -855,20 +900,20 @@ void Liveness::traverse(MachineBasicBlock *B, RefMap &LiveIn) { RefMap LiveInCopy = LiveIn; LiveIn.clear(); - for (const std::pair<RegisterRef,NodeSet> &LE : LiveInCopy) { - RegisterRef LRef = LE.first; - NodeSet &NewDefs = LiveIn[LRef]; // To be filled. - const NodeSet &OldDefs = LE.second; - for (NodeId R : OldDefs) { + for (const std::pair<RegisterId,NodeRefSet> &LE : LiveInCopy) { + RegisterRef LRef(LE.first); + NodeRefSet &NewDefs = LiveIn[LRef.Reg]; // To be filled. + const NodeRefSet &OldDefs = LE.second; + for (NodeRef OR : OldDefs) { // R is a def node that was live-on-exit - auto DA = DFG.addr<DefNode*>(R); + auto DA = DFG.addr<DefNode*>(OR.first); NodeAddr<InstrNode*> IA = DA.Addr->getOwner(DFG); NodeAddr<BlockNode*> BA = IA.Addr->getOwner(DFG); if (B != BA.Addr->getCode()) { // Defs from a different block need to be preserved. Defs from this // block will need to be processed further, except for phi defs, the // liveness of which is handled through the PhiLON/PhiLOX maps. - NewDefs.insert(R); + NewDefs.insert(OR); continue; } @@ -877,13 +922,14 @@ void Liveness::traverse(MachineBasicBlock *B, RefMap &LiveIn) { // and to the parts of the register actually covered by those defs. // (Note that phi defs should always be preserving.) RegisterAggr RRs(TRI); + LRef.Mask = OR.second; if (!DFG.IsPreservingDef(DA)) { assert(!(IA.Addr->getFlags() & NodeAttrs::Phi)); // DA is a non-phi def that is live-on-exit from this block, and // that is also located in this block. LRef is a register ref // whose use this def reaches. If DA covers LRef, then no part - // of LRef is exposed upwards. + // of LRef is exposed upwards.A if (RRs.insert(DA.Addr->getRegRef(DFG)).hasCoverOf(LRef)) continue; } @@ -902,10 +948,11 @@ void Liveness::traverse(MachineBasicBlock *B, RefMap &LiveIn) { // We have reached past the beginning of B, and the accumulated // registers are not covering LRef. The first def from the // upward chain will be live. - // FIXME: This is where the live-in lane mask could be set. - // It cannot be be changed directly, because it is a part - // of the map key (LRef). - NewDefs.insert(TA.Id); + // Subtract all accumulated defs (RRs) from LRef. + RegisterAggr L(TRI); + L.insert(LRef).clear(RRs); + assert(!L.empty()); + NewDefs.insert({TA.Id,L.begin()->second}); break; } @@ -925,7 +972,7 @@ void Liveness::traverse(MachineBasicBlock *B, RefMap &LiveIn) { if (Trace) { dbgs() << "after defs in block\n"; dbgs() << " LiveIn: " << Print<RefMap>(LiveIn, DFG) << '\n'; - dbgs() << " Local: " << Print<RegisterSet>(LiveMap[B], DFG) << '\n'; + dbgs() << " Local: " << Print<RegisterAggr>(LiveMap[B], DFG) << '\n'; } // Scan the block for upward-exposed uses and add them to the tracking set. @@ -934,40 +981,44 @@ void Liveness::traverse(MachineBasicBlock *B, RefMap &LiveIn) { if (IA.Addr->getKind() != NodeAttrs::Stmt) continue; for (NodeAddr<UseNode*> UA : IA.Addr->members_if(DFG.IsUse, DFG)) { - RegisterRef RR = UA.Addr->getRegRef(DFG); if (UA.Addr->getFlags() & NodeAttrs::Undef) continue; + RegisterRef RR = DFG.normalizeRef(UA.Addr->getRegRef(DFG)); for (NodeAddr<DefNode*> D : getAllReachingDefs(UA)) if (getBlockWithRef(D.Id) != B) - LiveIn[RR].insert(D.Id); + LiveIn[RR.Reg].insert({D.Id,RR.Mask}); } } if (Trace) { dbgs() << "after uses in block\n"; dbgs() << " LiveIn: " << Print<RefMap>(LiveIn, DFG) << '\n'; - dbgs() << " Local: " << Print<RegisterSet>(LiveMap[B], DFG) << '\n'; + dbgs() << " Local: " << Print<RegisterAggr>(LiveMap[B], DFG) << '\n'; } // Phi uses should not be propagated up the dominator tree, since they // are not dominated by their corresponding reaching defs. - RegisterSet &Local = LiveMap[B]; + RegisterAggr &Local = LiveMap[B]; RefMap &LON = PhiLON[B]; - for (auto &R : LON) - Local.insert(R.first); + for (auto &R : LON) { + LaneBitmask M = 0; + for (auto P : R.second) + M |= P.second; + Local.insert(RegisterRef(R.first,M)); + } if (Trace) { dbgs() << "after phi uses in block\n"; dbgs() << " LiveIn: " << Print<RefMap>(LiveIn, DFG) << '\n'; - dbgs() << " Local: " << Print<RegisterSet>(Local, DFG) << '\n'; + dbgs() << " Local: " << Print<RegisterAggr>(Local, DFG) << '\n'; } for (auto C : IIDF[B]) { - auto &LiveC = LiveMap[C]; - for (auto S : LiveIn) + RegisterAggr &LiveC = LiveMap[C]; + for (const std::pair<RegisterId,NodeRefSet> &S : LiveIn) for (auto R : S.second) - if (MDT.properlyDominates(getBlockWithRef(R), C)) - LiveC.insert(S.first); + if (MDT.properlyDominates(getBlockWithRef(R.first), C)) + LiveC.insert(RegisterRef(S.first, R.second)); } } diff --git a/llvm/lib/Target/Hexagon/RDFLiveness.h b/llvm/lib/Target/Hexagon/RDFLiveness.h index 8b88f3a2add..5fffa2d2f05 100644 --- a/llvm/lib/Target/Hexagon/RDFLiveness.h +++ b/llvm/lib/Target/Hexagon/RDFLiveness.h @@ -30,12 +30,28 @@ namespace llvm { namespace rdf { struct Liveness { public: - typedef std::map<MachineBasicBlock*,RegisterSet> LiveMapType; - typedef std::map<RegisterRef,NodeSet> RefMap; + // 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) {} + + RegisterAggr &operator[] (MachineBasicBlock *B) { + return Map.emplace(B, Empty).first->second; + } + private: + RegisterAggr Empty; + std::map<MachineBasicBlock*,RegisterAggr> Map; + }; + + typedef std::pair<NodeId,LaneBitmask> NodeRef; + typedef std::set<NodeRef> NodeRefSet; + // RegisterId in RefMap must be normalized. + 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), Empty(), NoRegs(g.getTRI()), Trace(false) {} + MRI(mri), LiveMap(g.getTRI()), Empty(), NoRegs(g.getTRI()), + Trace(false) {} NodeList getAllReachingDefs(RegisterRef RefRR, NodeAddr<RefNode*> RefA, bool FullChain, const RegisterAggr &DefRRs); diff --git a/llvm/test/CodeGen/Hexagon/rdf-phi-up.ll b/llvm/test/CodeGen/Hexagon/rdf-phi-up.ll new file mode 100644 index 00000000000..28f4c90c174 --- /dev/null +++ b/llvm/test/CodeGen/Hexagon/rdf-phi-up.ll @@ -0,0 +1,60 @@ +; RUN: llc -march=hexagon -verify-machineinstrs < %s | FileCheck %s +; Check that this testcase compiles successfully. +; CHECK-LABEL: fred: +; CHECK: call foo + +target triple = "hexagon" + +%struct.0 = type { i32, i16, i8* } + +declare void @llvm.lifetime.start(i64, i8* nocapture) #1 +declare void @llvm.lifetime.end(i64, i8* nocapture) #1 + +define i32 @fred(i8* readonly %p0, i32* %p1) local_unnamed_addr #0 { +entry: + %v0 = alloca i16, align 2 + %v1 = icmp eq i8* %p0, null + br i1 %v1, label %if.then, label %lor.lhs.false + +lor.lhs.false: ; preds = %entry + %v2 = bitcast i8* %p0 to %struct.0** + %v3 = load %struct.0*, %struct.0** %v2, align 4 + %v4 = icmp eq %struct.0* %v3, null + br i1 %v4, label %if.then, label %if.else + +if.then: ; preds = %lor.lhs.false, %ent + %v5 = icmp eq i32* %p1, null + br i1 %v5, label %cleanup, label %if.then3 + +if.then3: ; preds = %if.then + store i32 0, i32* %p1, align 4 + br label %cleanup + +if.else: ; preds = %lor.lhs.false + %v6 = bitcast i16* %v0 to i8* + call void @llvm.lifetime.start(i64 2, i8* nonnull %v6) #0 + store i16 0, i16* %v0, align 2 + %v7 = call i32 @foo(%struct.0* nonnull %v3, i16* nonnull %v0) #0 + %v8 = icmp eq i32* %p1, null + br i1 %v8, label %if.end7, label %if.then6 + +if.then6: ; preds = %if.else + %v9 = load i16, i16* %v0, align 2 + %v10 = zext i16 %v9 to i32 + store i32 %v10, i32* %p1, align 4 + br label %if.end7 + +if.end7: ; preds = %if.else, %if.then6 + call void @llvm.lifetime.end(i64 2, i8* nonnull %v6) #0 + br label %cleanup + +cleanup: ; preds = %if.then3, %if.then, + %v11 = phi i32 [ %v7, %if.end7 ], [ -2147024809, %if.then ], [ -2147024809, %if.then3 ] + ret i32 %v11 +} + +declare i32 @foo(%struct.0*, i16*) local_unnamed_addr #0 + +attributes #0 = { nounwind } +attributes #1 = { argmemonly nounwind } + |