@@ -441,42 +441,55 @@ using IsExpiredFn = function_ref<bool(const MachineInstr &, int WaitStates)>;
441441using GetNumWaitStatesFn = function_ref<unsigned int (const MachineInstr &)>;
442442
443443// Search for a hazard in a block and its predecessors.
444+ // StateT must implement getHashValue().
444445template <typename StateT>
445446static bool
446- hasHazard (StateT State ,
447+ hasHazard (StateT InitialState ,
447448 function_ref<HazardFnResult(StateT &, const MachineInstr &)> IsHazard,
448449 function_ref<void(StateT &, const MachineInstr &)> UpdateState,
449- const MachineBasicBlock *MBB,
450- MachineBasicBlock::const_reverse_instr_iterator I,
451- DenseSet<const MachineBasicBlock *> &Visited) {
452- for (auto E = MBB->instr_rend (); I != E; ++I) {
453- // No need to look at parent BUNDLE instructions.
454- if (I->isBundle ())
455- continue ;
450+ const MachineBasicBlock *InitialMBB,
451+ MachineBasicBlock::const_reverse_instr_iterator InitialI) {
452+ SmallVector<std::pair<const MachineBasicBlock *, StateT>> Worklist;
453+ DenseSet<std::pair<const MachineBasicBlock *, unsigned >> Visited;
454+ const MachineBasicBlock *MBB = InitialMBB;
455+ StateT State = InitialState;
456+ auto I = InitialI;
457+
458+ for (;;) {
459+ bool Expired = false ;
460+ for (auto E = MBB->instr_rend (); I != E; ++I) {
461+ // No need to look at parent BUNDLE instructions.
462+ if (I->isBundle ())
463+ continue ;
456464
457- switch (IsHazard (State, *I)) {
458- case HazardFound:
459- return true ;
460- case HazardExpired:
461- return false ;
462- default :
463- // Continue search
464- break ;
465- }
465+ auto Result = IsHazard (State, *I);
466+ if (Result == HazardFound)
467+ return true ;
468+ if (Result == HazardExpired) {
469+ Expired = true ;
470+ break ;
471+ }
466472
467- if (I->isInlineAsm () || I->isMetaInstruction ())
468- continue ;
473+ if (I->isInlineAsm () || I->isMetaInstruction ())
474+ continue ;
469475
470- UpdateState (State, *I);
471- }
476+ UpdateState (State, *I);
477+ }
472478
473- for (MachineBasicBlock *Pred : MBB->predecessors ()) {
474- if (!Visited.insert (Pred).second )
475- continue ;
479+ if (!Expired) {
480+ unsigned StateHash = State.getHashValue ();
481+ for (MachineBasicBlock *Pred : MBB->predecessors ()) {
482+ if (!Visited.insert (std::pair (Pred, StateHash)).second )
483+ continue ;
484+ Worklist.emplace_back (Pred, State);
485+ }
486+ }
476487
477- if (hasHazard (State, IsHazard, UpdateState, Pred, Pred->instr_rbegin (),
478- Visited))
479- return true ;
488+ if (Worklist.empty ())
489+ break ;
490+
491+ std::tie (MBB, State) = Worklist.pop_back_val ();
492+ I = MBB->instr_rbegin ();
480493 }
481494
482495 return false ;
@@ -1641,6 +1654,10 @@ bool GCNHazardRecognizer::fixVALUPartialForwardingHazard(MachineInstr *MI) {
16411654 SmallDenseMap<Register, int , 4 > DefPos;
16421655 int ExecPos = std::numeric_limits<int >::max();
16431656 int VALUs = 0 ;
1657+
1658+ unsigned getHashValue () const {
1659+ return hash_combine (ExecPos, VALUs, hash_combine_range (DefPos));
1660+ }
16441661 };
16451662
16461663 StateType State;
@@ -1735,9 +1752,8 @@ bool GCNHazardRecognizer::fixVALUPartialForwardingHazard(MachineInstr *MI) {
17351752 State.VALUs += 1 ;
17361753 };
17371754
1738- DenseSet<const MachineBasicBlock *> Visited;
17391755 if (!hasHazard<StateType>(State, IsHazardFn, UpdateStateFn, MI->getParent (),
1740- std::next(MI->getReverseIterator ()), Visited ))
1756+ std::next(MI->getReverseIterator ())))
17411757 return false;
17421758
17431759 BuildMI (*MI->getParent (), MI, MI->getDebugLoc(),
@@ -1778,6 +1794,8 @@ bool GCNHazardRecognizer::fixVALUTransUseHazard(MachineInstr *MI) {
17781794 struct StateType {
17791795 int VALUs = 0 ;
17801796 int TRANS = 0 ;
1797+
1798+ unsigned getHashValue () const { return hash_combine (VALUs, TRANS); }
17811799 };
17821800
17831801 StateType State;
@@ -1813,9 +1831,8 @@ bool GCNHazardRecognizer::fixVALUTransUseHazard(MachineInstr *MI) {
18131831 State.TRANS += 1 ;
18141832 };
18151833
1816- DenseSet<const MachineBasicBlock *> Visited;
18171834 if (!hasHazard<StateType>(State, IsHazardFn, UpdateStateFn, MI->getParent (),
1818- std::next (MI->getReverseIterator ()), Visited ))
1835+ std::next (MI->getReverseIterator ())))
18191836 return false ;
18201837
18211838 // Hazard is observed - insert a wait on va_dst counter to ensure hazard is
0 commit comments