Skip to content

Commit 0230c8e

Browse files
committed
[AMDGPU] Refine GCNHazardRecognizer hasHazard()
Remove recursion to avoid stack overflow on large CFGs. Avoid worklist for hazard search within single MachineBasicBlock. Ensure predecessors are visited for all state combinations.
1 parent 0d29279 commit 0230c8e

File tree

1 file changed

+48
-31
lines changed

1 file changed

+48
-31
lines changed

llvm/lib/Target/AMDGPU/GCNHazardRecognizer.cpp

Lines changed: 48 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -441,42 +441,55 @@ using IsExpiredFn = function_ref<bool(const MachineInstr &, int WaitStates)>;
441441
using GetNumWaitStatesFn = function_ref<unsigned int(const MachineInstr &)>;
442442

443443
// Search for a hazard in a block and its predecessors.
444+
// StateT must implement getHashValue().
444445
template <typename StateT>
445446
static 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

Comments
 (0)