Module Ir.Rewrites

The algebraic-rewrite tier over raw lowered code: pattern-directed substitutions that CHANGE the computation, where the schedule transforms only rearrange a fixed one. Assignments.lower applies the tier between to_low_level and Low_level.optimize, ahead of the analyses, so the traced store and the placements see the rewritten routine and a rewrite may remove a node's definition outright.

Each member is gated by config keys of its own (the approximate profile is the umbrella that turns them all on), classified Code_borne: the rewritten code carries the decision, so no digest needs the key. The tier is a static list -- explicit order, and no registration that a dropped unreferenced module could silently skip.

Members feed each other (a rewrite can expose another's pattern, in either order), so the tier runs the enabled members in order until the code stops changing, judged by structural equality. The contract that makes this terminate: a member is idempotent on its own output, and every application consumes at least one instance of its pattern. A member that keeps rewriting past max_rounds rounds is refused as malformed rather than looped on.

type target = {
  1. online_softmax_auto_block : int;
}

Device economics needed before lowering analyses. Supplied by backend limits rather than selected by backend name; kept separate from Backend_intf to avoid an IR/interface dependency cycle.

val conservative_target : target

Backend-free lowerings decline automatic block folding. Explicit numeric sizes still apply.

type rewrite = {
  1. name : string;
    (*

    The config key that gates it, or the keys when several do.

    *)
  2. enabled : unit -> bool;
  3. apply : target -> Low_level.t -> Low_level.t;
  4. reset : unit -> unit;
    (*

    Drops whatever the member retains across lowerings (memoized nodes, say): the session-reset hook, run by Tensor.unsafe_reinitialize through reset.

    *)
}
val tier : rewrite list

The members, in application order: Online_softmax (gh-ocannl-483), Winograd (gh-ocannl-505), Prefix_scan (gh-ocannl-1758), then Fp_algebra (gh-ocannl-998) -- the recognizers first, the normalizing algebra last, since contraction would hide the value reduction the softmax hoist matches and the d + a * b accumulations the Winograd and triangular-mask recognizers match.

val max_rounds : int
val reset : unit -> unit

Every member's reset, for the session-reset boundary.

val apply : ?target:target -> Low_level.t -> Low_level.t

The enabled members to a fixpoint; the identity when none is enabled.