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
305 lines
7.8 KiB
C++
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;
|
|
}
|
|
}
|
|
}
|
|
}
|