Files
derek.holloway 7502bf64a4
CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
Flatten subprojects into a single base monorepo
2026-09-02 16:34:47 -07:00

192 lines
7.8 KiB
C++

// Copyright Advanced Micro Devices, Inc., or its affiliates.
// SPDX-License-Identifier: MIT
#pragma once
#include <rocRoller/CodeGen/Instruction.hpp>
#include <rocRoller/Context.hpp>
#include <rocRoller/GPUArchitecture/GPUInstructionInfo.hpp>
#include <rocRoller/Scheduling/Scheduling.hpp>
namespace rocRoller
{
namespace Scheduling
{
template <typename T>
using WaitQueueMap = std::unordered_map<GPUWaitQueue, T>;
using WaitQueueRegisters = std::array<Register::ValuePtr, Instruction::MaxExtraRegisters>;
using WaitCntQueues = WaitQueueMap<std::vector<WaitQueueRegisters>>;
/**
* @brief This struct is used to store the _unallocated_ state of the waitcnt queues.
*
*/
struct WaitcntState
{
public:
WaitcntState();
WaitcntState(WaitQueueMap<bool> const& needsWaitZero,
WaitQueueMap<GPUWaitQueueType> const& typeInQueue,
WaitCntQueues const& instruction_queues_with_alloc);
bool operator==(const WaitcntState& rhs) const = default;
/**
* @brief Returns true if this WaitcntState and the provided WaitcntState are safe
* to see at a label and a branch that goes to that label.
*
* @param labelState
*/
void assertSafeToBranchTo(const WaitcntState& labelState,
std::string const& label) const;
private:
// These members are duplicates of the waitcntobserver members, except we're storing a
// std::vector<Register::RegisterId> for the registers instead of
// std::array<Register::ValuePtr, Instruction::MaxDstRegisters>
// so that we don't maintain the allocations.
WaitQueueMap<std::vector<std::vector<Register::RegisterId>>> m_instructionQueues;
WaitQueueMap<bool> m_needsWaitZero;
WaitQueueMap<GPUWaitQueueType> m_typeInQueue;
};
class WaitcntObserver
{
public:
WaitcntObserver();
WaitcntObserver(ContextPtr context);
InstructionStatus peek(Instruction const& inst) const;
void modify(Instruction& inst) const;
/**
* This function handles updating the waitqueues and flags when an instruction is scheduled.
* 1. If there is a wait included in the instruction, apply it to the queues.
* 2. Add n copies of the instruction's registers to all the queues that it affects, where n is its waitcnt.
* 3. If the wait is zero, or the queue already has an instruction of a different type, set the m_needsWaitZero flag.
* 4. Set the instruction type flag for each queue the instruction affects.
**/
void observe(Instruction const& inst);
constexpr static bool required(GPUArchitectureTarget const& target);
private:
std::weak_ptr<Context> m_context;
WaitCntQueues m_instructionQueues;
// This member tracks a flag for each queue which indicates that a waitcnt 0 is needed.
WaitQueueMap<bool> m_needsWaitZero;
// This member tracks the instruction type that is currently in a given queue.
// If there are ever multiple instruction types in a queue, and a register intersection occurs,
// a waitcnt 0 is required.
WaitQueueMap<GPUWaitQueueType> m_typeInQueue;
std::string m_barrierOpcode;
bool m_includeExplanation;
bool m_displayState;
// This member tracks, for every label, what the waitcnt state was when that label was encountered.
std::unordered_map<std::string, WaitcntState> m_labelStates;
// This member tracks, for every label, what the waitcnt state is everywhere a branch instruction targets that label.
std::unordered_map<std::string, std::vector<WaitcntState>> m_branchStates;
/**
* This function updates the given wait queue by applying the given waitcnt.
**/
void applyWaitToQueue(int waitCnt, GPUWaitQueue queue);
/**
* Determines if there's a waitcount that's needed due to a barrier if the
* alwaysWaitZeroBeforeBarrier kernelOption is set.
*
* @param inst
* @param[out] explanation is an output parameter for an explanation of the wait count required.
* @return WaitCount
*/
WaitCount computeZeroBarrierWaitCount(Instruction const& inst,
std::string* explanation = nullptr) const;
/**
* Determines if there's a waitcount that's needed due to the instruction having a
* WaitCount::SyncQueue() wait attached.
*
* @param inst
* @param[out] explanation is an output parameter for an explanation of the wait count required.
* @return WaitCount
*/
WaitCount computeSyncQueueWaitCount(Instruction const& inst,
std::string* explanation = nullptr) const;
/**
* Determines if there's a waitcount that's needed due to a register dependency
* intersection.
*
* It searches backwards through each wait queue looking for registers that
* intersect with the new instruction.
* If an intersection is found a wait is inserted for the intersection location
* or 0 if the wait_zero flag is set for the queue.
*
* @param inst
* @param[out] explanation is an output parameter for an explanation of the wait count required.
* @return WaitCount
*/
WaitCount computeRegisterWaitCount(Instruction const& inst,
std::string* explanation = nullptr) const;
/**
* @brief This function determines if an instruction needs a wait count inserted before
* it and provides an explanation as to why it's needed.
*
* @param inst
* @param[out] explanation is an output parameter for an explanation of the wait count required.
* @return WaitCount
*/
WaitCount computeWaitCount(Instruction const& inst,
std::string* explanation = nullptr) const;
/**
* @brief Get a string representation of the state of the Wait Queues
*
* @return std::string
*/
std::string getWaitQueueState() const;
/**
* @brief Add the current waitcnt state to the label state tracker.
*
* @param label the currently encountered label.
*/
void addLabelState(std::string const& label);
/**
* @brief Add the current waitcnt state to the branch state tracker.
*
* @param label the label currently being branched to.
*/
void addBranchState(std::string const& label);
/**
* @brief Assert that all branch and label waitcnt states are consistent.
*
* This function checks that the waitcnt state at every branch to a label is the same
* as the waitcnt state when that label was encountered.
*/
void assertLabelConsistency();
};
static_assert(CObserverConst<WaitcntObserver>);
}
}
#include <rocRoller/Scheduling/Observers/WaitcntObserver_impl.hpp>