You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Affine.access carries neither scalar gatedness nor local effects, so every between-two-points hazard question re-walks the raw code #1016
Grounded in lukstafi#750 (footprint-scoped materialization, #616). Its eligibility query asks one question — "between the producer's last write and the reader, and inside the producer's own span, what else runs?" — and the review surfaced its answer one member per round, because Affine.access (the routine's access relations, Low_level.affine_accesses) cannot say: round 1 tensor writes between producer and reader (fixed by placing the prologue at the producer), round 2 a sibling write inside the producer's statement, round 3 a write between two accumulating components, round 4 a Set_local between components, round 5 a Set_local inside the producer's statement and dead loops counted as writers, round 7 a read under a Where arm (a_guarded is the If statement only; scalar gates are invisible), round 10 a local written by the reader's statement. The query now carries three private walks over the raw code beside the access list — effectful / local_effects (statements with any effect, and with a local effect) and gated_readers (an Access_fold pass with gated_operands = Visit) — and so do the fan-in guard's reads_of_proc, computation_reads_merge and template_leaves, each a hand-rolled variant of the same read.
What a fix would touch: give Affine.access an a_gated : bool (the Access_fold context already computes it) and either emit local writes and declarations as effect rows of the same list (a Set_local is an access of a scope-local "node") or expose a sibling statement_effects view from the same walk in affine_accesses; then the eligibility query's three walks, and the guard's/merge scan's/leaves' hand-rolled reads, collapse into queries over one relation. The reviewer's genre — "an effect the access relations do not carry" — becomes unrepresentable rather than one-more-arm.
Another concrete instance landed in staging#758, resolving #1001: Online_softmax.has_opaque must classify Tile_mma itself as a code-motion barrier. Descending only into its fallback missed that hazard. The fix adds the explicit classification, but leaves another raw-statement walk beside the write census. This supports the shared effect/hazard representation proposed here.
Wave coordinator (2026-09-25 fleet wave), decision gate: proceeding on the sequencing plan's recommendation unless vetoed here before the worker's PR opens — a sibling statement_effects view built from the same walk, with a_gated added on Affine.access, rather than making local writes and declarations effect rows of access. A Set_local is not an access of a tensor node, and the four hand-rolled reads want "what else runs between two points", which a per-statement effect row answers directly. Evidence: the four reads collapse onto the view, with cc and Metal parity on the footprint tests.
Implementation PR: lukstafi#786. It follows the decision comment: a_gated on Affine.access, and a sibling Affine.statement_effect view from the same walk (Low_level.affine_relations). The footprint eligibility query, template_leaves, computation_reads_merge and Online_softmax.has_opaque now query that pair.
One departure from the comment: the fan-in guard's reads_of_proc stays a walk. It is a cost count that charges the wider Where arm, the same per-arm maximum trace_node_facts uses, and a boolean gate cannot say which arm a read belongs to. The PR gives the full rationale and the executed parity on cc and Metal.
Landed in lukstafi#786, merge commit b1e12c8ca. Codex approved it in round 1 with no findings. Every PR-matrix check on head 7963ca6c was green.
What landed
Affine.access.a_gated: a read under a scalar gate (a Where arm or a gated operand), following the Access_fold convention. A Local_scope body inside a gate is hoisted, so its reads are not gated.
Affine.statement_effect rows, built by the same walk (Low_level.affine_relations; affine_accesses and statement_effects are its two halves). Kinds: Local_write, Local_declare, Scope_body, Barrier, Staged, Mma, Merge_read. Helpers: Affine.loops_live, in_scope_body, within_statement.
These four readers now query the relation instead of walking the code: footprint_eligibility_query (its three private walks), template_leaves, computation_reads_merge and Online_softmax.has_opaque. Each classifies effect kinds with an exhaustive match, so adding a kind forces every consumer to handle it.
The rule and its rationale are in docs/agent-notes/lowering-and-analysis.md. The footprint paragraph in virtualization-and-inlining.md now names a_gated and the effect rows.
Parity and controls. Executed parity passed on cc and Metal for footprint_materialization, footprint_diagonal_einsum, online_softmax (plus fast_math) and virtual_chain_fanin. Negative controls: breaking any one of the four readers makes its own test rows fail.
Deliberately not done
The fan-in guard's reads_of_proc stays a walk. It is a cost count that charges the wider Where arm, the same per-arm maximum trace_node_facts uses, and a boolean gate cannot say which arm a read belongs to.
The online-softmax write census (writes_of_stmt / reads_of_body) stays hand-rolled, so Scope_body stays opaque there.
Pre-existing gap found (follow-up proposed to the wave coordinator): footprint_materialization's inherited-local row does not isolate the round-10 "reader statement writes a local" check. The row still passes with the check disabled, because a later retraction to inlining covers the case.
Activity
lukstafi commentedon Sep 19, 2026
Another concrete instance landed in staging#758, resolving #1001:
Online_softmax.has_opaquemust classifyTile_mmaitself as a code-motion barrier. Descending only into its fallback missed that hazard. The fix adds the explicit classification, but leaves another raw-statement walk beside the write census. This supports the shared effect/hazard representation proposed here.lukstafi commentedon Sep 25, 2026
Wave coordinator (2026-09-25 fleet wave), decision gate: proceeding on the sequencing plan's recommendation unless vetoed here before the worker's PR opens — a sibling
statement_effectsview built from the same walk, witha_gatedadded onAffine.access, rather than making local writes and declarations effect rows ofaccess. ASet_localis not an access of a tensor node, and the four hand-rolled reads want "what else runs between two points", which a per-statement effect row answers directly. Evidence: the four reads collapse onto the view, with cc and Metal parity on the footprint tests.lukstafi commentedon Sep 25, 2026
Implementation PR: lukstafi#786. It follows the decision comment:
a_gatedonAffine.access, and a siblingAffine.statement_effectview from the same walk (Low_level.affine_relations). The footprint eligibility query,template_leaves,computation_reads_mergeandOnline_softmax.has_opaquenow query that pair.One departure from the comment: the fan-in guard's
reads_of_procstays a walk. It is a cost count that charges the widerWherearm, the same per-arm maximumtrace_node_factsuses, and a boolean gate cannot say which arm a read belongs to. The PR gives the full rationale and the executed parity on cc and Metal.Merge pull request #786 from lukstafi/claude/issue-1016-affine-effect…
lukstafi commentedon Sep 25, 2026
Landed in lukstafi#786, merge commit
b1e12c8ca. Codex approved it in round 1 with no findings. Every PR-matrix check on head7963ca6cwas green.What landed
Affine.access.a_gated: a read under a scalar gate (aWherearm or a gated operand), following theAccess_foldconvention. ALocal_scopebody inside a gate is hoisted, so its reads are not gated.Affine.statement_effectrows, built by the same walk (Low_level.affine_relations;affine_accessesandstatement_effectsare its two halves). Kinds:Local_write,Local_declare,Scope_body,Barrier,Staged,Mma,Merge_read. Helpers:Affine.loops_live,in_scope_body,within_statement.footprint_eligibility_query(its three private walks),template_leaves,computation_reads_mergeandOnline_softmax.has_opaque. Each classifies effect kinds with an exhaustive match, so adding a kind forces every consumer to handle it.docs/agent-notes/lowering-and-analysis.md. The footprint paragraph invirtualization-and-inlining.mdnow namesa_gatedand the effect rows.Parity and controls. Executed parity passed on cc and Metal for footprint_materialization, footprint_diagonal_einsum, online_softmax (plus fast_math) and virtual_chain_fanin. Negative controls: breaking any one of the four readers makes its own test rows fail.
Deliberately not done
reads_of_procstays a walk. It is a cost count that charges the widerWherearm, the same per-arm maximumtrace_node_factsuses, and a boolean gate cannot say which arm a read belongs to.writes_of_stmt/reads_of_body) stays hand-rolled, soScope_bodystays opaque there.Pre-existing gap found (follow-up proposed to the wave coordinator): footprint_materialization's
inherited-localrow does not isolate the round-10 "reader statement writes a local" check. The row still passes with the check disabled, because a later retraction to inlining covers the case.Merge pull request #1016 from lukstafi/claude/w1005-1218-scalar-host-…