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
315 lines
11 KiB
C++
315 lines
11 KiB
C++
// Copyright Advanced Micro Devices, Inc., or its affiliates.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
#pragma once
|
|
|
|
#include <memory>
|
|
#include <optional>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include <rocRoller/CodeGen/WaitCount.hpp>
|
|
#include <rocRoller/InstructionValues/Register_fwd.hpp>
|
|
#include <rocRoller/Scheduling/Scheduler_fwd.hpp>
|
|
#include <rocRoller/Scheduling/Scheduling.hpp>
|
|
#include <rocRoller/Utilities/Settings_fwd.hpp>
|
|
|
|
namespace rocRoller
|
|
{
|
|
struct Instruction
|
|
{
|
|
enum
|
|
{
|
|
MaxDstRegisters = 2,
|
|
MaxSrcRegisters = 5,
|
|
MaxExtraRegisters = 5,
|
|
MaxModifiers = 10,
|
|
MaxAllocations = 4,
|
|
};
|
|
|
|
Instruction(std::string const& opcode,
|
|
std::initializer_list<Register::ValuePtr> dst,
|
|
std::initializer_list<Register::ValuePtr> src,
|
|
std::initializer_list<std::string> modifiers,
|
|
std::string const& comment);
|
|
|
|
Instruction();
|
|
|
|
static Instruction Allocate(Register::ValuePtr reg);
|
|
static Instruction Allocate(std::shared_ptr<Register::Allocation> reg);
|
|
static Instruction
|
|
Allocate(std::initializer_list<std::shared_ptr<Register::Allocation>> regs);
|
|
|
|
static Instruction Directive(std::string const& directive);
|
|
static Instruction Directive(std::string const& directive, std::string const& comment);
|
|
|
|
static Instruction Comment(std::string const& comment);
|
|
|
|
static Instruction Warning(std::string const& warning);
|
|
|
|
static Instruction Nop();
|
|
static Instruction Nop(int nopCount);
|
|
static Instruction Nop(std::string const& comment);
|
|
static Instruction Nop(int nopCount, std::string const& comment);
|
|
|
|
static Instruction Label(std::string const& name);
|
|
static Instruction Label(std::string&& name);
|
|
|
|
static Instruction Label(std::string const& name, std::string const& comment);
|
|
static Instruction Label(std::string&& name, std::string const& comment);
|
|
|
|
static Instruction Label(Register::ValuePtr label);
|
|
static Instruction Label(Register::ValuePtr label, std::string const& comment);
|
|
|
|
static Instruction InoutInstruction(std::string const& opcode,
|
|
std::initializer_list<Register::ValuePtr> inout,
|
|
std::initializer_list<std::string> modifiers,
|
|
std::string const& comment);
|
|
|
|
static Instruction Wait(WaitCount const& wait);
|
|
static Instruction Wait(WaitCount&& wait);
|
|
|
|
static Instruction Lock(Scheduling::Dependency dependency, std::string comment = "");
|
|
static Instruction Unlock(Scheduling::Dependency dependency, std::string comment = "");
|
|
static Instruction Unlock(std::string comment = "");
|
|
|
|
/**
|
|
* This instruction will be considered to write `reg` even though it
|
|
* will not be included in the actual dst operands in the string
|
|
* rendering. This will include it in the wait queue for the
|
|
* instruction if it's a memory instruction.
|
|
*/
|
|
Instruction& addExtraDst(Register::ValuePtr reg);
|
|
|
|
/**
|
|
* This instruction will implicitly add a waitcnt for any pending
|
|
* load/stores on `reg`, without including it in the input operands for
|
|
* the string rendering of this instruction.
|
|
*/
|
|
Instruction& addExtraSrc(Register::ValuePtr reg);
|
|
|
|
/**
|
|
* Returns all the destination operands that will appear in the instruction.
|
|
*/
|
|
auto const& getDsts() const;
|
|
|
|
/**
|
|
* Returns all the source operands that will appear in the instruction.
|
|
*/
|
|
auto const& getSrcs() const;
|
|
|
|
/**
|
|
* Returns all the 'extra' destination operands; i.e. ones that will
|
|
* not appear in the instruction.
|
|
*/
|
|
auto const& getExtraDsts() const;
|
|
|
|
/**
|
|
* Returns all the 'extra' source operands; i.e. ones that will
|
|
* not appear in the instruction.
|
|
*/
|
|
auto const& getExtraSrcs() const;
|
|
|
|
/**
|
|
* Yields all the destination operands, including ones that will not
|
|
* appear in the instruction.
|
|
*/
|
|
Generator<Register::ValuePtr> getAllDsts() const;
|
|
|
|
/**
|
|
* Yields all the source operands, including ones that will not
|
|
* appear in the instruction.
|
|
*/
|
|
Generator<Register::ValuePtr> getAllSrcs() const;
|
|
|
|
/**
|
|
* Yields all destination and source operands, including ones that will
|
|
* not appear in the instruction.
|
|
*/
|
|
Generator<Register::ValuePtr> getAllOperands() const;
|
|
|
|
bool hasRegisters() const;
|
|
constexpr bool readsSpecialRegisters() const;
|
|
WaitCount getWaitCount() const;
|
|
|
|
/**
|
|
* @brief Returns |currentSrc n previousDest| > 0 or |currentDest n previousDest| > 0
|
|
*
|
|
* @param previousDest Destination registers of previous instruction.
|
|
* @return Whether this instructions registers intersect with a past
|
|
* instruction's destination registers.
|
|
*/
|
|
template <CForwardRangeOf<Register::ValuePtr> T>
|
|
bool isAfterWriteDependency(T const& previousDest) const;
|
|
|
|
void toStream(std::ostream&, LogLevel level) const;
|
|
std::string toString(LogLevel level) const;
|
|
|
|
constexpr Scheduling::LockOperation getLockValue() const;
|
|
constexpr Scheduling::Dependency getDependency() const;
|
|
|
|
std::string const& getOpCode() const;
|
|
std::array<std::string, Instruction::MaxModifiers> getModifiers() const;
|
|
|
|
CoexecCategory getCategory() const;
|
|
|
|
constexpr int getNopCount() const
|
|
{
|
|
return m_nopCount;
|
|
}
|
|
|
|
Instruction& lock(Scheduling::Dependency dependency, std::string comment = "");
|
|
Instruction& unlock(Scheduling::Dependency dependency, std::string comment = "");
|
|
Instruction& unlock(std::string comment = "");
|
|
|
|
void addControlOp(int id);
|
|
std::vector<int> const& controlOps() const;
|
|
std::optional<int> innerControlOp() const;
|
|
|
|
std::string const& referencedArg() const;
|
|
void setReferencedArg(std::string arg);
|
|
|
|
void addAllocation(std::shared_ptr<Register::Allocation> alloc);
|
|
void addWaitCount(WaitCount const& wait);
|
|
void addComment(std::string const& comment);
|
|
void addWarning(std::string const& warning);
|
|
void addNop();
|
|
void addNop(int count);
|
|
void setNopMin(int count);
|
|
|
|
void setModeRegister(uint8_t mode);
|
|
std::optional<uint8_t> getModeRegister() const;
|
|
|
|
std::vector<std::string> const& comments() const;
|
|
|
|
constexpr int nopCount() const;
|
|
|
|
constexpr bool isCommentOnly() const;
|
|
constexpr bool isLabel() const;
|
|
std::string getLabel() const;
|
|
|
|
/**
|
|
* Get the status that was peeked by the Observers
|
|
*/
|
|
Scheduling::InstructionStatus const& peekedStatus() const;
|
|
|
|
/**
|
|
* Set the status that was peeked by the Observers
|
|
*/
|
|
void setPeekedStatus(Scheduling::InstructionStatus status);
|
|
|
|
/**
|
|
* How many instructions actually executed by the GPU are included?
|
|
* This includes the main instruction, as well as any s_nop or s_waitcnt
|
|
* instructions attached to it.
|
|
*/
|
|
int numExecutedInstructions() const;
|
|
|
|
/**
|
|
* Get the total number of cycles for this instruction.
|
|
* This includes executed instructions, stall cycles, and additional cycles.
|
|
*
|
|
* An estimation as stall cycles are an estimation.
|
|
*
|
|
* Used for observers to keep track of cycles (in terms of time).
|
|
*/
|
|
int totalCycles() const;
|
|
|
|
void allocateNow();
|
|
|
|
using AllocationArray = std::array<std::shared_ptr<Register::Allocation>, MaxAllocations>;
|
|
AllocationArray allocations() const;
|
|
|
|
/**
|
|
* Set the modelled per-workitem addresses (only for select LDS instructions for now)
|
|
*/
|
|
const std::optional<std::vector<size_t>>& getModelledAddresses() const
|
|
{
|
|
return m_addresses;
|
|
}
|
|
|
|
/**
|
|
* Set the modelled per-workitem addresses
|
|
*/
|
|
void setModelledAddresses(const std::vector<size_t>& addresses)
|
|
{
|
|
m_addresses = addresses;
|
|
}
|
|
|
|
private:
|
|
/**
|
|
* toString = preamble + functional + coda
|
|
*/
|
|
void preambleString(std::ostream& oss, LogLevel level) const;
|
|
void functionalString(std::ostream& oss, LogLevel level) const;
|
|
void codaString(std::ostream& oss, LogLevel level) const;
|
|
|
|
/**
|
|
* Attempts to find a pointer to the context by looking at all the operands.
|
|
*/
|
|
ContextPtr findContextFromOperands() const;
|
|
|
|
/**
|
|
* A comment detailing allocations that happened when scheduling this instruction.
|
|
*/
|
|
void allocationString(std::ostream& oss, LogLevel level) const;
|
|
|
|
/**
|
|
* Assembler directive(s), if this instruction contains any.
|
|
*/
|
|
void directiveString(std::ostream& oss, LogLevel level) const;
|
|
|
|
/**
|
|
* Just the main instruction.
|
|
*/
|
|
void coreInstructionString(std::ostream& oss) const;
|
|
|
|
bool requiresVnopForHazard() const;
|
|
|
|
/**
|
|
* When this instruction is scheduled, perform this register allocation.
|
|
*/
|
|
AllocationArray m_allocations;
|
|
|
|
int m_nopCount = 0;
|
|
|
|
std::string m_directive;
|
|
|
|
std::vector<std::string> m_warnings;
|
|
|
|
std::vector<std::string> m_comments;
|
|
|
|
std::vector<int> m_controlOps;
|
|
|
|
std::string m_label;
|
|
|
|
WaitCount m_waitCount;
|
|
|
|
std::string m_opcode;
|
|
|
|
std::string m_referencedArg;
|
|
|
|
Scheduling::LockOperation m_lockOp = Scheduling::LockOperation::None;
|
|
Scheduling::Dependency m_dependency = Scheduling::Dependency::None;
|
|
|
|
std::optional<uint8_t> m_MODESetValue;
|
|
|
|
std::array<Register::ValuePtr, MaxDstRegisters> m_inoutDsts;
|
|
std::array<Register::ValuePtr, MaxDstRegisters> m_dst;
|
|
std::array<Register::ValuePtr, MaxSrcRegisters> m_src;
|
|
|
|
std::array<Register::ValuePtr, MaxExtraRegisters> m_extraDsts;
|
|
std::array<Register::ValuePtr, MaxExtraRegisters> m_extraSrcs;
|
|
|
|
std::array<std::string, MaxModifiers> m_modifiers;
|
|
|
|
bool m_operandsAreInout = false;
|
|
|
|
Scheduling::InstructionStatus m_peekedStatus;
|
|
|
|
std::optional<std::vector<size_t>> m_addresses;
|
|
};
|
|
}
|
|
|
|
#include <rocRoller/CodeGen/Instruction_impl.hpp>
|