Template Function sequant::eval::stamp_lifetime_masks¶
Defined in File lifetime_mask.hpp
Function Documentation¶
-
template<meta::eval_node_range R>
void sequant::eval::stamp_lifetime_masks(R const &forest)¶ Stamp each canonical eval node’s cross-occurrence sliced-mode mask (
EvalExpr::sliced_modes) — the runtime residencyplace_at_this_levelconsumes to home each value. A mode slices a canonical node iff it slices every occurrence of that node inforest(a meet / set-intersection over occurrences). A node’s occurrence-local sliced set is the union of the enclosing loops opened at or above it —batch_loops_opened_here(anyBatchModeType:External opened at its open site, Contracted opened at its reduction site), each physical loop appearing once — filtered to the modes that live on the node’s own result slots (slot_modes_of, i.e.canon_indices()taken as-is — see there for why a composite slota<i,j>is just modea, never itsi,j proto pair). A node invariant to an outer batched loop — it does not carry that loop’s mode on any slot — is thus left all-full even under a batched ancestor, so it stays eligible for loop-invariant reuse. (Sourcing opens, not the per-carrying-nodenode_slice_mask, is what makes the accumulation a set: an External loop reaches its carriers by inheritance rather than a redundant own-node stamp, and a Contracted loop reaches its below-the-reduction carriers the same way — the case that genuinely needs the down-propagation.)This all-batched-modes meet subsumes the former per-occurrence
contracted_modesbolt-on: a node variant to an outer contracted (aux) loop carries that aux free on a result slot, so the aux mode survives the meet and lands insliced_modesdirectly.Occurrences are grouped by canonical identity (
hash_valueplus structuralTreeNodeEqualityComparatorequivalence). The meet is a set-intersection byIndexidentity: canonicalization gives consistent labels across occurrences, so a genuinely sliced-everywhere mode survives, while a block-agnostic node (e.g.s*C) whose occurrences bind disjoint concrete modes intersects to empty (all-full).Idempotent; a no-op on the off path: with no
node_slice_mask()stamps every occurrence set is empty, so every meet is empty and every mask is all-full (EvalExpr::sliced_modes_is default-empty), leaving runtime behavior unchanged.