Skip to content

compiler: Skip copy-backs only if no write to the guard intervenes - #3062

Draft
ggorman wants to merge 4 commits into
fix-buffering-guardsfrom
fix-buffering-skip-rule
Draft

ggorman wants to merge 4 commits into
fix-buffering-guardsfrom
fix-buffering-skip-rule

Conversation

@ggorman

@ggorman ggorman commented Oct 16, 2026

Copy link
Copy Markdown
Contributor

Stacked on #3061; the base switches to main once that merges.

The copy-back skip from #3050 evaluates the later write's guard at the earlier copy-back. If anything that guard reads (indices included) is written in between, the only firing write can be skipped. Single-writer reproducer (every Function has at most one firing write per step, slot and point):

cm = ConditionalDimension(name='cm', parent=time, relation='strict',
                          condition=And(CondEq(time, 3), T[0, 0, 0] < 3.5))
eqs = [Eq(f, T), Eq(T, T + 1), Eq(f, T + 1, implicit_dims=cm)]  # f save=4, T not saved

At time = 3 the increment makes cm false, so only Eq(f, T) fires. f[:, 1, 1] is [0, 1, 2, 3] with opt='noop' and [0, 1, 2, 0] with buffering on main. The indirect-guard variant (the guard reads T through an index Function) gives [2, 3, 4, 5] vs [2, 3, 4, 0].

The skip now applies only if nothing the later guard reads is written between the two copy-backs. Test: test_buffering.py::test_buffering_same_slot_skip[mutable|indirect]; both fail with only buffering.py reverted.

Per the #3050 discussion, the cases with two firing writes to a slot in one step are not used as evidence here.

🤖 Generated with Claude Code

ggorman and others added 4 commits October 16, 2026 10:49
GuardFactorNe inherited CondEq through GuardFactor ahead of CondNe, so it
was an equality and printed `==`. Negating a subsampling guard thus
reproduced the guard itself, selecting the timesteps on the subsampled
grid instead of those off it
A condition SymPy folds to `false`, e.g. `time < 0`, was printed as
`if (false)`, which is not C99 without `stdbool.h` and failed to compile
A condition such as `time >= 0` folds to `true` (`time` is nonnegative)
and gave a Cluster the guard {time: true}, distinct from no guard.
Buffering then created one buffer per guard for equivalent accesses
The guard of the later copy-back is evaluated at the earlier one, so the
skip is unsound if anything the guard reads, indices included, is written
in between
@FabioLuporini

Copy link
Copy Markdown
Contributor

@mloubout can this one be closed now?

@mloubout

Copy link
Copy Markdown
Contributor

@FabioLuporini not sure, this was open after merging the prvious fix. This is still an odd "MFE" that writes two different values to the same saved slot so not sure what case this is supposed to represent.

@ggorman
ggorman force-pushed the fix-buffering-guards branch from cdd0ce8 to 953054a Compare October 22, 2026 11:29

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants