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

305 lines
7.8 KiB
C++

// Copyright Advanced Micro Devices, Inc., or its affiliates.
// SPDX-License-Identifier: MIT
#include <rocRoller/CodeGen/Instruction.hpp>
#include <rocRoller/Context.hpp>
#include <rocRoller/Utilities/String.hpp>
namespace rocRoller
{
ContextPtr Instruction::findContextFromOperands() const
{
// TODO: Reevalute this method for retrieving/passing the context.
for(auto const& reg : getAllOperands())
if(reg->context())
return reg->context();
return nullptr;
}
bool Instruction::requiresVnopForHazard() const
{
auto ctx = findContextFromOperands();
return ctx && ctx->targetArchitecture().target().isGFX12GPU();
}
void Instruction::codaString(std::ostream& os, LogLevel level) const
{
if(m_lockOp != Scheduling::LockOperation::None && level >= LogLevel::Verbose)
{
os << " // " << m_lockOp << " " << m_dependency << std::endl;
}
if(level >= LogLevel::Terse && m_comments.size() > 1)
{
// Only include everything but the first comment in the coda string.
for(int i = 1; i < m_comments.size(); i++)
{
for(auto const& line : EscapeComment(m_comments[i]))
{
os << line;
}
os << "\n";
}
}
if(level >= LogLevel::Info)
{
if(m_extraDsts[0])
{
std::string comment = "Extra dsts:";
for(auto const& dst : m_extraDsts)
{
if(dst)
comment += " " + dst->description();
}
for(auto const& line : EscapeComment(comment))
os << line;
os << "\n";
}
if(m_extraSrcs[0])
{
std::string comment = "Extra srcs:";
for(auto const& src : m_extraSrcs)
{
if(src)
comment += " " + src->description();
}
for(auto const& line : EscapeComment(comment))
os << line;
os << "\n";
}
}
if(level >= LogLevel::Trace)
{
auto ctx = findContextFromOperands();
if(ctx)
{
auto status = ctx->observer()->peek(*this);
for(auto const& line : EscapeComment(m_peekedStatus.toString()))
os << line;
os << "\n";
auto category = GPUInstructionInfo::getCoexecCategory(m_opcode);
for(auto const& line : EscapeComment("Category: " + rocRoller::toString(category)))
os << line;
os << "\n";
}
}
}
void Instruction::addControlOp(int id)
{
m_controlOps.push_back(id);
}
CoexecCategory Instruction::getCategory() const
{
auto category = GPUInstructionInfo::getCoexecCategory(m_opcode);
if(category == CoexecCategory::NotAnInstruction && getWaitCount() != WaitCount())
{
category = CoexecCategory::Scalar;
}
return category;
}
std::vector<int> const& Instruction::controlOps() const
{
return m_controlOps;
}
std::optional<int> Instruction::innerControlOp() const
{
if(!m_controlOps.empty())
return m_controlOps.front();
return std::nullopt;
}
void Instruction::setReferencedArg(std::string arg)
{
m_referencedArg = std::move(arg);
}
std::string const& Instruction::referencedArg() const
{
return m_referencedArg;
}
std::vector<std::string> const& Instruction::comments() const
{
return m_comments;
}
Scheduling::InstructionStatus const& Instruction::peekedStatus() const
{
return m_peekedStatus;
}
void Instruction::setPeekedStatus(Scheduling::InstructionStatus status)
{
m_peekedStatus = std::move(status);
}
void Instruction::preambleString(std::ostream& os, LogLevel level) const
{
if(level >= LogLevel::Warning)
{
for(auto const& w : m_warnings)
{
for(auto const& s : EscapeComment(w))
{
os << s;
}
os << "\n";
}
}
allocationString(os, level);
}
void Instruction::directiveString(std::ostream& os, LogLevel level) const
{
os << m_directive;
if(!m_directive.empty())
os << "\n";
}
void Instruction::functionalString(std::ostream& os, LogLevel level) const
{
if(!m_label.empty())
{
os << m_label << ":\n";
}
directiveString(os, level);
m_waitCount.toStream(os, level);
if(m_nopCount > 0)
{
if(requiresVnopForHazard())
{
for(int i = 0; i < m_nopCount; i++)
os << "v_nop\n";
}
else
{
int count = m_nopCount;
while(count > 16)
{
// s_nop can only handle values from 0 to 0xf
os << "s_nop 0xf\n";
count -= 16;
}
// Note: "s_nop 0" is 1 nop, "s_nop 0xf" is 16 nops
os << "s_nop " << (count - 1) << "\n";
}
}
if(m_MODESetValue)
{
os << "s_set_vgpr_msb " << static_cast<uint16_t>(*m_MODESetValue) << "\n";
}
auto pos = os.tellp();
coreInstructionString(os);
if(level > LogLevel::Terse)
{
std::string input;
if(!m_controlOps.empty())
input = fmt::format("(op {}) ", m_controlOps.front());
if(!m_comments.empty())
input += m_comments.front();
// Only include the first comment in the functional string.
for(auto const& s : EscapeComment(input, 1))
{
os << s;
}
}
if(pos != os.tellp())
{
os << "\n";
}
}
void Instruction::allocationString(std::ostream& os, LogLevel level) const
{
if(level > LogLevel::Terse)
{
for(auto const& alloc : m_allocations)
{
if(alloc)
{
for(auto const& line : EscapeComment(alloc->descriptiveComment("Allocated")))
{
os << line;
}
}
}
}
}
void Instruction::coreInstructionString(std::ostream& os) const
{
if(m_opcode.empty())
{
return;
}
os << m_opcode << " ";
bool firstDstArg = true;
for(auto const& dst : m_dst)
{
if(dst)
{
if(!firstDstArg)
{
os << ", ";
}
dst->toStream(os, true);
firstDstArg = false;
}
}
for(auto const& src : m_src)
{
if(src && !firstDstArg)
{
os << ", ";
break;
}
}
bool firstSrcArg = true;
for(auto const& src : m_src)
{
if(src)
{
if(!firstSrcArg)
{
os << ", ";
}
src->toStream(os, true);
firstSrcArg = false;
}
}
for(std::string const& mod : m_modifiers)
{
if(!mod.empty())
{
os << " " << mod;
}
}
}
}