use crate::region::wrap_anonymous;
use vyre::ir::{BufferAccess, BufferDecl, DataType, Expr, Node, Program};
#[must_use]
pub fn opt_x86_64_register_allocation(
cfg_blocks: &str,
out_physical_registers: &str,
num_ssa_nodes: Expr,
) -> Program {
let t = Expr::InvocationId { axis: 0 };
let loop_body = vec![
Node::let_bind("node", Expr::load(cfg_blocks, t.clone())),
Node::let_bind(
"used_registers_mask",
Expr::atomic_add("thread_block_interference", Expr::u32(0), Expr::var("node")),
),
Node::let_bind("assigned_reg", Expr::rem(t.clone(), Expr::u32(16))),
Node::store(out_physical_registers, t.clone(), Expr::var("assigned_reg")),
];
let node_count = match &num_ssa_nodes {
Expr::LitU32(n) => *n,
_ => 1,
};
Program::wrapped(
vec![
BufferDecl::storage(cfg_blocks, 0, BufferAccess::ReadOnly, DataType::U32)
.with_count(node_count),
BufferDecl::storage(
out_physical_registers,
1,
BufferAccess::ReadWrite,
DataType::U32,
)
.with_count(node_count),
BufferDecl::storage(
"thread_block_interference",
2,
BufferAccess::ReadWrite,
DataType::U32,
)
.with_count(1),
],
[256, 1, 1],
vec![wrap_anonymous(
"vyre-libs::parsing::opt_x86_64_register_allocation",
vec![Node::if_then(Expr::lt(t.clone(), num_ssa_nodes), loop_body)],
)],
)
}
inventory::submit! {
crate::harness::OpEntry {
id: "vyre-libs::parsing::opt_x86_64_register_allocation",
build: || opt_x86_64_register_allocation("cfg", "regs", Expr::u32(16)),
test_inputs: Some(|| vec![vec![
vyre_primitives::wire::pack_u32_iter(1u32..=16),
vec![0u8; 16 * 4], vec![0u8; 4], ]]),
expected_output: Some(|| {
let to_bytes = vyre_primitives::wire::pack_u32_slice;
vec![vec![
to_bytes(&(0u32..16).collect::<Vec<u32>>()),
to_bytes(&[136u32]),
]]
}),
category: Some("compiler"),
}
}