Skip to content

Conversation

@sumleo
Copy link
Contributor

@sumleo sumleo commented Feb 12, 2026

Summary

The escape analysis in Heap2Local accepted ArrayRMW and ArrayCmpxchg as FullyConsumes, allowing non-escaping arrays with these operations through to the Array2Struct transformation. However, Array2Struct had no visitArrayRMW or visitArrayCmpxchg handlers. This caused these operations to be left unrewritten after the array-to-struct conversion, and the type rewriting infrastructure replaced them with unreachable blocks — silently turning working code into unconditional traps.

Before fix (array.atomic.rmw.add that should return old value becomes unreachable):

(block ;; (replaces unreachable ArrayRMW we can't emit)
  ...
  (unreachable)
)

Additionally, the escape analysis for ArrayRMW/ArrayCmpxchg was missing the constant-index check that ArrayGet/ArraySet both have, which Array2Struct requires to map array elements to struct fields.

Fix

  1. Add !curr->index->is<Const>() checks to the escape analysis for ArrayRMW and ArrayCmpxchg (matching ArrayGet/ArraySet)
  2. Add visitArrayRMW and visitArrayCmpxchg to Array2Struct that convert array atomic operations to their struct equivalents, following the pattern of visitArrayGet/visitArraySet

Test plan

  • Added test cases to test/lit/passes/heap2local-rmw.wast:
    • $array-rmw-add: array.atomic.rmw.add on array.new_fixed — fully optimized to locals
    • $array-cmpxchg: array.atomic.rmw.cmpxchg on array.new_fixed — fully optimized to locals
    • $array-rmw-nonconstant-index: non-constant index prevents optimization (left as-is)
  • All lit tests pass

The escape analysis in Heap2Local accepted ArrayRMW and ArrayCmpxchg as
FullyConsumes, allowing non-escaping arrays with these operations through
to the Array2Struct transformation. However, Array2Struct had no
visitArrayRMW or visitArrayCmpxchg handlers, so these operations were
left unrewritten after the array-to-struct conversion, producing broken
IR where array operations referenced a now-nonexistent array allocation.
This caused the operations to be silently replaced with unreachable
blocks, turning working code into unconditional traps.

Fix by:
1. Adding const-index checks to the escape analysis for ArrayRMW and
   ArrayCmpxchg (matching the existing checks for ArrayGet and ArraySet),
   since Array2Struct requires compile-time-known indices.
2. Adding visitArrayRMW and visitArrayCmpxchg to Array2Struct that
   convert array atomic operations to their struct equivalents (following
   the pattern of visitArrayGet and visitArraySet), with proper OOB
   handling.
@sumleo sumleo force-pushed the fix-heap2local-array-rmw branch from 0b2347e to e4d2f12 Compare February 12, 2026 01:54
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