-
Notifications
You must be signed in to change notification settings - Fork 15.3k
[AMDGPU] Refine GCNHazardRecognizer hasHazard() #138841
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 4 commits
0230c8e
2a18fbe
9532454
61a3e48
5a736bd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -441,42 +441,106 @@ using IsExpiredFn = function_ref<bool(const MachineInstr &, int WaitStates)>; | |
| using GetNumWaitStatesFn = function_ref<unsigned int(const MachineInstr &)>; | ||
|
|
||
| // Search for a hazard in a block and its predecessors. | ||
| template <typename StateT> | ||
| template <typename StateT, typename StateTraitsT> | ||
| static bool | ||
| hasHazard(StateT State, | ||
| hasHazard(StateT InitialState, | ||
| function_ref<HazardFnResult(StateT &, const MachineInstr &)> IsHazard, | ||
| function_ref<void(StateT &, const MachineInstr &)> UpdateState, | ||
|
Comment on lines
447
to
448
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not something to address in the current patch, but I think this |
||
| const MachineBasicBlock *MBB, | ||
| MachineBasicBlock::const_reverse_instr_iterator I, | ||
| DenseSet<const MachineBasicBlock *> &Visited) { | ||
| for (auto E = MBB->instr_rend(); I != E; ++I) { | ||
| // No need to look at parent BUNDLE instructions. | ||
| if (I->isBundle()) | ||
| continue; | ||
|
|
||
| switch (IsHazard(State, *I)) { | ||
| case HazardFound: | ||
| return true; | ||
| case HazardExpired: | ||
| return false; | ||
| default: | ||
| // Continue search | ||
| break; | ||
| const MachineBasicBlock *InitialMBB, | ||
| MachineBasicBlock::const_reverse_instr_iterator InitialI) { | ||
| struct StateMapKey { | ||
| SmallVectorImpl<StateT> *States; | ||
| unsigned Idx; | ||
| static bool isEqual(const StateMapKey &LHS, const StateMapKey &RHS) { | ||
| return LHS.States == RHS.States && LHS.Idx == RHS.Idx; | ||
| } | ||
| }; | ||
| struct StateMapKeyTraits : DenseMapInfo<StateMapKey> { | ||
jayfoad marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| static inline StateMapKey getEmptyKey() { | ||
| return {static_cast<SmallVectorImpl<StateT> *>( | ||
| DenseMapInfo<void *>::getEmptyKey()), | ||
| DenseMapInfo<unsigned>::getEmptyKey()}; | ||
| } | ||
| static inline StateMapKey getTombstoneKey() { | ||
| return {static_cast<SmallVectorImpl<StateT> *>( | ||
| DenseMapInfo<void *>::getTombstoneKey()), | ||
| DenseMapInfo<unsigned>::getTombstoneKey()}; | ||
| } | ||
| static unsigned getHashValue(const StateMapKey &Key) { | ||
| return StateTraitsT::getHashValue((*Key.States)[Key.Idx]); | ||
| } | ||
| static unsigned getHashValue(const StateT &State) { | ||
| return StateTraitsT::getHashValue(State); | ||
| } | ||
| static bool isEqual(const StateMapKey &LHS, const StateMapKey &RHS) { | ||
| const auto EKey = getEmptyKey(); | ||
| const auto TKey = getTombstoneKey(); | ||
| if (StateMapKey::isEqual(LHS, EKey) || StateMapKey::isEqual(RHS, EKey) || | ||
| StateMapKey::isEqual(LHS, TKey) || StateMapKey::isEqual(RHS, TKey)) | ||
| return StateMapKey::isEqual(LHS, RHS); | ||
| return StateTraitsT::isEqual((*LHS.States)[LHS.Idx], | ||
| (*RHS.States)[RHS.Idx]); | ||
| } | ||
| static bool isEqual(const StateT &LHS, const StateMapKey &RHS) { | ||
| if (StateMapKey::isEqual(RHS, getEmptyKey()) || | ||
| StateMapKey::isEqual(RHS, getTombstoneKey())) | ||
| return false; | ||
| return StateTraitsT::isEqual(LHS, (*RHS.States)[RHS.Idx]); | ||
| } | ||
| }; | ||
|
|
||
| if (I->isInlineAsm() || I->isMetaInstruction()) | ||
| continue; | ||
| SmallDenseMap<StateMapKey, unsigned, 8, StateMapKeyTraits> StateMap; | ||
| SmallVector<StateT, 8> States; | ||
|
|
||
| UpdateState(State, *I); | ||
| } | ||
| const MachineBasicBlock *MBB = InitialMBB; | ||
| StateT State = InitialState; | ||
| auto I = InitialI; | ||
perlfu marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| for (MachineBasicBlock *Pred : MBB->predecessors()) { | ||
| if (!Visited.insert(Pred).second) | ||
| continue; | ||
| SmallSetVector<std::pair<const MachineBasicBlock *, unsigned>, 16> Worklist; | ||
| unsigned WorkIdx = 0; | ||
| for (;;) { | ||
| bool Expired = false; | ||
| for (auto E = MBB->instr_rend(); I != E; ++I) { | ||
| // No need to look at parent BUNDLE instructions. | ||
| if (I->isBundle()) | ||
| continue; | ||
|
|
||
| if (hasHazard(State, IsHazard, UpdateState, Pred, Pred->instr_rbegin(), | ||
| Visited)) | ||
| return true; | ||
| auto Result = IsHazard(State, *I); | ||
| if (Result == HazardFound) | ||
| return true; | ||
| if (Result == HazardExpired) { | ||
| Expired = true; | ||
| break; | ||
| } | ||
|
|
||
| if (I->isInlineAsm() || I->isMetaInstruction()) | ||
| continue; | ||
|
|
||
| UpdateState(State, *I); | ||
| } | ||
|
|
||
| if (!Expired) { | ||
| auto StateIt = StateMap.find_as(State); | ||
perlfu marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| unsigned StateIdx; | ||
| if (StateIt != StateMap.end()) { | ||
| StateIdx = StateIt->getSecond(); | ||
| } else { | ||
| StateIdx = States.size(); | ||
| States.emplace_back(State); | ||
| StateMapKey Key = {&States, StateIdx}; | ||
| StateMap.insert(std::pair(Key, StateIdx)); | ||
| } | ||
| for (MachineBasicBlock *Pred : MBB->predecessors()) | ||
| Worklist.insert(std::pair(Pred, StateIdx)); | ||
| } | ||
|
|
||
| if (WorkIdx == Worklist.size()) | ||
| break; | ||
|
|
||
| unsigned StateIdx; | ||
| std::tie(MBB, StateIdx) = Worklist[WorkIdx++]; | ||
| State = States[StateIdx]; | ||
| I = MBB->instr_rbegin(); | ||
| } | ||
|
|
||
| return false; | ||
|
|
@@ -1642,6 +1706,16 @@ bool GCNHazardRecognizer::fixVALUPartialForwardingHazard(MachineInstr *MI) { | |
| int ExecPos = std::numeric_limits<int>::max(); | ||
| int VALUs = 0; | ||
| }; | ||
| struct StateTraits { | ||
| static unsigned getHashValue(const StateType &State) { | ||
| return hash_combine(State.ExecPos, State.VALUs, | ||
| hash_combine_range(State.DefPos)); | ||
| } | ||
| static bool isEqual(const StateType &LHS, const StateType &RHS) { | ||
| return LHS.DefPos == RHS.DefPos && LHS.ExecPos == RHS.ExecPos && | ||
| LHS.VALUs == RHS.VALUs; | ||
| } | ||
| }; | ||
|
|
||
| StateType State; | ||
|
|
||
|
|
@@ -1735,9 +1809,9 @@ bool GCNHazardRecognizer::fixVALUPartialForwardingHazard(MachineInstr *MI) { | |
| State.VALUs += 1; | ||
| }; | ||
|
|
||
| DenseSet<const MachineBasicBlock *> Visited; | ||
| if (!hasHazard<StateType>(State, IsHazardFn, UpdateStateFn, MI->getParent(), | ||
| std::next(MI->getReverseIterator()), Visited)) | ||
| if (!hasHazard<StateType, StateTraits>(State, IsHazardFn, UpdateStateFn, | ||
| MI->getParent(), | ||
| std::next(MI->getReverseIterator()))) | ||
| return false; | ||
|
|
||
| BuildMI(*MI->getParent(), MI, MI->getDebugLoc(), | ||
|
|
@@ -1779,6 +1853,14 @@ bool GCNHazardRecognizer::fixVALUTransUseHazard(MachineInstr *MI) { | |
| int VALUs = 0; | ||
| int TRANS = 0; | ||
| }; | ||
| struct StateTraits { | ||
| static unsigned getHashValue(const StateType &State) { | ||
| return hash_combine(State.VALUs, State.TRANS); | ||
| } | ||
| static bool isEqual(const StateType &LHS, const StateType &RHS) { | ||
| return LHS.VALUs == RHS.VALUs && LHS.TRANS == RHS.TRANS; | ||
| } | ||
| }; | ||
|
|
||
| StateType State; | ||
|
|
||
|
|
@@ -1813,9 +1895,9 @@ bool GCNHazardRecognizer::fixVALUTransUseHazard(MachineInstr *MI) { | |
| State.TRANS += 1; | ||
| }; | ||
|
|
||
| DenseSet<const MachineBasicBlock *> Visited; | ||
| if (!hasHazard<StateType>(State, IsHazardFn, UpdateStateFn, MI->getParent(), | ||
| std::next(MI->getReverseIterator()), Visited)) | ||
| if (!hasHazard<StateType, StateTraits>(State, IsHazardFn, UpdateStateFn, | ||
| MI->getParent(), | ||
| std::next(MI->getReverseIterator()))) | ||
| return false; | ||
|
|
||
| // Hazard is observed - insert a wait on va_dst counter to ensure hazard is | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.