You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Sequential `OutputSpan.append` calls each emitted their own `count <
capacity` check, since the inline `_precondition` lowered to `cond_fail`
with no semantic apply for `hoistFixedStorageBoundsChecksInBlock` to
recognise, and successive loads of the OutputSpan struct produced
distinct SSA selves that fragmented the merge group.
Split the check into a `_checkCanAppend` helper tagged
`@_semantics("fixed_storage.check_capacity")`. Teach the pass to look
through `load` / `load_borrow` for the merge-group key when the call
kind is `CheckCapacity`, and to substitute the first check's self when
moving subsequent ones (sound because `capacity` is invariant; the
helper reads no mutable fields). `CheckIndex` keying is unchanged so
reads against mutable `_count` still behave correctly.
Self substitution alone is unsound across instructions that could
replace the storage at the merge-group address — most commonly an
opaque `@inout` callee. Before merging a `CheckCapacity` call, scan the
range from the previous clustered check to the candidate and bail if
any intervening apply (other than a recognized fixed-storage semantic
call) or whole-storage `store` / `copy_addr` lands on the same address.
Field stores reach `struct_element_addr`-derived destinations and do
not bail.
Four sequential appends on the same `inout OutputSpan` now fold to one
merged `cond_fail` covering all four indices, mirroring `span_4_sum`.
0 commit comments