use tpt_gpu_ir_spec::{
text::{emit, EmitOptions, Instruction, Region},
types::{AddressSpace, ElemType, Type},
Op,
};
pub fn lower_topk(n: u64) -> Region {
let f32_ty = Type::scalar(ElemType::F32);
let mem = Type::memref(vec![n as i64], f32_ty.clone(), AddressSpace::Global);
let tensor = Type::tensor(vec![n as i64], f32_ty.clone(), AddressSpace::Global);
Region {
name: "vector_topk".to_string(),
args: vec![("embeddings".to_string(), mem)],
return_types: vec![f32_ty],
blocks: vec![tpt_gpu_ir_spec::text::Block {
label: "entry".to_string(),
instructions: vec![
Instruction {
result: Some("sim".to_string()),
op: Op::Load,
operands: vec!["embeddings".to_string()],
attrs: vec![],
result_type: Some(tensor),
},
Instruction {
result: Some("best".to_string()),
op: Op::ReduceMax,
operands: vec!["sim".to_string()],
attrs: vec![],
result_type: Some(Type::scalar(ElemType::F32)),
},
Instruction {
result: None,
op: Op::Return,
operands: vec!["best".to_string()],
attrs: vec![],
result_type: None,
},
],
}],
}
}
pub fn emit_topk(n: u64) -> String {
emit(&lower_topk(n), &EmitOptions::default())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn lowers_to_tptir_with_expected_ops() {
let text = emit_topk(1024);
assert!(text.contains("func @vector_topk"));
assert!(text.contains("^entry:"));
assert!(text.contains("load"));
assert!(text.contains("reduce_max"));
assert!(text.contains("return"));
}
}