Skip to content

Make LastStores a proper lattice - #14230

Merged
cfallin merged 1 commit into
bytecodealliance:mainfrom
fitzgen:alias-analysis-lattice
Sep 4, 2026
Merged

Make LastStores a proper lattice#14230
cfallin merged 1 commit into
bytecodealliance:mainfrom
fitzgen:alias-analysis-lattice

Conversation

@fitzgen

@fitzgen fitzgen commented Aug 28, 2026

Copy link
Copy Markdown
Member

There were two ways in which alias analysis's LastStores state was not a proper lattice, which made the order we processed the worklist and called LastStores::meet observable:

  1. We didn't have a single, canonical bottom value for the last store to a region. We were taking the first instruction in a block as an identifier for control-flow join points so that we would get different MemoryLocs for different control-flow joins, which is necessary to avoid illegally forwarding a value loaded inside one control-flow join to a load in another, different control-flow join. However, this meant that we effectively had multiple bottom elements, which made the path we descended through the "lattice" observable. The solution here was to create a separate LastStore dataflow value that has a single, canonical bottom element, and a distinct MemoryVersion value that is the same as LastStore but replaces its bottom value with a variant that identifies the associated control-flow join point. We use LastStore in our LastStores lattice, when we need a bottom element, and we use MemoryVersion in our MemoryLoc keys, to distinguish between different regions where we don't know anything about the contents of memory.

  2. We computed the observed-stores set while we computed the fixpoint of the initial LastStores inputs to each block. This was incorrect, however, because a LastStores could transiently contain a LastStore::Inst that disappears in later iterations of the fixpoint, and which instructions do or don't transiently appear in LastStores in that way depends on the order in which we call LastStores::meet. Therefore, observing stores while computing the fixpoint might or might not observe an instruction depending on the worklist processing order. The solution in this case was to only compute the observed-stores set after we've computed the LastStores fixpoint, at which point there are no transient LastStore::Insts anymore.

@fitzgen
fitzgen requested review from a team as code owners August 28, 2026 22:23
@fitzgen
fitzgen requested review from cfallin and removed request for a team August 28, 2026 22:23
@github-actions github-actions Bot added the cranelift Issues related to the Cranelift code generator label Aug 28, 2026
@fitzgen
fitzgen force-pushed the alias-analysis-lattice branch from 4ad30ed to 6e847e9 Compare August 31, 2026 14:48

@cfallin cfallin left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for thinking through this carefully -- definitely very subtle.

Some comments as I read below, but more importantly I have a high-level feeling of "this may be getting too complex", and I'm wondering how much of it we really need for our stated purposes. In particular, what I am seeing is that there are a whole bunch of specific complexities coming out of the one core decision to support inter-block merged versions better than "unknown":

  • The distinction between MemoryVersion and LastStore, and conversion between them;
  • The pre-pass to find "merge blocks", and the subtle semantics around the lattice value that refers to this (external) table. In particular I'm having trouble thinking about "merge token"-version values that flow across other merge blocks (e.g. within a subregion) -- why is this correct?
  • The observe-pass thing with Option<HashMap> and confusing control flow.

I wonder if we could benchmark the alternative where we fix the lattice the other way -- no loc-keyed new version that occurs at a meet-point, just send that to bottom instead. That's a much smaller fix that results in an enormously simpler analysis, and I think it would get at least the straight-line trampoline cases we immediately care about, and many of the intra-block and even simple inter-block opts for e.g. GC fields with separate regions. The only case it misses is where we have a merge point, no store (to do a strong-update and overwrite the identity) but instead a load, and we can't RLE a second load. But actually even in that case we could cache the loaded result on a key with the load's instruction, no? So I'm not seeing where we would actually lose anything with the simpler analysis. Happy to see counterexamples or hear your reasoning on this of course!

Comment thread cranelift/codegen/src/alias_analysis.rs Outdated
Comment thread cranelift/codegen/src/alias_analysis.rs Outdated
Comment thread cranelift/codegen/src/alias_analysis.rs Outdated
@fitzgen

fitzgen commented Aug 31, 2026

Copy link
Copy Markdown
Member Author

Some comments as I read below, but more importantly I have a high-level feeling of "this may be getting too complex", and I'm wondering how much of it we really need for our stated purposes. In particular, what I am seeing is that there are a whole bunch of specific complexities coming out of the one core decision to support inter-block merged versions better than "unknown":

It is not that we want to support better merged versions than "unknown", it is that for correctness we need to distinguish between these different control-flow join points so that we get different MemoryLocs for different control-flow join points and do not accidentally forward loads from one join point to loads in another join point. FWIW, this machinery to distinguish different join points already existed before I ever started touching alias analysis: this is the whole "if we don't agree on the last store, choose the first instruction in the block as a tombstone marker" logic in LastStores::meet that has been there since alias analysis first landed. That is, this is not new complexity, and, if anything, I'd argue it is getting less complex by explicitly putting this case into the types / its own enum variant, rather than implicitly reusing a random instruction as the last store, and thereby removing incidental complexity to more-directly model the inherent complexity.

  • The distinction between MemoryVersion and LastStore, and conversion between them;

Again, I believe this is inherent complexity, and is best dealt with by being honest about that and modeling it in the types:

  • In one case, we cannot have multiple "bottom" elements (the lattice case)
  • In another case, we must have multiple "bottom" elements for correctness (the MemoryLoc key for known memory values case)

Trying to have one thing satisfy two conflicting requirements simultaneously is going to lead to bugs in practice (as we have already seen, by realizing that the worklist traversal order is observable).

  • The pre-pass to find "merge blocks", and the subtle semantics around the lattice value that refers to this (external) table. In particular I'm having trouble thinking about "merge token"-version values that flow across other merge blocks (e.g. within a subregion) -- why is this correct?

I'm not sure I follow the question. Merge blocks do not flow across other merge points. A block's merge block is the first predecessor (or itself) that is either (a) the function entry or (b) has len(predecessors) != 1. If there was another merge point between a block and its merge block that is not the merge block, then that is a violation of the premise.

  • The observe-pass thing with Option<HashMap> and confusing control flow.

We have some options here, and I don't particularly love any of them. We could do any of:

  1. take an Option and only call observe when it is Some (what we do now, with some .is_some() checks to avoid iterating over collections when all we do while iterating over them is call other observe_* methods), or
  2. make functions compile-time generic over whether they are calling observe or not, or
  3. always call observe_* methods even when observed_stores.is_none() to avoid the special-casing from (1) and its additional control flow, or
  4. duplicate the definitions of all these functions to have one version that takes Observations and calls observe and one that doesn't take Observations and doesn't call `observe.

We are balancing code duplication, complexity, and whether or not we skip unnecessary work. I don't know how we can optimize all at once, though.

I wonder if we could benchmark the alternative where we fix the lattice the other way -- no loc-keyed new version that occurs at a meet-point, just send that to bottom instead.

As mentioned above, that would be unsound, because it means that we could have:

  • block A, which is a control-flow join point, and therefore has bottom as its last store
  • a load in block A
  • block B, which is also a control-flow join point, and therefore also has bottom as its last store
  • a load of the same address/type/etc... in block B

If we process block A first, then we will insert

MemoryLoc {
    last_store: None, // or whatever bottom is represented as
    address,
    offset,
    ty,
    extending_opcode,
    endianness,
}

as the key for the known value that we just loaded. Then, when we process block B, it will look up the exact same MemoryLoc, and, finding an entry, will forward the known memory value here and replace the redundant load. But that is invalid! We are just RLE'ing values from unrelated control-flow join points to each other! (And things are identical if we do block B and then A).

Zooming out, the only other way to avoid the merge blocks, without salting our MemoryLoc keys with some kind of token that similarly represents our scope, is to remove entries from AliasAnalysis::mem_values when they become invalid, which means switching to a scoped hash map of some sort (no big deal) but also changing the interface to AliasAnalysis. That interface change is a bit more annoying: it adds correctness requirements to block visitation order, rather than just enabling better optimization if done in dom tree pre-order, and requires additional push/pop pub methods that need to be called at the exact right times. That is all doable, but the changes leak out from just an internal implementation detail of alias_analysis.rs and into new invariants to uphold and API calls to make for code that uses AliasAnalysis, and this doesn't really seem any simpler (especially since it becomes non-local) to me than what this PR proposes...

@cfallin

cfallin commented Aug 31, 2026

Copy link
Copy Markdown
Member

It is not that we want to support better merged versions than "unknown", it is that for correctness we need to distinguish between these different control-flow join points so that we get different MemoryLocs for different control-flow join points and do not accidentally forward loads from one join point to loads in another join point. FWIW, this machinery to distinguish different join points already existed before I ever started touching alias analysis: this is the whole "if we don't agree on the last store, choose the first instruction in the block as a tombstone marker" logic in LastStores::meet that has been there since alias analysis first landed. That is, this is not new complexity, and, if anything, I'd argue it is getting less complex by explicitly putting this case into the types / its own enum variant, rather than implicitly reusing a random instruction as the last store, and thereby removing incidental complexity to more-directly model the inherent complexity.

Yes, agreed that it was a pre-existing issue.

There is something I still don't understand though. It seems that the above is assuming that we would still associate known values with locs that have "bottom" locations (i.e., merged locations). I was assuming (and I think had implied?) that we would simply not associate values with such locations.

That's far simpler and avoids all of this machinery, no?

@fitzgen

fitzgen commented Sep 2, 2026

Copy link
Copy Markdown
Member Author

There is something I still don't understand though. It seems that the above is assuming that we would still associate known values with locs that have "bottom" locations (i.e., merged locations). I was assuming (and I think had implied?) that we would simply not associate values with such locations.

Ah, I see what you're suggesting now, I had misunderstood your comment.

I prototyped this, not adding entries to AliasAnalysis::mem_values when the MemoryLoc key is the bottom element, and we get the following filetest failures:

Details
FAIL /Users/n.fitzgerald/scratch/wasmtime-alias-analysis-lattice/cranelift/filetests/filetests/egraph/alias_analysis.clif: optimize

Caused by:
    filecheck failed for function on line 5:
    #0 check: v3 = load.i64 region0 v0
    #1 check: store v0, v3
    #2 check: v7 = load.i64 v0
    #3 check: return v7
    > function %f(i64) -> i64 fast {
    >     region0 = 0 "heap"
    > 
    > block0(v0: i64):
    >     v3 = load.i64 region0 v0
          ^~~~~~~~~~~~~~~~~~~~~~~~
    Matched #0: \bv3 = load\.i64 region0 v0\b
    Missed #1: \bstore v0, v3\b
    >     v4 = load.i64 region0 v0
    >     v5 = band v3, v4
    >     store v0, v5
    >     v6 = load.i64 v3
    >     v7 = load.i64 v6
    >     return v7
    > }
    
FAIL /Users/n.fitzgerald/scratch/wasmtime-alias-analysis-lattice/cranelift/filetests/filetests/alias/dead-store-then-idempotent-store.clif: optimize

Caused by:
    compilation of function on line 8 does not match
    the text expectation
    
    --- expected
    +++ actual
    @@ -3,5 +3,6 @@
     
     block0(v0: i64):
         v1 = load.i32 notrap aligned region0 v0
    +    store notrap aligned region0 v1, v0
         return
     }
    
    
    This test assertion can be automatically updated by setting the
    CRANELIFT_TEST_BLESS=1 environment variable when running this test.
             
FAIL /Users/n.fitzgerald/scratch/wasmtime-alias-analysis-lattice/cranelift/filetests/filetests/alias/issue-13508.clif: alias-analysis

Caused by:
    filecheck failed for function on line 9:
    #0 check: v5 = load.i32 region0 v0
    #1 check: v6 -> v5
    #2 check: v8 = load.i32 region0 v0
    > function %f(i64, i64, i64) -> i32, i32, i32 apple_aarch64 {
    >     region0 = 2 "vmctx"
    > 
    > block0(v0: i64, v1: i64, v2: i64):
    >     v3 = iconst.i64 -1
    >     store notrap v3, v0  ; v3 = -1
    >     v4 = atomic_cas v2, v0, v0
    >     v5 = load.i32 region0 v0
          ^~~~~~~~~~~~~~~~~~~~~~~~
    Matched #0: \bv5 = load\.i32 region0 v0\b
    Missed #1: \bv6 \-> v5\b
    >     v6 = load.i32 region0 v0
    >     v7 = iconst.i32 42
    >     store notrap v7, v1  ; v7 = 42
    >     v8 = load.i32 region0 v0
    >     return v5, v6, v8
    > }
    
FAIL /Users/n.fitzgerald/scratch/wasmtime-alias-analysis-lattice/cranelift/filetests/filetests/alias/idempotent-store.clif: optimize

Caused by:
    compilation of function on line 6 does not match
    the text expectation
    
    --- expected
    +++ actual
    @@ -3,5 +3,6 @@
     
     block0(v0: i64):
         v1 = load.i32 region0 v0+8
    +    store region0 v1, v0+8
         return
     }
    
    
    This test assertion can be automatically updated by setting the
    CRANELIFT_TEST_BLESS=1 environment variable when running this test.
             
FAIL /Users/n.fitzgerald/scratch/wasmtime-alias-analysis-lattice/cranelift/filetests/filetests/alias/multiple-blocks.clif: alias-analysis

Caused by:
    filecheck failed for function on line 7:
    #0 check: v4 -> v3
    > function %f0(i64 vmctx, i32) -> i32 fast {
    Missed #0: \bv4 \-> v3\b
    >     gv0 = vmctx
    >     gv1 = load.i64 notrap aligned readonly gv0+8
    > 
    > block0(v0: i64, v1: i32):
    >     v2 = load.i64 notrap aligned readonly v0+8
    >     v3 = load.i32 v2+8
    >     brif v2, block2, block1
    > 
    > block1:
    >     v4 = load.i32 v2+8
    >     jump block3(v4)
    > 
    > block2:
    >     jump block3(v3)
    > 
    > block3(v5: i32):
    >     return v5
    > }
    
FAIL /Users/n.fitzgerald/scratch/wasmtime-alias-analysis-lattice/cranelift/filetests/filetests/alias/endianness.clif: optimize

Caused by:
    compilation of function on line 33 does not match
    the text expectation
    
    --- expected
    +++ actual
    @@ -3,5 +3,6 @@
     
     block0(v0: i64):
         v1 = load.i16 big region0 v0
    -    return v1, v1
    +    v2 = load.i16 big region0 v0
    +    return v1, v2
     }
    
    
    This test assertion can be automatically updated by setting the
    CRANELIFT_TEST_BLESS=1 environment variable when running this test.
             
FAIL /Users/n.fitzgerald/scratch/wasmtime-alias-analysis-lattice/cranelift/filetests/filetests/alias/simple-alias.clif: alias-analysis

Caused by:
    filecheck failed for function on line 9:
    #0 check: v5 -> v3
    #1 check: v7 -> v6
    > function %f0(i64 vmctx, i32) -> i32, i32, i32, i32 fast {
    Missed #0: \bv5 \-> v3\b
    >     gv0 = vmctx
    >     gv1 = load.i64 notrap aligned readonly gv0+8
    >     sig0 = (i64 vmctx) fast
    >     fn0 = %g sig0
    > 
    > block0(v0: i64, v1: i32):
    >     v2 = load.i64 notrap aligned readonly v0+8
    >     v3 = load.i32 v2+8
    >     v5 = load.i32 v2+8
    >     call fn0(v0)
    >     v6 = load.i32 v2+8
    >     v7 -> v6
    >     return v3, v5, v6, v7
    > }
    
FAIL /Users/n.fitzgerald/scratch/wasmtime-alias-analysis-lattice/cranelift/filetests/filetests/alias/join-order-independence.clif: optimize

Caused by:
    compilation of function on line 9 does not match
    the text expectation
    
    --- expected
    +++ actual
    @@ -14,5 +14,6 @@
         jump block4
     
     block4:
    -    return v3, v3
    +    v4 = load.i32 notrap aligned region0 v0
    +    return v3, v4
     }
    
    
    This test assertion can be automatically updated by setting the
    CRANELIFT_TEST_BLESS=1 environment variable when running this test.
             
FAIL /Users/n.fitzgerald/scratch/wasmtime-alias-analysis-lattice/cranelift/filetests/filetests/alias/join-single-predecessor.clif: optimize

Caused by:
    compilation of function on line 5 does not match
    the text expectation
    
    --- expected
    +++ actual
    @@ -16,9 +16,10 @@
         jump block4
     
     block4:
    +    v11 = load.i32 notrap aligned region0 v0
         store.i32 notrap aligned region0 v3, v0
         brif.i32 v1, block1, block5
     
     block5:
    -    return v10, v10
    +    return v10, v11
     }
    
    
    This test assertion can be automatically updated by setting the
    CRANELIFT_TEST_BLESS=1 environment variable when running this test.
             
FAIL /Users/n.fitzgerald/scratch/wasmtime-alias-analysis-lattice/cranelift/filetests/filetests/alias/fence-fallback-across-join.clif: optimize

Caused by:
    compilation of function on line 5 does not match
    the text expectation
    
    --- expected
    +++ actual
    @@ -12,5 +12,6 @@
         jump block3
     
     block3:
    -    return v3, v3
    +    v4 = load.i32 notrap aligned region0 v0
    +    return v3, v4
     }
    
    
    This test assertion can be automatically updated by setting the
    CRANELIFT_TEST_BLESS=1 environment variable when running this test.
             
FAIL /Users/n.fitzgerald/scratch/wasmtime-alias-analysis-lattice/cranelift/filetests/filetests/alias/check-unset-reset-flag.clif: optimize

Caused by:
    compilation of function on line 5 does not match
    the text expectation
    
    --- expected
    +++ actual
    @@ -4,6 +4,7 @@
     block0(v0: i64, v1: i32):
         v2 = load.i64 notrap aligned region0 v0
         trapz v2, user42
    +    store notrap aligned region0 v2, v0
         v4 = iadd v1, v1
         return v4
     }
    
    
    This test assertion can be automatically updated by setting the
    CRANELIFT_TEST_BLESS=1 environment variable when running this test.
             
FAIL /Users/n.fitzgerald/scratch/wasmtime-alias-analysis-lattice/cranelift/filetests/filetests/alias/forward-across-trap.clif: optimize

Caused by:
    compilation of function on line 7 does not match
    the text expectation
    
    --- expected
    +++ actual
    @@ -4,5 +4,6 @@
     block0(v0: i64, v1: i32):
         v2 = load.i64 notrap aligned region0 v0
         trapz v1, user42
    -    return v2, v2
    +    v3 = load.i64 notrap aligned region0 v0
    +    return v2, v3
     }
    
    
    This test assertion can be automatically updated by setting the
    CRANELIFT_TEST_BLESS=1 environment variable when running this test.
             
1289 tests
Error: 12 failures

A lot of those look like regressions to pretty simple cases that I'd really expect to be handled.

We also get the following disas test failures:

Details
failures:

---- ./tests/disas/dynamic-memory-yes-spectre-access-same-index-different-offsets.wat ----
failed to run tests "./tests/disas/dynamic-memory-yes-spectre-access-same-index-different-offsets.wat"

Caused by:
    Did not get the expected CLIF translation:

--- expected
+++ actual
@@ -18,15 +18,22 @@
 @0047                               v7 = iadd v6, v3
 @0047                               v9 = select_spectre_guard v5, v8, v7  ; v8 = 0
 @0047                               v10 = load.i32 little region4 v9
+@004c                               v12 = load.i64 notrap aligned region3 v0+64
+@004c                               v14 = load.i64 notrap aligned can_move region2 v0+56
+@004c                               v13 = icmp ugt v3, v12
+@004c                               v15 = iadd v14, v3
 @004c                               v16 = iconst.i64 4
-@004c                               v17 = iadd v7, v16  ; v16 = 4
-@004c                               v19 = select_spectre_guard v5, v8, v17  ; v8 = 0
+@004c                               v17 = iadd v15, v16  ; v16 = 4
+@004c                               v19 = select_spectre_guard v13, v8, v17  ; v8 = 0
 @004c                               v20 = load.i32 little region4 v19
 @0051                               v22 = iconst.i64 0x0010_0003
 @0051                               v23 = uadd_overflow_trap v3, v22, heap_oob  ; v22 = 0x0010_0003
-@0051                               v25 = icmp ugt v23, v4
+@0051                               v24 = load.i64 notrap aligned region3 v0+64
+@0051                               v26 = load.i64 notrap aligned can_move region2 v0+56
+@0051                               v25 = icmp ugt v23, v24
+@0051                               v27 = iadd v26, v3
 @0051                               v28 = iconst.i64 0x000f_ffff
-@0051                               v29 = iadd v7, v28  ; v28 = 0x000f_ffff
+@0051                               v29 = iadd v27, v28  ; v28 = 0x000f_ffff
 @0051                               v31 = select_spectre_guard v25, v8, v29  ; v8 = 0
 @0051                               v32 = load.i32 little region4 v31
 @0056                               jump block1
@@ -55,15 +62,22 @@
 @005d                               v10 = iadd v9, v6
 @005d                               v12 = select_spectre_guard v8, v11, v10  ; v11 = 0
 @005d                               store little region4 v3, v12
+@0064                               v14 = load.i64 notrap aligned region3 v0+64
+@0064                               v16 = load.i64 notrap aligned can_move region2 v0+56
+@0064                               v15 = icmp ugt v6, v14
+@0064                               v17 = iadd v16, v6
 @0064                               v18 = iconst.i64 4
-@0064                               v19 = iadd v10, v18  ; v18 = 4
-@0064                               v21 = select_spectre_guard v8, v11, v19  ; v11 = 0
+@0064                               v19 = iadd v17, v18  ; v18 = 4
+@0064                               v21 = select_spectre_guard v15, v11, v19  ; v11 = 0
 @0064                               store little region4 v4, v21
 @006b                               v23 = iconst.i64 0x0010_0003
 @006b                               v24 = uadd_overflow_trap v6, v23, heap_oob  ; v23 = 0x0010_0003
-@006b                               v26 = icmp ugt v24, v7
+@006b                               v25 = load.i64 notrap aligned region3 v0+64
+@006b                               v27 = load.i64 notrap aligned can_move region2 v0+56
+@006b                               v26 = icmp ugt v24, v25
+@006b                               v28 = iadd v27, v6
 @006b                               v29 = iconst.i64 0x000f_ffff
-@006b                               v30 = iadd v10, v29  ; v29 = 0x000f_ffff
+@006b                               v30 = iadd v28, v29  ; v29 = 0x000f_ffff
 @006b                               v32 = select_spectre_guard v26, v11, v30  ; v11 = 0
 @006b                               store little region4 v5, v32
 @0070                               jump block1


Note: You can re-run with the `WASMTIME_TEST_BLESS=1` environment
variable set to update test expectations.


---- ./tests/disas/alias-region-tables.wat ----
failed to run tests "./tests/disas/alias-region-tables.wat"

Caused by:
    Did not get the expected CLIF translation:

--- expected
+++ actual
@@ -41,9 +41,16 @@
 @0049                               v25 = iadd v22, v12
 @0049                               v27 = select_spectre_guard v20, v14, v25  ; v14 = 0
 @0049                               store user6 aligned region6 v17, v27
+@004d                               v31 = load.i64 notrap aligned region4 v4+8
+@004d                               v36 = load.i64 notrap aligned region3 v4
+@004d                               v32 = ireduce.i32 v31
+@004d                               v33 = icmp uge v2, v32
+@004d                               v39 = iadd v36, v12
+@004d                               v41 = select_spectre_guard v33, v14, v39  ; v14 = 0
+@004d                               v42 = load.i64 user6 aligned region5 v41
 @004d                               v43 = iconst.i64 -2
-@004d                               v44 = band v17, v43  ; v43 = -2
-@004d                               brif v17, block3(v44), block2
+@004d                               v44 = band v42, v43  ; v43 = -2
+@004d                               brif v42, block3(v44), block2
 
                                 block2 cold:
 @004d                               v46 = iconst.i32 0


Note: You can re-run with the `WASMTIME_TEST_BLESS=1` environment
variable set to update test expectations.


---- ./tests/disas/array-copy-i64.wat ----
failed to run tests "./tests/disas/array-copy-i64.wat"

Caused by:
    Did not get the expected CLIF translation:

--- expected
+++ actual
@@ -47,11 +47,13 @@
 @002b                               v64 = iadd v9, v63
 @002b                               v66 = icmp ugt v65, v64
 @002b                               trapnz v66, user2
+@002b                               v70 = load.i64 notrap aligned region3 v8+40
 @002b                               v50 = iadd v34, v25  ; v25 = 24
                                     v79 = ishl v39, v76  ; v76 = 3
 @002b                               v54 = iadd v50, v79
 @002b                               v72 = uadd_overflow_trap v54, v81, user2
-@002b                               v73 = icmp ugt v72, v64
+@002b                               v71 = iadd v9, v70
+@002b                               v73 = icmp ugt v72, v71
 @002b                               trapnz v73, user2
 @002b                               call fn0(v0, v30, v54, v81)
 @002f                               jump block1


Note: You can re-run with the `WASMTIME_TEST_BLESS=1` environment
variable set to update test expectations.


---- ./tests/disas/pulley/coremark-1.wat ----
failed to run tests "./tests/disas/pulley/coremark-1.wat"

Caused by:
    Did not get the expected CLIF translation:

--- expected
+++ actual
@@ -1,9 +1,10 @@
 wasm[0]::function[0]:
-      push_frame_save 16, x24
+      push_frame_save 16, x25
       xzero x6
       xload64le_o32 x1, x0, 56
+      xload64le_o32 x7, x0, 64
+      xload16le_u32_g32 x7, x1, x7, x2, 0
       xload64le_o32 x8, x0, 64
-      xload16le_u32_g32 x7, x1, x8, x2, 0
       xload16le_u32_g32 x8, x1, x8, x3, 0
       xsub32_u8 x4, x4, 1
       xmul32 x7, x7, x8
@@ -12,15 +13,15 @@
       xshr32_u_u6 x7, x7, 5
       xband32_s8 x7, x7, 127
       xmadd32 x6, x8, x7, x6
-      xmov x24, x6
+      xmov x25, x6
       xadd32 x2, x2, x5
       xadd32_u8 x3, x3, 2
-      br_if_not32 x4, 0xe    // target = 0x53
-  4b: xmov x6, x24
-      jump -0x40    // target = 0xe
-  53: call2 x0, x0, 0x10    // target = 0x63
-      xmov x0, x24
-      pop_frame_restore 16, x24
+      br_if_not32 x4, 0xe    // target = 0x5a
+  52: xmov x6, x25
+      jump -0x47    // target = 0xe
+  5a: call2 x0, x0, 0x10    // target = 0x6a
+      xmov x0, x25
+      pop_frame_restore 16, x25
       ret
 
 wasm[0]::function[1]::other:


Note: You can re-run with the `WASMTIME_TEST_BLESS=1` environment
variable set to update test expectations.


---- ./tests/disas/pulley/pulley64_memory32.wat ----
failed to run tests "./tests/disas/pulley/pulley64_memory32.wat"

Caused by:
    Did not get the expected CLIF translation:

--- expected
+++ actual
@@ -163,9 +163,10 @@
       xload64le_o32 x7, x0, 64
       ╰─╼ addrmap: 0xd7
       xload64le_o32 x8, x0, 56
-      xload16le_u32_g32 x0, x8, x7, x2, 0
-      xload16le_u32_g32 x1, x8, x7, x3, 0
+      xload16le_u32_g32 x7, x8, x7, x2, 0
+      xload16le_u32_g32bne x1, x8, *[x0 + 64], x3, 0
       ╰─╼ addrmap: 0xdc
+      xmov x0, x7
       pop_frame
       ╰─╼ addrmap: 0xdf
       ret
\ No newline at end of file


Note: You can re-run with the `WASMTIME_TEST_BLESS=1` environment
variable set to update test expectations.


---- ./tests/disas/component-model/sync-adapter-calls-x64.wat ----
failed to run tests "./tests/disas/component-model/sync-adapter-calls-x64.wat"

Caused by:
    Did not get the expected CLIF translation:

--- expected
+++ actual
@@ -3,41 +3,46 @@
       movq    %rsp, %rbp
       movq    8(%rdi), %r10
       movq    0x18(%r10), %r10
-      addq    $0x20, %r10
+      addq    $0x30, %r10
       cmpq    %rsp, %r10
-      ja      0xe6
-  39: subq    $0x20, %rsp
+      ja      0xfd
+  39: subq    $0x30, %rsp
+      movq    %rbx, 0x20(%rsp)
       movq    0x48(%rdi), %rdi
       movq    0xe8(%rdi), %rax
       movl    (%rax), %ecx
       testl   %ecx, %ecx
-      je      0xe8
-  52: movq    0x100(%rdi), %rdx
+      je      0xff
+  57: movq    0x100(%rdi), %rdx
       movl    (%rdx), %esi
       movl    $0, (%rdx)
-      movq    8(%rdi), %rdi
-      movq    0x88(%rdi), %r8
-      leaq    (%rsp), %r10
-      movq    %r8, (%rsp)
+      movq    8(%rdi), %r8
+      movq    0x88(%r8), %r9
+      leaq    (%rsp), %rbx
+      movq    %r9, (%rsp)
       movl    $2, 8(%rsp)
       movl    $0, 0xc(%rsp)
       movl    $1, 0x10(%rsp)
-      movl    0x80(%rdi), %r9d
-      movl    %r9d, 0x14(%rsp)
-      movl    $0, 0x80(%rdi)
-      movl    0x84(%rdi), %r11d
+      movl    0x80(%r8), %r10d
+      movl    %r10d, 0x14(%rsp)
+      movl    $0, 0x80(%r8)
+      movl    0x84(%r8), %r11d
       movl    %r11d, 0x18(%rsp)
-      movl    $0, 0x84(%rdi)
-      movq    %r10, 0x88(%rdi)
-      movq    %r8, 0x88(%rdi)
-      movl    %r9d, 0x80(%rdi)
-      movl    %r11d, 0x84(%rdi)
+      movl    $0, 0x84(%r8)
+      movq    %rbx, 0x88(%r8)
+      movq    0xd0(%rdi), %rdi
+      movl    (%rdi), %ebx
+      movl    %ebx, (%rdi)
+      movq    %r9, 0x88(%r8)
+      movl    %r10d, 0x80(%r8)
+      movl    %r11d, 0x84(%r8)
       movl    %ecx, (%rax)
       movl    %esi, (%rdx)
       movl    $0x4fc, %eax
-      addq    $0x20, %rsp
+      movq    0x20(%rsp), %rbx
+      addq    $0x30, %rsp
       movq    %rbp, %rsp
       popq    %rbp
       retq
-  e6: ud2
-  e8: ud2
\ No newline at end of file
+  fd: ud2
+  ff: ud2
\ No newline at end of file


Note: You can re-run with the `WASMTIME_TEST_BLESS=1` environment
variable set to update test expectations.


---- ./tests/disas/component-model/direct-adapter-calls.wat ----
failed to run tests "./tests/disas/component-model/direct-adapter-calls.wat"

Caused by:
    Did not get the expected CLIF translation:

--- expected
+++ actual
@@ -66,6 +66,7 @@
                                 block7:
 @009e                               v9 = load.i64 notrap aligned readonly can_move region2 v0+144
 @009e                               v10 = load.i32 notrap aligned region5 v9
+@00aa                               store notrap aligned region5 v10, v9
 @00ac                               v14 = load.i64 notrap aligned readonly can_move region4 v0+72
 @00ac                               try_call fn0(v14, v0, v2), sig1, block9(ret0), [ context v0, default: block6(
 


Note: You can re-run with the `WASMTIME_TEST_BLESS=1` environment
variable set to update test expectations.


---- ./tests/disas/component-model/direct-adapter-calls-inlining.wat ----
failed to run tests "./tests/disas/component-model/direct-adapter-calls-inlining.wat"

Caused by:
    Did not get the expected CLIF translation:

--- expected
+++ actual
@@ -37,6 +37,7 @@
                                 block9:
                                     v11 = load.i64 notrap aligned readonly can_move region3 v3+144
                                     v12 = load.i32 notrap aligned region5 v11
+                                    store notrap aligned region5 v12, v11
                                     jump block12
 
                                 block12:
@@ -46,6 +47,7 @@
                                     jump block11
 
                                 block11:
+                                    store.i32 notrap aligned region4 v10, v9
                                     jump block7
 
                                 block7:


Note: You can re-run with the `WASMTIME_TEST_BLESS=1` environment
variable set to update test expectations.


---- ./tests/disas/component-model/known-imported-adapter-memory.wat ----
failed to run tests "./tests/disas/component-model/known-imported-adapter-memory.wat"

Caused by:
    Did not get the expected CLIF translation:

--- expected
+++ actual
@@ -120,6 +120,7 @@
                                 block7:
 @0103                               v10 = load.i64 notrap aligned readonly can_move region2 v0+320
 @0103                               v11 = load.i32 notrap aligned region5 v10
+@010f                               store notrap aligned region5 v11, v10
 @0111                               v15 = load.i64 notrap aligned readonly can_move region4 v0+184
 @0111                               try_call fn0(v15, v0, v2), sig1, block9(ret0), [ context v0, default: block6(
 


Note: You can re-run with the `WASMTIME_TEST_BLESS=1` environment
variable set to update test expectations.


---- ./tests/disas/component-model/direct-adapter-calls-x64.wat ----
failed to run tests "./tests/disas/component-model/direct-adapter-calls-x64.wat"

Caused by:
    Did not get the expected CLIF translation:

--- expected
+++ actual
@@ -30,7 +30,7 @@
       movq    0x18(%r10), %r10
       addq    $0x60, %r10
       cmpq    %rsp, %r10
-      ja      0xfd
+      ja      0x105
   79: subq    $0x50, %rsp
       movq    %rbx, 0x20(%rsp)
       movq    %r12, 0x28(%rsp)
@@ -39,21 +39,24 @@
       movq    %r15, 0x40(%rsp)
       movq    %rdi, (%rsp)
       movq    (%rsp), %rdi
-      movq    0xa8(%rdi), %r10
-      movl    (%r10), %r11d
-      movq    %r10, 0x10(%rsp)
-      testl   %r11d, %r11d
-      movq    %r11, 8(%rsp)
-      je      0xff
-  bb: movq    (%rsp), %rdi
+      movq    0xa8(%rdi), %rcx
+      movl    (%rcx), %esi
+      movq    %rcx, 0x10(%rsp)
+      testl   %esi, %esi
+      movq    %rsi, 8(%rsp)
+      je      0x107
+  b9: movq    (%rsp), %rdi
+      movq    0x90(%rdi), %rax
+      movl    (%rax), %ecx
+      movl    %ecx, (%rax)
       movq    0x48(%rdi), %rdi
       movq    (%rsp), %rsi
       callq   0
       ├─╼ exception frame offset: SP = FP - 0x50
-      ╰─╼ exception handler: default handler, context at [SP+0x0], handler=0xfb
-      movq    0x10(%rsp), %r10
-      movq    8(%rsp), %r11
-      movl    %r11d, (%r10)
+      ╰─╼ exception handler: default handler, context at [SP+0x0], handler=0x103
+      movq    0x10(%rsp), %rcx
+      movq    8(%rsp), %rsi
+      movl    %esi, (%rcx)
       movq    0x20(%rsp), %rbx
       movq    0x28(%rsp), %r12
       movq    0x30(%rsp), %r13
@@ -63,6 +66,6 @@
       movq    %rbp, %rsp
       popq    %rbp
       retq
-  fb: ud2
-  fd: ud2
-  ff: ud2
\ No newline at end of file
+ 103: ud2
+ 105: ud2
+ 107: ud2
\ No newline at end of file


Note: You can re-run with the `WASMTIME_TEST_BLESS=1` environment
variable set to update test expectations.


---- ./tests/disas/component-model/sync-adapter-calls.wat ----
failed to run tests "./tests/disas/component-model/sync-adapter-calls.wat"

Caused by:
    Did not get the expected CLIF translation:

--- expected
+++ actual
@@ -70,6 +70,7 @@
                                     store notrap aligned region6 v19, v20+136
                                     v26 = load.i64 notrap aligned readonly can_move region3 v3+208
                                     v27 = load.i32 notrap aligned region15 v26
+                                    store notrap aligned region15 v27, v26
                                     jump block16
 
                                 block16:


Note: You can re-run with the `WASMTIME_TEST_BLESS=1` environment
variable set to update test expectations.


---- ./tests/disas/startup-data-active.wat ----
failed to run tests "./tests/disas/startup-data-active.wat"

Caused by:
    Did not get the expected CLIF translation:

--- expected
+++ actual
@@ -51,8 +51,13 @@
     v10 = uextend.i64 v6
     v14 = icmp ugt v10, v8
     trapnz v14, heap_oob
+    v20 = load.i32 notrap aligned region1 v0+120
+    v21 = uextend.i64 v20
+    v27 = icmp ugt v10, v21
+    trapnz v27, heap_oob
+    v28 = load.i64 notrap aligned region0 v0+112
     v15 = load.i64 notrap aligned readonly can_move region3 v0+56
-    call fn0(v0, v15, v2, v10)
+    call fn0(v0, v15, v28, v10)
     jump block2
 
 block2:


Note: You can re-run with the `WASMTIME_TEST_BLESS=1` environment
variable set to update test expectations.


---- ./tests/disas/memory-copy-fuel-const-len.wat ----
failed to run tests "./tests/disas/memory-copy-fuel-const-len.wat"

Caused by:
    Did not get the expected CLIF translation:

--- expected
+++ actual
@@ -35,9 +35,10 @@
 @002a                               v22 = iadd v18, v47  ; v47 = 16
 @002a                               v23 = icmp ugt v22, v17
 @002a                               trapnz v23, heap_oob
+@002a                               v29 = load.i64 notrap aligned region4 v0+64
 @002a                               v30 = uextend.i64 v3
 @002a                               v34 = iadd v30, v47  ; v47 = 16
-@002a                               v35 = icmp ugt v34, v17
+@002a                               v35 = icmp ugt v34, v29
 @002a                               trapnz v35, heap_oob
 @002a                               v24 = load.i64 notrap aligned readonly can_move region3 v0+56
 @002a                               v40 = iadd v24, v30


Note: You can re-run with the `WASMTIME_TEST_BLESS=1` environment
variable set to update test expectations.


---- ./tests/disas/memory-copy-fuel.wat ----
failed to run tests "./tests/disas/memory-copy-fuel.wat"

Caused by:
    Did not get the expected CLIF translation:

--- expected
+++ actual
@@ -50,9 +50,10 @@
 @0025                               v36 = iadd v32, v18
 @0025                               v37 = icmp ugt v36, v31
 @0025                               trapnz v37, heap_oob
+@0025                               v43 = load.i64 notrap aligned region4 v0+64
 @0025                               v44 = uextend.i64 v3
 @0025                               v48 = iadd v44, v18
-@0025                               v49 = icmp ugt v48, v31
+@0025                               v49 = icmp ugt v48, v43
 @0025                               trapnz v49, heap_oob
 @0025                               v38 = load.i64 notrap aligned readonly can_move region3 v0+56
 @0025                               v42 = iadd v38, v32


Note: You can re-run with the `WASMTIME_TEST_BLESS=1` environment
variable set to update test expectations.


---- ./tests/disas/memory_copy_host64.wat ----
failed to run tests "./tests/disas/memory_copy_host64.wat"

Caused by:
    Did not get the expected CLIF translation:

--- expected
+++ actual
@@ -17,9 +17,10 @@
 @0042                               v10 = iadd v6, v7
 @0042                               v11 = icmp ugt v10, v5
 @0042                               trapnz v11, heap_oob
+@0042                               v17 = load.i64 notrap aligned region3 v0+88
 @0042                               v18 = uextend.i64 v3
 @0042                               v22 = iadd v18, v7
-@0042                               v23 = icmp ugt v22, v5
+@0042                               v23 = icmp ugt v22, v17
 @0042                               trapnz v23, heap_oob
 @0042                               v12 = load.i64 notrap aligned readonly can_move region2 v0+80
 @0042                               v16 = iadd v12, v6
@@ -118,11 +119,13 @@
 @0069                               v7 = icmp ugt v6, v5
 @0069                               trapnz v7, heap_oob
 @0069                               v8 = load.i64 notrap aligned can_move region2 v0+112
+@0069                               v12 = load.i64 notrap aligned region3 v0+120
 @0069                               v13 = uadd_overflow_trap v3, v4, heap_oob
-@0069                               v14 = icmp ugt v13, v5
+@0069                               v14 = icmp ugt v13, v12
 @0069                               trapnz v14, heap_oob
+@0069                               v15 = load.i64 notrap aligned can_move region2 v0+112
 @0069                               v11 = iadd v8, v2
-@0069                               v18 = iadd v8, v3
+@0069                               v18 = iadd v15, v3
 @0069                               call fn0(v0, v11, v18, v4)
 @006d                               jump block1
 


Note: You can re-run with the `WASMTIME_TEST_BLESS=1` environment
variable set to update test expectations.


---- ./tests/disas/startup-elem-active.wat ----
failed to run tests "./tests/disas/startup-elem-active.wat"

Caused by:
    Did not get the expected CLIF translation:

--- expected
+++ actual
@@ -44,25 +44,34 @@
     v84 = icmp ult v6, v78  ; v78 = 4
     trapnz v84, user6
     v13 = load.i64 notrap aligned region0 v0+48
+    v25 = load.i64 notrap aligned region1 v0+56
+    v29 = load.i64 notrap aligned region0 v0+48
     v95 = iconst.i32 21
+    v26 = ireduce.i32 v25
     v2 = iconst.i32 1
-    v106 = icmp ule v5, v2  ; v2 = 1
+    v106 = icmp ule v26, v2  ; v2 = 1
     v71 = iconst.i64 0
-    v17 = iadd v13, v78  ; v78 = 4
-    v34 = select_spectre_guard v106, v71, v17  ; v71 = 0
+    v32 = iadd v29, v78  ; v78 = 4
+    v34 = select_spectre_guard v106, v71, v32  ; v71 = 0
     store user6 aligned region2 v95, v34  ; v95 = 21
+    v42 = load.i64 notrap aligned region1 v0+56
+    v46 = load.i64 notrap aligned region0 v0+48
     v109 = iconst.i32 23
+    v43 = ireduce.i32 v42
     v115 = iconst.i32 2
-    v121 = icmp ule v5, v115  ; v115 = 2
+    v121 = icmp ule v43, v115  ; v115 = 2
     v123 = iconst.i64 8
-    v49 = iadd v13, v123  ; v123 = 8
+    v49 = iadd v46, v123  ; v123 = 8
     v51 = select_spectre_guard v121, v71, v49  ; v71 = 0
     store user6 aligned region2 v109, v51  ; v109 = 23
+    v59 = load.i64 notrap aligned region1 v0+56
+    v63 = load.i64 notrap aligned region0 v0+48
     v125 = iconst.i32 25
+    v60 = ireduce.i32 v59
     v3 = iconst.i32 3
-    v136 = icmp ule v5, v3  ; v3 = 3
+    v136 = icmp ule v60, v3  ; v3 = 3
     v138 = iconst.i64 12
-    v66 = iadd v13, v138  ; v138 = 12
+    v66 = iadd v63, v138  ; v138 = 12
     v68 = select_spectre_guard v136, v71, v66  ; v71 = 0
     store user6 aligned region2 v125, v68  ; v125 = 25
     return


Note: You can re-run with the `WASMTIME_TEST_BLESS=1` environment
variable set to update test expectations.


---- ./tests/disas/array-copy-i8.wat ----
failed to run tests "./tests/disas/array-copy-i8.wat"

Caused by:
    Did not get the expected CLIF translation:

--- expected
+++ actual
@@ -44,10 +44,12 @@
 @002b                               v64 = iadd v9, v63
 @002b                               v66 = icmp ugt v65, v64
 @002b                               trapnz v66, user2
+@002b                               v70 = load.i64 notrap aligned region3 v8+40
 @002b                               v50 = iadd v34, v25  ; v25 = 20
 @002b                               v54 = iadd v50, v39
 @002b                               v72 = uadd_overflow_trap v54, v16, user2
-@002b                               v73 = icmp ugt v72, v64
+@002b                               v71 = iadd v9, v70
+@002b                               v73 = icmp ugt v72, v71
 @002b                               trapnz v73, user2
 @002b                               call fn0(v0, v30, v54, v16)
 @002f                               jump block1


Note: You can re-run with the `WASMTIME_TEST_BLESS=1` environment
variable set to update test expectations.


---- ./tests/disas/array-copy-anyref.wat ----
failed to run tests "./tests/disas/array-copy-anyref.wat"

Caused by:
    Did not get the expected CLIF translation:

--- expected
+++ actual
@@ -45,11 +45,13 @@
 @002b                               v64 = iadd v9, v63
 @002b                               v66 = icmp ugt v65, v64
 @002b                               trapnz v66, user2
+@002b                               v70 = load.i64 notrap aligned region3 v8+40
 @002b                               v50 = iadd v34, v25  ; v25 = 20
                                     v114 = ishl v39, v111  ; v111 = 2
 @002b                               v54 = iadd v50, v114
 @002b                               v72 = uadd_overflow_trap v54, v116, user2
-@002b                               v73 = icmp ugt v72, v64
+@002b                               v71 = iadd v9, v70
+@002b                               v73 = icmp ugt v72, v71
 @002b                               trapnz v73, user2
 @002b                               brif v6, block2, block5
 


Note: You can re-run with the `WASMTIME_TEST_BLESS=1` environment
variable set to update test expectations.


---- ./tests/disas/duplicate-loads-dynamic-memory.wat ----
failed to run tests "./tests/disas/duplicate-loads-dynamic-memory.wat"

Caused by:
    Did not get the expected CLIF translation:

--- expected
+++ actual
@@ -18,10 +18,16 @@
 @0057                               v7 = iadd v6, v3
 @0057                               v9 = select_spectre_guard v5, v8, v7  ; v8 = 0
 @0057                               v10 = load.i32 little region4 v9
+@005c                               v12 = load.i64 notrap aligned region3 v0+64
+@005c                               v14 = load.i64 notrap aligned can_move region2 v0+56
+@005c                               v13 = icmp ugt v3, v12
+@005c                               v15 = iadd v14, v3
+@005c                               v17 = select_spectre_guard v13, v8, v15  ; v8 = 0
+@005c                               v18 = load.i32 little region4 v17
 @005f                               jump block1
 
                                 block1:
-@005f                               return v10, v10
+@005f                               return v10, v18
 }
 
 function u0:1(i64 vmctx, i64, i32) -> i32, i32 tail {
@@ -46,8 +52,15 @@
 @0064                               v9 = iadd v7, v8  ; v8 = 1234
 @0064                               v11 = select_spectre_guard v5, v10, v9  ; v10 = 0
 @0064                               v12 = load.i32 little region4 v11
+@006a                               v14 = load.i64 notrap aligned region3 v0+64
+@006a                               v16 = load.i64 notrap aligned can_move region2 v0+56
+@006a                               v15 = icmp ugt v3, v14
+@006a                               v17 = iadd v16, v3
+@006a                               v19 = iadd v17, v8  ; v8 = 1234
+@006a                               v21 = select_spectre_guard v15, v10, v19  ; v10 = 0
+@006a                               v22 = load.i32 little region4 v21
 @006e                               jump block1
 
                                 block1:
-@006e                               return v12, v12
+@006e                               return v12, v22
 }
\ No newline at end of file


Note: You can re-run with the `WASMTIME_TEST_BLESS=1` environment
variable set to update test expectations.


---- ./tests/disas/array-fill-funcref.wat ----
failed to run tests "./tests/disas/array-fill-funcref.wat"

Caused by:
    Did not get the expected CLIF translation:

--- expected
+++ actual
@@ -144,9 +144,10 @@
 @0053                               v6 = call fn0(v0, v5), stack_map=[i32 @ ss0+0]  ; v5 = 3
                                     v55 = load.i32 notrap aligned region5 v56
 @0057                               trapz v55, user16
+                                    v53 = load.i32 notrap aligned region5 v56
 @0057                               v8 = load.i64 notrap aligned readonly can_move region0 v0+8
 @0057                               v9 = load.i64 notrap aligned readonly can_move region2 v8+32
-@0057                               v7 = uextend.i64 v55
+@0057                               v7 = uextend.i64 v53
 @0057                               v10 = iadd v9, v7
 @0057                               v11 = iconst.i64 16
 @0057                               v12 = iadd v10, v11  ; v11 = 16
@@ -157,9 +158,12 @@
 @0057                               v14 = uextend.i64 v13
 @0057                               v20 = icmp ugt v19, v14
 @0057                               trapnz v20, user17
+                                    v51 = load.i32 notrap aligned region5 v56
 @0057                               v37 = load.i64 notrap aligned region3 v8+40
+@0057                               v23 = uextend.i64 v51
+@0057                               v24 = iadd v9, v23
 @0057                               v25 = iconst.i64 20
-@0057                               v26 = iadd v10, v25  ; v25 = 20
+@0057                               v26 = iadd v24, v25  ; v25 = 20
                                     v59 = iconst.i64 2
                                     v60 = ishl v15, v59  ; v59 = 2
 @0057                               v30 = iadd v26, v60


Note: You can re-run with the `WASMTIME_TEST_BLESS=1` environment
variable set to update test expectations.


---- ./tests/disas/gc/drc/struct-new.wat ----
failed to run tests "./tests/disas/gc/drc/struct-new.wat"

Caused by:
    Did not get the expected CLIF translation:

--- expected
+++ actual
@@ -35,29 +35,36 @@
 @002a                               v18 = iadd v14, v17  ; v17 = 28
 @002a                               istore8 user2 little region5 v3, v18
                                     v51 = load.i32 notrap aligned region7 v52
+                                    v49 = load.i32 notrap aligned region7 v52
 @002a                               v21 = iconst.i32 1
 @002a                               v22 = band v51, v21  ; v21 = 1
 @002a                               v23 = iconst.i32 0
-@002a                               v24 = icmp eq v51, v23  ; v23 = 0
+@002a                               v24 = icmp eq v49, v23  ; v23 = 0
 @002a                               v25 = uextend.i32 v24
 @002a                               v26 = bor v22, v25
 @002a                               brif v26, block3, block2
 
                                 block2:
-@002a                               v27 = uextend.i64 v51
+                                    v47 = load.i32 notrap aligned region7 v52
+@002a                               v27 = uextend.i64 v47
 @002a                               v30 = iadd.i64 v12, v27
 @002a                               v31 = iconst.i64 8
 @002a                               v32 = iadd v30, v31  ; v31 = 8
 @002a                               v33 = load.i64 user2 region5 v32
+                                    v45 = load.i32 notrap aligned region7 v52
 @002a                               v34 = iconst.i64 1
 @002a                               v35 = iadd v33, v34  ; v34 = 1
-@002a                               store user2 region5 v35, v32
+@002a                               v36 = uextend.i64 v45
+@002a                               v39 = iadd.i64 v12, v36
+@002a                               v41 = iadd v39, v31  ; v31 = 8
+@002a                               store user2 region5 v35, v41
 @002a                               jump block3
 
                                 block3:
+                                    v43 = load.i32 notrap aligned region7 v52
 @002a                               v19 = iconst.i64 32
 @002a                               v20 = iadd.i64 v14, v19  ; v19 = 32
-@002a                               store.i32 user2 little region5 v51, v20
+@002a                               store user2 little region5 v43, v20
 @002d                               jump block1
 
                                 block1:


Note: You can re-run with the `WASMTIME_TEST_BLESS=1` environment
variable set to update test expectations.


---- ./tests/disas/gc/drc/multiple-array-get.wat ----
failed to run tests "./tests/disas/gc/drc/multiple-array-get.wat"

Caused by:
    Did not get the expected CLIF translation:

--- expected
+++ actual
@@ -39,13 +39,23 @@
 @0024                               v30 = uextend.i64 v29
 @0024                               v31 = isub v28, v30
 @0024                               v32 = load.i64 user2 little region4 v31
-@002b                               v40 = icmp ult v4, v11
+@002b                               v39 = load.i32 user2 readonly region4 v10
+@002b                               v40 = icmp ult v4, v39
 @002b                               trapz v40, user17
-                                    v78 = ishl v4, v70  ; v70 = 3
-@002b                               v51 = iadd v78, v19  ; v19 = 32
-@002b                               v57 = isub v20, v51
+@002b                               v42 = uextend.i64 v39
+                                    v79 = ishl v42, v62  ; v62 = 3
+@002b                               v45 = ushr v79, v16  ; v16 = 32
+@002b                               trapnz v45, user2
+                                    v84 = ishl v39, v70  ; v70 = 3
+@002b                               v48 = uadd_overflow_trap v84, v19, user2  ; v19 = 32
+@002b                               v52 = uadd_overflow_trap v2, v48, user2
+@002b                               v53 = uextend.i64 v52
+@002b                               v56 = iadd v7, v53
+                                    v89 = ishl v4, v70  ; v70 = 3
+@002b                               v51 = iadd v89, v19  ; v19 = 32
+@002b                               v57 = isub v48, v51
 @002b                               v58 = uextend.i64 v57
-@002b                               v59 = isub v28, v58
+@002b                               v59 = isub v56, v58
 @002b                               v60 = load.i64 user2 little region4 v59
 @002e                               jump block1
 


Note: You can re-run with the `WASMTIME_TEST_BLESS=1` environment
variable set to update test expectations.


---- ./tests/disas/gc/issue-11753.wat ----
failed to run tests "./tests/disas/gc/issue-11753.wat"

Caused by:
    Did not get the expected CLIF translation:

--- expected
+++ actual
@@ -5,7 +5,7 @@
       movq    0x18(%r10), %r10
       addq    $0x50, %r10
       cmpq    %rsp, %r10
-      ja      0x11a
+      ja      0x11d
   19: subq    $0x40, %rsp
       movq    %rbx, 0x10(%rsp)
       movq    %r12, 0x18(%rsp)
@@ -18,7 +18,7 @@
       leaq    0x20(%rcx), %rdx
       movl    4(%rsi), %r8d
       cmpq    %r8, %rdx
-      ja      0xe6
+      ja      0xe9
   4f: movq    %rdi, 8(%rsp)
       leal    0x20(%rax), %edi
       movl    %edi, (%rsi)
@@ -48,8 +48,9 @@
       movl    (%rsp), %eax
       ╰─╼ stack_map: frame_size=64, frame_offsets=[0]
       testl   %eax, %eax
-      je      0x11c
-  b1: movq    8(%rsp), %r9
+      je      0x11f
+  b1: movl    (%rsp), %eax
+      movq    8(%rsp), %r9
       movq    8(%r9), %rcx
       movq    0x20(%rcx), %rcx
       movl    %eax, %eax
@@ -64,19 +65,19 @@
       movq    %rbp, %rsp
       popq    %rbp
       retq
-  e6: movl    $0xb0000002, %esi
-  eb: movq    0x28(%rdi), %rax
-  ef: movq    %rdi, 8(%rsp)
-  f4: movl    (%rax), %edx
-  f6: movl    $0x20, %ecx
-  fb: movl    $0x10, %r8d
- 101: callq   0x286
- 106: movq    8(%rsp), %r9
- 10b: movq    8(%r9), %rcx
- 10f: movl    %eax, %esi
- 111: addq    0x20(%rcx), %rsi
- 115: jmp     0x88
- 11a: ud2
+  e9: movl    $0xb0000002, %esi
+  ee: movq    0x28(%rdi), %rax
+  f2: movq    %rdi, 8(%rsp)
+  f7: movl    (%rax), %edx
+  f9: movl    $0x20, %ecx
+  fe: movl    $0x10, %r8d
+ 104: callq   0x289
+ 109: movq    8(%rsp), %r9
+ 10e: movq    8(%r9), %rcx
+ 112: movl    %eax, %esi
+ 114: addq    0x20(%rcx), %rsi
+ 118: jmp     0x88
+ 11d: ud2
       ╰─╼ trap: Normal(StackOverflow)
- 11c: ud2
+ 11f: ud2
       ╰─╼ trap: Normal(NullReference)
\ No newline at end of file


Note: You can re-run with the `WASMTIME_TEST_BLESS=1` environment
variable set to update test expectations.


---- ./tests/disas/gc/drc/array-new-fixed-of-gc-refs.wat ----
failed to run tests "./tests/disas/gc/drc/array-new-fixed-of-gc-refs.wat"

Caused by:
    Did not get the expected CLIF translation:

--- expected
+++ actual
@@ -43,31 +43,38 @@
 @0025                               trapz v18, user16
 @0025                               v45 = uadd_overflow_trap v18, v216, user2  ; v216 = 40
                                     v201 = load.i32 notrap aligned region9 v202
+                                    v199 = load.i32 notrap aligned region9 v202
 @0025                               v53 = iconst.i32 1
 @0025                               v54 = band v201, v53  ; v53 = 1
 @0025                               v25 = iconst.i32 0
-@0025                               v56 = icmp eq v201, v25  ; v25 = 0
+@0025                               v56 = icmp eq v199, v25  ; v25 = 0
 @0025                               v57 = uextend.i32 v56
 @0025                               v58 = bor v54, v57
 @0025                               brif v58, block3, block2
 
                                 block2:
-@0025                               v59 = uextend.i64 v201
+                                    v197 = load.i32 notrap aligned region9 v202
+@0025                               v59 = uextend.i64 v197
 @0025                               v62 = iadd.i64 v20, v59
 @0025                               v63 = iconst.i64 8
 @0025                               v64 = iadd v62, v63  ; v63 = 8
 @0025                               v65 = load.i64 user2 region5 v64
+                                    v195 = load.i32 notrap aligned region9 v202
 @0025                               v66 = iconst.i64 1
 @0025                               v67 = iadd v65, v66  ; v66 = 1
-@0025                               store user2 region5 v67, v64
+@0025                               v68 = uextend.i64 v195
+@0025                               v71 = iadd.i64 v20, v68
+@0025                               v73 = iadd v71, v63  ; v63 = 8
+@0025                               store user2 region5 v67, v73
 @0025                               jump block3
 
                                 block3:
+                                    v193 = load.i32 notrap aligned region9 v202
 @0025                               v46 = uextend.i64 v45
 @0025                               v49 = iadd.i64 v20, v46
                                     v206 = iconst.i64 12
 @0025                               v52 = isub v49, v206  ; v206 = 12
-@0025                               store.i32 user2 little region5 v201, v52
+@0025                               store user2 little region5 v193, v52
                                     v306 = iadd.i64 v22, v23  ; v23 = 24
 @0025                               v81 = load.i32 user2 readonly region5 v306
                                     v307 = iconst.i32 1
@@ -85,32 +92,39 @@
 @0025                               v90 = uadd_overflow_trap v258, v6, user2  ; v6 = 28
 @0025                               v94 = uadd_overflow_trap.i32 v18, v90, user2
                                     v191 = load.i32 notrap aligned region8 v203
+                                    v189 = load.i32 notrap aligned region8 v203
                                     v309 = band v191, v307  ; v307 = 1
                                     v310 = iconst.i32 0
-                                    v311 = icmp eq v191, v310  ; v310 = 0
+                                    v311 = icmp eq v189, v310  ; v310 = 0
 @0025                               v106 = uextend.i32 v311
 @0025                               v107 = bor v309, v106
 @0025                               brif v107, block5, block4
 
                                 block4:
-@0025                               v108 = uextend.i64 v191
+                                    v187 = load.i32 notrap aligned region8 v203
+@0025                               v108 = uextend.i64 v187
 @0025                               v111 = iadd.i64 v20, v108
                                     v312 = iconst.i64 8
 @0025                               v113 = iadd v111, v312  ; v312 = 8
 @0025                               v114 = load.i64 user2 region5 v113
+                                    v185 = load.i32 notrap aligned region8 v203
                                     v313 = iconst.i64 1
 @0025                               v116 = iadd v114, v313  ; v313 = 1
-@0025                               store user2 region5 v116, v113
+@0025                               v117 = uextend.i64 v185
+@0025                               v120 = iadd.i64 v20, v117
+@0025                               v122 = iadd v120, v312  ; v312 = 8
+@0025                               store user2 region5 v116, v122
 @0025                               jump block5
 
                                 block5:
+                                    v183 = load.i32 notrap aligned region8 v203
 @0025                               v95 = uextend.i64 v94
 @0025                               v98 = iadd.i64 v20, v95
                                     v270 = iconst.i32 32
 @0025                               v99 = isub.i32 v90, v270  ; v270 = 32
 @0025                               v100 = uextend.i64 v99
 @0025                               v101 = isub v98, v100
-@0025                               store.i32 user2 little region5 v191, v101
+@0025                               store user2 little region5 v183, v101
                                     v314 = iadd.i64 v22, v23  ; v23 = 24
 @0025                               v130 = load.i32 user2 readonly region5 v314
                                     v315 = iconst.i32 2
@@ -127,33 +141,40 @@
 @0025                               v139 = uadd_overflow_trap v321, v322, user2  ; v322 = 28
 @0025                               v143 = uadd_overflow_trap.i32 v18, v139, user2
                                     v181 = load.i32 notrap aligned region7 v204
+                                    v179 = load.i32 notrap aligned region7 v204
                                     v323 = iconst.i32 1
                                     v324 = band v181, v323  ; v323 = 1
                                     v325 = iconst.i32 0
-                                    v326 = icmp eq v181, v325  ; v325 = 0
+                                    v326 = icmp eq v179, v325  ; v325 = 0
 @0025                               v155 = uextend.i32 v326
 @0025                               v156 = bor v324, v155
 @0025                               brif v156, block7, block6
 
                                 block6:
-@0025                               v157 = uextend.i64 v181
+                                    v177 = load.i32 notrap aligned region7 v204
+@0025                               v157 = uextend.i64 v177
 @0025                               v160 = iadd.i64 v20, v157
                                     v327 = iconst.i64 8
 @0025                               v162 = iadd v160, v327  ; v327 = 8
 @0025                               v163 = load.i64 user2 region5 v162
+                                    v175 = load.i32 notrap aligned region7 v204
                                     v328 = iconst.i64 1
 @0025                               v165 = iadd v163, v328  ; v328 = 1
-@0025                               store user2 region5 v165, v162
+@0025                               v166 = uextend.i64 v175
+@0025                               v169 = iadd.i64 v20, v166
+@0025                               v171 = iadd v169, v327  ; v327 = 8
+@0025                               store user2 region5 v165, v171
 @0025                               jump block7
 
                                 block7:
+                                    v173 = load.i32 notrap aligned region7 v204
 @0025                               v144 = uextend.i64 v143
 @0025                               v147 = iadd.i64 v20, v144
                                     v300 = iconst.i32 36
 @0025                               v148 = isub.i32 v139, v300  ; v300 = 36
 @0025                               v149 = uextend.i64 v148
 @0025                               v150 = isub v147, v149
-@0025                               store.i32 user2 little region5 v181, v150
+@0025                               store user2 little region5 v173, v150
 @0029                               jump block1
 
                                 block1:


Note: You can re-run with the `WASMTIME_TEST_BLESS=1` environment
variable set to update test expectations.


---- ./tests/disas/gc/copying/v128-fields.wat ----
failed to run tests "./tests/disas/gc/copying/v128-fields.wat"

Caused by:
    Did not get the expected CLIF translation:

--- expected
+++ actual
@@ -7,7 +7,6 @@
     gv0 = vmctx
     gv1 = load.i64 notrap aligned readonly can_move region0 gv0+8
     gv2 = load.i64 notrap aligned region1 gv1+24
-    const0 = 0x00000000000000000000000000000000
     stack_limit = gv2
 
                                 block0(v0: i64, v1: i64, v2: i32):
@@ -19,9 +18,10 @@
 @0022                               v7 = iconst.i64 16
 @0022                               v8 = iadd v6, v7  ; v7 = 16
 @0022                               v9 = load.i8x16 user2 little region4 v8
+@0028                               v16 = load.i8x16 user2 little region4 v8
 @002e                               jump block1
 
                                 block1:
-                                    v18 = vconst.i8x16 const0
-@002e                               return v18  ; v18 = const0
+@002c                               v17 = bxor.i8x16 v9, v16
+@002e                               return v17
 }
\ No newline at end of file


Note: You can re-run with the `WASMTIME_TEST_BLESS=1` environment
variable set to update test expectations.


---- ./tests/disas/gc/copying/multiple-array-get.wat ----
failed to run tests "./tests/disas/gc/copying/multiple-array-get.wat"

Caused by:
    Did not get the expected CLIF translation:

--- expected
+++ actual
@@ -39,13 +39,23 @@
 @0024                               v30 = uextend.i64 v29
 @0024                               v31 = isub v28, v30
 @0024                               v32 = load.i64 user2 little region4 v31
-@002b                               v40 = icmp ult v4, v11
+@002b                               v39 = load.i32 user2 readonly region4 v10
+@002b                               v40 = icmp ult v4, v39
 @002b                               trapz v40, user17
-                                    v78 = ishl v4, v70  ; v70 = 3
-@002b                               v51 = iadd v78, v19  ; v19 = 24
-@002b                               v57 = isub v20, v51
+@002b                               v42 = uextend.i64 v39
+                                    v79 = ishl v42, v62  ; v62 = 3
+@002b                               v45 = ushr v79, v16  ; v16 = 32
+@002b                               trapnz v45, user2
+                                    v84 = ishl v39, v70  ; v70 = 3
+@002b                               v48 = uadd_overflow_trap v84, v19, user2  ; v19 = 24
+@002b                               v52 = uadd_overflow_trap v2, v48, user2
+@002b                               v53 = uextend.i64 v52
+@002b                               v56 = iadd v7, v53
+                                    v89 = ishl v4, v70  ; v70 = 3
+@002b                               v51 = iadd v89, v19  ; v19 = 24
+@002b                               v57 = isub v48, v51
 @002b                               v58 = uextend.i64 v57
-@002b                               v59 = isub v28, v58
+@002b                               v59 = isub v56, v58
 @002b                               v60 = load.i64 user2 little region4 v59
 @002e                               jump block1
 


Note: You can re-run with the `WASMTIME_TEST_BLESS=1` environment
variable set to update test expectations.


---- ./tests/disas/gc/null/v128-fields.wat ----
failed to run tests "./tests/disas/gc/null/v128-fields.wat"

Caused by:
    Did not get the expected CLIF translation:

--- expected
+++ actual
@@ -7,7 +7,6 @@
     gv0 = vmctx
     gv1 = load.i64 notrap aligned readonly can_move region0 gv0+8
     gv2 = load.i64 notrap aligned region1 gv1+24
-    const0 = 0x00000000000000000000000000000000
     stack_limit = gv2
 
                                 block0(v0: i64, v1: i64, v2: i32):
@@ -19,9 +18,10 @@
 @0022                               v7 = iconst.i64 16
 @0022                               v8 = iadd v6, v7  ; v7 = 16
 @0022                               v9 = load.i8x16 user2 little region4 v8
+@0028                               v16 = load.i8x16 user2 little region4 v8
 @002e                               jump block1
 
                                 block1:
-                                    v18 = vconst.i8x16 const0
-@002e                               return v18  ; v18 = const0
+@002c                               v17 = bxor.i8x16 v9, v16
+@002e                               return v17
 }
\ No newline at end of file


Note: You can re-run with the `WASMTIME_TEST_BLESS=1` environment
variable set to update test expectations.


---- ./tests/disas/gc/null/multiple-array-get.wat ----
failed to run tests "./tests/disas/gc/null/multiple-array-get.wat"

Caused by:
    Did not get the expected CLIF translation:

--- expected
+++ actual
@@ -39,13 +39,23 @@
 @0024                               v30 = uextend.i64 v29
 @0024                               v31 = isub v28, v30
 @0024                               v32 = load.i64 user2 little region4 v31
-@002b                               v40 = icmp ult v4, v11
+@002b                               v39 = load.i32 user2 readonly region4 v10
+@002b                               v40 = icmp ult v4, v39
 @002b                               trapz v40, user17
-                                    v78 = ishl v4, v70  ; v70 = 3
-@002b                               v51 = iadd v78, v19  ; v19 = 16
-@002b                               v57 = isub v20, v51
+@002b                               v42 = uextend.i64 v39
+                                    v79 = ishl v42, v62  ; v62 = 3
+@002b                               v45 = ushr v79, v16  ; v16 = 32
+@002b                               trapnz v45, user2
+                                    v84 = ishl v39, v70  ; v70 = 3
+@002b                               v48 = uadd_overflow_trap v84, v19, user2  ; v19 = 16
+@002b                               v52 = uadd_overflow_trap v2, v48, user2
+@002b                               v53 = uextend.i64 v52
+@002b                               v56 = iadd v7, v53
+                                    v89 = ishl v4, v70  ; v70 = 3
+@002b                               v51 = iadd v89, v19  ; v19 = 16
+@002b                               v57 = isub v48, v51
 @002b                               v58 = uextend.i64 v57
-@002b                               v59 = isub v28, v58
+@002b                               v59 = isub v56, v58
 @002b                               v60 = load.i64 user2 little region4 v59
 @002e                               jump block1
 


Note: You can re-run with the `WASMTIME_TEST_BLESS=1` environment
variable set to update test expectations.


---- ./tests/disas/pulley-be-inline-copy.wat ----
failed to run tests "./tests/disas/pulley-be-inline-copy.wat"

Caused by:
    Did not get the expected CLIF translation:

--- expected
+++ actual
@@ -1,12 +1,13 @@
 wasm[0]::function[0]:
       push_frame
-      xload64be_o32 x4, x0, 64
-      br_if_xult64_u8 x4, 16, 0x2b    // target = 0x35
-      br_if_xult64_u8 x4, 32, 0x27    // target = 0x38
-  18: xload64be_o32 x6, x0, 56
-      vload128le_o32 v6, x6, 16
-      vstore128le_o32 x6, 0, v6
+      xload64be_o32 x5, x0, 64
+      br_if_xult64_u8 x5, 16, 0x34    // target = 0x3e
+  11: xload64be_o32 x6, x0, 64
+      br_if_xult64_u8 x6, 32, 0x27    // target = 0x41
+  21: xload64be_o32 x7, x0, 56
+      vload128le_o32 v7, x7, 16
+      vstore128le_o32 x7, 0, v7
       pop_frame
       ret
-  35: trap
-  38: trap
\ No newline at end of file
+  3e: trap
+  41: trap
\ No newline at end of file


Note: You can re-run with the `WASMTIME_TEST_BLESS=1` environment
variable set to update test expectations.


---- ./tests/disas/gc/array-copy-with-fuel.wat ----
failed to run tests "./tests/disas/gc/array-copy-with-fuel.wat"

Caused by:
    Did not get the expected CLIF translation:

--- expected
+++ actual
@@ -54,8 +54,9 @@
                                 block5(v139: i64):
                                     v161 = load.i32 notrap aligned region6 v162
 @002b                               trapz v161, user16
+                                    v159 = load.i32 notrap aligned region6 v162
 @002b                               v37 = load.i64 notrap aligned readonly can_move region3 v7+32
-@002b                               v35 = uextend.i64 v161
+@002b                               v35 = uextend.i64 v159
 @002b                               v38 = iadd v37, v35
 @002b                               v39 = iconst.i64 16
 @002b                               v40 = iadd v38, v39  ; v39 = 16
@@ -65,9 +66,11 @@
 @002b                               v42 = uextend.i64 v41
 @002b                               v48 = icmp ugt v47, v42
 @002b                               trapnz v48, user17
+                                    v157 = load.i32 notrap aligned region6 v162
                                     v155 = load.i32 notrap aligned region7 v163
 @002b                               trapz v155, user16
-@002b                               v59 = uextend.i64 v155
+                                    v153 = load.i32 notrap aligned region7 v163
+@002b                               v59 = uextend.i64 v153
 @002b                               v62 = iadd v37, v59
 @002b                               v64 = iadd v62, v39  ; v39 = 16
 @002b                               v65 = load.i32 user2 readonly region5 v64
@@ -76,9 +79,12 @@
 @002b                               v66 = uextend.i64 v65
 @002b                               v72 = icmp ugt v71, v66
 @002b                               trapnz v72, user17
+                                    v151 = load.i32 notrap aligned region7 v163
 @002b                               v91 = load.i64 notrap aligned region4 v7+40
+@002b                               v51 = uextend.i64 v157
+@002b                               v52 = iadd v37, v51
 @002b                               v53 = iconst.i64 20
-@002b                               v54 = iadd v38, v53  ; v53 = 20
+@002b                               v54 = iadd v52, v53  ; v53 = 20
                                     v165 = iconst.i64 2
                                     v166 = ishl v43, v165  ; v165 = 2
 @002b                               v58 = iadd v54, v166
@@ -87,15 +93,23 @@
 @002b                               v92 = iadd v37, v91
 @002b                               v94 = icmp ugt v93, v92
 @002b                               trapnz v94, user2
-@002b                               v78 = iadd v62, v53  ; v53 = 20
+@002b                               v98 = load.i64 notrap aligned region4 v7+40
+@002b                               v75 = uextend.i64 v151
+@002b                               v76 = iadd v37, v75
+@002b                               v78 = iadd v76, v53  ; v53 = 20
                                     v168 = ishl v67, v165  ; v165 = 2
 @002b                               v82 = iadd v78, v168
 @002b                               v100 = uadd_overflow_trap v82, v170, user2
-@002b                               v101 = icmp ugt v100, v92
+@002b                               v99 = iadd v37, v98
+@002b                               v101 = icmp ugt v100, v99
 @002b                               trapnz v101, user2
 @002b                               brif.i32 v6, block6, block9
 
                                 block6:
+                                    v143 = load.i32 notrap aligned region6 v162
+                                    v145 = load.i32 notrap aligned region7 v163
+                                    v147 = load.i32 notrap aligned region6 v162
+                                    v149 = load.i32 notrap aligned region7 v163
 @002b                               v102 = icmp.i64 ult v58, v82
 @002b                               v107 = iadd.i64 v58, v170
 @002b                               v108 = iadd.i64 v82, v170


Note: You can re-run with the `WASMTIME_TEST_BLESS=1` environment
variable set to update test expectations.


---- ./tests/disas/array-copy-inline.wat ----
failed to run tests "./tests/disas/array-copy-inline.wat"

Caused by:
    Did not get the expected CLIF translation:

--- expected
+++ actual
@@ -45,11 +45,13 @@
 @002a                               v64 = iadd v9, v63
 @002a                               v66 = icmp ugt v65, v64
 @002a                               trapnz v66, user2
+@002a                               v70 = load.i64 notrap aligned region3 v8+40
 @002a                               v50 = iadd v34, v25  ; v25 = 20
                                     v88 = ishl v39, v85  ; v85 = 2
 @002a                               v54 = iadd v50, v88
 @002a                               v72 = uadd_overflow_trap v54, v90, user2  ; v90 = 28
-@002a                               v73 = icmp ugt v72, v64
+@002a                               v71 = iadd v9, v70
+@002a                               v73 = icmp ugt v72, v71
 @002a                               trapnz v73, user2
 @002a                               v74 = load.i8x16 notrap aligned little region4 v54
 @002a                               v75 = load.i64 notrap aligned little region4 v54+16


Note: You can re-run with the `WASMTIME_TEST_BLESS=1` environment
variable set to update test expectations.


---- ./tests/disas/memory-copy-epochs.wat ----
failed to run tests "./tests/disas/memory-copy-epochs.wat"

Caused by:
    Did not get the expected CLIF translation:

--- expected
+++ actual
@@ -48,9 +48,10 @@
 @0025                               v27 = iadd v23, v24
 @0025                               v28 = icmp ugt v27, v22
 @0025                               trapnz v28, heap_oob
+@0025                               v34 = load.i64 notrap aligned region6 v0+64
 @0025                               v35 = uextend.i64 v3
 @0025                               v39 = iadd v35, v24
-@0025                               v40 = icmp ugt v39, v22
+@0025                               v40 = icmp ugt v39, v34
 @0025                               trapnz v40, heap_oob
 @0025                               v29 = load.i64 notrap aligned readonly can_move region5 v0+56
 @0025                               v33 = iadd v29, v23


Note: You can re-run with the `WASMTIME_TEST_BLESS=1` environment
variable set to update test expectations.


---- ./tests/disas/dynamic-memory-no-spectre-access-same-index-different-offsets.wat ----
failed to run tests "./tests/disas/dynamic-memory-no-spectre-access-same-index-different-offsets.wat"

Caused by:
    Did not get the expected CLIF translation:

--- expected
+++ actual
@@ -17,15 +17,23 @@
 @0047                               v6 = load.i64 notrap aligned can_move region2 v0+56
 @0047                               v7 = iadd v6, v3
 @0047                               v8 = load.i32 little region4 v7
+@004c                               v10 = load.i64 notrap aligned region3 v0+64
+@004c                               v11 = icmp ugt v3, v10
+@004c                               trapnz v11, heap_oob
+@004c                               v12 = load.i64 notrap aligned can_move region2 v0+56
+@004c                               v13 = iadd v12, v3
 @004c                               v14 = iconst.i64 4
-@004c                               v15 = iadd v7, v14  ; v14 = 4
+@004c                               v15 = iadd v13, v14  ; v14 = 4
 @004c                               v16 = load.i32 little region4 v15
 @0051                               v18 = iconst.i64 0x0010_0003
 @0051                               v19 = uadd_overflow_trap v3, v18, heap_oob  ; v18 = 0x0010_0003
-@0051                               v21 = icmp ugt v19, v4
+@0051                               v20 = load.i64 notrap aligned region3 v0+64
+@0051                               v21 = icmp ugt v19, v20
 @0051                               trapnz v21, heap_oob
+@0051                               v22 = load.i64 notrap aligned can_move region2 v0+56
+@0051                               v23 = iadd v22, v3
 @0051                               v24 = iconst.i64 0x000f_ffff
-@0051                               v25 = iadd v7, v24  ; v24 = 0x000f_ffff
+@0051                               v25 = iadd v23, v24  ; v24 = 0x000f_ffff
 @0051                               v26 = load.i32 little region4 v25
 @0056                               jump block1
 
@@ -52,15 +60,23 @@
 @005d                               v9 = load.i64 notrap aligned can_move region2 v0+56
 @005d                               v10 = iadd v9, v6
 @005d                               store little region4 v3, v10
+@0064                               v12 = load.i64 notrap aligned region3 v0+64
+@0064                               v13 = icmp ugt v6, v12
+@0064                               trapnz v13, heap_oob
+@0064                               v14 = load.i64 notrap aligned can_move region2 v0+56
+@0064                               v15 = iadd v14, v6
 @0064                               v16 = iconst.i64 4
-@0064                               v17 = iadd v10, v16  ; v16 = 4
+@0064                               v17 = iadd v15, v16  ; v16 = 4
 @0064                               store little region4 v4, v17
 @006b                               v19 = iconst.i64 0x0010_0003
 @006b                               v20 = uadd_overflow_trap v6, v19, heap_oob  ; v19 = 0x0010_0003
-@006b                               v22 = icmp ugt v20, v7
+@006b                               v21 = load.i64 notrap aligned region3 v0+64
+@006b                               v22 = icmp ugt v20, v21
 @006b                               trapnz v22, heap_oob
+@006b                               v23 = load.i64 notrap aligned can_move region2 v0+56
+@006b                               v24 = iadd v23, v6
 @006b                               v25 = iconst.i64 0x000f_ffff
-@006b                               v26 = iadd v10, v25  ; v25 = 0x000f_ffff
+@006b                               v26 = iadd v24, v25  ; v25 = 0x000f_ffff
 @006b                               store little region4 v5, v26
 @0070                               jump block1
 


Note: You can re-run with the `WASMTIME_TEST_BLESS=1` environment
variable set to update test expectations.


---- ./tests/disas/duplicate-loads-static-memory.wat ----
failed to run tests "./tests/disas/duplicate-loads-static-memory.wat"

Caused by:
    Did not get the expected CLIF translation:

--- expected
+++ actual
@@ -14,10 +14,11 @@
 @0057                               v3 = uextend.i64 v2
 @0057                               v5 = iadd v4, v3
 @0057                               v6 = load.i32 little region4 v5
+@005c                               v10 = load.i32 little region4 v5
 @005f                               jump block1
 
                                 block1:
-@005f                               return v6, v6
+@005f                               return v6, v10
 }
 
 function u0:1(i64 vmctx, i64, i32) -> i32, i32 tail {
@@ -38,8 +39,9 @@
 @0064                               v6 = iconst.i64 1234
 @0064                               v7 = iadd v5, v6  ; v6 = 1234
 @0064                               v8 = load.i32 little region4 v7
+@006a                               v14 = load.i32 little region4 v7
 @006e                               jump block1
 
                                 block1:
-@006e                               return v8, v8
+@006e                               return v8, v14
 }
\ No newline at end of file


Note: You can re-run with the `WASMTIME_TEST_BLESS=1` environment
variable set to update test expectations.


---- ./tests/disas/memory-copy-inline.wat ----
failed to run tests "./tests/disas/memory-copy-inline.wat"

Caused by:
    Did not get the expected CLIF translation:

--- expected
+++ actual
@@ -16,9 +16,10 @@
 @0024                               v10 = iadd v6, v31  ; v31 = 16
 @0024                               v11 = icmp ugt v10, v5
 @0024                               trapnz v11, heap_oob
+@0024                               v17 = load.i64 notrap aligned region3 v0+64
 @0024                               v18 = uextend.i64 v3
 @0024                               v22 = iadd v18, v31  ; v31 = 16
-@0024                               v23 = icmp ugt v22, v5
+@0024                               v23 = icmp ugt v22, v17
 @0024                               trapnz v23, heap_oob
 @0024                               v12 = load.i64 notrap aligned readonly can_move region2 v0+56
 @0024                               v28 = iadd v12, v18


Note: You can re-run with the `WASMTIME_TEST_BLESS=1` environment
variable set to update test expectations.


---- ./tests/disas/memory_copy_host32.wat ----
failed to run tests "./tests/disas/memory_copy_host32.wat"

Caused by:
    Did not get the expected CLIF translation:

--- expected
+++ actual
@@ -13,12 +13,15 @@
 @0042                               v12 = icmp ugt v10, v11
 @0042                               trapnz v12, heap_oob
 @0042                               v13 = load.i32 notrap aligned can_move region0 v0+40
+@0042                               v17 = load.i32 notrap aligned region1 v0+44
 @0042                               v18 = uextend.i64 v3
 @0042                               v22 = iadd v18, v7
-@0042                               v24 = icmp ugt v22, v11
+@0042                               v23 = uextend.i64 v17
+@0042                               v24 = icmp ugt v22, v23
 @0042                               trapnz v24, heap_oob
+@0042                               v25 = load.i32 notrap aligned can_move region0 v0+40
 @0042                               v16 = iadd v13, v2
-@0042                               v28 = iadd v13, v3
+@0042                               v28 = iadd v25, v3
 @0042                               call fn0(v0, v16, v28, v4)
 @0046                               jump block1
 
@@ -101,13 +104,16 @@
 @0069                               v8 = icmp ugt v6, v7
 @0069                               trapnz v8, heap_oob
 @0069                               v9 = load.i32 notrap aligned can_move region0 v0+56
+@0069                               v14 = load.i32 notrap aligned region1 v0+60
 @0069                               v15 = uadd_overflow_trap v3, v4, heap_oob
-@0069                               v17 = icmp ugt v15, v7
+@0069                               v16 = uextend.i64 v14
+@0069                               v17 = icmp ugt v15, v16
 @0069                               trapnz v17, heap_oob
+@0069                               v18 = load.i32 notrap aligned can_move region0 v0+56
 @0069                               v10 = ireduce.i32 v2
 @0069                               v13 = iadd v9, v10
 @0069                               v19 = ireduce.i32 v3
-@0069                               v22 = iadd v9, v19
+@0069                               v22 = iadd v18, v19
 @0069                               v23 = ireduce.i32 v4
 @0069                               call fn0(v0, v13, v22, v23)
 @006d                               jump block1


Note: You can re-run with the `WASMTIME_TEST_BLESS=1` environment
variable set to update test expectations.



failures:
    ./tests/disas/dynamic-memory-yes-spectre-access-same-index-different-offsets.wat
    ./tests/disas/alias-region-tables.wat
    ./tests/disas/array-copy-i64.wat
    ./tests/disas/pulley/coremark-1.wat
    ./tests/disas/pulley/pulley64_memory32.wat
    ./tests/disas/component-model/sync-adapter-calls-x64.wat
    ./tests/disas/component-model/direct-adapter-calls.wat
    ./tests/disas/component-model/direct-adapter-calls-inlining.wat
    ./tests/disas/component-model/known-imported-adapter-memory.wat
    ./tests/disas/component-model/direct-adapter-calls-x64.wat
    ./tests/disas/component-model/sync-adapter-calls.wat
    ./tests/disas/startup-data-active.wat
    ./tests/disas/memory-copy-fuel-const-len.wat
    ./tests/disas/memory-copy-fuel.wat
    ./tests/disas/memory_copy_host64.wat
    ./tests/disas/startup-elem-active.wat
    ./tests/disas/array-copy-i8.wat
    ./tests/disas/array-copy-anyref.wat
    ./tests/disas/duplicate-loads-dynamic-memory.wat
    ./tests/disas/array-fill-funcref.wat
    ./tests/disas/gc/drc/struct-new.wat
    ./tests/disas/gc/drc/multiple-array-get.wat
    ./tests/disas/gc/issue-11753.wat
    ./tests/disas/gc/drc/array-new-fixed-of-gc-refs.wat
    ./tests/disas/gc/copying/v128-fields.wat
    ./tests/disas/gc/copying/multiple-array-get.wat
    ./tests/disas/gc/null/v128-fields.wat
    ./tests/disas/gc/null/multiple-array-get.wat
    ./tests/disas/pulley-be-inline-copy.wat
    ./tests/disas/gc/array-copy-with-fuel.wat
    ./tests/disas/array-copy-inline.wat
    ./tests/disas/memory-copy-epochs.wat
    ./tests/disas/dynamic-memory-no-spectre-access-same-index-different-offsets.wat
    ./tests/disas/duplicate-loads-static-memory.wat
    ./tests/disas/memory-copy-inline.wat
    ./tests/disas/memory_copy_host32.wat

test result: FAILED. 2541 passed; 36 failed; 0 ignored; 0 measured; 0 filtered out; finished in 18.33s

So it looks like we are missing optimizations (mostly for GC- and component model adapter-related stuff) in practice, not just in theory for our filetests that attempt to enumerate all the cases.

@fitzgen

fitzgen commented Sep 2, 2026

Copy link
Copy Markdown
Member Author

The more I think about it, the more the scoped hash map I mentioned above becomes more appealing, since "scope" and where it is valid to reuse a known memory value is really what we are trying to capture here...

There were two ways in which alias analysis's `LastStores` state was not a
proper lattice, which made the order we processed the worklist and called
`LastStores::meet` observable:

1. We didn't have a single, canonical bottom value for the last store to a
region. We were taking the first instruction in a block as an identifier for
control-flow join points so that we would get different `MemoryLoc`s for
different control-flow joins, which is necessary to avoid illegally forwarding a
value loaded inside one control-flow join to a load in another, different
control-flow join. However, this meant that we effectively had multiple bottom
elements, which made the path we descended through the "lattice" observable. The
solution here is to make `LastStore::Unknown` a proper bottom for the lattice
and then add an "extent token" to `MemoryLoc`. The extent is computed
incrementally as we push and pop blocks from a pre-order traversal of the
dominator tree (which the egraphs pass that drives alias analysis already
performs).

2. We computed the observed-stores set while we computed the fixpoint of the
initial `LastStores` inputs to each block. This was incorrect, however, because
a `LastStores` could transiently contain a `LastStore::Inst` that disappears in
later iterations of the fixpoint, and which instructions do or don't transiently
appear in `LastStores` in that way depends on the order in which we call
`LastStores::meet`. Therefore, observing stores while computing the fixpoint
might or might not observe an instruction depending on the worklist processing
order. The solution in this case is to only compute the observed-stores set
after we've computed the `LastStores` fixpoint, at which point there are no
transient `LastStore::Inst`s anymore.
@fitzgen
fitzgen force-pushed the alias-analysis-lattice branch from 6e847e9 to 610904d Compare September 3, 2026 21:14
@fitzgen

fitzgen commented Sep 3, 2026

Copy link
Copy Markdown
Member Author

Just pushed a commit with the scope API version of the fix discussed above. I like this much better: we can incrementally compute extents (merge tokens) in a very simple, straightforward way and we can get rid of the post-pass to compute each block's extent and we can also get rid of the LastStore/MemoryVersion split.

@cfallin cfallin left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good to me -- thanks for the patience and rethinking here; I like where we ended up as well!

@cfallin
cfallin added this pull request to the merge queue Sep 3, 2026
Merged via the queue into bytecodealliance:main with commit b5b8f49 Sep 4, 2026
54 checks passed
@fitzgen
fitzgen deleted the alias-analysis-lattice branch September 4, 2026 15:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cranelift Issues related to the Cranelift code generator

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants