Skip to main content

fuel_dispatch/fkc/
cpu_link.rs

1// SPDX-License-Identifier: MIT OR Apache-2.0
2//! The built-in CPU backend's FKC `link_registry` (kernel-seam-interop §3.5,
3//! §4.3; FKC §12.6). Maps each CPU kernel contract's `entry_point` symbol to
4//! the production dispatch wrapper — the real, non-stub resolution the importer
5//! uses so an imported contract binds the **actual** kernel (no raw pointers in
6//! the serialized contract, FKC P9).
7//!
8//! For the built-in CPU backend the wrappers and this table co-locate in
9//! fuel-dispatch — the dispatch layer that adapts raw byte-kernels to
10//! [`KernelRef`]. An *external* provider (e.g. Baracuda) instead exports its own
11//! link registry across the FFI; this is Fuel's internal-provider analogue, and
12//! the first FKC conformance reference.
13
14use crate::fkc::lower::LinkRegistry;
15use crate::kernel::KernelRef;
16
17/// One `(contract entry_point symbol, production wrapper)` pair. The symbol
18/// matches the contract's `entry_point: "fuel_cpu_backend::byte_kernels::<op>_<dt>"`.
19macro_rules! ep {
20    ($op:literal, $dt:literal, $wrapper:ident) => {
21        (
22            concat!("fuel_cpu_backend::byte_kernels::", $op, "_", $dt),
23            crate::dispatch::$wrapper as KernelRef,
24        )
25    };
26}
27
28/// Like [`ep!`] but for a wrapper whose contract `entry_point` symbol is its
29/// FULLY-QUALIFIED `fuel_dispatch::dispatch::<wrapper>` path. The FlashAttn
30/// BACKWARD wrappers live in the dispatch layer (they select which gradient the
31/// shared byte-kernel writes via a `FaBackwardWhich` selector), so their
32/// contract `entry_point` carries the `fuel_dispatch::dispatch::` prefix — NOT
33/// `ep!`'s `fuel_cpu_backend::byte_kernels::<op>_<dt>` byte-kernel shape.
34macro_rules! ep_dispatch {
35    ($wrapper:ident) => {
36        (
37            concat!("fuel_dispatch::dispatch::", stringify!($wrapper)),
38            crate::dispatch::$wrapper as KernelRef,
39        )
40    };
41}
42
43/// One `(FUSED-contract entry_point symbol, production wrapper)` pair for a
44/// `fused_op` section. Unlike the primitive [`ep!`] / [`ep_dispatch!`] pairs, a
45/// fused contract declares a **dtype-agnostic BASE** `entry_point`
46/// `fuel_dispatch::dispatch::<op>_cpu` (e.g. `…::softmax_last_dim_cpu`) plus a
47/// per-input `dtypes: [F32, F64, BF16, F16]` list, so [`crate::fkc::lower::lower_fused`]
48/// **dtype-fans** it (§3.4, the fused analogue of the primitive fan-out): per
49/// fanned `dt` it resolves `<base>_<dt>` (e.g. `…::softmax_last_dim_cpu_f32`)
50/// through this table. Each such fanned symbol binds the `<op>_<dt>_cpu_wrapper`
51/// — the exact kernel fn the hand-written `register_default_fused_kernels` seam
52/// registers for that op's `dt` dtype tuple. Note the naming skew: the FANNED
53/// symbol is `<op>_cpu_<dt>` (base `…_cpu` + `_<dt>` suffix), while the wrapper
54/// fn is `<op>_<dt>_cpu_wrapper` (`_cpu` after `_<dt>`), so the mapping is
55/// spelled out per (op, dtype) row.
56macro_rules! fep {
57    ($symbol:literal, $wrapper:ident) => {
58        (
59            concat!("fuel_dispatch::dispatch::", $symbol),
60            crate::dispatch::$wrapper as KernelRef,
61        )
62    };
63}
64
65/// The CPU elementwise-binary family's `symbol → production wrapper` map
66/// (8 ops × 4 dtypes). The chassis umbrella section is `registrable: false`
67/// (§3.10 describe-only), so it never reaches resolution and is absent here.
68pub static CPU_BINARY_ENTRY_POINTS: &[(&str, KernelRef)] = &[
69    ep!("add", "f32", add_elementwise_f32_cpu_wrapper),
70    ep!("add", "f64", add_elementwise_f64_cpu_wrapper),
71    ep!("add", "f16", add_elementwise_f16_cpu_wrapper),
72    ep!("add", "bf16", add_elementwise_bf16_cpu_wrapper),
73    ep!("sub", "f32", sub_elementwise_f32_cpu_wrapper),
74    ep!("sub", "f64", sub_elementwise_f64_cpu_wrapper),
75    ep!("sub", "f16", sub_elementwise_f16_cpu_wrapper),
76    ep!("sub", "bf16", sub_elementwise_bf16_cpu_wrapper),
77    ep!("mul", "f32", mul_elementwise_f32_cpu_wrapper),
78    ep!("mul", "f64", mul_elementwise_f64_cpu_wrapper),
79    ep!("mul", "f16", mul_elementwise_f16_cpu_wrapper),
80    ep!("mul", "bf16", mul_elementwise_bf16_cpu_wrapper),
81    ep!("div", "f32", div_elementwise_f32_cpu_wrapper),
82    ep!("div", "f64", div_elementwise_f64_cpu_wrapper),
83    ep!("div", "f16", div_elementwise_f16_cpu_wrapper),
84    ep!("div", "bf16", div_elementwise_bf16_cpu_wrapper),
85    ep!("maximum", "f32", maximum_elementwise_f32_cpu_wrapper),
86    ep!("maximum", "f64", maximum_elementwise_f64_cpu_wrapper),
87    ep!("maximum", "f16", maximum_elementwise_f16_cpu_wrapper),
88    ep!("maximum", "bf16", maximum_elementwise_bf16_cpu_wrapper),
89    ep!("minimum", "f32", minimum_elementwise_f32_cpu_wrapper),
90    ep!("minimum", "f64", minimum_elementwise_f64_cpu_wrapper),
91    ep!("minimum", "f16", minimum_elementwise_f16_cpu_wrapper),
92    ep!("minimum", "bf16", minimum_elementwise_bf16_cpu_wrapper),
93    ep!("pow", "f32", pow_elementwise_f32_cpu_wrapper),
94    ep!("pow", "f64", pow_elementwise_f64_cpu_wrapper),
95    ep!("pow", "f16", pow_elementwise_f16_cpu_wrapper),
96    ep!("pow", "bf16", pow_elementwise_bf16_cpu_wrapper),
97    ep!("rem", "f32", rem_elementwise_f32_cpu_wrapper),
98    ep!("rem", "f64", rem_elementwise_f64_cpu_wrapper),
99    ep!("rem", "f16", rem_elementwise_f16_cpu_wrapper),
100    ep!("rem", "bf16", rem_elementwise_bf16_cpu_wrapper),
101];
102
103/// The CPU out-of-place scalar-param family's `symbol → production wrapper`
104/// map (affine / clamp / powi × 4 dtypes + powi_backward × 4 = 16 kernels).
105/// Contract: `fuel-dispatch/kernel-contracts/cpu/affine-clamp-powi.fkc.md`. The scalar
106/// params (affine mul/add, clamp min/max, powi exp) ride in `OpParams`, NOT the
107/// dtype-list, so the binding keys stay `[t, t]` for the single-input forward
108/// ops and `[t, t, t]` for the two-input `powi_backward`. The `ep!` symbol is
109/// built from `$op`/`$dt`, so the three f32 hand-written wrappers whose fn-name
110/// differs from the symbol (`clamp_elementwise_f32`, `powi_elementwise_f32`)
111/// still map to the contract's `clamp_f32` / `powi_f32` entry points.
112pub static CPU_AFFINE_CLAMP_POWI_ENTRY_POINTS: &[(&str, KernelRef)] = &[
113    // affine (y = mul*x + add)
114    ep!("affine", "f32", affine_f32_cpu_wrapper),
115    ep!("affine", "f64", affine_f64_cpu_wrapper),
116    ep!("affine", "bf16", affine_bf16_cpu_wrapper),
117    ep!("affine", "f16", affine_f16_cpu_wrapper),
118    // clamp (y = clamp(x, min, max))
119    ep!("clamp", "f32", clamp_elementwise_f32_cpu_wrapper),
120    ep!("clamp", "f64", clamp_f64_cpu_wrapper),
121    ep!("clamp", "bf16", clamp_bf16_cpu_wrapper),
122    ep!("clamp", "f16", clamp_f16_cpu_wrapper),
123    // powi (y = x.powi(exp))
124    ep!("powi", "f32", powi_elementwise_f32_cpu_wrapper),
125    ep!("powi", "f64", powi_f64_cpu_wrapper),
126    ep!("powi", "bf16", powi_bf16_cpu_wrapper),
127    ep!("powi", "f16", powi_f16_cpu_wrapper),
128    // powi_backward (grad_x = exp*x^(exp-1)*upstream) — TWO inputs (x, upstream)
129    ep!("powi_backward", "f32", powi_backward_f32_cpu_wrapper),
130    ep!("powi_backward", "f64", powi_backward_f64_cpu_wrapper),
131    ep!("powi_backward", "bf16", powi_backward_bf16_cpu_wrapper),
132    ep!("powi_backward", "f16", powi_backward_f16_cpu_wrapper),
133];
134
135/// The CPU elementwise-unary family's `symbol → production wrapper` map
136/// (22 ops × 4 dtypes = 88 kernels). Contract:
137/// `fuel-dispatch/kernel-contracts/cpu/elementwise-unary.fkc.md`. Each per-op section
138/// declares a BASE `entry_point` (e.g. `…::relu`) and enumerates
139/// `dtypes: [F32,F64,BF16,F16]`; the importer's §3.4 multi-dtype fan-out then
140/// resolves `<base>_<dtype>` (e.g. `relu_f32`) against this table — so the
141/// `$op` literals below are the byte-kernel BASES, NOT the OpKind names. The
142/// two GELU flavors stay distinct, and since S13 their OpKind names no
143/// longer match their (unrenamed) byte-kernel bases: `OpKind::GeluTanhElementwise`
144/// (the canonical tanh GELU) has base `gelu` (wrapper `gelu_elementwise_<dt>`),
145/// while `OpKind::GeluElementwise` (bare `Gelu` means erf since S13) has base
146/// `gelu_erf` (wrapper `gelu_erf_elementwise_<dt>`). The `unary` chassis
147/// umbrella is `registrable: false` (§3.10 describe-only) and never resolves,
148/// so it is absent here.
149pub static CPU_UNARY_ENTRY_POINTS: &[(&str, KernelRef)] = &[
150    ep!("relu", "f32", relu_elementwise_f32_cpu_wrapper),
151    ep!("relu", "f64", relu_elementwise_f64_cpu_wrapper),
152    ep!("relu", "bf16", relu_elementwise_bf16_cpu_wrapper),
153    ep!("relu", "f16", relu_elementwise_f16_cpu_wrapper),
154    ep!("neg", "f32", neg_elementwise_f32_cpu_wrapper),
155    ep!("neg", "f64", neg_elementwise_f64_cpu_wrapper),
156    ep!("neg", "bf16", neg_elementwise_bf16_cpu_wrapper),
157    ep!("neg", "f16", neg_elementwise_f16_cpu_wrapper),
158    ep!("sqr", "f32", sqr_elementwise_f32_cpu_wrapper),
159    ep!("sqr", "f64", sqr_elementwise_f64_cpu_wrapper),
160    ep!("sqr", "bf16", sqr_elementwise_bf16_cpu_wrapper),
161    ep!("sqr", "f16", sqr_elementwise_f16_cpu_wrapper),
162    ep!("sqrt", "f32", sqrt_elementwise_f32_cpu_wrapper),
163    ep!("sqrt", "f64", sqrt_elementwise_f64_cpu_wrapper),
164    ep!("sqrt", "bf16", sqrt_elementwise_bf16_cpu_wrapper),
165    ep!("sqrt", "f16", sqrt_elementwise_f16_cpu_wrapper),
166    ep!("recip", "f32", recip_elementwise_f32_cpu_wrapper),
167    ep!("recip", "f64", recip_elementwise_f64_cpu_wrapper),
168    ep!("recip", "bf16", recip_elementwise_bf16_cpu_wrapper),
169    ep!("recip", "f16", recip_elementwise_f16_cpu_wrapper),
170    ep!("abs", "f32", abs_elementwise_f32_cpu_wrapper),
171    ep!("abs", "f64", abs_elementwise_f64_cpu_wrapper),
172    ep!("abs", "bf16", abs_elementwise_bf16_cpu_wrapper),
173    ep!("abs", "f16", abs_elementwise_f16_cpu_wrapper),
174    ep!("tanh", "f32", tanh_elementwise_f32_cpu_wrapper),
175    ep!("tanh", "f64", tanh_elementwise_f64_cpu_wrapper),
176    ep!("tanh", "bf16", tanh_elementwise_bf16_cpu_wrapper),
177    ep!("tanh", "f16", tanh_elementwise_f16_cpu_wrapper),
178    ep!("exp", "f32", exp_elementwise_f32_cpu_wrapper),
179    ep!("exp", "f64", exp_elementwise_f64_cpu_wrapper),
180    ep!("exp", "bf16", exp_elementwise_bf16_cpu_wrapper),
181    ep!("exp", "f16", exp_elementwise_f16_cpu_wrapper),
182    ep!("log", "f32", log_elementwise_f32_cpu_wrapper),
183    ep!("log", "f64", log_elementwise_f64_cpu_wrapper),
184    ep!("log", "bf16", log_elementwise_bf16_cpu_wrapper),
185    ep!("log", "f16", log_elementwise_f16_cpu_wrapper),
186    ep!("sin", "f32", sin_elementwise_f32_cpu_wrapper),
187    ep!("sin", "f64", sin_elementwise_f64_cpu_wrapper),
188    ep!("sin", "bf16", sin_elementwise_bf16_cpu_wrapper),
189    ep!("sin", "f16", sin_elementwise_f16_cpu_wrapper),
190    ep!("cos", "f32", cos_elementwise_f32_cpu_wrapper),
191    ep!("cos", "f64", cos_elementwise_f64_cpu_wrapper),
192    ep!("cos", "bf16", cos_elementwise_bf16_cpu_wrapper),
193    ep!("cos", "f16", cos_elementwise_f16_cpu_wrapper),
194    ep!("sigmoid", "f32", sigmoid_elementwise_f32_cpu_wrapper),
195    ep!("sigmoid", "f64", sigmoid_elementwise_f64_cpu_wrapper),
196    ep!("sigmoid", "bf16", sigmoid_elementwise_bf16_cpu_wrapper),
197    ep!("sigmoid", "f16", sigmoid_elementwise_f16_cpu_wrapper),
198    ep!("silu", "f32", silu_elementwise_f32_cpu_wrapper),
199    ep!("silu", "f64", silu_elementwise_f64_cpu_wrapper),
200    ep!("silu", "bf16", silu_elementwise_bf16_cpu_wrapper),
201    ep!("silu", "f16", silu_elementwise_f16_cpu_wrapper),
202    ep!("step", "f32", step_elementwise_f32_cpu_wrapper),
203    ep!("step", "f64", step_elementwise_f64_cpu_wrapper),
204    ep!("step", "bf16", step_elementwise_bf16_cpu_wrapper),
205    ep!("step", "f16", step_elementwise_f16_cpu_wrapper),
206    // gelu_tanh (OpKind::GeluTanhElementwise, tanh approx): base `gelu`
207    // (matches the real byte_kernels::gelu_* symbol -- NOT renamed by S13,
208    // only the Op-level vocabulary was), wrapper `gelu_elementwise_*`.
209    ep!("gelu", "f32", gelu_elementwise_f32_cpu_wrapper),
210    ep!("gelu", "f64", gelu_elementwise_f64_cpu_wrapper),
211    ep!("gelu", "bf16", gelu_elementwise_bf16_cpu_wrapper),
212    ep!("gelu", "f16", gelu_elementwise_f16_cpu_wrapper),
213    ep!("floor", "f32", floor_elementwise_f32_cpu_wrapper),
214    ep!("floor", "f64", floor_elementwise_f64_cpu_wrapper),
215    ep!("floor", "bf16", floor_elementwise_bf16_cpu_wrapper),
216    ep!("floor", "f16", floor_elementwise_f16_cpu_wrapper),
217    ep!("ceil", "f32", ceil_elementwise_f32_cpu_wrapper),
218    ep!("ceil", "f64", ceil_elementwise_f64_cpu_wrapper),
219    ep!("ceil", "bf16", ceil_elementwise_bf16_cpu_wrapper),
220    ep!("ceil", "f16", ceil_elementwise_f16_cpu_wrapper),
221    ep!("round", "f32", round_elementwise_f32_cpu_wrapper),
222    ep!("round", "f64", round_elementwise_f64_cpu_wrapper),
223    ep!("round", "bf16", round_elementwise_bf16_cpu_wrapper),
224    ep!("round", "f16", round_elementwise_f16_cpu_wrapper),
225    ep!("sign", "f32", sign_elementwise_f32_cpu_wrapper),
226    ep!("sign", "f64", sign_elementwise_f64_cpu_wrapper),
227    ep!("sign", "bf16", sign_elementwise_bf16_cpu_wrapper),
228    ep!("sign", "f16", sign_elementwise_f16_cpu_wrapper),
229    ep!("erf", "f32", erf_elementwise_f32_cpu_wrapper),
230    ep!("erf", "f64", erf_elementwise_f64_cpu_wrapper),
231    ep!("erf", "bf16", erf_elementwise_bf16_cpu_wrapper),
232    ep!("erf", "f16", erf_elementwise_f16_cpu_wrapper),
233    // gelu (OpKind::GeluElementwise, exact erf): base `gelu_erf` (matches the
234    // real byte_kernels::gelu_erf_* symbol, unrenamed), DISTINCT from the
235    // tanh block above.
236    ep!("gelu_erf", "f32", gelu_erf_elementwise_f32_cpu_wrapper),
237    ep!("gelu_erf", "f64", gelu_erf_elementwise_f64_cpu_wrapper),
238    ep!("gelu_erf", "bf16", gelu_erf_elementwise_bf16_cpu_wrapper),
239    ep!("gelu_erf", "f16", gelu_erf_elementwise_f16_cpu_wrapper),
240    ep!("rsqrt", "f32", rsqrt_elementwise_f32_cpu_wrapper),
241    ep!("rsqrt", "f64", rsqrt_elementwise_f64_cpu_wrapper),
242    ep!("rsqrt", "bf16", rsqrt_elementwise_bf16_cpu_wrapper),
243    ep!("rsqrt", "f16", rsqrt_elementwise_f16_cpu_wrapper),
244];
245
246/// The CPU elementwise-COMPARE family's `symbol → production wrapper` map
247/// (6 ops × 4 dtypes = 24). Contract:
248/// `fuel-dispatch/kernel-contracts/cpu/compare-where.fkc.md`. Each thunk is a
249/// single-(op,dtype) section (its `lhs`/`rhs` enumerate ONE dtype), so it does
250/// NOT fan — the importer resolves its declared symbol AS-IS. That symbol
251/// carries the `_u8` output-mask suffix (`T × T → U8` mask, `return.out:
252/// fixed(U8)`), so the `ep!` dtype slot is `<dt>_u8` (e.g. `eq_f32_u8`), NOT
253/// the plain `<dt>` the binary/unary families use. The `## compare` chassis
254/// umbrella is `registrable: false` (§3.10 describe-only) and never resolves,
255/// so it is absent here.
256pub static CPU_COMPARE_ENTRY_POINTS: &[(&str, KernelRef)] = &[
257    ep!("eq", "f32_u8", eq_elementwise_f32_cpu_wrapper),
258    ep!("eq", "f64_u8", eq_elementwise_f64_cpu_wrapper),
259    ep!("eq", "bf16_u8", eq_elementwise_bf16_cpu_wrapper),
260    ep!("eq", "f16_u8", eq_elementwise_f16_cpu_wrapper),
261    ep!("ne", "f32_u8", ne_elementwise_f32_cpu_wrapper),
262    ep!("ne", "f64_u8", ne_elementwise_f64_cpu_wrapper),
263    ep!("ne", "bf16_u8", ne_elementwise_bf16_cpu_wrapper),
264    ep!("ne", "f16_u8", ne_elementwise_f16_cpu_wrapper),
265    ep!("lt", "f32_u8", lt_elementwise_f32_cpu_wrapper),
266    ep!("lt", "f64_u8", lt_elementwise_f64_cpu_wrapper),
267    ep!("lt", "bf16_u8", lt_elementwise_bf16_cpu_wrapper),
268    ep!("lt", "f16_u8", lt_elementwise_f16_cpu_wrapper),
269    ep!("le", "f32_u8", le_elementwise_f32_cpu_wrapper),
270    ep!("le", "f64_u8", le_elementwise_f64_cpu_wrapper),
271    ep!("le", "bf16_u8", le_elementwise_bf16_cpu_wrapper),
272    ep!("le", "f16_u8", le_elementwise_f16_cpu_wrapper),
273    ep!("gt", "f32_u8", gt_elementwise_f32_cpu_wrapper),
274    ep!("gt", "f64_u8", gt_elementwise_f64_cpu_wrapper),
275    ep!("gt", "bf16_u8", gt_elementwise_bf16_cpu_wrapper),
276    ep!("gt", "f16_u8", gt_elementwise_f16_cpu_wrapper),
277    ep!("ge", "f32_u8", ge_elementwise_f32_cpu_wrapper),
278    ep!("ge", "f64_u8", ge_elementwise_f64_cpu_wrapper),
279    ep!("ge", "bf16_u8", ge_elementwise_bf16_cpu_wrapper),
280    ep!("ge", "f16_u8", ge_elementwise_f16_cpu_wrapper),
281];
282
283/// The CPU ternary-select (`where`) family's `symbol → production wrapper` map
284/// (1 op × 4 dtypes = 4). Contract:
285/// `fuel-dispatch/kernel-contracts/cpu/compare-where.fkc.md`. The single `where_kernel`
286/// section enumerates `a`/`b` `dtypes: [F32,F64,BF16,F16]`, so it FANS (§3.4):
287/// its declared BASE `entry_point` `…::where` resolves `<base>_<dtype>` =
288/// `where_{f32,f64,bf16,f16}` against this table. The binding key is
289/// `[U8, T, T, T]` (cond U8 + a/b/out share T; `out: passthrough(a)` → T).
290pub static CPU_WHERE_ENTRY_POINTS: &[(&str, KernelRef)] = &[
291    ep!("where", "f32", where_f32_cpu_wrapper),
292    ep!("where", "f64", where_f64_cpu_wrapper),
293    ep!("where", "bf16", where_bf16_cpu_wrapper),
294    ep!("where", "f16", where_f16_cpu_wrapper),
295];
296
297/// The CPU per-axis REDUCE family's `symbol → production wrapper` map
298/// (4 ops × 4 dtypes = 16). Contract: `fuel-dispatch/kernel-contracts/cpu/reduce.fkc.md`.
299/// Each per-(op, dtype) section (`## sum_reduce_f32`, …) declares a SPECIFIC
300/// single-dtype `entry_point` (`…::sum_reduce_f32`), so it does NOT fan — the
301/// importer resolves that symbol AS-IS. The binding key is `[T, T]` (input +
302/// `passthrough(input)` output; the reduce axes + keepdim ride in
303/// `OpParams::Reduce`, NOT the dtype-list). The `## reduce` chassis umbrella is
304/// `registrable: false` (§3.10 describe-only) and never resolves, so it is
305/// absent here; the f32-only `argmax_dim_f32` / `argmin_dim_f32` sections are
306/// `registrable: false` (deferred — production registers Arg{Max,Min}Dim for all
307/// input dtypes via a hand-written dispatch) and are likewise absent.
308pub static CPU_REDUCE_ENTRY_POINTS: &[(&str, KernelRef)] = &[
309    ep!("sum_reduce", "f32", sum_reduce_f32_cpu_wrapper),
310    ep!("sum_reduce", "f64", sum_reduce_f64_cpu_wrapper),
311    ep!("sum_reduce", "bf16", sum_reduce_bf16_cpu_wrapper),
312    ep!("sum_reduce", "f16", sum_reduce_f16_cpu_wrapper),
313    ep!("mean_reduce", "f32", mean_reduce_f32_cpu_wrapper),
314    ep!("mean_reduce", "f64", mean_reduce_f64_cpu_wrapper),
315    ep!("mean_reduce", "bf16", mean_reduce_bf16_cpu_wrapper),
316    ep!("mean_reduce", "f16", mean_reduce_f16_cpu_wrapper),
317    ep!("max_reduce", "f32", max_reduce_f32_cpu_wrapper),
318    ep!("max_reduce", "f64", max_reduce_f64_cpu_wrapper),
319    ep!("max_reduce", "bf16", max_reduce_bf16_cpu_wrapper),
320    ep!("max_reduce", "f16", max_reduce_f16_cpu_wrapper),
321    ep!("min_reduce", "f32", min_reduce_f32_cpu_wrapper),
322    ep!("min_reduce", "f64", min_reduce_f64_cpu_wrapper),
323    ep!("min_reduce", "bf16", min_reduce_bf16_cpu_wrapper),
324    ep!("min_reduce", "f16", min_reduce_f16_cpu_wrapper),
325];
326
327/// The CPU broadcast-target REDUCE-TO family's `symbol → production wrapper`
328/// map (ReduceSumTo / ReduceMaxTo × 4 dtypes = 8, key `[T, T]`, +
329/// ReduceMaxToBackward × 4 dtypes = 4, key `[T, T, T]` = 12). Contract:
330/// `fuel-dispatch/kernel-contracts/cpu/reduce-to.fkc.md`. Each per-(op, dtype) section
331/// (`## reduce_sum_to_f32`, …) declares a SPECIFIC single-dtype `entry_point`
332/// (`…::reduce_sum_to_f32`), so it does NOT fan — the importer resolves that
333/// symbol AS-IS. The forward keys are `[T, T]` (input + `passthrough(input)`
334/// output; the target `input_shape`/`output_shape` ride in
335/// `OpParams::ReduceSumTo` / `OpParams::ReduceMaxTo`, NOT the dtype-list); the
336/// backward key is `[T, T, T]` (x, upstream + `passthrough(x)` output). The
337/// `## reduce_to` chassis umbrella is `registrable: false` (§3.10 describe-only)
338/// and never resolves, so it is absent here (without it the chassis would
339/// double-register `ReduceSumTo`/`[F32]` → `DuplicateKernelRef` at init).
340pub static CPU_REDUCE_TO_ENTRY_POINTS: &[(&str, KernelRef)] = &[
341    ep!("reduce_sum_to", "f32", reduce_sum_to_f32_cpu_wrapper),
342    ep!("reduce_sum_to", "f64", reduce_sum_to_f64_cpu_wrapper),
343    ep!("reduce_sum_to", "bf16", reduce_sum_to_bf16_cpu_wrapper),
344    ep!("reduce_sum_to", "f16", reduce_sum_to_f16_cpu_wrapper),
345    ep!("reduce_max_to", "f32", reduce_max_to_f32_cpu_wrapper),
346    ep!("reduce_max_to", "f64", reduce_max_to_f64_cpu_wrapper),
347    ep!("reduce_max_to", "bf16", reduce_max_to_bf16_cpu_wrapper),
348    ep!("reduce_max_to", "f16", reduce_max_to_f16_cpu_wrapper),
349    ep!(
350        "reduce_max_to_backward",
351        "f32",
352        reduce_max_to_backward_f32_cpu_wrapper
353    ),
354    ep!(
355        "reduce_max_to_backward",
356        "f64",
357        reduce_max_to_backward_f64_cpu_wrapper
358    ),
359    ep!(
360        "reduce_max_to_backward",
361        "bf16",
362        reduce_max_to_backward_bf16_cpu_wrapper
363    ),
364    ep!(
365        "reduce_max_to_backward",
366        "f16",
367        reduce_max_to_backward_f16_cpu_wrapper
368    ),
369];
370
371/// The CPU last-dim NORM (forward) family's `symbol → production wrapper` map
372/// (Softmax / LogSoftmax / RmsNorm / LayerNorm last-dim × 4 dtypes = 16). Contract:
373/// `fuel-dispatch/kernel-contracts/cpu/norm.fkc.md`. Each per-(op, dtype) section
374/// (`## softmax_last_dim_f32`, `## rms_norm_last_dim_f32`, …) declares a SPECIFIC
375/// single-dtype `entry_point` (`…::softmax_last_dim_f32`), so none of them fan —
376/// the importer resolves that symbol AS-IS. The binding key is `[T, T]` (a SINGLE
377/// input + `passthrough(input)` output; the RMS/LayerNorm kernels carry NO affine
378/// gamma/beta operand — they are the bare normalization — and `outer_count` /
379/// `last_dim` / `eps` ride in `OpParams::{SoftmaxLastDim,LogSoftmaxLastDim,
380/// NormLastDim}`, NOT the dtype-list), identical to the deleted `&unary(t)` regs.
381/// The `log_softmax` wrapper fn-names (`log_softmax_<dt>_cpu_wrapper`) differ from
382/// their `log_softmax_last_dim_<dt>` symbol — the `ep!` symbol is built from the
383/// `$op`/`$dt` literals, so the mapping still binds the correct contract symbol
384/// (mirrors the clamp/powi/where fn-vs-symbol cases). This contract has NO `##`
385/// chassis umbrella section, so there is no `registrable: false` describe-only
386/// entry to omit; the BACKWARD forms live in a separate norm-backward contract.
387pub static CPU_NORM_ENTRY_POINTS: &[(&str, KernelRef)] = &[
388    ep!("softmax_last_dim", "f32", softmax_last_dim_f32_cpu_wrapper),
389    ep!("softmax_last_dim", "f64", softmax_last_dim_f64_cpu_wrapper),
390    ep!(
391        "softmax_last_dim",
392        "bf16",
393        softmax_last_dim_bf16_cpu_wrapper
394    ),
395    ep!("softmax_last_dim", "f16", softmax_last_dim_f16_cpu_wrapper),
396    ep!("log_softmax_last_dim", "f32", log_softmax_f32_cpu_wrapper),
397    ep!("log_softmax_last_dim", "f64", log_softmax_f64_cpu_wrapper),
398    ep!("log_softmax_last_dim", "bf16", log_softmax_bf16_cpu_wrapper),
399    ep!("log_softmax_last_dim", "f16", log_softmax_f16_cpu_wrapper),
400    ep!(
401        "rms_norm_last_dim",
402        "f32",
403        rms_norm_last_dim_f32_cpu_wrapper
404    ),
405    ep!(
406        "rms_norm_last_dim",
407        "f64",
408        rms_norm_last_dim_f64_cpu_wrapper
409    ),
410    ep!(
411        "rms_norm_last_dim",
412        "bf16",
413        rms_norm_last_dim_bf16_cpu_wrapper
414    ),
415    ep!(
416        "rms_norm_last_dim",
417        "f16",
418        rms_norm_last_dim_f16_cpu_wrapper
419    ),
420    ep!(
421        "layer_norm_last_dim",
422        "f32",
423        layer_norm_last_dim_f32_cpu_wrapper
424    ),
425    ep!(
426        "layer_norm_last_dim",
427        "f64",
428        layer_norm_last_dim_f64_cpu_wrapper
429    ),
430    ep!(
431        "layer_norm_last_dim",
432        "bf16",
433        layer_norm_last_dim_bf16_cpu_wrapper
434    ),
435    ep!(
436        "layer_norm_last_dim",
437        "f16",
438        layer_norm_last_dim_f16_cpu_wrapper
439    ),
440];
441
442/// The CPU last-dim NORM-BACKWARD family's `symbol → production wrapper` map
443/// (Softmax / LogSoftmax / RmsNorm / LayerNorm last-dim BACKWARD × 4 dtypes = 16).
444/// Contract: `fuel-dispatch/kernel-contracts/cpu/norm-backward.fkc.md`. Each per-(op, dtype)
445/// section (`## softmax_last_dim_backward_f32`, `## rms_norm_last_dim_backward_f32`,
446/// …) declares a SPECIFIC single-dtype `entry_point`
447/// (`…::softmax_last_dim_backward_f32`), so none of them fan — the importer
448/// resolves that symbol AS-IS. The binding key is `[T, T, T]` — the BARE backward
449/// takes TWO inputs (softmax/log-softmax: the forward output `y` + the upstream
450/// gradient `g`; layer/rms-norm: the forward input `x` + `g`, stats recomputed) and
451/// writes ONE `passthrough(y|x)` output, and outer_count / last_dim / eps ride in
452/// `OpParams::{SoftmaxLastDim,LogSoftmaxLastDim,NormLastDim}`, NOT the dtype-list —
453/// identical to the deleted `&binary(t)` regs. The `log_softmax` backward wrapper
454/// fn-names (`log_softmax_backward_<dt>_cpu_wrapper`) differ from their
455/// `log_softmax_last_dim_backward_<dt>` symbol — the `ep!` symbol is built from the
456/// `$op`/`$dt` literals, so the mapping still binds the correct contract symbol
457/// (mirrors the forward `log_softmax` fn-vs-symbol case). This contract has NO `##`
458/// chassis umbrella section, so there is no `registrable: false` describe-only entry
459/// to omit; the FORWARD forms live in the separate norm contract.
460pub static CPU_NORM_BACKWARD_ENTRY_POINTS: &[(&str, KernelRef)] = &[
461    ep!(
462        "softmax_last_dim_backward",
463        "f32",
464        softmax_last_dim_backward_f32_cpu_wrapper
465    ),
466    ep!(
467        "softmax_last_dim_backward",
468        "f64",
469        softmax_last_dim_backward_f64_cpu_wrapper
470    ),
471    ep!(
472        "softmax_last_dim_backward",
473        "bf16",
474        softmax_last_dim_backward_bf16_cpu_wrapper
475    ),
476    ep!(
477        "softmax_last_dim_backward",
478        "f16",
479        softmax_last_dim_backward_f16_cpu_wrapper
480    ),
481    ep!(
482        "log_softmax_last_dim_backward",
483        "f32",
484        log_softmax_backward_f32_cpu_wrapper
485    ),
486    ep!(
487        "log_softmax_last_dim_backward",
488        "f64",
489        log_softmax_backward_f64_cpu_wrapper
490    ),
491    ep!(
492        "log_softmax_last_dim_backward",
493        "bf16",
494        log_softmax_backward_bf16_cpu_wrapper
495    ),
496    ep!(
497        "log_softmax_last_dim_backward",
498        "f16",
499        log_softmax_backward_f16_cpu_wrapper
500    ),
501    ep!(
502        "rms_norm_last_dim_backward",
503        "f32",
504        rms_norm_last_dim_backward_f32_cpu_wrapper
505    ),
506    ep!(
507        "rms_norm_last_dim_backward",
508        "f64",
509        rms_norm_last_dim_backward_f64_cpu_wrapper
510    ),
511    ep!(
512        "rms_norm_last_dim_backward",
513        "bf16",
514        rms_norm_last_dim_backward_bf16_cpu_wrapper
515    ),
516    ep!(
517        "rms_norm_last_dim_backward",
518        "f16",
519        rms_norm_last_dim_backward_f16_cpu_wrapper
520    ),
521    ep!(
522        "layer_norm_last_dim_backward",
523        "f32",
524        layer_norm_last_dim_backward_f32_cpu_wrapper
525    ),
526    ep!(
527        "layer_norm_last_dim_backward",
528        "f64",
529        layer_norm_last_dim_backward_f64_cpu_wrapper
530    ),
531    ep!(
532        "layer_norm_last_dim_backward",
533        "bf16",
534        layer_norm_last_dim_backward_bf16_cpu_wrapper
535    ),
536    ep!(
537        "layer_norm_last_dim_backward",
538        "f16",
539        layer_norm_last_dim_backward_f16_cpu_wrapper
540    ),
541];
542
543/// The CPU RoPE (rotary position embedding) family's `symbol → production
544/// wrapper` map (1 op × 4 dtypes = 4). Contract:
545/// `fuel-dispatch/kernel-contracts/cpu/rope.fkc.md`. Each per-dtype section
546/// (`## rope_f32`, …) declares a SPECIFIC single-dtype `entry_point`
547/// (`…::rope_f32`), so none of them fan — the importer resolves that symbol
548/// AS-IS. The binding key is `[T, T, T, T]` — RoPE takes THREE inputs (`x` +
549/// the precomputed `cos`/`sin` tables, all one dtype; the `[seq, head_dim]`
550/// tables broadcast over the `outer_count` axis by the kernel re-indexing them
551/// per outer, NOT a stride-0 view) and writes ONE `passthrough(x)` output;
552/// outer_count / seq / head_dim ride in `OpParams::Rope`, NOT the dtype-list —
553/// identical to the deleted `rope_dts(t)` regs. This contract has NO `##`
554/// chassis umbrella section, so there is no `registrable: false` describe-only
555/// entry to omit. RoPE is ALSO registered in the `FusedKernelRegistry`
556/// (`register_default_fused_kernels`, `FusedOps::ROPE`) — that is a SEPARATE
557/// registry seam and stays untouched; this map only serves the
558/// `KernelBindingTable` primitive path.
559pub static CPU_ROPE_ENTRY_POINTS: &[(&str, KernelRef)] = &[
560    ep!("rope", "f32", rope_f32_cpu_wrapper),
561    ep!("rope", "f64", rope_f64_cpu_wrapper),
562    ep!("rope", "bf16", rope_bf16_cpu_wrapper),
563    ep!("rope", "f16", rope_f16_cpu_wrapper),
564];
565
566/// The CPU SSM / Mamba family's `symbol → production wrapper` map — the FULL
567/// family: FusedSoftmaxCrossEntropy + CausalConv1d + SelectiveScan +
568/// SsdChunkScan (4 ops × 4 dtypes = 16). Contract:
569/// `fuel-dispatch/kernel-contracts/cpu/ssm.fkc.md`. Each per-(op, dtype) section
570/// (`## fused_softmax_cross_entropy_f32`, `## selective_scan_f32`, …) declares a
571/// SPECIFIC single-dtype `entry_point` (`…::selective_scan_f32`), so none of
572/// them fan — the importer resolves that symbol AS-IS. Binding keys:
573/// - FSCE: `[T, I64, F32]` (logits T + I64 targets → `fixed(F32)` output;
574///   n_rows / vocab / reduction / ignore_index ride in
575///   `OpParams::FusedSoftmaxCrossEntropy`, NOT the dtype-list).
576/// - CausalConv1d: `[T, T, T, T]` (x, weight, bias + `passthrough(x)` output;
577///   batch / channels / seq / kernel / use_silu ride in `OpParams::CausalConv1d`).
578/// - SelectiveScan / SsdChunkScan: `[T; 6]` — 5 inputs (u,delta,a,b,c /
579///   x,dt,a,b,c) + the ONE bundled output slot. These sections return a
580///   `return.bundle` multi-output (Option C, one packed buffer `[y ; last_state]`);
581///   the importer's key-builder now appends the bundle's PRIMARY-slot dtype
582///   (`passthrough(u)` / `passthrough(x)` → T) to the key tail (`fkc/lower.rs`
583///   `assemble_dtype_variants`), so a bundle section keys `[T; 6]` byte-for-byte
584///   the deleted hand-written reg. The geometry / delta_softplus / chunk_size
585///   ride in `OpParams::{SelectiveScan, SsdChunkScan}`, NOT the dtype-list.
586///
587/// These sections have NO `##` chassis umbrella, so there is no
588/// `registrable: false` describe-only entry to omit.
589pub static CPU_SSM_ENTRY_POINTS: &[(&str, KernelRef)] = &[
590    ep!(
591        "fused_softmax_cross_entropy",
592        "f32",
593        fused_softmax_cross_entropy_f32_cpu_wrapper
594    ),
595    ep!(
596        "fused_softmax_cross_entropy",
597        "f64",
598        fused_softmax_cross_entropy_f64_cpu_wrapper
599    ),
600    ep!(
601        "fused_softmax_cross_entropy",
602        "bf16",
603        fused_softmax_cross_entropy_bf16_cpu_wrapper
604    ),
605    ep!(
606        "fused_softmax_cross_entropy",
607        "f16",
608        fused_softmax_cross_entropy_f16_cpu_wrapper
609    ),
610    ep!("causal_conv1d", "f32", causal_conv1d_f32_cpu_wrapper),
611    ep!("causal_conv1d", "f64", causal_conv1d_f64_cpu_wrapper),
612    ep!("causal_conv1d", "bf16", causal_conv1d_bf16_cpu_wrapper),
613    ep!("causal_conv1d", "f16", causal_conv1d_f16_cpu_wrapper),
614    ep!("selective_scan", "f32", selective_scan_f32_cpu_wrapper),
615    ep!("selective_scan", "f64", selective_scan_f64_cpu_wrapper),
616    ep!("selective_scan", "bf16", selective_scan_bf16_cpu_wrapper),
617    ep!("selective_scan", "f16", selective_scan_f16_cpu_wrapper),
618    ep!("ssd_chunk_scan", "f32", ssd_chunk_scan_f32_cpu_wrapper),
619    ep!("ssd_chunk_scan", "f64", ssd_chunk_scan_f64_cpu_wrapper),
620    ep!("ssd_chunk_scan", "bf16", ssd_chunk_scan_bf16_cpu_wrapper),
621    ep!("ssd_chunk_scan", "f16", ssd_chunk_scan_f16_cpu_wrapper),
622];
623
624/// The CPU 2D-convolution family's `symbol → production wrapper` map — the FULL
625/// family: Conv2D + ConvTranspose2D × 4 dtypes = 8 symbols (each symbol serves
626/// BOTH operand-count keys). Contract: `fuel-dispatch/kernel-contracts/cpu/conv.fkc.md`.
627/// Each per-(op, dtype) section (`## conv2d_f32`, `## conv_transpose2d_f32`, …)
628/// declares a SPECIFIC single-dtype `entry_point` (`…::conv2d_f32`), so none of
629/// them dtype-fan — the importer resolves that symbol AS-IS. Because the contract
630/// marks `bias` as `optional: true`, the importer's key-builder fans each section
631/// into BOTH the no-bias key `[T, T, T]` (x, weight + out) and the with-bias key
632/// `[T, T, T, T]` (x, weight, bias + `passthrough(x)` output) — both resolving
633/// this SAME symbol/wrapper (the CPU wrapper handles 2 or 3 inputs). The spatial
634/// geometry (x_shape/w_shape/out_shape, stride/padding/`[output_padding]`/dilation,
635/// groups) rides in `OpParams::{Conv2D, ConvTranspose2D}`, NOT the dtype-list.
636/// This map is the SOLE registration path for the whole family: every
637/// hand-written `table.register(Conv2D/ConvTranspose2D, …)` reg (both operand
638/// counts) is DELETED.
639///
640/// The conv ops' SEPARATE `FusedKernelRegistry` seam
641/// (`register_default_fused_kernels`, `FusedOps::{CONV2D, CONV_TRANSPOSE2D}`,
642/// both no-bias + with-bias) is untouched; this map only serves the
643/// `KernelBindingTable` primitive path. These sections have NO `##` chassis
644/// umbrella, so there is no `registrable: false` describe-only entry to omit.
645pub static CPU_CONV_ENTRY_POINTS: &[(&str, KernelRef)] = &[
646    ep!("conv2d", "f32", conv2d_f32_cpu_wrapper),
647    ep!("conv2d", "f64", conv2d_f64_cpu_wrapper),
648    ep!("conv2d", "bf16", conv2d_bf16_cpu_wrapper),
649    ep!("conv2d", "f16", conv2d_f16_cpu_wrapper),
650    ep!("conv_transpose2d", "f32", conv_transpose2d_f32_cpu_wrapper),
651    ep!("conv_transpose2d", "f64", conv_transpose2d_f64_cpu_wrapper),
652    ep!(
653        "conv_transpose2d",
654        "bf16",
655        conv_transpose2d_bf16_cpu_wrapper
656    ),
657    ep!("conv_transpose2d", "f16", conv_transpose2d_f16_cpu_wrapper),
658];
659
660/// The CPU **padding** family's `symbol → production wrapper` map — the FULL
661/// family: mode-unified forward `Pad` × 6 dtypes = 6 + `PadBackward` × 4 dtypes
662/// = 4 (all key `[T, T]`). Contract: `fuel-dispatch/kernel-contracts/cpu/padding.fkc.md`.
663///
664/// - **Forward `Pad`** is a dtype-agnostic byte kernel with a SINGLE production
665///   wrapper — the mode-dispatching `pad_cpu_wrapper` (dispatch layer), which
666///   selects `pad_const_cpu` / `pad_reflect_cpu` / `pad_replicate_cpu` at runtime
667///   via `mode_tag` (incl. the reflect `before/after <= n-1` validation). The
668///   contract's ONE registrable `## pad` section declares a BASE `entry_point`
669///   (`…::pad_cpu`, a SYNTHETIC umbrella — there is no real `pad_cpu` byte kernel;
670///   the three real mode kernels are `pad_{const,reflect,replicate}_cpu`) + an
671///   enumerated `dtypes` list trimmed to production's wired 6
672///   (`U8/U32/BF16/F16/F32/F64`), so the importer's §3.4 multi-dtype fan-out
673///   resolves `pad_cpu_<dtype>` (a FABRICATED per-dtype symbol) — every dtype
674///   variant mapping to the ONE `pad_cpu_wrapper`, exactly the Flip/Roll/Concat
675///   pattern. The fan emits BYTE-FOR-BYTE the deleted hand-written
676///   `table.register(Pad, &unary(t), …)` regs (key `[T, T]`, `out:
677///   passthrough(input)`; the in_shape/out_shape/padding/mode_tag/fill_bytes ride
678///   in `OpParams::Pad`, NOT the dtype-list). The three per-mode sections
679///   (`pad_const_cpu` / `pad_reflect_cpu` / `pad_replicate_cpu`) and the
680///   `pad_walk_cpu` helper are `registrable: false` (§3.10 describe-only mode
681///   documentation) and never resolve, so they are ABSENT here.
682/// - **`PadBackward`** is per-dtype (typed gradient accumulation — bf16/f16/f32
683///   widen the scratch accumulator to f64, unlike the dtype-agnostic forward
684///   copy). Each per-dtype section (`## pad_backward_f32`, …) declares a SPECIFIC
685///   single-dtype `entry_point` (`…::pad_backward_f32`) resolved AS-IS (no fan),
686///   key `[T, T]` (grad_out + `passthrough(grad_out)` grad_in; in_shape/out_shape/
687///   padding/mode_tag ride in `OpParams::PadBackward`).
688pub static CPU_PADDING_ENTRY_POINTS: &[(&str, KernelRef)] = &[
689    // Forward Pad — mode-unified dtype-agnostic byte kernel; the fabricated
690    // `pad_cpu_<dt>` symbol maps to the ONE mode-dispatching `pad_cpu_wrapper`.
691    ep!("pad_cpu", "u8", pad_cpu_wrapper),
692    ep!("pad_cpu", "u32", pad_cpu_wrapper),
693    ep!("pad_cpu", "bf16", pad_cpu_wrapper),
694    ep!("pad_cpu", "f16", pad_cpu_wrapper),
695    ep!("pad_cpu", "f32", pad_cpu_wrapper),
696    ep!("pad_cpu", "f64", pad_cpu_wrapper),
697    // PadBackward — per-dtype typed accumulation; resolved AS-IS (no fan).
698    ep!("pad_backward", "f32", pad_backward_f32_cpu_wrapper),
699    ep!("pad_backward", "f64", pad_backward_f64_cpu_wrapper),
700    ep!("pad_backward", "bf16", pad_backward_bf16_cpu_wrapper),
701    ep!("pad_backward", "f16", pad_backward_f16_cpu_wrapper),
702];
703
704/// The CPU **shape-ops** family's `symbol → production wrapper` map — the
705/// MIGRATED subset (Flip + Roll + Concat + MaskedFill + WriteSlice +
706/// WriteSliceRotating dtype-fanned + CumSum per-dtype). Contract:
707/// `fuel-dispatch/kernel-contracts/cpu/shape-ops.fkc.md`.
708///
709/// - **Flip** / **Roll** / **Concat** / **MaskedFill** / **WriteSlice** /
710///   **WriteSliceRotating** are **dtype-agnostic byte kernels** with a SINGLE
711///   production wrapper each. Their contract sections declare a BASE
712///   `entry_point` (`…::flip_cpu`, `…::roll_cpu`, `…::concat_cpu`,
713///   `…::masked_fill_cpu`, `…::write_slice_cpu`, `…::write_slice_rotating_cpu`) +
714///   an enumerated `dtypes` list, so the importer's §3.4 multi-dtype fan-out
715///   resolves `<base>_<dtype>` (`flip_cpu_f32`, …) — a FABRICATED per-dtype
716///   symbol (there is no real `flip_cpu_f32` fn) that every dtype variant maps to
717///   the ONE dtype-agnostic wrapper. The contract's `dtypes` list was trimmed to
718///   production's wired set (Flip/Roll/MaskedFill/WriteSlice/WriteSliceRotating 6:
719///   F32/F64/BF16/F16/U32/U8; Concat 9: +I16/I32/I64) so the fan emits
720///   BYTE-FOR-BYTE the deleted hand-written regs — Flip/Roll/Concat/WriteSlice/
721///   WriteSliceRotating key `[T, T]`, MaskedFill key `[T, U8, T]` (`input` is the
722///   sole varying operand; `mask` stays the fixed U8 slot; `out:
723///   passthrough(input)`). **WriteSlice / WriteSliceRotating** model `dest` as the
724///   in-place OUTPUT slot (not a key input) and — for the rotating op — the U32
725///   `position` as a NON-KEY runtime operand, so the importer keys `[T_src, T_out]`
726///   = `[T, T]`, matching `build_lookup_dtypes`' canonicalization exactly.
727/// - **CumSum** is per-dtype (typed accumulation, NOT a byte copy — f32/f64
728///   native, bf16/f16 widen to an f32 accumulator), so each `cumsum_<dt>`
729///   section declares a SPECIFIC single-dtype `entry_point` resolved AS-IS (no
730///   fan), key `[T, T]`, mapping to its OWN typed wrapper.
731///
732/// DEFERRED (absent here — never resolved): `contiguize` and `triangular` are
733/// `registrable: false` chassis/describe-only sections (no `OpKind::Contiguize`;
734/// `triangular` is the umbrella backing the two hand-written `Triu`/`Tril`
735/// OpKinds, not a keyable section).
736pub static CPU_SHAPE_OPS_ENTRY_POINTS: &[(&str, KernelRef)] = &[
737    // Flip — dtype-agnostic byte reorder; one wrapper fanned per dtype.
738    ep!("flip_cpu", "f32", flip_cpu_wrapper),
739    ep!("flip_cpu", "f64", flip_cpu_wrapper),
740    ep!("flip_cpu", "bf16", flip_cpu_wrapper),
741    ep!("flip_cpu", "f16", flip_cpu_wrapper),
742    ep!("flip_cpu", "u32", flip_cpu_wrapper),
743    ep!("flip_cpu", "u8", flip_cpu_wrapper),
744    // Roll — dtype-agnostic cyclic shift.
745    ep!("roll_cpu", "f32", roll_cpu_wrapper),
746    ep!("roll_cpu", "f64", roll_cpu_wrapper),
747    ep!("roll_cpu", "bf16", roll_cpu_wrapper),
748    ep!("roll_cpu", "f16", roll_cpu_wrapper),
749    ep!("roll_cpu", "u32", roll_cpu_wrapper),
750    ep!("roll_cpu", "u8", roll_cpu_wrapper),
751    // Concat — variadic uniform-dtype join collapsed to the [T, T] shorthand.
752    ep!("concat_cpu", "f32", concat_cpu_wrapper),
753    ep!("concat_cpu", "f64", concat_cpu_wrapper),
754    ep!("concat_cpu", "bf16", concat_cpu_wrapper),
755    ep!("concat_cpu", "f16", concat_cpu_wrapper),
756    ep!("concat_cpu", "u32", concat_cpu_wrapper),
757    ep!("concat_cpu", "u8", concat_cpu_wrapper),
758    ep!("concat_cpu", "i16", concat_cpu_wrapper),
759    ep!("concat_cpu", "i32", concat_cpu_wrapper),
760    ep!("concat_cpu", "i64", concat_cpu_wrapper),
761    // MaskedFill — dtype-agnostic data + fixed U8 mask; key [T, U8, T].
762    ep!("masked_fill_cpu", "f32", masked_fill_cpu_wrapper),
763    ep!("masked_fill_cpu", "f64", masked_fill_cpu_wrapper),
764    ep!("masked_fill_cpu", "bf16", masked_fill_cpu_wrapper),
765    ep!("masked_fill_cpu", "f16", masked_fill_cpu_wrapper),
766    ep!("masked_fill_cpu", "u32", masked_fill_cpu_wrapper),
767    ep!("masked_fill_cpu", "u8", masked_fill_cpu_wrapper),
768    // CumSum — per-dtype typed kernels, resolved AS-IS (no fan).
769    ep!("cumsum", "f32", cumsum_f32_cpu_wrapper),
770    ep!("cumsum", "f64", cumsum_f64_cpu_wrapper),
771    ep!("cumsum", "bf16", cumsum_bf16_cpu_wrapper),
772    ep!("cumsum", "f16", cumsum_f16_cpu_wrapper),
773    // WriteSlice — in-place rectangular scatter; dtype-agnostic byte copy, one
774    // wrapper fanned per dtype. `dest` is the in-place OUTPUT slot, so the key is
775    // `[T_src, T_out]` = [T, T]; the fabricated `write_slice_cpu_<dt>` symbol maps
776    // to the ONE dtype-agnostic wrapper.
777    ep!("write_slice_cpu", "f32", write_slice_cpu_wrapper),
778    ep!("write_slice_cpu", "f64", write_slice_cpu_wrapper),
779    ep!("write_slice_cpu", "bf16", write_slice_cpu_wrapper),
780    ep!("write_slice_cpu", "f16", write_slice_cpu_wrapper),
781    ep!("write_slice_cpu", "u32", write_slice_cpu_wrapper),
782    ep!("write_slice_cpu", "u8", write_slice_cpu_wrapper),
783    // WriteSliceRotating — in-place ring-buffer scatter; same [T, T] key (dest =
784    // output slot; the runtime `position` U32 operand is NOT a key slot). One
785    // dtype-agnostic wrapper fanned per dtype.
786    ep!(
787        "write_slice_rotating_cpu",
788        "f32",
789        write_slice_rotating_cpu_wrapper
790    ),
791    ep!(
792        "write_slice_rotating_cpu",
793        "f64",
794        write_slice_rotating_cpu_wrapper
795    ),
796    ep!(
797        "write_slice_rotating_cpu",
798        "bf16",
799        write_slice_rotating_cpu_wrapper
800    ),
801    ep!(
802        "write_slice_rotating_cpu",
803        "f16",
804        write_slice_rotating_cpu_wrapper
805    ),
806    ep!(
807        "write_slice_rotating_cpu",
808        "u32",
809        write_slice_rotating_cpu_wrapper
810    ),
811    ep!(
812        "write_slice_rotating_cpu",
813        "u8",
814        write_slice_rotating_cpu_wrapper
815    ),
816    // WriteSliceDoff — in-place scatter with a device-resident I64 start on one
817    // axis (no wrap). Same [T, T] key (dest = output slot; the runtime I64
818    // `offset` operand is NOT a key slot). One dtype-agnostic wrapper per dtype.
819    ep!("write_slice_doff_cpu", "f32", write_slice_doff_cpu_wrapper),
820    ep!("write_slice_doff_cpu", "f64", write_slice_doff_cpu_wrapper),
821    ep!("write_slice_doff_cpu", "bf16", write_slice_doff_cpu_wrapper),
822    ep!("write_slice_doff_cpu", "f16", write_slice_doff_cpu_wrapper),
823    ep!("write_slice_doff_cpu", "u32", write_slice_doff_cpu_wrapper),
824    ep!("write_slice_doff_cpu", "u8", write_slice_doff_cpu_wrapper),
825];
826
827/// The CPU **indexing / gather / scatter** family's `symbol → production
828/// wrapper` map — the FULL family (IndexSelect + Gather dtype-fanned, IndexAdd +
829/// ScatterAdd per-dtype). Contract: `fuel-dispatch/kernel-contracts/cpu/indexing.fkc.md`.
830///
831/// - **IndexSelect** / **Gather** are **dtype-agnostic byte copies** (parameter-
832///   ized `dtype_size`, one copy per selected/gathered element) with a SINGLE
833///   production wrapper each. Their contract sections declare a BASE `entry_point`
834///   (`…::index_select_cpu` / `…::gather_cpu`) + an enumerated `dtypes` list, so
835///   the importer's §3.4 fan-out resolves `<base>_<dtype>` (`index_select_cpu_f32`,
836///   …) — a FABRICATED per-dtype symbol (there is no real `index_select_cpu_f32`
837///   fn) that every dtype variant maps to the ONE dtype-agnostic wrapper. The
838///   `indices` operand is the FIXED U32 slot and `out: passthrough(source)`, so
839///   the fan emits key `[T, U32, T]`. The contract's `dtypes` list was trimmed to
840///   production's 9 wired dtypes (F32/F64/BF16/F16/U32/U8/I16/I32/I64) — I8 is
841///   describable (byte-agnostic) but NOT wired — so the fan emits BYTE-FOR-BYTE
842///   the deleted hand-written `table.register(IndexSelect/Gather, …)` regs.
843/// - **IndexAdd** / **ScatterAdd** are **per-dtype** (typed accumulation — f32/f64
844///   native, bf16/f16 widen to an f32 accumulator; out seeded from `base` then
845///   `+= src`), so each `index_add_<dt>` / `scatter_add_<dt>` section declares a
846///   SPECIFIC single-dtype `entry_point` resolved AS-IS (no fan), key
847///   `[T, U32, T, T]` (`base`, U32 `indices`, `src`, `passthrough(base)` output),
848///   mapping to its OWN typed wrapper — 4 dtypes each (F32/F64/BF16/F16).
849pub static CPU_INDEXING_ENTRY_POINTS: &[(&str, KernelRef)] = &[
850    // IndexSelect — dtype-agnostic byte copy; the fabricated
851    // `index_select_cpu_<dt>` symbol maps to the ONE `index_select_cpu_wrapper`.
852    ep!("index_select_cpu", "f32", index_select_cpu_wrapper),
853    ep!("index_select_cpu", "f64", index_select_cpu_wrapper),
854    ep!("index_select_cpu", "bf16", index_select_cpu_wrapper),
855    ep!("index_select_cpu", "f16", index_select_cpu_wrapper),
856    ep!("index_select_cpu", "u32", index_select_cpu_wrapper),
857    ep!("index_select_cpu", "u8", index_select_cpu_wrapper),
858    ep!("index_select_cpu", "i16", index_select_cpu_wrapper),
859    ep!("index_select_cpu", "i32", index_select_cpu_wrapper),
860    ep!("index_select_cpu", "i64", index_select_cpu_wrapper),
861    // Gather — dtype-agnostic byte copy.
862    ep!("gather_cpu", "f32", gather_cpu_wrapper),
863    ep!("gather_cpu", "f64", gather_cpu_wrapper),
864    ep!("gather_cpu", "bf16", gather_cpu_wrapper),
865    ep!("gather_cpu", "f16", gather_cpu_wrapper),
866    ep!("gather_cpu", "u32", gather_cpu_wrapper),
867    ep!("gather_cpu", "u8", gather_cpu_wrapper),
868    ep!("gather_cpu", "i16", gather_cpu_wrapper),
869    ep!("gather_cpu", "i32", gather_cpu_wrapper),
870    ep!("gather_cpu", "i64", gather_cpu_wrapper),
871    // IndexAdd — per-dtype typed accumulation; resolved AS-IS (no fan).
872    ep!("index_add", "f32", index_add_f32_cpu_wrapper),
873    ep!("index_add", "f64", index_add_f64_cpu_wrapper),
874    ep!("index_add", "bf16", index_add_bf16_cpu_wrapper),
875    ep!("index_add", "f16", index_add_f16_cpu_wrapper),
876    // ScatterAdd — per-dtype typed accumulation; resolved AS-IS (no fan).
877    ep!("scatter_add", "f32", scatter_add_f32_cpu_wrapper),
878    ep!("scatter_add", "f64", scatter_add_f64_cpu_wrapper),
879    ep!("scatter_add", "bf16", scatter_add_bf16_cpu_wrapper),
880    ep!("scatter_add", "f16", scatter_add_f16_cpu_wrapper),
881];
882
883/// The CPU **matmul** family's `symbol → production wrapper` map — the FULL
884/// portable family: bare batched `MatMul` (6 dtypes) + fused `FusedLinear`
885/// (matmul + bias-add, 4 dtypes) = 10 entry points. Contract:
886/// `fuel-dispatch/kernel-contracts/cpu/matmul.fkc.md`.
887///
888/// Each per-(op, dtype) section (`## matmul_f32`, `## fused_linear_f32`, …)
889/// declares a SPECIFIC single-dtype `entry_point` (`…::matmul_f32`), so none of
890/// them dtype-fan — the importer resolves that symbol AS-IS. Binding keys:
891/// - **MatMul** `[T, T, T]` (lhs, rhs + `passthrough(lhs)` output); the batch
892///   geometry (lhs_batch_dims/rhs_batch_dims/m/n/k) rides in `OpParams::Matmul`,
893///   NOT the dtype-list. Float variants (F32/F64/BF16/F16) accumulate in
894///   f32/native and narrow on store; integer variants (I8/U8) accumulate in i32
895///   and SATURATE on store.
896/// - **FusedLinear** `[T, T, T, T]` (a, b, bias + `passthrough(a)` output);
897///   `bias` is a REQUIRED 1-D `[N]` operand (NOT `optional`, so no optional
898///   {absent, present} fan — a single 4-slot key per dtype). Reuses
899///   `OpParams::Matmul` for shape; the kernel seeds the accumulator with the
900///   bias then accumulates over `k`.
901///
902/// This map covers ONLY the portable (`kernel_source: "portable-cpu"`) kernels
903/// this contract declares. The MKL / AOCL BLAS siblings live in SEPARATE
904/// external backend crates (`fuel-mkl-cpu-backend` / `fuel-aocl-cpu-backend`),
905/// register through the exported dispatch helpers with their own
906/// `"mkl"`/`"aocl"` `kernel_source` tags as ranked ALTERNATIVES at the SAME
907/// keys, and are out of scope here (untouched). The quant `QMatMul` /
908/// `Nf4Matmul` OpKinds have their own contracts and stay hand-written. These
909/// sections have NO `##` chassis umbrella, so there is no `registrable: false`
910/// describe-only entry to omit; the SEPARATE `FusedKernelRegistry`
911/// `FusedOps::FUSED_LINEAR` seam (`register_default_fused_kernels`) is
912/// hand-written (the matmul contract declares no `fused_op`), and stays
913/// untouched — this map only serves the `KernelBindingTable` primitive path.
914pub static CPU_MATMUL_ENTRY_POINTS: &[(&str, KernelRef)] = &[
915    // Bare batched MatMul — key [T, T, T].
916    ep!("matmul", "f32", matmul_f32_cpu_wrapper),
917    ep!("matmul", "f64", matmul_f64_cpu_wrapper),
918    ep!("matmul", "bf16", matmul_bf16_cpu_wrapper),
919    ep!("matmul", "f16", matmul_f16_cpu_wrapper),
920    ep!("matmul", "i8", matmul_i8_cpu_wrapper),
921    ep!("matmul", "u8", matmul_u8_cpu_wrapper),
922    // Fused matmul + bias-add — key [T, T, T, T].
923    ep!("fused_linear", "f32", fused_linear_f32_cpu_wrapper),
924    ep!("fused_linear", "f64", fused_linear_f64_cpu_wrapper),
925    ep!("fused_linear", "bf16", fused_linear_bf16_cpu_wrapper),
926    ep!("fused_linear", "f16", fused_linear_f16_cpu_wrapper),
927];
928
929/// The CPU **attention** family's `symbol → production wrapper` map — the
930/// MIGRATED (`KernelBindingTable`) subset: forward `FlashAttn` (4 dtypes) +
931/// `FlashAttnBackward{Q,K,V}` (3 selectors × 4 dtypes) = 16 entry points.
932/// Contract: `fuel-dispatch/kernel-contracts/cpu/attention.fkc.md`.
933///
934/// Each per-(op, dtype) section (`## flash_attn_f32`, `## flash_attn_backward_q_f32`,
935/// …) declares a SPECIFIC single-dtype `entry_point`, so none of them dtype-fan
936/// — the importer resolves that symbol AS-IS. Because the contract marks
937/// `alibi_slopes` as `optional: true` (the LAST input), the importer's
938/// key-builder fans each section into BOTH the no-alibi key (`[q,k,v,out]` /
939/// `[q,k,v,do,out]`) and the with-alibi key (`+alibi`) — both resolving this
940/// SAME symbol/wrapper (the CPU wrapper handles the presence/absence of the
941/// alibi operand). The softmax/mask geometry rides in `OpParams::FlashAttn`
942/// (shared by the forward op AND the three backward selectors — there is no
943/// dedicated backward `OpParams` variant), NOT the dtype-list.
944///
945/// Two symbol shapes:
946/// - **Forward FlashAttn** kernels are byte-kernel symbols
947///   (`fuel_cpu_backend::byte_kernels::flash_attn_<dt>`, the `ep!` shape).
948/// - **FlashAttnBackward{Q,K,V}** wrappers live in the dispatch layer (they pin
949///   which gradient the shared byte-kernel writes via a `FaBackwardWhich`
950///   selector), so their symbol is the fully-qualified
951///   `fuel_dispatch::dispatch::<wrapper>` path (the `ep_dispatch!` shape).
952///
953/// **PagedAttn is REGISTRABLE** (`registrable: true` in the contract). Its
954/// `fdx.gather: paged_blocks` pool is import METADATA (§3.9.1: the block_table /
955/// context_lens ride as ordinary U32 operands + `OpParams::PagedAttn`, so
956/// registration does not depend on the FDX gather VIEW, which stays
957/// [consumer-ahead]), so the importer validates the gather block for coherence
958/// and resolves the four paged `byte_kernels::paged_attn_<dt>` symbols here. The
959/// contract marks `alibi_slopes` as `optional: true` (last input), so the
960/// key-builder fans each paged section into BOTH the no-alibi key
961/// `[q,kc,vc,bt:U32,cl:U32,out]` and the with-alibi key `+alibi` — both resolving
962/// the SAME wrapper (the CPU `paged_attn_<dt>_cpu_wrapper` handles 5 or 6 inputs).
963/// The SEPARATE `FusedKernelRegistry` FLASH_ATTN* / PAGED_ATTN seam
964/// (`register_default_fused_kernels`) is a distinct registry and stays untouched;
965/// this map only serves the `KernelBindingTable` primitive path.
966pub static CPU_ATTENTION_ENTRY_POINTS: &[(&str, KernelRef)] = &[
967    // Forward FlashAttn — byte-kernel symbols; keys [T,T,T,T] / [T,T,T,T,T].
968    ep!("flash_attn", "f32", flash_attn_f32_cpu_wrapper),
969    ep!("flash_attn", "f64", flash_attn_f64_cpu_wrapper),
970    ep!("flash_attn", "bf16", flash_attn_bf16_cpu_wrapper),
971    ep!("flash_attn", "f16", flash_attn_f16_cpu_wrapper),
972    // FlashAttnBackward{Q,K,V} — dispatch-layer wrapper symbols;
973    // keys [T,T,T,T,T] / [T,T,T,T,T,T].
974    ep_dispatch!(flash_attn_backward_q_f32_cpu_wrapper),
975    ep_dispatch!(flash_attn_backward_q_f64_cpu_wrapper),
976    ep_dispatch!(flash_attn_backward_q_bf16_cpu_wrapper),
977    ep_dispatch!(flash_attn_backward_q_f16_cpu_wrapper),
978    ep_dispatch!(flash_attn_backward_k_f32_cpu_wrapper),
979    ep_dispatch!(flash_attn_backward_k_f64_cpu_wrapper),
980    ep_dispatch!(flash_attn_backward_k_bf16_cpu_wrapper),
981    ep_dispatch!(flash_attn_backward_k_f16_cpu_wrapper),
982    ep_dispatch!(flash_attn_backward_v_f32_cpu_wrapper),
983    ep_dispatch!(flash_attn_backward_v_f64_cpu_wrapper),
984    ep_dispatch!(flash_attn_backward_v_bf16_cpu_wrapper),
985    ep_dispatch!(flash_attn_backward_v_f16_cpu_wrapper),
986    // PagedAttn — byte-kernel symbols; keys [T,T,T,U32,U32,T] (+[T] with-alibi).
987    // The optional-operand fan resolves both keys to the same per-dtype wrapper.
988    ep!("paged_attn", "f32", paged_attn_f32_cpu_wrapper),
989    ep!("paged_attn", "f64", paged_attn_f64_cpu_wrapper),
990    ep!("paged_attn", "bf16", paged_attn_bf16_cpu_wrapper),
991    ep!("paged_attn", "f16", paged_attn_f16_cpu_wrapper),
992];
993
994/// The CPU **in-place scalar-param** family's `symbol → production wrapper`
995/// map — the FULL family: 21 in-place unary ops (`<op>_inplace`, each fanned
996/// ×4 dtypes = 84) + `InplaceAffine` / `ClampInplace` / `PowIInplace`
997/// (`affine_inplace` / `clamp_inplace` / `powi_inplace`, 4 dtypes each = 12) =
998/// 96 entry points. Contract:
999/// `fuel-dispatch/kernel-contracts/cpu/inplace-unary-affine.fkc.md`.
1000///
1001/// - **In-place unary** (`relu_inplace` … `gelu_erf_inplace`): each per-op
1002///   section declares a BASE `entry_point` (`…::relu_inplace`) + enumerates
1003///   `dtypes: [F32,F64,BF16,F16]`, so the importer's §3.4 multi-dtype fan-out
1004///   resolves `<base>_<dtype>` (`relu_inplace_f32`) against this table — the
1005///   `$op` literals below are the byte-kernel BASES (`<op>_inplace`), NOT the
1006///   OpKind names -- and since S13 the two no longer share a root spelling at
1007///   all. The two GELU flavors stay distinct: base `gelu_inplace` (the real
1008///   byte_kernels symbol, unrenamed) now binds `OpKind::GeluTanhInplace` (the
1009///   canonical tanh GELU) vs base `gelu_erf_inplace` (also unrenamed) now
1010///   binding `OpKind::GeluInplace` (bare `Gelu` means erf since S13).
1011/// - **InplaceAffine / ClampInplace / PowIInplace** are per-dtype SINGLE
1012///   sections (one enumerated dtype each), so they do NOT fan — the importer
1013///   resolves their specific `<op>_inplace_<dt>` symbol AS-IS. The affine rows
1014///   carry the THREE-WAY naming skew: the byte-kernel/entry_point suffix is
1015///   `affine_inplace_<dt>` while the production wrapper fn is
1016///   `inplace_affine_<dt>_cpu_wrapper` (words swapped) — the `ep!` symbol is
1017///   built from the `$op`/`$dt` literals (`affine_inplace`), so the mapping
1018///   still binds the correct contract symbol to the swapped-name wrapper
1019///   (mirrors the clamp/powi/log_softmax fn-vs-symbol cases). Clamp/powi
1020///   wrapper fn-names match their symbols directly.
1021///
1022/// Every binding keys `[T, T]` (the single `out` operand + its
1023/// `passthrough(out)` mirror; the executor's `WorkItemKind::InplaceKernel` arm
1024/// passes the target as `outputs[0]`, so the wrapper takes 0 inputs + 1 output,
1025/// but the binding-table KEY is `[T, T]`). Scalar params (affine `mul`/`add`,
1026/// clamp `min`/`max`, powi `exp`) ride in `OpParams::{Affine, Clamp, PowI}`, NOT
1027/// the dtype-list. The `## unary_inplace` chassis umbrella is `registrable: false`
1028/// (§3.10 describe-only) and never resolves, so it is absent here.
1029pub static CPU_INPLACE_ENTRY_POINTS: &[(&str, KernelRef)] = &[
1030    // In-place unary — 21 ops × 4 dtypes, base `<op>_inplace` fanned per dtype.
1031    ep!("relu_inplace", "f32", relu_inplace_f32_cpu_wrapper),
1032    ep!("relu_inplace", "f64", relu_inplace_f64_cpu_wrapper),
1033    ep!("relu_inplace", "bf16", relu_inplace_bf16_cpu_wrapper),
1034    ep!("relu_inplace", "f16", relu_inplace_f16_cpu_wrapper),
1035    ep!("silu_inplace", "f32", silu_inplace_f32_cpu_wrapper),
1036    ep!("silu_inplace", "f64", silu_inplace_f64_cpu_wrapper),
1037    ep!("silu_inplace", "bf16", silu_inplace_bf16_cpu_wrapper),
1038    ep!("silu_inplace", "f16", silu_inplace_f16_cpu_wrapper),
1039    ep!("gelu_inplace", "f32", gelu_inplace_f32_cpu_wrapper),
1040    ep!("gelu_inplace", "f64", gelu_inplace_f64_cpu_wrapper),
1041    ep!("gelu_inplace", "bf16", gelu_inplace_bf16_cpu_wrapper),
1042    ep!("gelu_inplace", "f16", gelu_inplace_f16_cpu_wrapper),
1043    ep!("tanh_inplace", "f32", tanh_inplace_f32_cpu_wrapper),
1044    ep!("tanh_inplace", "f64", tanh_inplace_f64_cpu_wrapper),
1045    ep!("tanh_inplace", "bf16", tanh_inplace_bf16_cpu_wrapper),
1046    ep!("tanh_inplace", "f16", tanh_inplace_f16_cpu_wrapper),
1047    ep!("sigmoid_inplace", "f32", sigmoid_inplace_f32_cpu_wrapper),
1048    ep!("sigmoid_inplace", "f64", sigmoid_inplace_f64_cpu_wrapper),
1049    ep!("sigmoid_inplace", "bf16", sigmoid_inplace_bf16_cpu_wrapper),
1050    ep!("sigmoid_inplace", "f16", sigmoid_inplace_f16_cpu_wrapper),
1051    ep!("neg_inplace", "f32", neg_inplace_f32_cpu_wrapper),
1052    ep!("neg_inplace", "f64", neg_inplace_f64_cpu_wrapper),
1053    ep!("neg_inplace", "bf16", neg_inplace_bf16_cpu_wrapper),
1054    ep!("neg_inplace", "f16", neg_inplace_f16_cpu_wrapper),
1055    ep!("abs_inplace", "f32", abs_inplace_f32_cpu_wrapper),
1056    ep!("abs_inplace", "f64", abs_inplace_f64_cpu_wrapper),
1057    ep!("abs_inplace", "bf16", abs_inplace_bf16_cpu_wrapper),
1058    ep!("abs_inplace", "f16", abs_inplace_f16_cpu_wrapper),
1059    ep!("sqr_inplace", "f32", sqr_inplace_f32_cpu_wrapper),
1060    ep!("sqr_inplace", "f64", sqr_inplace_f64_cpu_wrapper),
1061    ep!("sqr_inplace", "bf16", sqr_inplace_bf16_cpu_wrapper),
1062    ep!("sqr_inplace", "f16", sqr_inplace_f16_cpu_wrapper),
1063    ep!("sqrt_inplace", "f32", sqrt_inplace_f32_cpu_wrapper),
1064    ep!("sqrt_inplace", "f64", sqrt_inplace_f64_cpu_wrapper),
1065    ep!("sqrt_inplace", "bf16", sqrt_inplace_bf16_cpu_wrapper),
1066    ep!("sqrt_inplace", "f16", sqrt_inplace_f16_cpu_wrapper),
1067    ep!("rsqrt_inplace", "f32", rsqrt_inplace_f32_cpu_wrapper),
1068    ep!("rsqrt_inplace", "f64", rsqrt_inplace_f64_cpu_wrapper),
1069    ep!("rsqrt_inplace", "bf16", rsqrt_inplace_bf16_cpu_wrapper),
1070    ep!("rsqrt_inplace", "f16", rsqrt_inplace_f16_cpu_wrapper),
1071    ep!("recip_inplace", "f32", recip_inplace_f32_cpu_wrapper),
1072    ep!("recip_inplace", "f64", recip_inplace_f64_cpu_wrapper),
1073    ep!("recip_inplace", "bf16", recip_inplace_bf16_cpu_wrapper),
1074    ep!("recip_inplace", "f16", recip_inplace_f16_cpu_wrapper),
1075    ep!("exp_inplace", "f32", exp_inplace_f32_cpu_wrapper),
1076    ep!("exp_inplace", "f64", exp_inplace_f64_cpu_wrapper),
1077    ep!("exp_inplace", "bf16", exp_inplace_bf16_cpu_wrapper),
1078    ep!("exp_inplace", "f16", exp_inplace_f16_cpu_wrapper),
1079    ep!("log_inplace", "f32", log_inplace_f32_cpu_wrapper),
1080    ep!("log_inplace", "f64", log_inplace_f64_cpu_wrapper),
1081    ep!("log_inplace", "bf16", log_inplace_bf16_cpu_wrapper),
1082    ep!("log_inplace", "f16", log_inplace_f16_cpu_wrapper),
1083    ep!("sin_inplace", "f32", sin_inplace_f32_cpu_wrapper),
1084    ep!("sin_inplace", "f64", sin_inplace_f64_cpu_wrapper),
1085    ep!("sin_inplace", "bf16", sin_inplace_bf16_cpu_wrapper),
1086    ep!("sin_inplace", "f16", sin_inplace_f16_cpu_wrapper),
1087    ep!("cos_inplace", "f32", cos_inplace_f32_cpu_wrapper),
1088    ep!("cos_inplace", "f64", cos_inplace_f64_cpu_wrapper),
1089    ep!("cos_inplace", "bf16", cos_inplace_bf16_cpu_wrapper),
1090    ep!("cos_inplace", "f16", cos_inplace_f16_cpu_wrapper),
1091    ep!("sign_inplace", "f32", sign_inplace_f32_cpu_wrapper),
1092    ep!("sign_inplace", "f64", sign_inplace_f64_cpu_wrapper),
1093    ep!("sign_inplace", "bf16", sign_inplace_bf16_cpu_wrapper),
1094    ep!("sign_inplace", "f16", sign_inplace_f16_cpu_wrapper),
1095    ep!("floor_inplace", "f32", floor_inplace_f32_cpu_wrapper),
1096    ep!("floor_inplace", "f64", floor_inplace_f64_cpu_wrapper),
1097    ep!("floor_inplace", "bf16", floor_inplace_bf16_cpu_wrapper),
1098    ep!("floor_inplace", "f16", floor_inplace_f16_cpu_wrapper),
1099    ep!("ceil_inplace", "f32", ceil_inplace_f32_cpu_wrapper),
1100    ep!("ceil_inplace", "f64", ceil_inplace_f64_cpu_wrapper),
1101    ep!("ceil_inplace", "bf16", ceil_inplace_bf16_cpu_wrapper),
1102    ep!("ceil_inplace", "f16", ceil_inplace_f16_cpu_wrapper),
1103    ep!("round_inplace", "f32", round_inplace_f32_cpu_wrapper),
1104    ep!("round_inplace", "f64", round_inplace_f64_cpu_wrapper),
1105    ep!("round_inplace", "bf16", round_inplace_bf16_cpu_wrapper),
1106    ep!("round_inplace", "f16", round_inplace_f16_cpu_wrapper),
1107    ep!("erf_inplace", "f32", erf_inplace_f32_cpu_wrapper),
1108    ep!("erf_inplace", "f64", erf_inplace_f64_cpu_wrapper),
1109    ep!("erf_inplace", "bf16", erf_inplace_bf16_cpu_wrapper),
1110    ep!("erf_inplace", "f16", erf_inplace_f16_cpu_wrapper),
1111    ep!("gelu_erf_inplace", "f32", gelu_erf_inplace_f32_cpu_wrapper),
1112    ep!("gelu_erf_inplace", "f64", gelu_erf_inplace_f64_cpu_wrapper),
1113    ep!(
1114        "gelu_erf_inplace",
1115        "bf16",
1116        gelu_erf_inplace_bf16_cpu_wrapper
1117    ),
1118    ep!("gelu_erf_inplace", "f16", gelu_erf_inplace_f16_cpu_wrapper),
1119    // InplaceAffine — symbol `affine_inplace_<dt>`, wrapper `inplace_affine_<dt>_cpu_wrapper`
1120    // (words swapped); resolved AS-IS (single-dtype sections).
1121    ep!("affine_inplace", "f32", inplace_affine_f32_cpu_wrapper),
1122    ep!("affine_inplace", "f64", inplace_affine_f64_cpu_wrapper),
1123    ep!("affine_inplace", "bf16", inplace_affine_bf16_cpu_wrapper),
1124    ep!("affine_inplace", "f16", inplace_affine_f16_cpu_wrapper),
1125    // ClampInplace — symbol == wrapper base; resolved AS-IS.
1126    ep!("clamp_inplace", "f32", clamp_inplace_f32_cpu_wrapper),
1127    ep!("clamp_inplace", "f64", clamp_inplace_f64_cpu_wrapper),
1128    ep!("clamp_inplace", "bf16", clamp_inplace_bf16_cpu_wrapper),
1129    ep!("clamp_inplace", "f16", clamp_inplace_f16_cpu_wrapper),
1130    // PowIInplace — symbol == wrapper base; resolved AS-IS.
1131    ep!("powi_inplace", "f32", powi_inplace_f32_cpu_wrapper),
1132    ep!("powi_inplace", "f64", powi_inplace_f64_cpu_wrapper),
1133    ep!("powi_inplace", "bf16", powi_inplace_bf16_cpu_wrapper),
1134    ep!("powi_inplace", "f16", powi_inplace_f16_cpu_wrapper),
1135];
1136
1137/// The CPU **cast** family's `symbol → production wrapper` map — the FULL
1138/// directed-pair matrix: every ordered pair of the 11 real numeric dtypes
1139/// {F32,F64,F16,BF16,F8E4M3,U8,I8,U32,I16,I32,I64}, identity excluded =
1140/// 11 × 10 = 110 entry points. Contract: `fuel-dispatch/kernel-contracts/cpu/cast.fkc.md`.
1141///
1142/// Each per-pair section (`## cast_f64_to_f32`, …) declares a SPECIFIC
1143/// single-dtype `src` input + a `fixed(DST)` output, so it does NOT dtype-fan —
1144/// the importer keys `[SRC, DST]` (byte-for-byte the deleted hand-written
1145/// `table.register(Cast, &[SRC, DST], …)` regs) and resolves the section's
1146/// SPECIFIC `cast_<src>_to_<dst>` byte-kernel `entry_point` AS-IS. Because the
1147/// binding lookup is keyed on the **target** dtype (the Node's dtype), all 10 of
1148/// a target's source pairs bind the SAME per-target `cast_to_<dst>_cpu_wrapper`
1149/// (which `match`es on the source dtype internally to pick the right byte
1150/// kernel) — the synthetic-umbrella precedent (10 distinct real byte-kernel
1151/// entry_points → 1 wrapper, like `pad_cpu`'s fabricated per-dtype symbols → the
1152/// one `pad_cpu_wrapper`, except here every entry_point IS a real distinct byte
1153/// kernel). This map is the SOLE registration path for the whole family: every
1154/// hand-written `table.register(Cast, …)` reg is DELETED. Identity pairs
1155/// (`[T, T]`) are never registered — the optimizer elides identity `Cast` before
1156/// dispatch. These sections have NO `##` chassis umbrella, so there is no
1157/// `registrable: false` describe-only entry to omit.
1158pub static CPU_CAST_ENTRY_POINTS: &[(&str, KernelRef)] = &[
1159    // -> F32
1160    ep!("cast", "f64_to_f32", cast_to_f32_cpu_wrapper),
1161    ep!("cast", "f16_to_f32", cast_to_f32_cpu_wrapper),
1162    ep!("cast", "bf16_to_f32", cast_to_f32_cpu_wrapper),
1163    ep!("cast", "f8e4m3_to_f32", cast_to_f32_cpu_wrapper),
1164    ep!("cast", "u8_to_f32", cast_to_f32_cpu_wrapper),
1165    ep!("cast", "i8_to_f32", cast_to_f32_cpu_wrapper),
1166    ep!("cast", "u32_to_f32", cast_to_f32_cpu_wrapper),
1167    ep!("cast", "i16_to_f32", cast_to_f32_cpu_wrapper),
1168    ep!("cast", "i32_to_f32", cast_to_f32_cpu_wrapper),
1169    ep!("cast", "i64_to_f32", cast_to_f32_cpu_wrapper),
1170    // -> F64
1171    ep!("cast", "f32_to_f64", cast_to_f64_cpu_wrapper),
1172    ep!("cast", "f16_to_f64", cast_to_f64_cpu_wrapper),
1173    ep!("cast", "bf16_to_f64", cast_to_f64_cpu_wrapper),
1174    ep!("cast", "f8e4m3_to_f64", cast_to_f64_cpu_wrapper),
1175    ep!("cast", "u8_to_f64", cast_to_f64_cpu_wrapper),
1176    ep!("cast", "i8_to_f64", cast_to_f64_cpu_wrapper),
1177    ep!("cast", "u32_to_f64", cast_to_f64_cpu_wrapper),
1178    ep!("cast", "i16_to_f64", cast_to_f64_cpu_wrapper),
1179    ep!("cast", "i32_to_f64", cast_to_f64_cpu_wrapper),
1180    ep!("cast", "i64_to_f64", cast_to_f64_cpu_wrapper),
1181    // -> F16
1182    ep!("cast", "f32_to_f16", cast_to_f16_cpu_wrapper),
1183    ep!("cast", "f64_to_f16", cast_to_f16_cpu_wrapper),
1184    ep!("cast", "bf16_to_f16", cast_to_f16_cpu_wrapper),
1185    ep!("cast", "f8e4m3_to_f16", cast_to_f16_cpu_wrapper),
1186    ep!("cast", "u8_to_f16", cast_to_f16_cpu_wrapper),
1187    ep!("cast", "i8_to_f16", cast_to_f16_cpu_wrapper),
1188    ep!("cast", "u32_to_f16", cast_to_f16_cpu_wrapper),
1189    ep!("cast", "i16_to_f16", cast_to_f16_cpu_wrapper),
1190    ep!("cast", "i32_to_f16", cast_to_f16_cpu_wrapper),
1191    ep!("cast", "i64_to_f16", cast_to_f16_cpu_wrapper),
1192    // -> BF16
1193    ep!("cast", "f32_to_bf16", cast_to_bf16_cpu_wrapper),
1194    ep!("cast", "f64_to_bf16", cast_to_bf16_cpu_wrapper),
1195    ep!("cast", "f16_to_bf16", cast_to_bf16_cpu_wrapper),
1196    ep!("cast", "f8e4m3_to_bf16", cast_to_bf16_cpu_wrapper),
1197    ep!("cast", "u8_to_bf16", cast_to_bf16_cpu_wrapper),
1198    ep!("cast", "i8_to_bf16", cast_to_bf16_cpu_wrapper),
1199    ep!("cast", "u32_to_bf16", cast_to_bf16_cpu_wrapper),
1200    ep!("cast", "i16_to_bf16", cast_to_bf16_cpu_wrapper),
1201    ep!("cast", "i32_to_bf16", cast_to_bf16_cpu_wrapper),
1202    ep!("cast", "i64_to_bf16", cast_to_bf16_cpu_wrapper),
1203    // -> F8E4M3
1204    ep!("cast", "f32_to_f8e4m3", cast_to_f8e4m3_cpu_wrapper),
1205    ep!("cast", "f64_to_f8e4m3", cast_to_f8e4m3_cpu_wrapper),
1206    ep!("cast", "f16_to_f8e4m3", cast_to_f8e4m3_cpu_wrapper),
1207    ep!("cast", "bf16_to_f8e4m3", cast_to_f8e4m3_cpu_wrapper),
1208    ep!("cast", "u8_to_f8e4m3", cast_to_f8e4m3_cpu_wrapper),
1209    ep!("cast", "i8_to_f8e4m3", cast_to_f8e4m3_cpu_wrapper),
1210    ep!("cast", "u32_to_f8e4m3", cast_to_f8e4m3_cpu_wrapper),
1211    ep!("cast", "i16_to_f8e4m3", cast_to_f8e4m3_cpu_wrapper),
1212    ep!("cast", "i32_to_f8e4m3", cast_to_f8e4m3_cpu_wrapper),
1213    ep!("cast", "i64_to_f8e4m3", cast_to_f8e4m3_cpu_wrapper),
1214    // -> U8
1215    ep!("cast", "f32_to_u8", cast_to_u8_cpu_wrapper),
1216    ep!("cast", "f64_to_u8", cast_to_u8_cpu_wrapper),
1217    ep!("cast", "f16_to_u8", cast_to_u8_cpu_wrapper),
1218    ep!("cast", "bf16_to_u8", cast_to_u8_cpu_wrapper),
1219    ep!("cast", "f8e4m3_to_u8", cast_to_u8_cpu_wrapper),
1220    ep!("cast", "i8_to_u8", cast_to_u8_cpu_wrapper),
1221    ep!("cast", "u32_to_u8", cast_to_u8_cpu_wrapper),
1222    ep!("cast", "i16_to_u8", cast_to_u8_cpu_wrapper),
1223    ep!("cast", "i32_to_u8", cast_to_u8_cpu_wrapper),
1224    ep!("cast", "i64_to_u8", cast_to_u8_cpu_wrapper),
1225    // -> I8
1226    ep!("cast", "f32_to_i8", cast_to_i8_cpu_wrapper),
1227    ep!("cast", "f64_to_i8", cast_to_i8_cpu_wrapper),
1228    ep!("cast", "f16_to_i8", cast_to_i8_cpu_wrapper),
1229    ep!("cast", "bf16_to_i8", cast_to_i8_cpu_wrapper),
1230    ep!("cast", "f8e4m3_to_i8", cast_to_i8_cpu_wrapper),
1231    ep!("cast", "u8_to_i8", cast_to_i8_cpu_wrapper),
1232    ep!("cast", "u32_to_i8", cast_to_i8_cpu_wrapper),
1233    ep!("cast", "i16_to_i8", cast_to_i8_cpu_wrapper),
1234    ep!("cast", "i32_to_i8", cast_to_i8_cpu_wrapper),
1235    ep!("cast", "i64_to_i8", cast_to_i8_cpu_wrapper),
1236    // -> U32
1237    ep!("cast", "f32_to_u32", cast_to_u32_cpu_wrapper),
1238    ep!("cast", "f64_to_u32", cast_to_u32_cpu_wrapper),
1239    ep!("cast", "f16_to_u32", cast_to_u32_cpu_wrapper),
1240    ep!("cast", "bf16_to_u32", cast_to_u32_cpu_wrapper),
1241    ep!("cast", "f8e4m3_to_u32", cast_to_u32_cpu_wrapper),
1242    ep!("cast", "u8_to_u32", cast_to_u32_cpu_wrapper),
1243    ep!("cast", "i8_to_u32", cast_to_u32_cpu_wrapper),
1244    ep!("cast", "i16_to_u32", cast_to_u32_cpu_wrapper),
1245    ep!("cast", "i32_to_u32", cast_to_u32_cpu_wrapper),
1246    ep!("cast", "i64_to_u32", cast_to_u32_cpu_wrapper),
1247    // -> I16
1248    ep!("cast", "f32_to_i16", cast_to_i16_cpu_wrapper),
1249    ep!("cast", "f64_to_i16", cast_to_i16_cpu_wrapper),
1250    ep!("cast", "f16_to_i16", cast_to_i16_cpu_wrapper),
1251    ep!("cast", "bf16_to_i16", cast_to_i16_cpu_wrapper),
1252    ep!("cast", "f8e4m3_to_i16", cast_to_i16_cpu_wrapper),
1253    ep!("cast", "u8_to_i16", cast_to_i16_cpu_wrapper),
1254    ep!("cast", "i8_to_i16", cast_to_i16_cpu_wrapper),
1255    ep!("cast", "u32_to_i16", cast_to_i16_cpu_wrapper),
1256    ep!("cast", "i32_to_i16", cast_to_i16_cpu_wrapper),
1257    ep!("cast", "i64_to_i16", cast_to_i16_cpu_wrapper),
1258    // -> I32
1259    ep!("cast", "f32_to_i32", cast_to_i32_cpu_wrapper),
1260    ep!("cast", "f64_to_i32", cast_to_i32_cpu_wrapper),
1261    ep!("cast", "f16_to_i32", cast_to_i32_cpu_wrapper),
1262    ep!("cast", "bf16_to_i32", cast_to_i32_cpu_wrapper),
1263    ep!("cast", "f8e4m3_to_i32", cast_to_i32_cpu_wrapper),
1264    ep!("cast", "u8_to_i32", cast_to_i32_cpu_wrapper),
1265    ep!("cast", "i8_to_i32", cast_to_i32_cpu_wrapper),
1266    ep!("cast", "u32_to_i32", cast_to_i32_cpu_wrapper),
1267    ep!("cast", "i16_to_i32", cast_to_i32_cpu_wrapper),
1268    ep!("cast", "i64_to_i32", cast_to_i32_cpu_wrapper),
1269    // -> I64
1270    ep!("cast", "f32_to_i64", cast_to_i64_cpu_wrapper),
1271    ep!("cast", "f64_to_i64", cast_to_i64_cpu_wrapper),
1272    ep!("cast", "f16_to_i64", cast_to_i64_cpu_wrapper),
1273    ep!("cast", "bf16_to_i64", cast_to_i64_cpu_wrapper),
1274    ep!("cast", "f8e4m3_to_i64", cast_to_i64_cpu_wrapper),
1275    ep!("cast", "u8_to_i64", cast_to_i64_cpu_wrapper),
1276    ep!("cast", "i8_to_i64", cast_to_i64_cpu_wrapper),
1277    ep!("cast", "u32_to_i64", cast_to_i64_cpu_wrapper),
1278    ep!("cast", "i16_to_i64", cast_to_i64_cpu_wrapper),
1279    ep!("cast", "i32_to_i64", cast_to_i64_cpu_wrapper),
1280    // ---- Bool cast pairs (GAP-168) ----
1281    // 11 sources -> Bool, all binding the one per-target Bool wrapper.
1282    ep!("cast", "f32_to_bool", cast_to_bool_cpu_wrapper),
1283    ep!("cast", "f64_to_bool", cast_to_bool_cpu_wrapper),
1284    ep!("cast", "f16_to_bool", cast_to_bool_cpu_wrapper),
1285    ep!("cast", "bf16_to_bool", cast_to_bool_cpu_wrapper),
1286    ep!("cast", "f8e4m3_to_bool", cast_to_bool_cpu_wrapper),
1287    ep!("cast", "u8_to_bool", cast_to_bool_cpu_wrapper),
1288    ep!("cast", "i8_to_bool", cast_to_bool_cpu_wrapper),
1289    ep!("cast", "u32_to_bool", cast_to_bool_cpu_wrapper),
1290    ep!("cast", "i16_to_bool", cast_to_bool_cpu_wrapper),
1291    ep!("cast", "i32_to_bool", cast_to_bool_cpu_wrapper),
1292    ep!("cast", "i64_to_bool", cast_to_bool_cpu_wrapper),
1293    // Bool -> 11 targets, each binding that target's existing wrapper.
1294    ep!("cast", "bool_to_f32", cast_to_f32_cpu_wrapper),
1295    ep!("cast", "bool_to_f64", cast_to_f64_cpu_wrapper),
1296    ep!("cast", "bool_to_f16", cast_to_f16_cpu_wrapper),
1297    ep!("cast", "bool_to_bf16", cast_to_bf16_cpu_wrapper),
1298    ep!("cast", "bool_to_f8e4m3", cast_to_f8e4m3_cpu_wrapper),
1299    ep!("cast", "bool_to_u8", cast_to_u8_cpu_wrapper),
1300    ep!("cast", "bool_to_i8", cast_to_i8_cpu_wrapper),
1301    ep!("cast", "bool_to_u32", cast_to_u32_cpu_wrapper),
1302    ep!("cast", "bool_to_i16", cast_to_i16_cpu_wrapper),
1303    ep!("cast", "bool_to_i32", cast_to_i32_cpu_wrapper),
1304    ep!("cast", "bool_to_i64", cast_to_i64_cpu_wrapper),
1305];
1306
1307/// The CPU norm/softmax **FUSED** family's `symbol → production wrapper` map —
1308/// the FIRST fused-registry link table (the `fused_op` analogue of the
1309/// primitive `CPU_*_ENTRY_POINTS`). Contract:
1310/// `fuel-dispatch/kernel-contracts/fused/norm-softmax.fkc.md`.
1311///
1312/// Eight `fused_op` sections — three forward (`SOFTMAX_LAST_DIM` /
1313/// `RMS_NORM_LAST_DIM` / `LAYER_NORM_LAST_DIM`, key `[T, T]`) plus five backward
1314/// helpers (`SOFTMAX_LAST_DIM_BACKWARD` / `LAYER_NORM_LAST_DIM_BACKWARD` /
1315/// `RMS_NORM_LAST_DIM_BACKWARD` / `REDUCE_MAX_TO_BACKWARD` / `POWI_BACKWARD`,
1316/// key `[T, T, T]`). Each declares a dtype-agnostic BASE `entry_point`
1317/// `…::<op>_cpu` **plus a per-input `dtypes: [F32, F64, BF16, F16]` list**, so
1318/// `crate::fkc::lower::lower_fused` **dtype-fans** it (§3.4, via the `fep!` macro) into
1319/// four per-dtype impls: per fanned `dt` it resolves `<base>_<dt>`
1320/// (`…::<op>_cpu_f32`, `…_f64`, `…_bf16`, `…_f16`) against this table (8 ops ×
1321/// 4 dtypes = 32 rows). Each row binds the `<op>_<dt>_cpu_wrapper` — the exact
1322/// kernel fn the hand-written `register_default_fused_kernels` seam registers
1323/// for that op's `dt` dtype tuple — so an imported impl binds the SAME
1324/// executable kernel per dtype (a 1:1 replacement for the hand-written per-dtype
1325/// registrations, not just the F32 representative).
1326///
1327/// This map serves the SEPARATE [`crate::fused::FusedKernelRegistry`] seam (the
1328/// join target `register_default_fused_kernels` populates), NOT the primitive
1329/// `KernelBindingTable`. It is the live resolution behind the fused import seam:
1330/// an authored `fused_op` bundle imported through [`CpuLinkRegistry`] binds the
1331/// real CPU fused kernels (FKC P9 — no raw pointers in the serialized contract).
1332pub static CPU_FUSED_NORM_ENTRY_POINTS: &[(&str, KernelRef)] = &[
1333    // Forward (key [T, T]) — SoftmaxLastDim / RmsNormLastDim / LayerNormLastDim.
1334    fep!("softmax_last_dim_cpu_f32", softmax_last_dim_f32_cpu_wrapper),
1335    fep!("softmax_last_dim_cpu_f64", softmax_last_dim_f64_cpu_wrapper),
1336    fep!(
1337        "softmax_last_dim_cpu_bf16",
1338        softmax_last_dim_bf16_cpu_wrapper
1339    ),
1340    fep!("softmax_last_dim_cpu_f16", softmax_last_dim_f16_cpu_wrapper),
1341    fep!(
1342        "rms_norm_last_dim_cpu_f32",
1343        rms_norm_last_dim_f32_cpu_wrapper
1344    ),
1345    fep!(
1346        "rms_norm_last_dim_cpu_f64",
1347        rms_norm_last_dim_f64_cpu_wrapper
1348    ),
1349    fep!(
1350        "rms_norm_last_dim_cpu_bf16",
1351        rms_norm_last_dim_bf16_cpu_wrapper
1352    ),
1353    fep!(
1354        "rms_norm_last_dim_cpu_f16",
1355        rms_norm_last_dim_f16_cpu_wrapper
1356    ),
1357    fep!(
1358        "layer_norm_last_dim_cpu_f32",
1359        layer_norm_last_dim_f32_cpu_wrapper
1360    ),
1361    fep!(
1362        "layer_norm_last_dim_cpu_f64",
1363        layer_norm_last_dim_f64_cpu_wrapper
1364    ),
1365    fep!(
1366        "layer_norm_last_dim_cpu_bf16",
1367        layer_norm_last_dim_bf16_cpu_wrapper
1368    ),
1369    fep!(
1370        "layer_norm_last_dim_cpu_f16",
1371        layer_norm_last_dim_f16_cpu_wrapper
1372    ),
1373    // Backward (key [T, T, T]) — Softmax / LayerNorm / RmsNorm backward.
1374    fep!(
1375        "softmax_last_dim_backward_cpu_f32",
1376        softmax_last_dim_backward_f32_cpu_wrapper
1377    ),
1378    fep!(
1379        "softmax_last_dim_backward_cpu_f64",
1380        softmax_last_dim_backward_f64_cpu_wrapper
1381    ),
1382    fep!(
1383        "softmax_last_dim_backward_cpu_bf16",
1384        softmax_last_dim_backward_bf16_cpu_wrapper
1385    ),
1386    fep!(
1387        "softmax_last_dim_backward_cpu_f16",
1388        softmax_last_dim_backward_f16_cpu_wrapper
1389    ),
1390    fep!(
1391        "layer_norm_last_dim_backward_cpu_f32",
1392        layer_norm_last_dim_backward_f32_cpu_wrapper
1393    ),
1394    fep!(
1395        "layer_norm_last_dim_backward_cpu_f64",
1396        layer_norm_last_dim_backward_f64_cpu_wrapper
1397    ),
1398    fep!(
1399        "layer_norm_last_dim_backward_cpu_bf16",
1400        layer_norm_last_dim_backward_bf16_cpu_wrapper
1401    ),
1402    fep!(
1403        "layer_norm_last_dim_backward_cpu_f16",
1404        layer_norm_last_dim_backward_f16_cpu_wrapper
1405    ),
1406    fep!(
1407        "rms_norm_last_dim_backward_cpu_f32",
1408        rms_norm_last_dim_backward_f32_cpu_wrapper
1409    ),
1410    fep!(
1411        "rms_norm_last_dim_backward_cpu_f64",
1412        rms_norm_last_dim_backward_f64_cpu_wrapper
1413    ),
1414    fep!(
1415        "rms_norm_last_dim_backward_cpu_bf16",
1416        rms_norm_last_dim_backward_bf16_cpu_wrapper
1417    ),
1418    fep!(
1419        "rms_norm_last_dim_backward_cpu_f16",
1420        rms_norm_last_dim_backward_f16_cpu_wrapper
1421    ),
1422    // Backward of primitives (key [T, T, T]) — ReduceMaxTo / PowI backward.
1423    fep!(
1424        "reduce_max_to_backward_cpu_f32",
1425        reduce_max_to_backward_f32_cpu_wrapper
1426    ),
1427    fep!(
1428        "reduce_max_to_backward_cpu_f64",
1429        reduce_max_to_backward_f64_cpu_wrapper
1430    ),
1431    fep!(
1432        "reduce_max_to_backward_cpu_bf16",
1433        reduce_max_to_backward_bf16_cpu_wrapper
1434    ),
1435    fep!(
1436        "reduce_max_to_backward_cpu_f16",
1437        reduce_max_to_backward_f16_cpu_wrapper
1438    ),
1439    fep!("powi_backward_cpu_f32", powi_backward_f32_cpu_wrapper),
1440    fep!("powi_backward_cpu_f64", powi_backward_f64_cpu_wrapper),
1441    fep!("powi_backward_cpu_bf16", powi_backward_bf16_cpu_wrapper),
1442    fep!("powi_backward_cpu_f16", powi_backward_f16_cpu_wrapper),
1443];
1444
1445/// The CPU **linear / quantized-matmul** FUSED family's `symbol → production
1446/// wrapper` map — the MIGRATED subset of the `audited: true` linear-quant
1447/// bundle. Contract: `fuel-dispatch/kernel-contracts/fused/linear-quant.fkc.md`.
1448///
1449/// Four of the bundle's five `fused_op` sections migrate here (the fifth,
1450/// `nf4_matmul`, is `registrable: false` — its `fdx.quant.family: AFFINE_BLOCK`
1451/// is consumer-ahead, §6 — so it never lowers/resolves and its hand-written
1452/// `FusedOps::NF4_MATMUL` regs stay authoritative; it is absent here):
1453///
1454/// - **FUSED_LINEAR** — a multi-dtype section (`a`/`b`/`bias`
1455///   `dtypes: [F32, F64, BF16, F16]`) on a dtype-agnostic BASE `entry_point`
1456///   `…::fused_linear_cpu`, so `crate::fkc::lower::lower_fused` **dtype-fans**
1457///   it (§3.4, via the `fep!` macro) into 4 per-dtype impls resolving
1458///   `…::fused_linear_cpu_<dt>`, key `[T, T, T, T]` (a, b, bias +
1459///   `passthrough(a)` out).
1460/// - **QMATMUL** — a NON-fanning section (all operands single-dtype: `a` F32,
1461///   `w_q_bytes` U32 (the LOGICAL dispatch dtype — the physical GGML block
1462///   byte-honesty rides `fdx.quant: GGML_BLOCK`, §storage logical/physical
1463///   split), output F32), so its BASE `entry_point` `…::qmatmul_cpu` resolves
1464///   AS-IS (no `_<dt>` suffix), key `[F32, U32, F32]` byte-for-byte the deleted
1465///   hand-written `QM_F32` reg.
1466/// - **INPLACE_AFFINE** — a multi-dtype section (`x`
1467///   `dtypes: [F32, F64, BF16, F16]`) fanned into 4 per-dtype impls resolving
1468///   `…::inplace_affine_cpu_<dt>`, key `[T, T]` (out aliases x). NOTE the
1469///   fn-vs-symbol skew: the fanned symbol is `inplace_affine_cpu_<dt>` (base
1470///   `…_cpu` + `_<dt>`) while the wrapper fn is `inplace_affine_<dt>_cpu_wrapper`
1471///   (`_cpu` after `_<dt>`) — spelled out per row.
1472/// - **FUSED_SOFTMAX_CROSS_ENTROPY** — a multi-dtype section (`logits`
1473///   `dtypes: [F32, F64, BF16, F16]`; `targets` fixed I64; output `fixed(F32)`)
1474///   fanned into 4 per-dtype impls resolving
1475///   `…::fused_softmax_cross_entropy_cpu_<dt>`, key `[T, I64, F32]` byte-for-byte
1476///   the deleted hand-written `FSCE_<dt>` regs (the fan varies ONLY `logits`;
1477///   `targets` I64 + `fixed(F32)` output are constant across variants).
1478///
1479/// Each fanned row binds the `<op>_<dt>_cpu_wrapper` — the exact kernel fn the
1480/// deleted hand-written `register_default_fused_kernels` seam registered for
1481/// that op's `dt` dtype tuple — so an imported impl binds the SAME executable
1482/// kernel per dtype (a 1:1 replacement, real revision hash vs the hand-written
1483/// UNTRACKED sentinel). Serves the [`crate::fused::FusedKernelRegistry`] seam
1484/// (the join target `register_default_fused_kernels` populates), NOT the
1485/// primitive `KernelBindingTable`.
1486pub static CPU_FUSED_LINEAR_QUANT_ENTRY_POINTS: &[(&str, KernelRef)] = &[
1487    // FUSED_LINEAR — key [T, T, T, T]; multi-dtype fan over {F32, F64, BF16, F16}.
1488    fep!("fused_linear_cpu_f32", fused_linear_f32_cpu_wrapper),
1489    fep!("fused_linear_cpu_f64", fused_linear_f64_cpu_wrapper),
1490    fep!("fused_linear_cpu_bf16", fused_linear_bf16_cpu_wrapper),
1491    fep!("fused_linear_cpu_f16", fused_linear_f16_cpu_wrapper),
1492    // QMATMUL — key [F32, U32, F32]; NON-fanning, BASE symbol resolved AS-IS.
1493    fep!("qmatmul_cpu", qmatmul_f32_cpu_wrapper),
1494    // INPLACE_AFFINE — key [T, T]; multi-dtype fan. Symbol `inplace_affine_cpu_<dt>`
1495    // → wrapper `inplace_affine_<dt>_cpu_wrapper` (the `_cpu`/`_<dt>` skew).
1496    fep!("inplace_affine_cpu_f32", inplace_affine_f32_cpu_wrapper),
1497    fep!("inplace_affine_cpu_f64", inplace_affine_f64_cpu_wrapper),
1498    fep!("inplace_affine_cpu_bf16", inplace_affine_bf16_cpu_wrapper),
1499    fep!("inplace_affine_cpu_f16", inplace_affine_f16_cpu_wrapper),
1500    // FUSED_SOFTMAX_CROSS_ENTROPY — key [T, I64, F32]; fan varies ONLY logits.
1501    fep!(
1502        "fused_softmax_cross_entropy_cpu_f32",
1503        fused_softmax_cross_entropy_f32_cpu_wrapper
1504    ),
1505    fep!(
1506        "fused_softmax_cross_entropy_cpu_f64",
1507        fused_softmax_cross_entropy_f64_cpu_wrapper
1508    ),
1509    fep!(
1510        "fused_softmax_cross_entropy_cpu_bf16",
1511        fused_softmax_cross_entropy_bf16_cpu_wrapper
1512    ),
1513    fep!(
1514        "fused_softmax_cross_entropy_cpu_f16",
1515        fused_softmax_cross_entropy_f16_cpu_wrapper
1516    ),
1517];
1518
1519/// The CPU **conv / RoPE / SSM** FUSED family's `symbol → production wrapper`
1520/// map — the FULL `audited: true` conv-rope bundle. Contract:
1521/// `fuel-dispatch/kernel-contracts/fused/conv-rope.fkc.md`.
1522///
1523/// All SIX `fused_op` sections migrate here; each declares a dtype-agnostic
1524/// BASE `entry_point` `…::<op>_cpu` **plus a per-input `dtypes: [F32, F64, BF16,
1525/// F16]` list**, so `crate::fkc::lower::lower_fused` **dtype-fans** it (§3.4,
1526/// via the `fep!` macro) into four per-dtype impls resolving `<base>_<dt>` — one row per
1527/// (op, dtype) below (6 ops × 4 dtypes = 24 rows). The naming skew is the norm
1528/// family's: the FANNED symbol is `<op>_cpu_<dt>` (base `…_cpu` + `_<dt>`) while
1529/// the wrapper fn is `<op>_<dt>_cpu_wrapper`.
1530///
1531/// The 24 rows fan into **32 registered impls** because two sections
1532/// multiply their key count without adding a symbol row:
1533/// - **CONV2D** / **CONV_TRANSPOSE2D** mark `bias` `optional: true`, so the
1534///   importer's key-builder fans EACH per-dtype section into BOTH the no-bias
1535///   key `[T, T, T]` and the with-bias key `[T, T, T, T]` — both resolving the
1536///   SAME fanned symbol/wrapper (`conv2d_cpu_<dt>` → `conv2d_<dt>_cpu_wrapper`;
1537///   the CPU wrapper handles 2 or 3 inputs, the optional operand riding op-params
1538///   not a distinct symbol). So conv2d = 4 rows → 8 impls, conv_transpose2d =
1539///   4 rows → 8 impls (the CPU transposed-conv scatter kernel seeds the output
1540///   with `bias[co]` or `0`).
1541/// - **SELECTIVE_SCAN** / **SSD_CHUNK_SCAN** declare a `return.bundle`
1542///   multi-output (Option C, one packed `[y ; last_state]` buffer); the key-
1543///   builder appends the bundle's PRIMARY-slot dtype (`passthrough(u)` /
1544///   `passthrough(x)` → T) to the 5-input tail, so each keys `[T; 6]`
1545///   byte-for-byte the deleted hand-written reg. 4 rows → 4 impls each.
1546///
1547/// Net: ROPE 4 + CONV2D 8 + CONV_TRANSPOSE2D 8 + CAUSAL_CONV1D 4 +
1548/// SELECTIVE_SCAN 4 + SSD_CHUNK_SCAN 4 = 32 impls. Each row binds the exact
1549/// per-dtype kernel fn the deleted hand-written `register_default_fused_kernels`
1550/// seam registered (a 1:1 replacement, real revision hash vs the hand-written
1551/// UNTRACKED sentinel). Serves the [`crate::fused::FusedKernelRegistry`] seam
1552/// (the join target `register_default_fused_kernels` populates), NOT the
1553/// primitive `KernelBindingTable` (the `cpu/conv.fkc.md` / `cpu/ssm.fkc.md` /
1554/// `cpu/rope.fkc.md` primitive tables are separate and stay untouched).
1555pub static CPU_FUSED_CONV_ROPE_ENTRY_POINTS: &[(&str, KernelRef)] = &[
1556    // ROPE — key [T, T, T, T] (x, cos, sin + passthrough(x) out); 4 dtypes.
1557    fep!("rope_cpu_f32", rope_f32_cpu_wrapper),
1558    fep!("rope_cpu_f64", rope_f64_cpu_wrapper),
1559    fep!("rope_cpu_bf16", rope_bf16_cpu_wrapper),
1560    fep!("rope_cpu_f16", rope_f16_cpu_wrapper),
1561    // CONV2D — optional bias fans no-bias [T,T,T] + with-bias [T,T,T,T]; 4 rows → 8 impls.
1562    fep!("conv2d_cpu_f32", conv2d_f32_cpu_wrapper),
1563    fep!("conv2d_cpu_f64", conv2d_f64_cpu_wrapper),
1564    fep!("conv2d_cpu_bf16", conv2d_bf16_cpu_wrapper),
1565    fep!("conv2d_cpu_f16", conv2d_f16_cpu_wrapper),
1566    // CONV_TRANSPOSE2D — optional bias fans no-bias + with-bias; 4 rows → 8 impls.
1567    fep!("conv_transpose2d_cpu_f32", conv_transpose2d_f32_cpu_wrapper),
1568    fep!("conv_transpose2d_cpu_f64", conv_transpose2d_f64_cpu_wrapper),
1569    fep!(
1570        "conv_transpose2d_cpu_bf16",
1571        conv_transpose2d_bf16_cpu_wrapper
1572    ),
1573    fep!("conv_transpose2d_cpu_f16", conv_transpose2d_f16_cpu_wrapper),
1574    // CAUSAL_CONV1D — key [T, T, T, T] (x, weight, bias + passthrough(x) out); 4 dtypes.
1575    fep!("causal_conv1d_cpu_f32", causal_conv1d_f32_cpu_wrapper),
1576    fep!("causal_conv1d_cpu_f64", causal_conv1d_f64_cpu_wrapper),
1577    fep!("causal_conv1d_cpu_bf16", causal_conv1d_bf16_cpu_wrapper),
1578    fep!("causal_conv1d_cpu_f16", causal_conv1d_f16_cpu_wrapper),
1579    // SELECTIVE_SCAN — return.bundle: 5 inputs + primary-slot dtype → key [T; 6]; 4 dtypes.
1580    fep!("selective_scan_cpu_f32", selective_scan_f32_cpu_wrapper),
1581    fep!("selective_scan_cpu_f64", selective_scan_f64_cpu_wrapper),
1582    fep!("selective_scan_cpu_bf16", selective_scan_bf16_cpu_wrapper),
1583    fep!("selective_scan_cpu_f16", selective_scan_f16_cpu_wrapper),
1584    // SSD_CHUNK_SCAN — return.bundle: 5 inputs + primary-slot dtype → key [T; 6]; 4 dtypes.
1585    fep!("ssd_chunk_scan_cpu_f32", ssd_chunk_scan_f32_cpu_wrapper),
1586    fep!("ssd_chunk_scan_cpu_f64", ssd_chunk_scan_f64_cpu_wrapper),
1587    fep!("ssd_chunk_scan_cpu_bf16", ssd_chunk_scan_bf16_cpu_wrapper),
1588    fep!("ssd_chunk_scan_cpu_f16", ssd_chunk_scan_f16_cpu_wrapper),
1589];
1590
1591/// The built-in CPU backend's [`LinkRegistry`] — resolves a contract's
1592/// `entry_point` symbols against [`CPU_BINARY_ENTRY_POINTS`],
1593/// [`CPU_AFFINE_CLAMP_POWI_ENTRY_POINTS`], [`CPU_UNARY_ENTRY_POINTS`],
1594/// [`CPU_COMPARE_ENTRY_POINTS`], [`CPU_WHERE_ENTRY_POINTS`],
1595/// [`CPU_REDUCE_ENTRY_POINTS`], [`CPU_REDUCE_TO_ENTRY_POINTS`],
1596/// [`CPU_NORM_ENTRY_POINTS`], [`CPU_NORM_BACKWARD_ENTRY_POINTS`],
1597/// [`CPU_ROPE_ENTRY_POINTS`], [`CPU_SSM_ENTRY_POINTS`],
1598/// [`CPU_CONV_ENTRY_POINTS`], [`CPU_PADDING_ENTRY_POINTS`],
1599/// [`CPU_SHAPE_OPS_ENTRY_POINTS`], `CPU_INDEXING_ENTRY_POINTS`,
1600/// [`CPU_MATMUL_ENTRY_POINTS`],
1601/// [`CPU_ATTENTION_ENTRY_POINTS`], [`CPU_INPLACE_ENTRY_POINTS`], and
1602/// `CPU_CAST_ENTRY_POINTS`.
1603/// Unresolved → `None`, which the importer turns into a typed
1604/// `UnknownEntryPoint` error (never a panic, never a fabricated pointer).
1605pub struct CpuLinkRegistry;
1606
1607impl LinkRegistry for CpuLinkRegistry {
1608    fn resolve_primitive(&self, symbol: &str) -> Option<KernelRef> {
1609        CPU_BINARY_ENTRY_POINTS
1610            .iter()
1611            .chain(CPU_AFFINE_CLAMP_POWI_ENTRY_POINTS.iter())
1612            .chain(CPU_UNARY_ENTRY_POINTS.iter())
1613            .chain(CPU_COMPARE_ENTRY_POINTS.iter())
1614            .chain(CPU_WHERE_ENTRY_POINTS.iter())
1615            .chain(CPU_REDUCE_ENTRY_POINTS.iter())
1616            .chain(CPU_REDUCE_TO_ENTRY_POINTS.iter())
1617            .chain(CPU_NORM_ENTRY_POINTS.iter())
1618            .chain(CPU_NORM_BACKWARD_ENTRY_POINTS.iter())
1619            .chain(CPU_ROPE_ENTRY_POINTS.iter())
1620            .chain(CPU_SSM_ENTRY_POINTS.iter())
1621            .chain(CPU_CONV_ENTRY_POINTS.iter())
1622            .chain(CPU_PADDING_ENTRY_POINTS.iter())
1623            .chain(CPU_SHAPE_OPS_ENTRY_POINTS.iter())
1624            .chain(CPU_INDEXING_ENTRY_POINTS.iter())
1625            .chain(CPU_MATMUL_ENTRY_POINTS.iter())
1626            .chain(CPU_ATTENTION_ENTRY_POINTS.iter())
1627            .chain(CPU_INPLACE_ENTRY_POINTS.iter())
1628            .chain(CPU_CAST_ENTRY_POINTS.iter())
1629            .find(|(s, _)| *s == symbol)
1630            .map(|(_, k)| *k)
1631    }
1632
1633    fn resolve_fused(&self, symbol: &str) -> Option<KernelRef> {
1634        // FUSED (`fused_op`) resolution — the live fused import seam. Chains the
1635        // per-family fused entry-point tables (the norm/softmax family,
1636        // `CPU_FUSED_NORM_ENTRY_POINTS`; the linear/quant-matmul family,
1637        // `CPU_FUSED_LINEAR_QUANT_ENTRY_POINTS`; and the conv/RoPE/SSM family,
1638        // `CPU_FUSED_CONV_ROPE_ENTRY_POINTS`). Unresolved → `None`, which the
1639        // importer turns into a typed `UnknownEntryPoint` (never a panic, never a
1640        // fabricated pointer — FKC P9).
1641        //
1642        // All three checked-in fused bundles are now `audited: true` and WIRED,
1643        // PRODUCTION-migrated in `register_default_fused_kernels`:
1644        //   - `fused/norm-softmax.fkc.md` — 8 sections → 32 impls (SOFTMAX /
1645        //     RMS_NORM / LAYER_NORM_LAST_DIM (+backward), REDUCE_MAX_TO_BACKWARD,
1646        //     POWI_BACKWARD) via `CPU_FUSED_NORM_ENTRY_POINTS`.
1647        //   - `fused/linear-quant.fkc.md` — FUSED_LINEAR / QMATMUL /
1648        //     INPLACE_AFFINE / FUSED_SOFTMAX_CROSS_ENTROPY (its fifth section
1649        //     `nf4_matmul` is `registrable: false` — `fdx.quant.family:
1650        //     AFFINE_BLOCK` consumer-ahead, §6 — so NF4's hand-written regs stay
1651        //     authoritative) via `CPU_FUSED_LINEAR_QUANT_ENTRY_POINTS`.
1652        //   - `fused/conv-rope.fkc.md` — all 6 sections → 32 impls (ROPE, CONV2D,
1653        //     CONV_TRANSPOSE2D, CAUSAL_CONV1D, SELECTIVE_SCAN, SSD_CHUNK_SCAN) via
1654        //     `CPU_FUSED_CONV_ROPE_ENTRY_POINTS`.
1655        //
1656        // Still hand-written in `register_default_fused_kernels` (no fused
1657        // contract yet): FLASH_ATTN / FLASH_ATTN_BACKWARD_{Q,K,V} / PAGED_ATTN,
1658        // plus the deferred NF4_MATMUL. The `cpu/*.fkc.md` corpora are all
1659        // primitive `op_kind` contracts (the "fused" in FusedLinear /
1660        // FusedSoftmaxCrossEntropy names an intra-op fusion, NOT a graph
1661        // `FusedOpId`); their separate primitive `KernelBindingTable` seams stay
1662        // untouched.
1663        CPU_FUSED_NORM_ENTRY_POINTS
1664            .iter()
1665            .chain(CPU_FUSED_LINEAR_QUANT_ENTRY_POINTS.iter())
1666            .chain(CPU_FUSED_CONV_ROPE_ENTRY_POINTS.iter())
1667            .find(|(s, _)| *s == symbol)
1668            .map(|(_, k)| *k)
1669    }
1670}