Skip to content

llvm-to-affine-access: split stores through selected views into the arms - #3032

Open
wsmoses wants to merge 2 commits into
mainfrom
pb/store-select
Open

wsmoses wants to merge 2 commits into
mainfrom
pb/store-select

Conversation

@wsmoses

@wsmoses wsmoses commented Aug 31, 2026

Copy link
Copy Markdown
Member

The store twin of LoadSelect: a store through a selected view executes on whichever arm the condition chose, so it splits into an scf.if with one store per arm — each through a concrete view the later rewrites can see.

Loads through selected views have split this way since LoadSelect (the pattern right above), but stores kept the select alive: MFEM's symmetric/nonsymmetric kernels (Reshape(pa_data.Read(), ..., symmetric ? 6 : 9, NE)-style layout selects, and symmetric ? realbuf : nullptr guards) reached raising as writes through branch-chosen buffers, which the raiser's whole-buffer-select path explicitly refuses ("a write would have to fan back out into both source buffers"). Splitting at the same place as the loads does that fan-out in the IR, after which each arm's store is an ordinary conditional store: null-armed ones drop (#3010) and real ones raise as masked stores.

Measured on the 7 MFEM kernel TUs that fail with the raising-side gep normalizations disabled: this pattern alone flips none of them — their store-through-branch instances go through affine.if/scf.if results (clang's own control flow, with per-arm loads), not arith.selects, so they are #3016's territory (its expandBufferBranches handles if-yields for loads and stores). This PR closes the select-form gap for symmetry and for the cases the early pipeline does produce.

Second commit — the if form: an access through an if that merely multiplexes two views defined above it cannot move into the original arms (its other operands are computed after the if), but it can re-condition at the access site: a fresh if with the same guard, each arm accessing its concrete view. Covers loads and stores through both scf.if and affine.if results; views produced inside an arm stay untouched (dominance guard). On the real curlcurl TU this eliminates every memref-yielding if from the pre-raise IR (89 → 0).

Updated measurement: even so, none of the 7 gated MFEM TUs flip — the remaining gates are pointer-typed if yields with in-arm work (scf.if -> !llvm.ptr with loads inside the arms, gep chains on the if result) and per-TU extras, which are #3016's region-aware expansion territory. These patterns clear the shapes the early pipeline can clear.

🤖 Generated with Claude Code

https://claude.ai/code/session_016zErYp7upmqr4NHfhod9UD

wsmoses and others added 2 commits August 30, 2026 20:46
The store twin of LoadSelect: a store through a selected view executes
on whichever arm the condition chose, so it splits into an if with one
store per arm - each through a concrete view the later rewrites can see.
Loads through selected views have split this way since LoadSelect;
stores kept the select alive and reached raising as writes through
branch-chosen buffers, which the raiser refuses.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016zErYp7upmqr4NHfhod9UD
…iews

An access through an if that merely multiplexes two views defined above
it cannot move into the original arms - its other operands are computed
after the if - but it can re-condition at the access site: a fresh if
with the same guard, each arm accessing its concrete view. Covers loads
and stores through both scf.if and affine.if results; views produced
inside an arm stay untouched.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016zErYp7upmqr4NHfhod9UD
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant