Skip to content

Affine.access carries neither scalar gatedness nor local effects, so every between-two-points hazard question re-walks the raw code #1016

Closed
lukstafi/ocannl-staging
#786

Description

@lukstafi

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.

Activity

  1. added this to the v1.1.1 milestone on Sep 18, 2026
  2. lukstafi commented on Sep 19, 2026

    @lukstafi
    CollaboratorAuthor

    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.

  3. lukstafi commented on Sep 25, 2026

    @lukstafi
    CollaboratorAuthor

    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.

  4. lukstafi commented on Sep 25, 2026

    @lukstafi
    CollaboratorAuthor

    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.

  5. added a commit that references this issue on Sep 25, 2026
  6. lukstafi commented on Sep 25, 2026

    @lukstafi
    CollaboratorAuthor

    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.

  7. added a commit that references this issue on Oct 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions