use cutile::prelude::*;
use cutile_compiler::compiler::utils::CompileOptions;
mod common;
#[cutile::module]
mod load_like_module {
use cutile::core::*;
#[cutile::entry()]
fn add_free_fn<const S: [i32; 1]>(
z: &mut Tensor<f32, S>,
x: &Tensor<f32, { [-1] }>,
y: &Tensor<f32, { [-1] }>,
) {
let tx = load_tile_like(x, z);
let ty = load_tile_like(y, z);
z.store(tx + ty);
}
#[cutile::entry()]
fn add_method<const S: [i32; 1]>(
z: &mut Tensor<f32, S>,
x: &Tensor<f32, { [-1] }>,
y: &Tensor<f32, { [-1] }>,
) {
let tx = x.load_like(z);
let ty = y.load_like(z);
z.store(tx + ty);
}
}
use load_like_module::__module_ast_self as load_like_module_ast;
use load_like_module::add_method;
fn compile(name: &str) -> String {
common::compile_to_ir(
load_like_module_ast,
"load_like_module",
name,
&["4".to_string()],
&[("z", &[1]), ("x", &[1]), ("y", &[1])],
&[],
&[],
None,
&CompileOptions::default(),
)
.expect("Failed to compile.")
}
fn live_ops(module: &str) -> Vec<String> {
module
.lines()
.map(str::trim)
.filter(|line| !line.is_empty())
.filter(|line| !line.contains("= constant "))
.map(|line| {
let mut out = String::new();
let mut chars = line.chars().peekable();
while let Some(c) = chars.next() {
if c == '%' {
while chars.peek().is_some_and(|d| d.is_ascii_digit()) {
chars.next();
}
out.push('%');
} else {
out.push(c);
}
}
out
})
.collect()
}
#[test]
fn both_spellings_lower_to_the_same_live_ops() {
common::with_test_stack(|| {
let free_fn = compile("add_free_fn").replace("add_free_fn", "K");
let method = compile("add_method").replace("add_method", "K");
assert_eq!(
live_ops(&free_fn),
live_ops(&method),
"load_like must lower to the same live ops as load_tile_like"
);
assert_eq!(
free_fn.matches("assert").count(),
method.matches("assert").count()
);
});
}
#[test]
fn method_form_runs_end_to_end() {
common::with_test_stack(|| {
let len = 32usize;
let z_host = add_method(
api::zeros(&[len]).partition([4]),
api::arange::<f32>(len),
api::ones(&[len]),
)
.grid(((len / 4) as u32, 1, 1))
.first()
.unpartition()
.to_host_vec()
.sync()
.expect("add_method kernel");
for (i, v) in z_host.iter().enumerate() {
assert_eq!(*v, i as f32 + 1.0, "index {i}");
}
});
}