Function sequant::eval::classify_axis

Function Documentation

inline LoopRole sequant::eval::classify_axis(container::svector<Index> const &carried, container::svector<Index> const &contracted_below, Index const &axis, container::svector<OccurrenceRec> const &occurrences, container::svector<Index> const &sliced, std::function<int(OccurrenceRec const&, Index const&)> const &enclosing_slot = {})

Classify one batch-loop axis axis against one value, given the value’s own result indices carried, the axes it contracts at its own node contracted_below (see contracted_indices in eval.hpp), and every use-site occurrences of the value in the forest.

The four-way decision tree:

  • Q1: does carried hold an index of axis's IndexSpace (compared by base_key(), i.e. Type not identity)?

    • no -> Q2a: does contracted_below hold an index of that type (the value reduces the axis at its own node)? -> Reduction; otherwise the axis merely encloses the value without touching it -> LoopInvariant.

    • yes -> Q2b: for every occurrence that has an enclosing loop of that axis type in its OccurrenceRec::ectx, gather all same-type enclosing loops (there may be several nested loops of one space, each binding a distinct carried index) and check that every one of the occurrence’s own carried indices of that type is bound (via the ordinal-and-proto-aware Index::operator==) to some enclosing loop. An occurrence may carry more than one same-space index &#8212; e.g. an outer product carrying two occ indices, each lockstep with its own nested loop, or a lockstep slot beside a free one. Every same-type carried slot lockstep with some enclosing loop, at every such occurrence -> LoopLocal; a carried slot with no matching enclosing loop at any occurrence (a free / cross-iteration read) -> LoopCarried. If no occurrence has an enclosing loop of that type at all, the axis is a plain free result index with nothing to lock it to a loop iteration -> LoopCarried.

Parameters:

enclosing_slot – (optional) the fusion loop_slot of the enclosing loop with tree-frame label L at occurrence occ (the parent occurrence’s slot for L; -1 if unknown). Lockstep with an enclosing loop is then loop-instance-aware: a same-space enclosing loop of a different fusion instance is not this value’s loop &#8212; the value is LoopCarried (an assembled escape of its own nest that the other nest reads sliced), not LoopLocal. Label equality alone would conflate the instances (e.g. a 4-occupied intermediate built per batch inside its own nest and read from a sibling nest).