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

649 lines
29 KiB
C++

// Copyright Advanced Micro Devices, Inc., or its affiliates.
// SPDX-License-Identifier: MIT
#ifdef ROCROLLER_USE_HIP
#include <hip/hip_ext.h>
#include <hip/hip_runtime.h>
#endif /* ROCROLLER_USE_HIP */
#include <rocRoller/AssemblyKernel.hpp>
#include <rocRoller/CodeGen/ArgumentLoader.hpp>
#include <rocRoller/CodeGen/Arithmetic/ArithmeticGenerator.hpp>
#include <rocRoller/CodeGen/BranchGenerator.hpp>
#include <rocRoller/CodeGen/MemoryInstructions.hpp>
#include <rocRoller/CommandSolution.hpp>
#include <rocRoller/ExecutableKernel.hpp>
#include <rocRoller/InstructionValues/LabelAllocator.hpp>
#include <rocRoller/KernelArguments.hpp>
#include <rocRoller/Operations/Command.hpp>
#include <rocRoller/Scheduling/Scheduler.hpp>
#include <rocRoller/Utilities/Generator.hpp>
#include "GPUContextFixture.hpp"
#include "Utilities.hpp"
using namespace rocRoller;
namespace rocRollerTest
{
class DependencyTest
: public CurrentGPUContextFixture,
public ::testing::WithParamInterface<std::tuple<Scheduling::SchedulerProcedure, int>>
{
public:
Scheduling::SchedulerProcedure procedure;
protected:
void SetUp() override
{
m_kernelOptions->assertWaitCntState = false;
std::tie(procedure, m_randomSeed) = GetParam();
CurrentGPUContextFixture::SetUp();
m_context->setRandomSeed(m_randomSeed);
}
int m_randomSeed;
};
/**
* double_and_check will double the value and check if its below a certain threshold.
* First call is to double up to 1000 starting with 6. The second call is up to 100, so
* thos double_and_check should return immediately since we are already above 100.
* Interleaving these two will have the double_and_check(100) vcc be set to true when
* double_and_check(1000) checks for looping and will quit early. Also interleave comments
* to see how they affect scheduling.
**/
TEST_P(DependencyTest, GPU_ForLoopsWithVCC)
{
ASSERT_EQ(true, isLocalDevice());
auto command = std::make_shared<Command>();
VariableType floatPtr{DataType::Float, PointerType::PointerGlobal};
VariableType floatVal{DataType::Float, PointerType::Value};
VariableType uintVal{DataType::UInt32, PointerType::Value};
auto ptrTag = command->allocateTag();
auto ptr_arg = command->allocateArgument(floatPtr, ptrTag, ArgumentType::Value);
auto valTag = command->allocateTag();
auto val_arg = command->allocateArgument(floatVal, valTag, ArgumentType::Value);
auto sizeTag = command->allocateTag();
auto size_arg = command->allocateArgument(uintVal, sizeTag, ArgumentType::Size);
auto ptr2Tag = command->allocateTag();
auto ptr_arg2 = command->allocateArgument(floatPtr, ptr2Tag, ArgumentType::Value);
auto val2Tag = command->allocateTag();
auto val_arg2 = command->allocateArgument(floatVal, val2Tag, ArgumentType::Value);
auto size2Tag = command->allocateTag();
auto size_arg2 = command->allocateArgument(uintVal, size2Tag, ArgumentType::Size);
auto ptr_exp = std::make_shared<Expression::Expression>(ptr_arg);
auto val_exp = std::make_shared<Expression::Expression>(val_arg);
auto size_exp = std::make_shared<Expression::Expression>(size_arg);
auto ptr_exp2 = std::make_shared<Expression::Expression>(ptr_arg2);
auto val_exp2 = std::make_shared<Expression::Expression>(val_arg2);
auto size_exp2 = std::make_shared<Expression::Expression>(size_arg2);
auto one = std::make_shared<Expression::Expression>(1u);
auto zero = std::make_shared<Expression::Expression>(0u);
auto k = m_context->kernel();
k->setKernelDimensions(1);
k->addArgument({"ptr1",
{DataType::Float, PointerType::PointerGlobal},
DataDirection::WriteOnly,
ptr_exp});
k->addArgument({"val1", {DataType::Float}, DataDirection::ReadOnly, val_exp});
k->addArgument({"ptr2",
{DataType::Float, PointerType::PointerGlobal},
DataDirection::WriteOnly,
ptr_exp2});
k->addArgument({"val2", {DataType::Float}, DataDirection::ReadOnly, val_exp});
k->setWorkgroupSize({1, 1, 1});
k->setWorkitemCount({size_exp, one, one});
k->setDynamicSharedMemBytes(zero);
m_context->schedule(k->preamble());
m_context->schedule(k->prolog());
std::vector<Generator<Instruction>> sequences;
auto double_and_check = [&](float check_val, int n) -> Generator<Instruction> {
Register::ValuePtr s_ptr, s_value;
co_yield m_context->argLoader()->getValue("ptr" + std::to_string(n), s_ptr);
co_yield m_context->argLoader()->getValue("val" + std::to_string(n), s_value);
auto v_ptr = Register::Value::Placeholder(m_context,
Register::Type::Vector,
{DataType::Float, PointerType::PointerGlobal},
1);
auto v_value = Register::Value::Placeholder(
m_context, Register::Type::Vector, DataType::Float, 1);
auto v_target = Register::Value::Placeholder(
m_context, Register::Type::Vector, DataType::Float, 1);
co_yield m_context->copier()->copy(v_ptr, s_ptr, "Move pointer");
co_yield m_context->copier()->copy(v_value, s_value, "Move value");
// v_target is val we check against
co_yield m_context->copier()->copy(
v_target, Register::Value::Literal(check_val), "Move value");
auto loop_start = Register::Value::Label("main_loop_" + std::to_string(n));
co_yield Instruction::Label(loop_start)
.lock(Scheduling::Dependency::Branch, "Loop Start");
Register::ValuePtr s_condition;
s_condition = m_context->getVCC();
// Double the input value.
co_yield Expression::generate(
v_value, v_value->expression() + v_value->expression(), m_context);
co_yield Instruction::Lock(Scheduling::Dependency::VCC);
// Compare against the stop value.
co_yield Expression::generate(
s_condition, v_value->expression() < v_target->expression(), m_context);
co_yield m_context->brancher()->branchIfNonZero(
loop_start, s_condition, "// Conditionally branching to the label register.");
co_yield Instruction::Unlock("unlock VCC");
co_yield Instruction::Unlock("Loop end");
co_yield m_context->mem()->storeGlobal(v_ptr, v_value, 0, 4);
};
auto comment_generator = [&](int max_comments) -> Generator<Instruction> {
int i = 0;
while(i < max_comments)
{
co_yield Instruction::Comment("Comment " + std::to_string(i++));
}
};
sequences.push_back(double_and_check(1000.f, 2));
sequences.push_back(double_and_check(100.f, 1));
sequences.push_back(comment_generator(5));
std::shared_ptr<Scheduling::Scheduler> scheduler = Component::GetNew<Scheduling::Scheduler>(
procedure, Scheduling::CostFunction::MinNops, m_context);
m_context->schedule((*scheduler)(sequences));
m_context->schedule(k->postamble());
m_context->schedule(k->amdgpu_metadata());
CommandKernel commandKernel;
commandKernel.setContext(m_context);
commandKernel.generateKernel();
auto ptr = make_shared_device<float>();
float val = 6.0f;
unsigned int size = 1;
auto ptr2 = make_shared_device<float>();
float val2 = 3.0f;
unsigned int size2 = 1;
ASSERT_THAT(hipMemset(ptr.get(), 0, sizeof(float)), HasHipSuccess(0));
ASSERT_THAT(hipMemset(ptr2.get(), 0, sizeof(float)), HasHipSuccess(0));
CommandArguments commandArgs = command->createArguments();
commandArgs.setArgument(ptrTag, ArgumentType::Value, ptr.get());
commandArgs.setArgument(valTag, ArgumentType::Value, val);
commandArgs.setArgument(sizeTag, ArgumentType::Size, size);
commandArgs.setArgument(ptr2Tag, ArgumentType::Value, ptr2.get());
commandArgs.setArgument(val2Tag, ArgumentType::Value, val2);
commandArgs.setArgument(size2Tag, ArgumentType::Size, size2);
commandKernel.launchKernel(commandArgs.runtimeArguments());
float resultValue1 = 0.0f;
float resultValue2 = 0.0f;
ASSERT_THAT(hipMemcpy(&resultValue1, ptr.get(), sizeof(float), hipMemcpyDefault),
HasHipSuccess(0));
ASSERT_THAT(hipMemcpy(&resultValue2, ptr2.get(), sizeof(float), hipMemcpyDefault),
HasHipSuccess(0));
EXPECT_GT(resultValue1, 100.0f);
EXPECT_GT(resultValue2, 1000.0f);
}
/**
* scalar_overflow lambda will set scc to true with a scalar addition overflow.
* scalar_compare will set scc to false with a comparison of two values.
* scalar_overflow will check if we overflow and set the result accordingly.
* However, scalar_compare will overwrite scc before the branch checks scc.
**/
TEST_P(DependencyTest, GPU_SCC)
{
ASSERT_EQ(true, isLocalDevice());
auto command = std::make_shared<Command>();
VariableType intPtr{DataType::Int32, PointerType::PointerGlobal};
VariableType intVal{DataType::Int32, PointerType::Value};
VariableType uintVal{DataType::UInt32, PointerType::Value};
auto ptrTag = command->allocateTag();
auto ptr_arg = command->allocateArgument(intPtr, ptrTag, ArgumentType::Value);
auto valTag = command->allocateTag();
auto val_arg = command->allocateArgument(intVal, valTag, ArgumentType::Value);
auto sizeTag = command->allocateTag();
auto size_arg = command->allocateArgument(uintVal, sizeTag, ArgumentType::Size);
auto ptr_exp = std::make_shared<Expression::Expression>(ptr_arg);
auto val_exp = std::make_shared<Expression::Expression>(val_arg);
auto size_exp = std::make_shared<Expression::Expression>(size_arg);
auto one = std::make_shared<Expression::Expression>(1u);
auto zero = std::make_shared<Expression::Expression>(0u);
auto k = m_context->kernel();
k->setKernelDimensions(1);
k->addArgument({"ptr",
{DataType::Int32, PointerType::PointerGlobal},
DataDirection::WriteOnly,
ptr_exp});
k->addArgument({"val", {DataType::Int32}, DataDirection::ReadOnly, val_exp});
k->setWorkgroupSize({1, 1, 1});
k->setWorkitemCount({one, one, one});
k->setDynamicSharedMemBytes(zero);
m_context->schedule(k->preamble());
m_context->schedule(k->prolog());
std::vector<Generator<Instruction>> sequences;
auto r_value
= Register::Value::Placeholder(m_context, Register::Type::Vector, DataType::Int32, 1);
auto r_ptr = Register::Value::Placeholder(
m_context, Register::Type::Vector, {DataType::Int32, PointerType::PointerGlobal}, 1);
auto scalar_overflow = [&]() -> Generator<Instruction> {
Register::ValuePtr s_ptr, s_value;
co_yield m_context->argLoader()->getValue("ptr", s_ptr);
co_yield m_context->argLoader()->getValue("val", s_value);
co_yield m_context->copier()->copy(r_ptr, s_ptr, "Move pointer");
co_yield m_context->copier()->copy(r_value, s_value, "Move value");
auto s_res = Register::Value::Placeholder(
m_context, Register::Type::Scalar, DataType::Int32, 1);
auto s_lhs = Register::Value::Placeholder(
m_context, Register::Type::Scalar, DataType::Int32, 1);
auto s_rhs = Register::Value::Placeholder(
m_context, Register::Type::Scalar, DataType::Int32, 1);
co_yield m_context->copier()->fill(s_lhs, Register::Value::Literal(0x7FEFFFFF));
co_yield m_context->copier()->fill(s_rhs, Register::Value::Literal(0x6DCBFFFF));
co_yield Instruction::Lock(Scheduling::Dependency::SCC);
co_yield generateOp<Expression::Add>(s_res, s_lhs, s_rhs);
auto scc_zero = Register::Value::Label("scc_zero");
auto end = Register::Value::Label("end");
co_yield m_context->brancher()->branchIfNonZero(scc_zero, m_context->getSCC());
co_yield m_context->copier()->copy(r_value, Register::Value::Literal(1729));
co_yield m_context->brancher()->branch(end);
co_yield Instruction::Label(scc_zero);
co_yield m_context->copier()->copy(r_value, Register::Value::Literal(3014));
co_yield Instruction::Label(end).unlock();
co_yield m_context->mem()->storeGlobal(r_ptr, r_value, 0, 4);
};
auto scalar_compare = [&]() -> Generator<Instruction> {
auto s_small = Register::Value::Placeholder(
m_context, Register::Type::Scalar, DataType::Int32, 1);
auto s_big = Register::Value::Placeholder(
m_context, Register::Type::Scalar, DataType::Int32, 1);
auto s_condition = Register::Value::Placeholder(
m_context, Register::Type::Scalar, DataType::Int32, 1);
co_yield m_context->copier()->fill(s_small, Register::Value::Literal(2));
co_yield m_context->copier()->fill(s_big, Register::Value::Literal(5));
co_yield generateOp<Expression::Add>(s_small, s_small, Register::Value::Literal(1));
co_yield generateOp<Expression::Add>(s_big, s_big, Register::Value::Literal(2));
co_yield generateOp<Expression::Multiply>(s_small, s_small, s_small);
co_yield generateOp<Expression::Multiply>(s_big, s_big, s_big);
co_yield Expression::generate(
s_condition, s_small->expression() > s_big->expression(), m_context);
};
sequences.push_back(scalar_overflow());
sequences.push_back(scalar_compare());
std::shared_ptr<Scheduling::Scheduler> scheduler = Component::GetNew<Scheduling::Scheduler>(
procedure, Scheduling::CostFunction::MinNops, m_context);
m_context->schedule((*scheduler)(sequences));
m_context->schedule(k->postamble());
m_context->schedule(k->amdgpu_metadata());
CommandKernel commandKernel;
commandKernel.setContext(m_context);
commandKernel.generateKernel();
auto h_ptr = make_shared_device<int>();
int h_val = 11;
unsigned int h_size = 1;
ASSERT_THAT(hipMemset(h_ptr.get(), 0, sizeof(int)), HasHipSuccess(0));
CommandArguments commandArgs = command->createArguments();
commandArgs.setArgument(ptrTag, ArgumentType::Value, h_ptr.get());
commandArgs.setArgument(valTag, ArgumentType::Value, h_val);
commandArgs.setArgument(sizeTag, ArgumentType::Size, h_size);
commandKernel.launchKernel(commandArgs.runtimeArguments());
int resultValue = 0;
ASSERT_THAT(hipMemcpy(&resultValue, h_ptr.get(), sizeof(int), hipMemcpyDefault),
HasHipSuccess(0));
EXPECT_EQ(resultValue, 3014);
}
TEST_P(DependencyTest, GPU_VCCCarry)
{
auto k = m_context->kernel();
k->setKernelDimensions(1);
auto command = std::make_shared<Command>();
VariableType Int64Value(DataType::Int64, PointerType::Value);
VariableType UInt64Value(DataType::UInt64, PointerType::Value);
VariableType Int64Pointer(DataType::Int64, PointerType::PointerGlobal);
auto resultTag = command->allocateTag();
auto result_exp
= command->allocateArgument(Int64Pointer, resultTag, ArgumentType::Value)->expression();
auto aTag = command->allocateTag();
auto a_exp = command->allocateArgument(Int64Value, aTag, ArgumentType::Value)->expression();
auto bTag = command->allocateTag();
auto b_exp = command->allocateArgument(Int64Value, bTag, ArgumentType::Value)->expression();
auto one = std::make_shared<Expression::Expression>(1u);
auto zero = std::make_shared<Expression::Expression>(0u);
k->addArgument({"result", Int64Pointer, DataDirection::WriteOnly, result_exp});
k->addArgument({"a", DataType::Int64, DataDirection::ReadOnly, a_exp});
k->addArgument({"b", DataType::Int64, DataDirection::ReadOnly, b_exp});
k->setWorkgroupSize({1, 1, 1});
k->setWorkitemCount({one, one, one});
k->setDynamicSharedMemBytes(zero);
m_context->schedule(k->preamble());
m_context->schedule(k->prolog());
Register::ValuePtr s_result, s_a, s_b;
auto v_result = Register::Value::Placeholder(
m_context, Register::Type::Vector, {DataType::Int64, PointerType::PointerGlobal}, 1);
auto v_a
= Register::Value::Placeholder(m_context, Register::Type::Vector, DataType::Int64, 1);
auto v_b
= Register::Value::Placeholder(m_context, Register::Type::Vector, DataType::Int64, 1);
auto v_c
= Register::Value::Placeholder(m_context, Register::Type::Vector, DataType::Int64, 1);
auto setup = [&]() -> Generator<Instruction> {
co_yield m_context->argLoader()->getValue("result", s_result);
co_yield m_context->argLoader()->getValue("a", s_a);
co_yield m_context->argLoader()->getValue("b", s_b);
co_yield m_context->copier()->copy(v_result, s_result, "Move pointer");
co_yield m_context->copier()->copy(v_a, s_a, "Move value");
co_yield m_context->copier()->copy(v_b, s_b, "Move value");
};
auto int64_addc = [&]() -> Generator<Instruction> {
co_yield generateOp<Expression::Add>(v_c, v_a, v_b);
co_yield m_context->mem()->storeGlobal(v_result, v_c, 0, 8);
};
// With consume comments, padding comments no longer needed to interleave VCC overwrite
auto set_vcc_to_zero = [&]() -> Generator<Instruction> {
Register::ValuePtr vcc;
vcc = m_context->getVCC();
co_yield Instruction::Comment("Padding Comment");
co_yield Instruction::Comment("Padding Comment");
co_yield Expression::generate(vcc, v_b->expression() > v_a->expression(), m_context);
};
m_context->schedule(setup());
std::vector<Generator<Instruction>> sequences;
sequences.push_back(int64_addc());
sequences.push_back(set_vcc_to_zero());
std::shared_ptr<Scheduling::Scheduler> scheduler = Component::GetNew<Scheduling::Scheduler>(
procedure, Scheduling::CostFunction::MinNops, m_context);
m_context->schedule((*scheduler)(sequences));
m_context->schedule(k->postamble());
m_context->schedule(k->amdgpu_metadata());
int64_t result = 0;
auto d_result = make_shared_device<int64_t>();
CommandKernel commandKernel;
commandKernel.setContext(m_context);
commandKernel.generateKernel();
CommandArguments commandArgs = command->createArguments();
commandArgs.setArgument(resultTag, ArgumentType::Value, d_result.get());
commandArgs.setArgument(aTag, ArgumentType::Value, 0x11111111FFFFFFFF);
commandArgs.setArgument(bTag, ArgumentType::Value, 0x1111111111111111);
commandKernel.launchKernel(commandArgs.runtimeArguments());
ASSERT_THAT(hipMemcpy(&result, d_result.get(), sizeof(int64_t), hipMemcpyDefault),
HasHipSuccess(0));
// 0x2222222211111110 (when carry overwritten), (correct) 0x2222222311111110 = 2459565876208275728
EXPECT_EQ(result, 2459565880503243024);
}
/**
* VCC test that interleaves two streams that both set vcc to different values.
* Output of the kernel is dependent on vcc value.
**/
TEST_P(DependencyTest, GPU_VCC)
{
ASSERT_EQ(true, isLocalDevice());
auto command = std::make_shared<Command>();
VariableType intPtr{DataType::Int32, PointerType::PointerGlobal};
VariableType intVal{DataType::Int32, PointerType::Value};
VariableType uintVal{DataType::UInt32, PointerType::Value};
auto ptrTag = command->allocateTag();
auto ptr_arg = command->allocateArgument(intPtr, ptrTag, ArgumentType::Value);
auto valTag = command->allocateTag();
auto val_arg = command->allocateArgument(intVal, valTag, ArgumentType::Value);
auto sizeTag = command->allocateTag();
auto size_arg = command->allocateArgument(uintVal, sizeTag, ArgumentType::Size);
auto ptr_exp = std::make_shared<Expression::Expression>(ptr_arg);
auto val_exp = std::make_shared<Expression::Expression>(val_arg);
auto size_exp = std::make_shared<Expression::Expression>(size_arg);
auto one = std::make_shared<Expression::Expression>(1u);
auto zero = std::make_shared<Expression::Expression>(0u);
auto k = m_context->kernel();
k->setKernelDimensions(1);
k->addArgument({"ptr",
{DataType::Int32, PointerType::PointerGlobal},
DataDirection::WriteOnly,
ptr_exp});
k->addArgument({"val", {DataType::Int32}, DataDirection::ReadOnly, val_exp});
k->setWorkgroupSize({1, 1, 1});
k->setWorkitemCount({one, one, one});
k->setDynamicSharedMemBytes(zero);
m_context->schedule(k->preamble());
m_context->schedule(k->prolog());
std::vector<Generator<Instruction>> sequences;
auto v_value
= Register::Value::Placeholder(m_context, Register::Type::Vector, DataType::Int32, 1);
auto v_ptr = Register::Value::Placeholder(
m_context, Register::Type::Vector, {DataType::Int32, PointerType::PointerGlobal}, 1);
auto set_vcc = [&]() -> Generator<Instruction> {
Register::ValuePtr s_ptr, s_value;
co_yield m_context->argLoader()->getValue("ptr", s_ptr);
co_yield m_context->argLoader()->getValue("val", s_value);
auto v_lhs = Register::Value::Placeholder(
m_context, Register::Type::Vector, DataType::Int32, 1);
auto v_rhs = Register::Value::Placeholder(
m_context, Register::Type::Vector, DataType::Int32, 1);
auto v_res = Register::Value::Placeholder(
m_context, Register::Type::Vector, DataType::Int32, 1);
co_yield m_context->copier()->copy(v_ptr, s_ptr, "Move pointer");
co_yield m_context->copier()->copy(v_value, s_value, "Move value");
co_yield m_context->copier()->fill(v_lhs, Register::Value::Literal(2));
co_yield m_context->copier()->fill(v_rhs, Register::Value::Literal(4));
Register::ValuePtr vcc;
vcc = m_context->getVCC();
co_yield Instruction::Lock(Scheduling::Dependency::VCC);
co_yield Expression::generate(
vcc, v_rhs->expression() > v_lhs->expression(), m_context);
co_yield Expression::generate(
v_res, v_lhs->expression() - v_rhs->expression(), m_context);
co_yield Expression::generate(
v_res, v_rhs->expression() * v_rhs->expression(), m_context);
co_yield Expression::generate(
v_res, v_res->expression() + v_lhs->expression(), m_context);
co_yield Expression::generate(
v_res, v_res->expression() * v_res->expression(), m_context);
auto label = Register::Value::Label("label");
auto end = Register::Value::Label("end");
co_yield m_context->brancher()->branchIfNonZero(label, vcc);
co_yield m_context->copier()->copy(v_value, Register::Value::Literal(20));
co_yield m_context->brancher()->branch(end);
co_yield Instruction::Label(label);
co_yield m_context->copier()->copy(v_value, Register::Value::Literal(10));
co_yield Instruction::Label(end);
co_yield Instruction::Unlock("unlock VCC");
co_yield m_context->mem()->storeGlobal(v_ptr, v_value, 0, 4);
};
auto set_vcc2 = [&]() -> Generator<Instruction> {
Register::ValuePtr s_ptr, s_value;
co_yield m_context->argLoader()->getValue("ptr", s_ptr);
co_yield m_context->argLoader()->getValue("val", s_value);
auto v_lhs2 = Register::Value::Placeholder(
m_context, Register::Type::Vector, DataType::Int32, 1);
auto v_rhs2 = Register::Value::Placeholder(
m_context, Register::Type::Vector, DataType::Int32, 1);
auto v_res2 = Register::Value::Placeholder(
m_context, Register::Type::Vector, DataType::Int32, 1);
co_yield m_context->copier()->fill(v_lhs2, Register::Value::Literal(2));
co_yield m_context->copier()->fill(v_rhs2, Register::Value::Literal(8));
Register::ValuePtr vcc;
vcc = m_context->getVCC();
co_yield Expression::generate(
v_res2, v_rhs2->expression() + v_lhs2->expression(), m_context);
co_yield Expression::generate(
v_res2, v_res2->expression() * v_lhs2->expression(), m_context);
co_yield Expression::generate(
v_res2, v_res2->expression() * v_res2->expression(), m_context);
co_yield Instruction::Lock(Scheduling::Dependency::VCC);
co_yield Expression::generate(
vcc, v_lhs2->expression() == v_rhs2->expression(), m_context);
co_yield Instruction::Unlock("unlock VCC");
};
sequences.push_back(set_vcc());
sequences.push_back(set_vcc2());
std::shared_ptr<Scheduling::Scheduler> scheduler = Component::GetNew<Scheduling::Scheduler>(
procedure, Scheduling::CostFunction::MinNops, m_context);
m_context->schedule((*scheduler)(sequences));
m_context->schedule(k->postamble());
m_context->schedule(k->amdgpu_metadata());
CommandKernel commandKernel;
commandKernel.setContext(m_context);
commandKernel.generateKernel();
auto h_ptr = make_shared_device<int>();
int h_val = 11;
unsigned int h_size = 1;
ASSERT_THAT(hipMemset(h_ptr.get(), 0, sizeof(int)), HasHipSuccess(0));
CommandArguments commandArgs = command->createArguments();
commandArgs.setArgument(ptrTag, ArgumentType::Value, h_ptr.get());
commandArgs.setArgument(valTag, ArgumentType::Value, h_val);
commandArgs.setArgument(sizeTag, ArgumentType::Size, h_size);
commandKernel.launchKernel(commandArgs.runtimeArguments());
int resultValue = 0;
ASSERT_THAT(hipMemcpy(&resultValue, h_ptr.get(), sizeof(int), hipMemcpyDefault),
HasHipSuccess(0));
EXPECT_EQ(resultValue, 10);
}
INSTANTIATE_TEST_SUITE_P(
DependencyTest,
DependencyTest,
::testing::ValuesIn({std::make_tuple(Scheduling::SchedulerProcedure::Sequential, 0),
std::make_tuple(Scheduling::SchedulerProcedure::RoundRobin, 0),
std::make_tuple(Scheduling::SchedulerProcedure::Random, 0),
std::make_tuple(Scheduling::SchedulerProcedure::Random, 5),
std::make_tuple(Scheduling::SchedulerProcedure::Random, 18),
std::make_tuple(Scheduling::SchedulerProcedure::Random, 21),
std::make_tuple(Scheduling::SchedulerProcedure::Random, 34),
std::make_tuple(Scheduling::SchedulerProcedure::Random, 48),
std::make_tuple(Scheduling::SchedulerProcedure::Random, 49),
std::make_tuple(Scheduling::SchedulerProcedure::Random, 52),
std::make_tuple(Scheduling::SchedulerProcedure::Random, 63),
std::make_tuple(Scheduling::SchedulerProcedure::Random, 73),
std::make_tuple(Scheduling::SchedulerProcedure::Random, 89),
std::make_tuple(Scheduling::SchedulerProcedure::Random, 90),
std::make_tuple(Scheduling::SchedulerProcedure::Random, 96),
std::make_tuple(Scheduling::SchedulerProcedure::Random, 97),
std::make_tuple(Scheduling::SchedulerProcedure::Random, 98)}));
}