Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 21 additions & 2 deletions docs/audit/compiler/COMPILER_AUDIT.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,27 @@ multiple root audit documents and compiler archive files.
locked by `tests/unit/test_strict_dispatch.py` (short-circuit + legacy-path
tests). **SwiGLU is now derived too** (`_match_swiglu_at` handles the DAG —
gate/up share %x — inside the known-chain scan) and consumed by the
executor. Still open: Target IR (C++ fusion passes) re-discovers the same
chains.
executor. **Target IR descriptor consume/emit — landed 2026-06-11.** All 7
Apple fusion passes now *emit* a first-class fusion descriptor on the fused
call (`tessera.fusion.kernel` + `tessera.fusion.source`): the 4 chain passes
(matmul→softmax→matmul / matmul→softmax / matmul→gelu / matmul→rmsnorm) also
*consume* an upstream `tessera.fusion.intent` (source `"descriptor"` vs
`"rediscovered"`, with a Decision-#21 warning on descriptor/IR disagreement);
the 3 composite passes (swiglu / mla_decode / native_sparse_attn) emit
`source = "composite_op"` (the pre-fused op *is* the descriptor). The Python
emit-half `canonical_compile.stamp_fusion_intents(module)` stamps the intent on
each recognized chain's terminal op from the canonical `_KNOWN_FUSION_CHAINS`,
so the frontend produces descriptor-annotated IR. Lit:
`tests/tessera-ir/phase8/apple_gpu_fusion_descriptor.mlir`; Python:
`tests/unit/test_apple_fusion_descriptor.py` + `test_fusion_intent_emitter.py`
(incl. an emit↔consume contract guard). **Auto-wired 2026-06-11:**
`driver.compile_graph_module` calls `stamp_fusion_intents(module)` before
rendering the Graph IR for Apple targets (gated to `apple_gpu`/`apple_cpu`;
the descriptor is backend-agnostic so it extends when other backends consume
it), so every Apple compile now produces descriptor-annotated Graph IR that
the Target IR passes consume. The intent is stamped into the op's MLIR `attrs`
(not `kwargs`, which are the op's real call arguments in the reference/runtime
path). Loop closed end-to-end.
- **Layout and binding contracts are uneven.** Graph/Schedule/Tile/Target IR
need stronger dtype, layout, aliasing, and buffer-binding contracts.
- **Complete claims need fixtures.** A completed backend claim should resolve to
Expand Down
8 changes: 4 additions & 4 deletions docs/audit/generated/test_coverage.csv
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ gated_attention,6,0,0,6,0,,needs_direct_test,category default for 'attention'
gated_deltanet,7,2,0,9,0,,needs_direct_test,category default for 'attention'
gather,9,3,0,12,0,fp32 fp4_e2m1 fp6_e3m2 fp8_e4m3 fp8_e5m2 nvfp4,needs_direct_test,category default for 'layout_transform'
ge,1,0,0,1,1,,covered_by_family,category default for 'comparison'
gelu,24,16,1,40,0,bf16 f16 f32 fp16 fp32,covered_by_family,category default for 'elementwise'
gelu,26,17,1,43,0,bf16 f16 f32 fp16 fp32,covered_by_family,category default for 'elementwise'
gemm,69,2,6,71,0,bf16 f16 f32 fp16 fp32 fp4_e2m1 fp6_e2m3 fp8_e4m3 nvfp4,structural_only,unclassified — defaults to structural_only
gguf_export,1,0,0,1,1,,structural_only,category default for 'aot'
gqa_attention,5,0,0,5,0,,needs_direct_test,category default for 'attention'
Expand Down Expand Up @@ -252,7 +252,7 @@ mae_loss,1,0,0,1,1,,covered_by_family,category default for 'loss'
map,0,0,0,0,1,,structural_only,category default for 'control_flow'
masked_categorical,10,0,0,10,0,,structural_only,unclassified — defaults to structural_only
masked_fill,4,0,0,4,0,fp32 fp4_e2m1 fp6_e3m2 fp8_e4m3 fp8_e5m2 nvfp4,needs_direct_test,category default for 'layout_transform'
matmul,296,152,15,448,0,bf16 f16 f32 fp16 fp32 fp4_e2m1 fp6_e2m3 fp8_e4m3 nvfp4,structural_only,unclassified — defaults to structural_only
matmul,309,158,15,467,0,bf16 f16 f32 fp16 fp32 fp4_e2m1 fp6_e2m3 fp8_e4m3 nvfp4,structural_only,unclassified — defaults to structural_only
max,1,0,0,1,1,,structural_only,unclassified — defaults to structural_only
max_pool,4,0,0,4,0,,needs_direct_test,category default for 'pooling'
maximum,2,0,0,2,0,,structural_only,unclassified — defaults to structural_only
Expand Down Expand Up @@ -332,7 +332,7 @@ repeat,1,0,0,1,1,,structural_only,unclassified — defaults to structural_only
reshape,4,5,0,9,0,,structural_only,unclassified — defaults to structural_only
retention,6,0,1,6,0,,needs_direct_test,category default for 'attention'
rfft,3,0,0,3,0,fp32,needs_direct_test,category default for 'spectral'
rmsnorm,53,9,2,62,0,bf16 fp32,needs_direct_test,category default for 'normalization'
rmsnorm,54,10,2,64,0,bf16 fp32,needs_direct_test,category default for 'normalization'
rmsnorm_safe,3,5,0,8,0,,needs_direct_test,category default for 'normalization'
rng_bernoulli,0,0,0,0,1,,covered_by_family,category default for 'rng'
rng_beta,0,0,0,0,1,,covered_by_family,category default for 'rng'
Expand Down Expand Up @@ -386,7 +386,7 @@ sin,1,0,0,1,1,,covered_by_family,category default for 'elementwise'
sinh,1,0,0,1,1,,covered_by_family,category default for 'elementwise'
slice,1,0,0,1,1,,structural_only,unclassified — defaults to structural_only
smooth_l1_loss,1,0,0,1,1,,covered_by_family,category default for 'loss'
softmax,70,35,4,105,0,bf16 f16 f32 fp16 fp32 fp4_e2m1 fp6_e2m3 fp8_e4m3 nvfp4,needs_direct_test,category default for 'stable_reduction'
softmax,75,37,4,112,0,bf16 f16 f32 fp16 fp32 fp4_e2m1 fp6_e2m3 fp8_e4m3 nvfp4,needs_direct_test,category default for 'stable_reduction'
softmax_safe,3,4,0,7,0,,needs_direct_test,category default for 'stable_reduction'
softplus,2,0,0,2,0,,covered_by_family,category default for 'elementwise'
sort,3,0,0,3,0,,structural_only,unclassified — defaults to structural_only
Expand Down
10 changes: 5 additions & 5 deletions docs/audit/generated/test_coverage.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Generated from `python/tessera/compiler/test_coverage_audit.py`. Don't edit by
## Headline

- **449** ops in `primitive_coverage` registry.
- **2242** total Python-test references, **571** total lit-fixture references.
- **2263** total Python-test references, **581** total lit-fixture references.
- **103** ops have **zero** references in either test surface.
- **201** ops have ≤1 reference ("thinly tested").
- **48** ops have ≥10 references ("well tested").
Expand All @@ -17,19 +17,19 @@ Generated from `python/tessera/compiler/test_coverage_audit.py`. Don't edit by

| Op | py refs | lit refs | total | neg | dtypes |
|----|--------:|---------:|------:|----:|--------|
| `matmul` | 296 | 152 | 448 | 15 | `bf16`, `f16`, `f32`, `fp16` … |
| `matmul` | 309 | 158 | 467 | 15 | `bf16`, `f16`, `f32`, `fp16` … |
| `flash_attn` | 79 | 42 | 121 | 4 | `bf16`, `f32`, `fp16`, `fp32` … |
| `softmax` | 70 | 35 | 105 | 4 | `bf16`, `f16`, `f32`, `fp16` … |
| `softmax` | 75 | 37 | 112 | 4 | `bf16`, `f16`, `f32`, `fp16` … |
| `relu` | 92 | 7 | 99 | 9 | `bf16`, `f16`, `f32`, `fp32` |
| `silu` | 76 | 2 | 78 | 5 | `bf16`, `f16`, `f32`, `fp16` … |
| `gemm` | 69 | 2 | 71 | 6 | `bf16`, `f16`, `f32`, `fp16` … |
| `add` | 62 | 6 | 68 | 8 | `bf16`, `f16`, `f32`, `fp32` |
| `reduce` | 66 | 0 | 66 | 6 | `f32`, `fp16`, `fp32`, `fp4_e2m1` … |
| `rmsnorm` | 54 | 10 | 64 | 2 | `bf16`, `fp32` |
| `mul` | 62 | 0 | 62 | 6 | `fp16`, `fp32`, `fp4_e2m1`, `fp6_e2m3` … |
| `rmsnorm` | 53 | 9 | 62 | 2 | `bf16`, `fp32` |
| `attn_local_window_2d` | 34 | 25 | 59 | 1 | `fp32` |
| `cholesky` | 15 | 30 | 45 | 0 | `bf16`, `f16`, `f32`, `fp16` … |
| `gelu` | 24 | 16 | 40 | 1 | `bf16`, `f16`, `f32`, `fp16` … |
| `gelu` | 26 | 17 | 43 | 1 | `bf16`, `f16`, `f32`, `fp16` … |
| `linear_attn` | 31 | 8 | 39 | 1 | |
| `grouped_gemm` | 27 | 10 | 37 | 2 | `fp32`, `fp4_e2m1`, `fp8_e4m3`, `fp8_e5m2` … |
| `selective_ssm` | 36 | 0 | 36 | 2 | |
Expand Down
51 changes: 51 additions & 0 deletions python/tessera/compiler/canonical_compile.py
Original file line number Diff line number Diff line change
Expand Up @@ -746,6 +746,57 @@ def _derive_compile_metadata(module: GraphIRModule) -> dict[str, Any]:
}


# Linear fusion chains the Apple Target IR passes re-discover and now also
# consume from a descriptor. (swiglu / mla / nsa lower a pre-fused op — the op
# *is* the descriptor — so they don't need an intent stamp.)
_INTENT_KERNELS: frozenset[str] = frozenset({
"matmul_softmax_matmul", "matmul_softmax", "matmul_gelu", "matmul_rmsnorm",
})


def stamp_fusion_intents(module: GraphIRModule) -> int:
"""Decision #19 emit-half — stamp ``tessera.fusion.intent`` on the terminal
op of each recognized linear fusion chain so the Apple Target IR fusion
passes *consume* the compiler's fusion decision (the emitted call is tagged
``source = "descriptor"``) instead of re-discovering the chain. Returns the
number of chains stamped. Idempotent.

The terminal op (the highest-index op of the chain — the tail matmul /
softmax / gelu / rmsnorm) is exactly where each C++ pass reads the intent.
"""
groups = _derive_fusion_groups(module)
by_fn = {fn.name: fn for fn in module.functions}
stamped = 0
for group in groups:
if group.get("kind") != "known_chain":
continue
kernel = group.get("fused_kernel")
if kernel not in _INTENT_KERNELS:
continue
fn_name = group.get("function")
fn = by_fn.get(fn_name) if isinstance(fn_name, str) else None
if fn is None:
continue
indices = [int(e["index"]) for e in group.get("ops", ())
if isinstance(e, Mapping) and isinstance(e.get("index"), int)]
if not indices:
continue
terminal = max(indices)
if 0 <= terminal < len(fn.body):
op = fn.body[terminal]
# Stamp into `attrs` (the MLIR-attribute-only field), NOT `kwargs`:
# kwargs are forwarded as the op's real call arguments in the
# reference/runtime execution path, so a descriptor placed there
# would leak into the numpy op call (e.g. gelu(**kwargs)).
intent_attr = f'tessera.fusion.intent = "{kernel}"'
if not op.attrs:
op.attrs = intent_attr
elif "tessera.fusion.intent" not in op.attrs:
op.attrs = f"{op.attrs}, {intent_attr}"
stamped += 1
return stamped


# --- Synthesizers --------------------------------------------------------

def _result_from_bundle(
Expand Down
11 changes: 11 additions & 0 deletions python/tessera/compiler/driver.py
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,17 @@ def compile_graph_module(
enable_tool_validation: bool = True,
) -> CompileArtifactBundle:
target_kind = normalize_target_kind(target)
# Decision #19 — auto-emit fusion descriptors. Before the Graph IR is
# rendered, stamp `tessera.fusion.intent` on each recognized fusion chain's
# terminal op so the Apple Target IR fusion passes *consume* the compiler's
# intent (the fused call is tagged source="descriptor") instead of
# re-discovering the chain. Apple-gated (the only Target IR consumer today);
# the descriptor is backend-agnostic, so this extends to other backends when
# their Target IR consumes it. Lazy import avoids the canonical_compile ↔
# driver cycle.
if target_kind in ("apple_gpu", "apple_cpu"):
from .canonical_compile import stamp_fusion_intents
stamp_fusion_intents(module)
graph_text = module.to_mlir()
function_name = module.functions[0].name if module.functions else "<unknown>"
request = CompileRequest(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,10 +148,14 @@ struct LowerMLADecodeFusionToAppleGPU : public RewritePattern {
i32Ty, i32Ty, i32Ty, i32Ty, i32Ty, i32Ty}, {});
ensureExternalDecl(mod, kMLADecodeF32Symbol, fnTy);

rewriter.create<func::CallOp>(
auto callOp = rewriter.create<func::CallOp>(
loc, kMLADecodeF32Symbol, TypeRange{},
ValueRange{xPtr, wDkvPtr, wUkPtr, wUvPtr, qPtr, oPtr,
Bv, Skv, Dx, Dlat, Sq, Dh});
// Decision #19 — emit the fusion descriptor. MLA decode lowers a pre-fused
// tessera.mla_decode_fused op (the op is the descriptor): source="composite_op".
callOp->setAttr("tessera.fusion.kernel", rewriter.getStringAttr("mla_decode"));
callOp->setAttr("tessera.fusion.source", rewriter.getStringAttr("composite_op"));

auto outTensorTy = RankedTensorType::get({B, S_q, D_h}, elem);
Value result =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,12 @@ struct LowerMatmulGeluFusionToAppleGPU : public RewritePattern {
if (geluOp->getNumOperands() < 1) return failure();
Value geluIn = geluOp->getOperand(0);

// Decision #19 — consume the compiler's fusion descriptor when present.
StringRef intent;
if (auto a = geluOp->getAttrOfType<StringAttr>("tessera.fusion.intent"))
intent = a.getValue();
bool descriptorDriven = (intent == "matmul_gelu");

auto gTy = dyn_cast<RankedTensorType>(geluIn.getType());
if (!gTy || gTy.getRank() != 2)
return rewriter.notifyMatchFailure(geluOp, "matmul_gelu fusion: rank-2 only");
Expand All @@ -63,8 +69,13 @@ struct LowerMatmulGeluFusionToAppleGPU : public RewritePattern {
Operation *defOp = geluIn.getDefiningOp();
if (!defOp)
return rewriter.notifyMatchFailure(geluOp, "matmul_gelu fusion: no defining op");
if (defOp->getName().getStringRef() != "tessera.matmul")
if (defOp->getName().getStringRef() != "tessera.matmul") {
if (descriptorDriven) // Decision #21 — descriptor/IR disagreement.
geluOp->emitWarning(
"tessera.fusion.intent = \"matmul_gelu\" but gelu operand is not "
"from tessera.matmul — descriptor/IR mismatch; falling back");
return rewriter.notifyMatchFailure(geluOp, "matmul_gelu fusion: defining op is not tessera.matmul");
}
if (!geluIn.hasOneUse())
return rewriter.notifyMatchFailure(geluOp, "matmul_gelu fusion: matmul result has multiple uses");

Expand Down Expand Up @@ -123,9 +134,12 @@ struct LowerMatmulGeluFusionToAppleGPU : public RewritePattern {
ctx, {i64Ty, i64Ty, i64Ty, i32Ty, i32Ty, i32Ty}, {});
ensureExternalDecl(mod, kMatmulGeluF32Symbol, fnTy);

rewriter.create<func::CallOp>(
auto callOp = rewriter.create<func::CallOp>(
loc, kMatmulGeluF32Symbol, TypeRange{},
ValueRange{aPtr, bPtr, oPtr, Mv, Nv, Kv});
callOp->setAttr("tessera.fusion.kernel", rewriter.getStringAttr("matmul_gelu"));
callOp->setAttr("tessera.fusion.source",
rewriter.getStringAttr(descriptorDriven ? "descriptor" : "rediscovered"));

auto outTensorTy = RankedTensorType::get({M, N}, f32Ty);
Value result =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,12 @@ struct LowerMatmulRMSNormPatternBase : public RewritePattern {
if (normOp->getNumOperands() < 1) return failure();
Value normIn = normOp->getOperand(0);

// Decision #19 — consume the compiler's fusion descriptor when present.
StringRef intent;
if (auto a = normOp->getAttrOfType<StringAttr>("tessera.fusion.intent"))
intent = a.getValue();
bool descriptorDriven = (intent == "matmul_rmsnorm");

auto nTy = dyn_cast<RankedTensorType>(normIn.getType());
if (!nTy || nTy.getRank() != 2)
return rewriter.notifyMatchFailure(normOp, "matmul_rmsnorm fusion: rank-2 only");
Expand All @@ -73,8 +79,13 @@ struct LowerMatmulRMSNormPatternBase : public RewritePattern {
Operation *defOp = normIn.getDefiningOp();
if (!defOp)
return rewriter.notifyMatchFailure(normOp, "matmul_rmsnorm fusion: no defining op");
if (defOp->getName().getStringRef() != "tessera.matmul")
if (defOp->getName().getStringRef() != "tessera.matmul") {
if (descriptorDriven) // Decision #21 — descriptor/IR disagreement.
normOp->emitWarning(
"tessera.fusion.intent = \"matmul_rmsnorm\" but norm operand is not "
"from tessera.matmul — descriptor/IR mismatch; falling back");
return rewriter.notifyMatchFailure(normOp, "matmul_rmsnorm fusion: defining op is not tessera.matmul");
}
if (!normIn.hasOneUse())
return rewriter.notifyMatchFailure(normOp, "matmul_rmsnorm fusion: matmul result has multiple uses");

Expand Down Expand Up @@ -140,9 +151,12 @@ struct LowerMatmulRMSNormPatternBase : public RewritePattern {
ctx, {i64Ty, i64Ty, i64Ty, i32Ty, i32Ty, i32Ty, f32Ty}, {});
ensureExternalDecl(mod, kMatmulRMSNormF32Symbol, fnTy);

rewriter.create<func::CallOp>(
auto callOp = rewriter.create<func::CallOp>(
loc, kMatmulRMSNormF32Symbol, TypeRange{},
ValueRange{aPtr, bPtr, oPtr, Mv, Nv, Kv, epsV});
callOp->setAttr("tessera.fusion.kernel", rewriter.getStringAttr("matmul_rmsnorm"));
callOp->setAttr("tessera.fusion.source",
rewriter.getStringAttr(descriptorDriven ? "descriptor" : "rediscovered"));

auto outTensorTy = RankedTensorType::get({M, N}, f32Ty);
Value result =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,12 @@ struct LowerMatmulSoftmaxFusionToAppleGPU : public RewritePattern {
return failure();
Value softmaxIn = softmaxOp->getOperand(0);

// Decision #19 — consume the compiler's fusion descriptor when present.
StringRef intent;
if (auto a = softmaxOp->getAttrOfType<StringAttr>("tessera.fusion.intent"))
intent = a.getValue();
bool descriptorDriven = (intent == "matmul_softmax");

// axis: defaults to -1. Anything else falls out of fusion.
int64_t axis = -1;
if (auto attr = softmaxOp->getAttrOfType<IntegerAttr>("axis"))
Expand Down Expand Up @@ -100,8 +106,13 @@ struct LowerMatmulSoftmaxFusionToAppleGPU : public RewritePattern {
Operation *defOp = softmaxIn.getDefiningOp();
if (!defOp)
return rewriter.notifyMatchFailure(softmaxOp, "fusion: softmax operand has no defining op");
if (defOp->getName().getStringRef() != "tessera.matmul")
if (defOp->getName().getStringRef() != "tessera.matmul") {
if (descriptorDriven) // Decision #21 — descriptor/IR disagreement.
softmaxOp->emitWarning(
"tessera.fusion.intent = \"matmul_softmax\" but softmax operand is "
"not from tessera.matmul — descriptor/IR mismatch; falling back");
return rewriter.notifyMatchFailure(softmaxOp, "fusion: defining op is not tessera.matmul");
}
if (!softmaxIn.hasOneUse())
return rewriter.notifyMatchFailure(softmaxOp, "fusion: matmul result has multiple uses");

Expand Down Expand Up @@ -163,9 +174,12 @@ struct LowerMatmulSoftmaxFusionToAppleGPU : public RewritePattern {
ctx, {i64Ty, i64Ty, i64Ty, i32Ty, i32Ty, i32Ty}, {});
ensureExternalDecl(mod, symbol, fnTy);

rewriter.create<func::CallOp>(
auto callOp = rewriter.create<func::CallOp>(
loc, symbol, TypeRange{},
ValueRange{aPtr, bPtr, oPtr, Mv, Nv, Kv});
callOp->setAttr("tessera.fusion.kernel", rewriter.getStringAttr("matmul_softmax"));
callOp->setAttr("tessera.fusion.source",
rewriter.getStringAttr(descriptorDriven ? "descriptor" : "rediscovered"));

auto outTensorTy = RankedTensorType::get({M, N}, smElem);
Value result =
Expand Down
Loading
Loading