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
186 lines
7.6 KiB
C++
186 lines
7.6 KiB
C++
// Copyright Advanced Micro Devices, Inc., or its affiliates.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
#include <catch2/catch_test_macros.hpp>
|
|
#include <catch2/generators/catch_generators.hpp>
|
|
|
|
#include <common/SourceMatcher.hpp>
|
|
|
|
#include "CustomSections.hpp"
|
|
#include "TestContext.hpp"
|
|
|
|
#include <rocRoller/CodeGen/BranchGenerator.hpp>
|
|
#include <rocRoller/InstructionValues/LabelAllocator.hpp>
|
|
#include <rocRoller/Scheduling/Scheduler.hpp>
|
|
|
|
using namespace rocRoller;
|
|
|
|
namespace BranchGeneratorTest
|
|
{
|
|
TEST_CASE("fail to generate invalid branches", "[branches][codegen]")
|
|
{
|
|
auto ctx = TestContext::ForDefaultTarget().get();
|
|
auto brancher = BranchGenerator(ctx);
|
|
|
|
auto l0 = Register::Value::Label("l0");
|
|
auto s0 = Register::Value::Placeholder(ctx, Register::Type::Scalar, DataType::UInt32, 1);
|
|
s0->allocateNow();
|
|
|
|
CHECK_THROWS_AS(ctx->schedule(brancher.branch(s0)), FatalError);
|
|
CHECK_THROWS_AS(ctx->schedule(brancher.branchConditional(s0, s0, true)), FatalError);
|
|
}
|
|
|
|
TEST_CASE("basic branch code generation", "[branches][codegen]")
|
|
{
|
|
SUPPORTED_ARCH_SECTION(arch)
|
|
{
|
|
auto ctx = TestContext::ForTarget(arch).get();
|
|
auto k = ctx->kernel();
|
|
|
|
ctx->schedule(k->preamble());
|
|
ctx->schedule(k->prolog());
|
|
|
|
auto kb = [&]() -> Generator<Instruction> {
|
|
auto l0 = ctx->labelAllocator()->label("l0");
|
|
co_yield Instruction::Label(l0);
|
|
|
|
auto wavefront_size = k->wavefront_size();
|
|
|
|
auto scc = ctx->getSCC();
|
|
auto vcc = ctx->getVCC();
|
|
|
|
auto s0
|
|
= Register::Value::Placeholder(ctx,
|
|
Register::Type::Scalar,
|
|
DataType::UInt32,
|
|
wavefront_size / 32,
|
|
Register::AllocationOptions::FullyContiguous());
|
|
co_yield s0->allocate();
|
|
|
|
co_yield ctx->brancher()->branch(l0);
|
|
|
|
co_yield ctx->brancher()->branchConditional(l0, s0, true);
|
|
co_yield ctx->brancher()->branchConditional(l0, s0, false);
|
|
co_yield ctx->brancher()->branchIfZero(l0, s0);
|
|
co_yield ctx->brancher()->branchIfNonZero(l0, s0);
|
|
|
|
co_yield ctx->brancher()->branchConditional(l0, scc, true);
|
|
co_yield ctx->brancher()->branchConditional(l0, scc, false);
|
|
co_yield ctx->brancher()->branchIfZero(l0, scc);
|
|
co_yield ctx->brancher()->branchIfNonZero(l0, scc);
|
|
|
|
co_yield ctx->brancher()->branchConditional(l0, vcc, true);
|
|
co_yield ctx->brancher()->branchConditional(l0, vcc, false);
|
|
co_yield ctx->brancher()->branchIfZero(l0, vcc);
|
|
co_yield ctx->brancher()->branchIfNonZero(l0, vcc);
|
|
};
|
|
|
|
ctx->schedule(kb());
|
|
ctx->schedule(k->postamble());
|
|
ctx->schedule(k->amdgpu_metadata());
|
|
|
|
std::vector<char> assembledKernel = ctx->instructions()->assemble();
|
|
CHECK(assembledKernel.size() > 0);
|
|
}
|
|
}
|
|
|
|
TEST_CASE("expect waits before branch if alwaysWaitBeforeBranch is true", "[branches][codegen]")
|
|
{
|
|
SUPPORTED_ARCH_SECTION(arch)
|
|
{
|
|
auto testCtx = TestContext::ForTarget(arch, {{.alwaysWaitBeforeBranch = true}});
|
|
auto ctx = testCtx.get();
|
|
auto k = ctx->kernel();
|
|
|
|
ctx->schedule(k->preamble());
|
|
ctx->schedule(k->prolog());
|
|
|
|
auto kb = [&]() -> Generator<Instruction> {
|
|
auto l0 = ctx->labelAllocator()->label("l0");
|
|
co_yield Instruction::Lock(Scheduling::Dependency::Branch);
|
|
co_yield Instruction::Label(l0);
|
|
co_yield ctx->brancher()->branch(l0);
|
|
co_yield Instruction::Unlock();
|
|
};
|
|
|
|
auto const& arch = ctx->targetArchitecture();
|
|
std::string expected = std::string("s_waitcnt vmcnt(0) lgkmcnt(0)");
|
|
if(arch.HasCapability(GPUCapability::HasExpcnt))
|
|
{
|
|
expected += std::string(" expcnt(0)");
|
|
}
|
|
expected += std::string("\n") + std::string("s_branch");
|
|
if(arch.HasCapability(GPUCapability::HasSplitWaitCounters))
|
|
{
|
|
expected = std::string("s_wait_loadcnt 0\ns_wait_storecnt 0\ns_wait_kmcnt "
|
|
"0\ns_wait_dscnt 0");
|
|
if(arch.HasCapability(GPUCapability::HasExpcnt))
|
|
{
|
|
expected += std::string("\ns_wait_expcnt 0");
|
|
}
|
|
if(arch.HasCapability(GPUCapability::HasTensorcnt))
|
|
{
|
|
expected += std::string("\ns_wait_tensorcnt 0");
|
|
}
|
|
if(arch.HasCapability(GPUCapability::HasVGPRIndexing))
|
|
{
|
|
expected += std::string("\ns_set_vgpr_msb 0");
|
|
}
|
|
expected += std::string("\n") + std::string("s_branch");
|
|
}
|
|
|
|
auto scheduler = Component::GetNew<Scheduling::Scheduler>(
|
|
Scheduling::SchedulerProcedure::Sequential, Scheduling::CostFunction::None, ctx);
|
|
std::vector<Generator<Instruction>> generators;
|
|
generators.push_back(kb());
|
|
ctx->schedule((*scheduler)(generators));
|
|
CHECK(NormalizedSource(testCtx.output()).find(expected) != std::string::npos);
|
|
}
|
|
}
|
|
|
|
TEST_CASE("DO NOT wait before branch if alwaysWaitBeforeBranch is false", "[branches][codegen]")
|
|
{
|
|
SUPPORTED_ARCH_SECTION(arch)
|
|
{
|
|
auto testCtx = TestContext::ForTarget(arch, {{.alwaysWaitBeforeBranch = false}});
|
|
auto ctx = testCtx.get();
|
|
auto k = ctx->kernel();
|
|
|
|
ctx->schedule(k->preamble());
|
|
ctx->schedule(k->prolog());
|
|
auto kb = [&]() -> Generator<Instruction> {
|
|
auto l0 = ctx->labelAllocator()->label("l0");
|
|
co_yield Instruction::Lock(Scheduling::Dependency::Branch);
|
|
co_yield Instruction::Label(l0);
|
|
co_yield ctx->brancher()->branch(l0);
|
|
co_yield Instruction::Unlock();
|
|
};
|
|
|
|
auto const& arch = ctx->targetArchitecture();
|
|
std::string expected = std::string("s_waitcnt vmcnt(0) lgkmcnt(0) expcnt(0)");
|
|
if(arch.HasCapability(GPUCapability::HasExpcnt))
|
|
{
|
|
expected += std::string(" expcnt(0)");
|
|
}
|
|
expected += std::string("\n") + std::string("s_branch");
|
|
if(arch.HasCapability(GPUCapability::HasSplitWaitCounters))
|
|
{
|
|
expected = std::string("s_wait_loadcnt 0\ns_wait_storecnt 0\ns_wait_kmcnt "
|
|
"0\ns_wait_dscnt 0\ns_wait_expcnt 0");
|
|
if(arch.HasCapability(GPUCapability::HasExpcnt))
|
|
{
|
|
expected += std::string("s_wait_expcnt 0");
|
|
}
|
|
expected += std::string("\n") + std::string("s_branch");
|
|
}
|
|
|
|
auto scheduler = Component::GetNew<Scheduling::Scheduler>(
|
|
Scheduling::SchedulerProcedure::Sequential, Scheduling::CostFunction::None, ctx);
|
|
std::vector<Generator<Instruction>> generators;
|
|
generators.push_back(kb());
|
|
ctx->schedule((*scheduler)(generators));
|
|
CHECK_FALSE(NormalizedSource(testCtx.output()).find(expected) != std::string::npos);
|
|
}
|
|
}
|
|
}
|