use crate::fkc::ImportWarning;
use crate::fkc::error::FkcError;
use crate::fkc::lower::lower_dtype;
use crate::fkc::schema::FkcKernel;
use crate::fkc::shape_constraint::solve_probe_shapes;
use fuel_graph::registry::{FusedOpId, FusedOpParams, default_registry};
use fuel_ir::{DType, Shape};
pub type ProbeComboRef<'a> = &'a [(String, Shape, DType)];
fn role<'a>(combo: ProbeComboRef<'a>, name: &str) -> Option<&'a (String, Shape, DType)> {
combo.iter().find(|(r, _, _)| r == name)
}
fn inner<'a>(rule: &'a str, head: &str) -> Option<&'a str> {
rule.trim()
.strip_prefix(head)?
.strip_suffix(')')
.map(str::trim)
}
pub fn eval_dtype_rule(
rule: &str,
combo: ProbeComboRef,
section: &str,
) -> Result<Option<DType>, FkcError> {
if let Some(tok) = inner(rule, "fixed(") {
return Ok(Some(lower_dtype(tok, section, "return")?));
}
if let Some(r) = inner(rule, "passthrough(") {
return Ok(role(combo, r).map(|(_, _, d)| *d));
}
Ok(None)
}
pub fn eval_shape_rule(
rule: &str,
combo: ProbeComboRef,
params: &[i64],
_section: &str,
) -> Result<Option<Shape>, FkcError> {
let rule = rule.trim();
if let Some(r) = inner(rule, "same_as(") {
return Ok(role(combo, r).map(|(_, s, _)| s.clone()));
}
if rule.starts_with("matmul(") {
let Some((lhs, rhs)) = crate::fkc::shape_expr_parse::parse_matmul_operands(rule, combo)
else {
return Ok(None);
};
if lhs.len() < 2
|| rhs.len() < 2
|| lhs.len() != rhs.len()
|| lhs.iter().chain(rhs.iter()).any(|&d| d < 0)
{
return Ok(None);
}
let out = crate::fkc::shape_expr::matmul_shape(&lhs, &rhs);
let dims: Vec<usize> = out.iter().map(|&d| d as usize).collect();
return Ok(Some(Shape::from_dims(&dims)));
}
if is_dimexpr_head(rule) {
let Some(dim) = crate::fkc::shape_expr_parse::parse_dim(rule, combo) else {
return Ok(None);
};
let operands: Vec<Vec<i64>> = combo.iter().map(|(_, s, _)| shape_to_i64(s)).collect();
return match crate::fkc::shape_expr::eval_dim(&dim, &operands, params) {
Ok(crate::fkc::shape_expr::DimValue::Concrete(d)) if d >= 0 => {
Ok(Some(Shape::from_dims(&[d as usize])))
}
Ok(_) | Err(_) => Ok(None),
};
}
Ok(None)
}
fn guard_rule<T>(
warnings: &mut Vec<ImportWarning>,
section: &str,
what: &str,
f: impl FnOnce() -> T,
) -> Option<T> {
match std::panic::catch_unwind(std::panic::AssertUnwindSafe(f)) {
Ok(v) => Some(v),
Err(_) => {
warnings.push(ImportWarning {
section: section.into(),
message: format!(
"return cross-check: the registered {what} fn panicked on the probe combo \
(likely an input-arity mismatch); differential skipped for this combo \
(never-panic backstop — see the debug-vs-release note on guard_rule)"
),
});
None
}
}
}
fn expected_min_inputs(variant: Option<&str>) -> Option<usize> {
match variant {
Some("FlashAttn") | Some("FlashAttnBackward") => Some(4),
Some("PagedAttn") => Some(5),
Some("Conv2D") => Some(2),
_ => None,
}
}
fn distinct_role_probe(combo: ProbeComboRef) -> Vec<(String, Shape, DType)> {
combo
.iter()
.enumerate()
.map(|(i, (role, shape, dt))| {
let mut dims: Vec<usize> = shape.dims().to_vec();
if let Some(d0) = dims.first_mut() {
*d0 += i; }
(role.clone(), Shape::from_dims(&dims), *dt)
})
.collect()
}
fn is_params_dependent_synth_variant(variant: Option<&str>) -> bool {
matches!(
variant,
Some(
"Conv2D" | "ConvTranspose2D" | "QMatMul" | "FusedSoftmaxCrossEntropy" | "CausalConv1d"
)
)
}
fn is_dimexpr_head(rule: &str) -> bool {
const HEADS: &[&str] = &[
"extent(", "const(", "param(", "add(", "sub(", "mul(", "div(",
];
HEADS.iter().any(|h| rule.starts_with(h))
}
fn shape_to_i64(s: &Shape) -> Vec<i64> {
s.dims().iter().map(|&d| d as i64).collect()
}
pub fn synth_probe_params(variant: Option<&str>) -> Result<Option<FusedOpParams>, FkcError> {
const EPS: f64 = 1e-5;
Ok(match variant {
Some("SoftmaxLastDim") => Some(FusedOpParams::SoftmaxLastDim),
Some("SoftmaxLastDimBackward") => Some(FusedOpParams::SoftmaxLastDimBackward),
Some("RmsNormLastDim") => Some(FusedOpParams::RmsNormLastDim { eps: EPS }),
Some("LayerNormLastDim") => Some(FusedOpParams::LayerNormLastDim { eps: EPS }),
Some("RmsNormLastDimBackward") => Some(FusedOpParams::RmsNormLastDimBackward { eps: EPS }),
Some("LayerNormLastDimBackward") => {
Some(FusedOpParams::LayerNormLastDimBackward { eps: EPS })
}
Some("ReduceMaxToBackward") => Some(FusedOpParams::ReduceMaxToBackward),
Some("PowIBackward") => Some(FusedOpParams::PowIBackward { exp: 2 }),
Some("Rope") => Some(FusedOpParams::Rope),
Some("FusedLinear") => Some(FusedOpParams::FusedLinear),
Some("InplaceAffine") => Some(FusedOpParams::InplaceAffine { mul: 1.0, add: 0.0 }),
Some("FlashAttn") => Some(FusedOpParams::FlashAttn {
softmax_scale: 1.0,
causal: false,
window_size_left: None,
window_size_right: None,
softcap: None,
k_len: None,
}),
Some("PagedAttn") => Some(FusedOpParams::PagedAttn {
softmax_scale: 1.0,
block_size: 16,
softcap: None,
}),
Some("FlashAttnBackward") => Some(FusedOpParams::FlashAttnBackward {
softmax_scale: 1.0,
causal: false,
window_size_left: None,
window_size_right: None,
softcap: None,
}),
Some("SelectiveScan") => Some(FusedOpParams::SelectiveScan {
delta_softplus: false,
}),
Some("SsdChunkScan") => Some(FusedOpParams::SsdChunkScan { chunk_size: 1 }),
_ => None,
})
}
pub fn synth_probe_param_points(
variant: Option<&str>,
combo: ProbeComboRef,
) -> Vec<(FusedOpParams, Vec<i64>)> {
use fuel_graph::registry::Reduction;
fn points(params: Vec<FusedOpParams>) -> Vec<(FusedOpParams, Vec<i64>)> {
params
.into_iter()
.map(|p| {
let ints = p.key().ints;
(p, ints)
})
.collect()
}
match variant {
Some("Conv2D") => {
let (Some((_, x, _)), Some((_, w, _))) = (combo.first(), combo.get(1)) else {
return Vec::new();
};
let (xd, wd) = (x.dims(), w.dims());
if xd.len() != 4 || wd.len() != 4 {
return Vec::new();
}
let (h, w_in, kh, kw) = (xd[2], xd[3], wd[2], wd[3]);
if h == 0 || w_in == 0 || kh == 0 || kw == 0 {
return Vec::new();
}
points(vec![
FusedOpParams::Conv2D {
stride: (1, 2),
padding: (kh / 2, kw / 2 + 3),
groups: 1,
},
FusedOpParams::Conv2D {
stride: (3, 4),
padding: (kh / 2 + 5, kw / 2 + 6),
groups: 2,
},
])
}
Some("ConvTranspose2D") => points(vec![
FusedOpParams::ConvTranspose2D {
stride: (2, 3),
padding: (0, 1),
output_padding: (1, 2),
dilation: (4, 5),
groups: 1,
},
FusedOpParams::ConvTranspose2D {
stride: (5, 4),
padding: (3, 2),
output_padding: (4, 0),
dilation: (2, 6),
groups: 3,
},
]),
Some("QMatMul") => {
let (Some((_, a, _)), Some((_, w, _))) = (combo.first(), combo.get(1)) else {
return Vec::new();
};
let (Some(&k), Some(&n)) = (a.dims().last(), w.dims().first()) else {
return Vec::new();
};
points(vec![FusedOpParams::QMatMul {
quant_type: fuel_graph::QuantType::Q4_0,
k,
n,
}])
}
Some("FusedSoftmaxCrossEntropy") => points(vec![
FusedOpParams::FusedSoftmaxCrossEntropy {
reduction: Reduction::None,
ignore_index: -100,
},
FusedOpParams::FusedSoftmaxCrossEntropy {
reduction: Reduction::Mean,
ignore_index: -100,
},
]),
Some("CausalConv1d") => points(vec![
FusedOpParams::CausalConv1d { use_silu: false },
]),
_ => Vec::new(),
}
}
pub fn cross_check_fused_section(
kernel: &FkcKernel,
id: FusedOpId,
warnings: &mut Vec<ImportWarning>,
) -> Result<(), FkcError> {
let section = kernel.kernel.as_str();
let Some(entry) = default_registry().entry(id) else {
return Ok(());
};
let Some(accept) = kernel.accept.as_ref() else {
return Ok(());
};
let Some(ret) = kernel.return_.as_ref() else {
return Ok(());
};
let variant = accept.op_params.as_ref().and_then(|s| s.variant.as_deref());
let combos = match solve_probe_shapes(&accept.inputs, section, warnings) {
Ok(c) => c,
Err(e) => {
warnings.push(ImportWarning {
section: section.into(),
message: format!("return cross-check skipped: {e}"),
});
return Ok(());
}
};
let single = synth_probe_params(variant)?;
let probe_arity = accept.inputs.len();
let arity_ok = match expected_min_inputs(variant) {
Some(min) if probe_arity < min => {
warnings.push(ImportWarning {
section: section.into(),
message: format!(
"return cross-check: fused variant {} declares {probe_arity} input(s) but its \
registered rule fn requires >= {min}; the shape/dtype differential is skipped \
(consistently in debug and release — the fn's arity debug_assert fires only in debug)",
variant.unwrap_or("<unknown>"),
),
});
false
}
_ => true,
};
for combo in &combos {
if !arity_ok {
break;
}
let in_shapes: Vec<Shape> = combo.iter().map(|(_, s, _)| s.clone()).collect();
let in_dtypes: Vec<DType> = combo.iter().map(|(_, _, d)| *d).collect();
let Some(out) = ret.outputs.first() else {
continue;
};
let role_name = out.name.as_deref().unwrap_or("out");
let points: Vec<(FusedOpParams, Vec<i64>)> = match single.as_ref() {
Some(p) => vec![(p.clone(), p.key().ints)],
None => {
let pts = synth_probe_param_points(variant, combo);
if pts.is_empty() && is_params_dependent_synth_variant(variant) {
warnings.push(ImportWarning {
section: section.into(),
message: format!(
"return cross-check: no param point could be synthesized for \
params-dependent variant {} from this probe combo (operand shapes \
unreadable by the shape-coupled derivation); shape/dtype \
differentials skipped for this combo",
variant.unwrap_or("<unknown>"),
),
});
}
pts
}
};
for (p, ints) in &points {
if let Some(rule) = out.dtype_rule.as_deref()
&& let Some(declared) = eval_dtype_rule(rule, combo, section)?
{
let Some(real) = guard_rule(warnings, section, "dtype_rule", || {
(entry.dtype_rule)(&in_dtypes, p)
}) else {
continue;
};
if declared != real {
return Err(FkcError::ShapeRuleMismatch {
section: section.into(),
role: role_name.into(),
expected: format!("dtype {declared:?}"),
actual: format!("dtype {real:?}"),
});
}
}
if let Some(rule) = out.shape_rule.as_deref() {
if let Some(declared) = eval_shape_rule(rule, combo, ints, section)? {
let Some(real) = guard_rule(warnings, section, "shape_rule", || {
(entry.shape_rule)(&in_shapes, p)
}) else {
continue;
};
if declared != real {
return Err(FkcError::ShapeRuleMismatch {
section: section.into(),
role: role_name.into(),
expected: format!("shape {declared:?}"),
actual: format!("shape {real:?}"),
});
}
}
}
}
}
if let (Some(bundle), Some(output_views), Some(p)) =
(ret.bundle.as_ref(), entry.output_views, single.as_ref())
&& let Some(combo) = combos.first()
{
let distinct = distinct_role_probe(combo);
let in_shapes: Vec<Shape> = distinct.iter().map(|(_, s, _)| s.clone()).collect();
let in_dtypes: Vec<DType> = distinct.iter().map(|(_, _, d)| *d).collect();
if let Some(views) = guard_rule(warnings, section, "output_views", || {
output_views(&in_shapes, &in_dtypes, p)
}) {
check_bundle_arity(section, views.len(), bundle)?;
if let serde_yaml_ng::Value::Sequence(slots) = bundle {
for (i, slot) in slots.iter().enumerate() {
let serde_yaml_ng::Value::Mapping(map) = slot else {
continue;
};
let slot_name = map
.get(serde_yaml_ng::Value::String("name".into()))
.and_then(|v| v.as_str())
.map(str::to_string)
.unwrap_or_else(|| format!("slot{i}"));
if let Some(rule) = map
.get(serde_yaml_ng::Value::String("shape_rule".into()))
.and_then(|v| v.as_str())
{
if let Some(shape) =
eval_shape_rule(rule, &distinct, &p.key().ints, section)?
{
check_slot_rank(section, &slot_name, &shape)?;
if let Some(view) = views.get(i)
&& shape != view.shape
{
return Err(FkcError::ShapeRuleMismatch {
section: section.into(),
role: slot_name.clone(),
expected: format!("shape {:?}", view.shape),
actual: format!("shape {shape:?}"),
});
}
}
}
}
}
}
}
Ok(())
}
pub fn check_slot_rank(section: &str, slot: &str, shape: &Shape) -> Result<(), FkcError> {
let rank = shape.rank();
if rank > 6 {
return Err(FkcError::BundleSlotRankExceeded {
section: section.into(),
slot: slot.into(),
rank,
});
}
Ok(())
}
pub fn bundle_slot_names(ret: &Option<crate::fkc::schema::ReturnBlock>) -> Vec<String> {
let Some(ret) = ret.as_ref() else {
return Vec::new();
};
let Some(bundle) = ret.bundle.as_ref() else {
return Vec::new();
};
let serde_yaml_ng::Value::Sequence(slots) = bundle else {
return Vec::new();
};
slots
.iter()
.enumerate()
.map(|(i, slot)| {
let serde_yaml_ng::Value::Mapping(map) = slot else {
return format!("slot{i}");
};
map.get(serde_yaml_ng::Value::String("name".into()))
.and_then(|v| v.as_str())
.map(str::to_string)
.unwrap_or_else(|| format!("slot{i}"))
})
.collect()
}
pub fn bundle_slot_count(bundle: &serde_yaml_ng::Value) -> Option<usize> {
match bundle {
serde_yaml_ng::Value::Sequence(s) => Some(s.len()),
_ => None,
}
}
pub fn check_bundle_arity(
section: &str,
output_views_arity: usize,
bundle: &serde_yaml_ng::Value,
) -> Result<(), FkcError> {
if let Some(declared) = bundle_slot_count(bundle)
&& declared != output_views_arity
{
return Err(FkcError::BundleArityMismatch {
section: section.into(),
expected: output_views_arity,
actual: declared,
});
}
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
use fuel_ir::{DType, Shape};
#[test]
fn synth_probe_params_builds_the_matching_variant_or_none() {
use fuel_graph::registry::FusedOpParams;
assert!(matches!(
synth_probe_params(Some("SoftmaxLastDim")).unwrap(),
Some(FusedOpParams::SoftmaxLastDim)
));
assert!(matches!(
synth_probe_params(Some("RmsNormLastDim")).unwrap(),
Some(FusedOpParams::RmsNormLastDim { .. })
));
assert!(matches!(
synth_probe_params(Some("InplaceAffine")).unwrap(),
Some(FusedOpParams::InplaceAffine { .. })
));
assert!(matches!(
synth_probe_params(Some("FlashAttn")).unwrap(),
Some(FusedOpParams::FlashAttn { .. })
));
assert!(matches!(
synth_probe_params(Some("PagedAttn")).unwrap(),
Some(FusedOpParams::PagedAttn { .. })
));
assert!(matches!(
synth_probe_params(Some("FlashAttnBackward")).unwrap(),
Some(FusedOpParams::FlashAttnBackward { .. })
));
assert!(matches!(
synth_probe_params(Some("SelectiveScan")).unwrap(),
Some(FusedOpParams::SelectiveScan { .. })
));
assert!(matches!(
synth_probe_params(Some("SsdChunkScan")).unwrap(),
Some(FusedOpParams::SsdChunkScan { .. })
));
assert!(synth_probe_params(Some("Conv2D")).unwrap().is_none());
let conv_combo: Vec<(String, Shape, DType)> = vec![
("x".into(), Shape::from_dims(&[2, 3, 8, 8]), DType::F32),
("weight".into(), Shape::from_dims(&[4, 3, 3, 3]), DType::F32),
];
assert!(
!synth_probe_param_points(Some("Conv2D"), &conv_combo).is_empty(),
"Conv2D synth is no longer None — the points path covers it",
);
assert!(synth_probe_params(None).unwrap().is_none());
match synth_probe_params(Some("QMatMul")).unwrap() {
None => {}
Some(p) => assert!(matches!(p, FusedOpParams::QMatMul { .. })),
}
}
#[test]
fn bundle_slot_count_disagreeing_with_output_views_arity_is_rejected() {
let two_slots: serde_yaml_ng::Value = serde_yaml_ng::from_str(
"- { name: y, shape_rule: same_as(u) }\n- { name: last_state, shape_rule: from_params(state) }").unwrap();
assert_eq!(bundle_slot_count(&two_slots), Some(2));
let err = check_bundle_arity("selective_scan", 3, &two_slots)
.expect_err("declared 2 vs 3 real output_views slots must be rejected");
assert!(
matches!(
err,
FkcError::BundleArityMismatch {
expected: 3,
actual: 2,
..
}
),
"got {err:?}"
);
assert!(check_bundle_arity("selective_scan", 2, &two_slots).is_ok());
}
#[test]
fn shape_rule_derived_bundle_slot_over_rank6_is_rejected() {
use fuel_ir::Shape;
let rank7 = Shape::from_dims(&[2, 2, 2, 2, 2, 2, 2]);
let err = check_slot_rank("s", "big_slot", &rank7).expect_err("rank 7 must be rejected");
assert!(
matches!(err, FkcError::BundleSlotRankExceeded { rank: 7, .. }),
"got {err:?}"
);
assert!(check_slot_rank("s", "ok_slot", &Shape::from_dims(&[1, 1, 1, 1, 1, 1])).is_ok());
}
#[test]
fn interpreter_evaluates_supported_vocab_and_skips_the_rest() {
let combo: Vec<(String, Shape, DType)> = vec![
("x".into(), Shape::from_dims(&[2, 3]), DType::F32),
("upstream".into(), Shape::from_dims(&[4, 5]), DType::F16),
];
let c: ProbeComboRef = &combo;
assert_eq!(
eval_dtype_rule("fixed(F16)", c, "k").unwrap(),
Some(DType::F16)
);
assert_eq!(
eval_dtype_rule("passthrough(x)", c, "k").unwrap(),
Some(DType::F32)
);
assert_eq!(eval_dtype_rule("dequant(w)", c, "k").unwrap(), None);
assert_eq!(
eval_shape_rule("same_as(upstream)", c, &[], "k").unwrap(),
Some(Shape::from_dims(&[4, 5]))
);
assert_eq!(
eval_shape_rule("from_params(q)", c, &[], "k").unwrap(),
None
);
assert_eq!(eval_shape_rule("matmul(a, b)", c, &[], "k").unwrap(), None);
assert_eq!(
eval_shape_rule("same_as(does_not_exist)", c, &[], "k").unwrap(),
None
);
assert_eq!(
eval_shape_rule("extent(x, 0)", c, &[], "k").unwrap(),
Some(Shape::from_dims(&[2]))
);
assert_eq!(
eval_shape_rule("const(9)", c, &[], "k").unwrap(),
Some(Shape::from_dims(&[9]))
);
assert_eq!(
eval_shape_rule("div(extent(x, last), const(2))", c, &[], "k").unwrap(),
Some(Shape::from_dims(&[1]))
);
assert_eq!(
eval_shape_rule("mul(extent(x, 0), const(3))", c, &[], "k").unwrap(),
Some(Shape::from_dims(&[6]))
);
assert_eq!(
eval_shape_rule("extent(nope, 0)", c, &[], "k").unwrap(),
None
);
assert_eq!(eval_shape_rule("param(0)", c, &[], "k").unwrap(), None);
assert_eq!(
eval_shape_rule("div(extent(x, last), const(0))", c, &[], "k").unwrap(),
None
);
assert_eq!(
eval_shape_rule("sub(const(2), extent(x, 1))", c, &[], "k").unwrap(),
None
); }
#[test]
fn eval_shape_rule_threads_param_values_through_the_oracle() {
let combo: Vec<(String, Shape, DType)> =
vec![("x".into(), Shape::from_dims(&[2, 3]), DType::F32)];
let c: ProbeComboRef = &combo;
assert_eq!(
eval_shape_rule("param(0)", c, &[7], "k").unwrap(),
Some(Shape::from_dims(&[7]))
);
assert_eq!(
eval_shape_rule("mul(extent(x, 0), param(1))", c, &[7, 5], "k").unwrap(),
Some(Shape::from_dims(&[10])),
);
assert_eq!(eval_shape_rule("param(2)", c, &[7, 5], "k").unwrap(), None);
assert_eq!(eval_shape_rule("param(0)", c, &[-3], "k").unwrap(), None);
assert_eq!(eval_shape_rule("param(0)", c, &[], "k").unwrap(), None);
}
#[test]
fn eval_shape_rule_matmul_resolves_roles_to_contraction_shape() {
let combo: Vec<(String, Shape, DType)> = vec![
("a".into(), Shape::from_dims(&[8, 4096]), DType::F32),
("b".into(), Shape::from_dims(&[4096, 1024]), DType::F32),
("bias".into(), Shape::from_dims(&[1024]), DType::F32),
];
let c: ProbeComboRef = &combo;
assert_eq!(
eval_shape_rule("matmul(a, b)", c, &[], "k").unwrap(),
Some(Shape::from_dims(&[8, 1024]))
);
assert_eq!(
eval_shape_rule("matmul(a,b)", c, &[], "k").unwrap(),
Some(Shape::from_dims(&[8, 1024]))
);
let batched: Vec<(String, Shape, DType)> = vec![
("a".into(), Shape::from_dims(&[4, 8, 16]), DType::F32),
("b".into(), Shape::from_dims(&[4, 16, 32]), DType::F32),
];
assert_eq!(
eval_shape_rule("matmul(a, b)", &batched, &[], "k").unwrap(),
Some(Shape::from_dims(&[4, 8, 32])),
);
assert_eq!(
eval_shape_rule("matmul(a, nope)", c, &[], "k").unwrap(),
None
);
let rank1: Vec<(String, Shape, DType)> = vec![
("a".into(), Shape::from_dims(&[8]), DType::F32),
("b".into(), Shape::from_dims(&[8]), DType::F32),
];
assert_eq!(
eval_shape_rule("matmul(a, b)", &rank1, &[], "k").unwrap(),
None
);
let rank_mismatch: Vec<(String, Shape, DType)> = vec![
("a".into(), Shape::from_dims(&[4, 8, 16]), DType::F32),
("b".into(), Shape::from_dims(&[16, 32]), DType::F32),
];
assert_eq!(
eval_shape_rule("matmul(a, b)", &rank_mismatch, &[], "k").unwrap(),
None
);
}
#[test]
fn guard_rule_warns_on_a_caught_panic_instead_of_silently_skipping() {
let mut warnings: Vec<ImportWarning> = Vec::new();
let prev = std::panic::take_hook();
std::panic::set_hook(Box::new(|_| {}));
let caught: Option<i32> = guard_rule(&mut warnings, "sec", "shape_rule", || {
panic!("simulated debug_assert arity panic");
});
std::panic::set_hook(prev);
assert!(
caught.is_none(),
"a caught panic yields None (skip this differential)"
);
assert_eq!(
warnings.len(),
1,
"the caught panic must surface exactly one warning"
);
assert_eq!(warnings[0].section, "sec");
assert!(
warnings[0].message.contains("shape_rule") && warnings[0].message.contains("panicked"),
"the warning names the skipped differential + the panic: {:?}",
warnings[0].message,
);
let ok: Option<i32> = guard_rule(&mut warnings, "sec", "dtype_rule", || 7);
assert_eq!(ok, Some(7));
assert_eq!(warnings.len(), 1, "a successful call adds no warning");
}
#[test]
fn expected_min_inputs_covers_attention_family_and_conv2d() {
assert_eq!(expected_min_inputs(Some("FlashAttn")), Some(4));
assert_eq!(expected_min_inputs(Some("FlashAttnBackward")), Some(4));
assert_eq!(expected_min_inputs(Some("PagedAttn")), Some(5));
assert_eq!(expected_min_inputs(Some("Conv2D")), Some(2));
assert_eq!(expected_min_inputs(Some("SelectiveScan")), None);
assert_eq!(expected_min_inputs(Some("InplaceAffine")), None);
assert_eq!(expected_min_inputs(None), None);
}
#[test]
fn distinct_role_probe_bumps_dim0_by_position_leaving_operand0() {
let combo: Vec<(String, Shape, DType)> = vec![
("u".into(), Shape::from_dims(&[2, 3, 4]), DType::F32),
("b".into(), Shape::from_dims(&[2, 3, 4]), DType::F32),
("c".into(), Shape::from_dims(&[2, 3, 4]), DType::F32),
];
let d = distinct_role_probe(&combo);
assert_eq!(d[0].1, Shape::from_dims(&[2, 3, 4]), "operand 0 unchanged");
assert_eq!(d[1].1, Shape::from_dims(&[3, 3, 4]), "operand 1 dim0 +1");
assert_eq!(d[2].1, Shape::from_dims(&[4, 3, 4]), "operand 2 dim0 +2");
assert_ne!(d[0].1, d[1].1);
}
#[test]
fn synth_probe_param_points_pins_per_variant_tables_and_key_ints_flattening() {
use fuel_graph::registry::Reduction;
let conv: Vec<(String, Shape, DType)> = vec![
("x".into(), Shape::from_dims(&[2, 3, 8, 8]), DType::F32),
("weight".into(), Shape::from_dims(&[4, 3, 3, 3]), DType::F32),
];
let pts = synth_probe_param_points(Some("Conv2D"), &conv);
assert_eq!(
pts.len(),
2,
"Conv2D needs >= 2 points (no single-point false-green)"
);
assert!(
matches!(
pts[0].0,
FusedOpParams::Conv2D {
stride: (1, 2),
padding: (1, 4),
groups: 1
}
),
"got {:?}",
pts[0].0,
);
assert_eq!(pts[0].1, vec![1, 2, 1, 4, 1]);
assert!(
matches!(
pts[1].0,
FusedOpParams::Conv2D {
stride: (3, 4),
padding: (6, 7),
groups: 2
}
),
"got {:?}",
pts[1].0,
);
assert_eq!(pts[1].1, vec![3, 4, 6, 7, 2]);
assert_ne!(
pts[0].1, pts[1].1,
"the two points must differ (param-dependence observable)"
);
let pts = synth_probe_param_points(Some("ConvTranspose2D"), &conv);
assert_eq!(pts.len(), 2, "ConvTranspose2D needs >= 2 points");
assert!(
matches!(pts[0].0, FusedOpParams::ConvTranspose2D { .. }),
"got {:?}",
pts[0].0
);
assert_eq!(pts[0].1, vec![2, 3, 0, 1, 1, 2, 4, 5, 1]);
assert!(
matches!(pts[1].0, FusedOpParams::ConvTranspose2D { .. }),
"got {:?}",
pts[1].0
);
assert_eq!(pts[1].1, vec![5, 4, 3, 2, 4, 0, 2, 6, 3]);
let qm: Vec<(String, Shape, DType)> = vec![
("a".into(), Shape::from_dims(&[8, 4096]), DType::F32),
(
"w_q_bytes".into(),
Shape::from_dims(&[1024, 128]),
DType::U32,
),
];
let pts = synth_probe_param_points(Some("QMatMul"), &qm);
assert_eq!(pts.len(), 1);
assert!(
matches!(
pts[0].0,
FusedOpParams::QMatMul {
k: 4096,
n: 1024,
..
}
),
"k/n must derive from the combo; got {:?}",
pts[0].0,
);
assert_eq!(pts[0].1, vec![1, 4096, 1024]);
let fsce: Vec<(String, Shape, DType)> = vec![
("logits".into(), Shape::from_dims(&[8, 32000]), DType::F32),
("targets".into(), Shape::from_dims(&[8]), DType::I64),
];
let pts = synth_probe_param_points(Some("FusedSoftmaxCrossEntropy"), &fsce);
assert_eq!(pts.len(), 2, "FSCE needs both reduction branches covered");
assert!(
matches!(
pts[0].0,
FusedOpParams::FusedSoftmaxCrossEntropy {
reduction: Reduction::None,
ignore_index: -100
}
),
"got {:?}",
pts[0].0
);
assert_eq!(pts[0].1, vec![2, -100], "Reduction::None.key() = 2");
assert!(
matches!(
pts[1].0,
FusedOpParams::FusedSoftmaxCrossEntropy {
reduction: Reduction::Mean,
ignore_index: -100
}
),
"got {:?}",
pts[1].0
);
assert_eq!(pts[1].1, vec![0, -100], "Reduction::Mean.key() = 0");
let cc: Vec<(String, Shape, DType)> = vec![
("x".into(), Shape::from_dims(&[2, 4, 19]), DType::F32),
("weight".into(), Shape::from_dims(&[4, 1, 4]), DType::F32),
("bias".into(), Shape::from_dims(&[4]), DType::F32),
];
let pts = synth_probe_param_points(Some("CausalConv1d"), &cc);
assert_eq!(pts.len(), 1);
assert!(
matches!(pts[0].0, FusedOpParams::CausalConv1d { use_silu: false }),
"got {:?}",
pts[0].0
);
assert_eq!(pts[0].1, vec![0]);
}
#[test]
fn synth_param_points_distinguish_every_ints_slot_pair() {
let combo: Vec<(String, Shape, DType)> = vec![
("x".into(), Shape::from_dims(&[2, 3, 8, 8]), DType::F32),
("weight".into(), Shape::from_dims(&[4, 3, 3, 3]), DType::F32),
];
for v in [
"Conv2D",
"ConvTranspose2D",
"QMatMul",
"FusedSoftmaxCrossEntropy",
"CausalConv1d",
] {
let pts = synth_probe_param_points(Some(v), &combo);
assert!(!pts.is_empty(), "{v} must synthesize points");
let len = pts[0].1.len();
for i in 0..len {
for j in (i + 1)..len {
assert!(
pts.iter().any(|(_, ints)| ints[i] != ints[j]),
"{v}: ints slots {i} and {j} are equal at EVERY synth point \
(order-degenerate: a slot reorder in the key().ints flattening, \
or a param({i})/param({j}) confusion in a declared rule, would \
false-green)",
);
}
}
}
}
#[test]
fn synth_probe_param_points_ints_equal_key_ints_for_every_point() {
let combo: Vec<(String, Shape, DType)> = vec![
("x".into(), Shape::from_dims(&[2, 3, 8, 8]), DType::F32),
("weight".into(), Shape::from_dims(&[4, 3, 3, 3]), DType::F32),
];
for v in [
"Conv2D",
"ConvTranspose2D",
"QMatMul",
"FusedSoftmaxCrossEntropy",
"CausalConv1d",
] {
let pts = synth_probe_param_points(Some(v), &combo);
assert!(!pts.is_empty(), "{v} must synthesize at least one point");
for (p, ints) in &pts {
assert_eq!(
ints,
&p.key().ints,
"{v}: ints must be the key().ints flattening"
);
}
}
}
#[test]
fn synth_probe_param_points_declines_unknown_variants_and_unreadable_combos() {
let conv_ok: Vec<(String, Shape, DType)> = vec![
("x".into(), Shape::from_dims(&[2, 3, 8, 8]), DType::F32),
("weight".into(), Shape::from_dims(&[4, 3, 3, 3]), DType::F32),
];
assert!(synth_probe_param_points(None, &conv_ok).is_empty());
assert!(synth_probe_param_points(Some("SoftmaxLastDim"), &conv_ok).is_empty());
assert!(synth_probe_param_points(Some("Bogus"), &conv_ok).is_empty());
assert!(synth_probe_param_points(Some("Conv2D"), &conv_ok[..1]).is_empty());
let rank3: Vec<(String, Shape, DType)> = vec![
("x".into(), Shape::from_dims(&[3, 8, 8]), DType::F32),
("weight".into(), Shape::from_dims(&[4, 3, 3, 3]), DType::F32),
];
assert!(synth_probe_param_points(Some("Conv2D"), &rank3).is_empty());
let zero_h: Vec<(String, Shape, DType)> = vec![
("x".into(), Shape::from_dims(&[2, 3, 0, 8]), DType::F32),
("weight".into(), Shape::from_dims(&[4, 3, 3, 3]), DType::F32),
];
assert!(synth_probe_param_points(Some("Conv2D"), &zero_h).is_empty());
let qm: Vec<(String, Shape, DType)> = vec![
("a".into(), Shape::from_dims(&[8, 4096]), DType::F32),
(
"w_q_bytes".into(),
Shape::from_dims(&[1024, 128]),
DType::U32,
),
];
assert!(synth_probe_param_points(Some("QMatMul"), &qm[..1]).is_empty());
let scalar_a: Vec<(String, Shape, DType)> = vec![
("a".into(), Shape::from_dims(&[]), DType::F32),
(
"w_q_bytes".into(),
Shape::from_dims(&[1024, 128]),
DType::U32,
),
];
assert!(synth_probe_param_points(Some("QMatMul"), &scalar_a).is_empty());
}
#[test]
fn synth_conv2d_points_are_valid_for_the_real_registry_shape_fn() {
use fuel_graph::registry::FusedOps;
let entry = default_registry()
.entry(FusedOps::CONV2D)
.expect("CONV2D registered");
let cases = [
(
Shape::from_dims(&[1, 1, 1, 7]),
Shape::from_dims(&[1, 1, 5, 5]),
),
(
Shape::from_dims(&[2, 3, 8, 8]),
Shape::from_dims(&[4, 3, 3, 3]),
),
(
Shape::from_dims(&[2, 3, 8, 8]),
Shape::from_dims(&[4, 3, 4, 4]),
),
];
for (x, w) in cases {
let combo: Vec<(String, Shape, DType)> = vec![
("x".into(), x.clone(), DType::F32),
("weight".into(), w.clone(), DType::F32),
];
let pts = synth_probe_param_points(Some("Conv2D"), &combo);
assert_eq!(pts.len(), 2, "x={x:?} w={w:?}");
for (p, _) in &pts {
let out = (entry.shape_rule)(&[x.clone(), w.clone()], p);
assert_eq!(out.rank(), 4, "x={x:?} w={w:?} params={p:?}");
}
}
}
#[test]
fn bundle_slot_names_extracts_names_from_a_real_return_block() {
let ret: crate::fkc::schema::ReturnBlock = serde_yaml_ng::from_str(
"outputs: []\nbundle:\n - { name: y, shape_rule: same_as(u) }\n - { name: last_state, shape_rule: from_params(state) }",
)
.expect("parses");
assert_eq!(
bundle_slot_names(&Some(ret)),
vec!["y".to_string(), "last_state".to_string()]
);
assert_eq!(bundle_slot_names(&None), Vec::<String>::new());
}
#[test]
fn corpus_prose_pins_param_index_tables_matching_key_ints() {
use fuel_graph::registry::Reduction;
const CONV_ROPE: &str =
include_str!("../../../docs/kernel-contracts/fused/conv-rope.fkc.md");
const LINEAR_QUANT: &str =
include_str!("../../../docs/kernel-contracts/fused/linear-quant.fkc.md");
fn table_row<'a>(doc: &'a str, doc_name: &str, variant: &str) -> &'a str {
let marker = format!("| `{variant}` |");
doc.lines()
.find(|l| l.contains(&marker))
.unwrap_or_else(|| {
panic!("{doc_name} prose is missing the `{variant}` param-index table row")
})
}
fn assert_row_pins(doc: &str, doc_name: &str, variant: &str, params: &FusedOpParams) {
let ints = params.key().ints;
let row = table_row(doc, doc_name, variant);
for i in 0..ints.len() {
assert!(
row.contains(&format!("param({i})=")),
"{doc_name}: `{variant}` row must pin param({i}) (key().ints has {} slots)",
ints.len(),
);
}
assert!(
!row.contains(&format!("param({})", ints.len())),
"{doc_name}: `{variant}` row pins more slots than key().ints carries ({})",
ints.len(),
);
}
assert_row_pins(
CONV_ROPE,
"conv-rope.fkc.md",
"Conv2D",
&FusedOpParams::Conv2D {
stride: (1, 1),
padding: (0, 0),
groups: 1,
},
);
assert_row_pins(
CONV_ROPE,
"conv-rope.fkc.md",
"ConvTranspose2D",
&FusedOpParams::ConvTranspose2D {
stride: (1, 1),
padding: (0, 0),
output_padding: (0, 0),
dilation: (1, 1),
groups: 1,
},
);
assert_row_pins(
CONV_ROPE,
"conv-rope.fkc.md",
"CausalConv1d",
&FusedOpParams::CausalConv1d { use_silu: false },
);
assert_row_pins(
CONV_ROPE,
"conv-rope.fkc.md",
"SelectiveScan",
&FusedOpParams::SelectiveScan {
delta_softplus: false,
},
);
assert_row_pins(
CONV_ROPE,
"conv-rope.fkc.md",
"SsdChunkScan",
&FusedOpParams::SsdChunkScan { chunk_size: 256 },
);
assert_row_pins(
LINEAR_QUANT,
"linear-quant.fkc.md",
"QMatMul",
&FusedOpParams::QMatMul {
quant_type: fuel_graph::QuantType::Q4_0,
k: 32,
n: 4,
},
);
assert_row_pins(
LINEAR_QUANT,
"linear-quant.fkc.md",
"FusedSoftmaxCrossEntropy",
&FusedOpParams::FusedSoftmaxCrossEntropy {
reduction: Reduction::Mean,
ignore_index: -100,
},
);
assert_row_pins(
LINEAR_QUANT,
"linear-quant.fkc.md",
"Nf4Matmul",
&FusedOpParams::Nf4Matmul { block_size: 64 },
);
for (doc, doc_name) in [
(CONV_ROPE, "conv-rope.fkc.md"),
(LINEAR_QUANT, "linear-quant.fkc.md"),
] {
assert!(
doc.contains("`param(N)` indexes the `FusedOpParams::key().ints` flattening"),
"{doc_name} must carry the C-4 param-threading convention note",
);
}
}
}