diff options
author | Thomas Lively <7121787+tlively@users.noreply.github.com> | 2021-10-14 14:11:59 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-10-14 21:11:59 +0000 |
commit | bf665976b1526ca7cf11bacf5745563dfe193206 (patch) | |
tree | a6bb2cf0fa5d1972fe55f872418665778e00dde5 /test/lit/passes | |
parent | d592bad2b8fa777dab9682d2d2e47f9957c8051d (diff) | |
download | binaryen-bf665976b1526ca7cf11bacf5745563dfe193206.tar.gz binaryen-bf665976b1526ca7cf11bacf5745563dfe193206.tar.bz2 binaryen-bf665976b1526ca7cf11bacf5745563dfe193206.zip |
Switch from "extends" to M4 nominal syntax (#4248)
Switch from "extends" to M4 nominal syntax
Change all test inputs from using the old (extends $super) syntax to using the
new *_subtype syntax for their inputs and also update the printer to emit the
new syntax. Add a new test explicitly testing the old notation to make sure it
keeps working until we remove support for it.
Diffstat (limited to 'test/lit/passes')
-rw-r--r-- | test/lit/passes/cfp.wast | 188 | ||||
-rw-r--r-- | test/lit/passes/dae-gc-refine-params.wast | 18 | ||||
-rw-r--r-- | test/lit/passes/dae-gc-refine-return.wast | 16 | ||||
-rw-r--r-- | test/lit/passes/dae-gc.wast | 29 | ||||
-rw-r--r-- | test/lit/passes/gto-mutability.wast | 52 | ||||
-rw-r--r-- | test/lit/passes/heap2local.wast | 1142 | ||||
-rw-r--r-- | test/lit/passes/inlining_all-features.wast | 83 | ||||
-rw-r--r-- | test/lit/passes/instrument-memory-gc.wast | 132 | ||||
-rw-r--r-- | test/lit/passes/local-subtyping-nn.wast | 33 | ||||
-rw-r--r-- | test/lit/passes/name-types.wast | 10 | ||||
-rw-r--r-- | test/lit/passes/optimize-instructions-call_ref-roundtrip.wast | 8 | ||||
-rw-r--r-- | test/lit/passes/optimize-instructions-gc-iit.wast | 14 | ||||
-rw-r--r-- | test/lit/passes/optimize-instructions-gc.wast | 20 | ||||
-rw-r--r-- | test/lit/passes/precompute-gc.wast | 457 | ||||
-rw-r--r-- | test/lit/passes/roundtrip-gc-types.wast | 10 | ||||
-rw-r--r-- | test/lit/passes/simplify-locals-gc.wast | 65 |
16 files changed, 2105 insertions, 172 deletions
diff --git a/test/lit/passes/cfp.wast b/test/lit/passes/cfp.wast index db6e108bf..99fd9d209 100644 --- a/test/lit/passes/cfp.wast +++ b/test/lit/passes/cfp.wast @@ -4,9 +4,9 @@ ;; name getting in the way) (module - ;; CHECK: (type $none_=>_none (func)) + ;; CHECK: (type $none_=>_none (func_subtype func)) - ;; CHECK: (type $struct (struct (field i32))) + ;; CHECK: (type $struct (struct_subtype (field i32) data)) (type $struct (struct i32)) ;; CHECK: (func $impossible-get ;; CHECK-NEXT: (drop @@ -31,9 +31,9 @@ ) (module - ;; CHECK: (type $struct (struct (field i64))) + ;; CHECK: (type $struct (struct_subtype (field i64) data)) (type $struct (struct i64)) - ;; CHECK: (type $none_=>_none (func)) + ;; CHECK: (type $none_=>_none (func_subtype func)) ;; CHECK: (func $test ;; CHECK-NEXT: (drop @@ -74,9 +74,9 @@ ) (module - ;; CHECK: (type $struct (struct (field f32))) + ;; CHECK: (type $struct (struct_subtype (field f32) data)) (type $struct (struct f32)) - ;; CHECK: (type $none_=>_none (func)) + ;; CHECK: (type $none_=>_none (func_subtype func)) ;; CHECK: (func $test ;; CHECK-NEXT: (drop @@ -114,9 +114,9 @@ ) (module - ;; CHECK: (type $struct (struct (field f32))) + ;; CHECK: (type $struct (struct_subtype (field f32) data)) (type $struct (struct f32)) - ;; CHECK: (type $f32_=>_none (func (param f32))) + ;; CHECK: (type $f32_=>_none (func_subtype (param f32) func)) ;; CHECK: (func $test (param $f f32) ;; CHECK-NEXT: (drop @@ -150,9 +150,9 @@ ;; Create in one function, get in another. The 10 should be forwarded to the ;; get. (module - ;; CHECK: (type $none_=>_none (func)) + ;; CHECK: (type $none_=>_none (func_subtype func)) - ;; CHECK: (type $struct (struct (field i32))) + ;; CHECK: (type $struct (struct_subtype (field i32) data)) (type $struct (struct i32)) ;; CHECK: (func $create ;; CHECK-NEXT: (drop @@ -194,9 +194,9 @@ ;; As before, but with the order of functions reversed to check for any ordering ;; issues. (module - ;; CHECK: (type $none_=>_none (func)) + ;; CHECK: (type $none_=>_none (func_subtype func)) - ;; CHECK: (type $struct (struct (field i32))) + ;; CHECK: (type $struct (struct_subtype (field i32) data)) (type $struct (struct i32)) ;; CHECK: (func $get @@ -240,9 +240,9 @@ ;; Different values assigned in the same function, in different struct.news, ;; so we cannot optimize the struct.get away. (module - ;; CHECK: (type $struct (struct (field f32))) + ;; CHECK: (type $struct (struct_subtype (field f32) data)) (type $struct (struct f32)) - ;; CHECK: (type $none_=>_none (func)) + ;; CHECK: (type $none_=>_none (func_subtype func)) ;; CHECK: (func $test ;; CHECK-NEXT: (drop @@ -286,9 +286,9 @@ ;; Different values assigned in different functions, and one is a struct.set. (module - ;; CHECK: (type $struct (struct (field (mut f32)))) + ;; CHECK: (type $struct (struct_subtype (field (mut f32)) data)) (type $struct (struct (mut f32))) - ;; CHECK: (type $none_=>_none (func)) + ;; CHECK: (type $none_=>_none (func_subtype func)) ;; CHECK: (func $create ;; CHECK-NEXT: (drop @@ -337,9 +337,9 @@ ;; As the last testcase, but the values happen to coincide, so we can optimize ;; the get into a constant. (module - ;; CHECK: (type $struct (struct (field (mut f32)))) + ;; CHECK: (type $struct (struct_subtype (field (mut f32)) data)) (type $struct (struct (mut f32))) - ;; CHECK: (type $none_=>_none (func)) + ;; CHECK: (type $none_=>_none (func_subtype func)) ;; CHECK: (func $create ;; CHECK-NEXT: (drop @@ -392,11 +392,11 @@ ;; Check that we look into the fallthrough value that is assigned. (module - ;; CHECK: (type $struct (struct (field (mut f32)))) + ;; CHECK: (type $struct (struct_subtype (field (mut f32)) data)) (type $struct (struct (mut f32))) - ;; CHECK: (type $none_=>_none (func)) + ;; CHECK: (type $none_=>_none (func_subtype func)) - ;; CHECK: (type $i32_=>_none (func (param i32))) + ;; CHECK: (type $i32_=>_none (func_subtype (param i32) func)) ;; CHECK: (func $create ;; CHECK-NEXT: (drop @@ -465,9 +465,9 @@ ;; Test a function reference instead of a number. (module - ;; CHECK: (type $none_=>_none (func)) + ;; CHECK: (type $none_=>_none (func_subtype func)) - ;; CHECK: (type $struct (struct (field funcref))) + ;; CHECK: (type $struct (struct_subtype (field funcref) data)) (type $struct (struct funcref)) ;; CHECK: (elem declare func $test) @@ -507,7 +507,7 @@ ;; Test for unreachable creations, sets, and gets. (module (type $struct (struct (mut i32))) - ;; CHECK: (type $none_=>_none (func)) + ;; CHECK: (type $none_=>_none (func_subtype func)) ;; CHECK: (func $test ;; CHECK-NEXT: (drop @@ -555,12 +555,12 @@ ;; subtype, the get must trap anyhow (the reference it receives can ;; only be null in this closed world). (module - ;; CHECK: (type $none_=>_none (func)) + ;; CHECK: (type $none_=>_none (func_subtype func)) - ;; CHECK: (type $struct (struct (field i32))) + ;; CHECK: (type $struct (struct_subtype (field i32) data)) (type $struct (struct i32)) - ;; CHECK: (type $substruct (struct (field i32)) (extends $struct)) - (type $substruct (struct i32) (extends $struct)) + ;; CHECK: (type $substruct (struct_subtype (field i32) $struct)) + (type $substruct (struct_subtype i32 $struct)) ;; CHECK: (func $create ;; CHECK-NEXT: (drop @@ -602,12 +602,12 @@ ;; will optimize the result to the only possible value. (In practice, though, ;; it will trap anyhow.) (module - ;; CHECK: (type $struct (struct (field (mut i32)))) + ;; CHECK: (type $struct (struct_subtype (field (mut i32)) data)) (type $struct (struct (mut i32))) - ;; CHECK: (type $none_=>_none (func)) + ;; CHECK: (type $none_=>_none (func_subtype func)) - ;; CHECK: (type $substruct (struct (field (mut i32))) (extends $struct)) - (type $substruct (struct (mut i32)) (extends $struct)) + ;; CHECK: (type $substruct (struct_subtype (field (mut i32)) $struct)) + (type $substruct (struct_subtype (mut i32) $struct)) ;; CHECK: (func $create ;; CHECK-NEXT: (drop @@ -658,12 +658,12 @@ ;; reference to the subtype (we never create a supertype) and so we ;; can optimize. (module - ;; CHECK: (type $none_=>_none (func)) + ;; CHECK: (type $none_=>_none (func_subtype func)) - ;; CHECK: (type $substruct (struct (field i32) (field f64)) (extends $struct)) - (type $substruct (struct i32 f64) (extends $struct)) + ;; CHECK: (type $substruct (struct_subtype (field i32) (field f64) $struct)) + (type $substruct (struct_subtype i32 f64 $struct)) - ;; CHECK: (type $struct (struct (field i32))) + ;; CHECK: (type $struct (struct_subtype (field i32) data)) (type $struct (struct i32)) ;; CHECK: (func $create @@ -708,12 +708,12 @@ ;; Subtyping: Create both a subtype and a supertype, with identical constants ;; for the shared field, and get the supertype. (module - ;; CHECK: (type $none_=>_none (func)) + ;; CHECK: (type $none_=>_none (func_subtype func)) - ;; CHECK: (type $struct (struct (field i32))) + ;; CHECK: (type $struct (struct_subtype (field i32) data)) (type $struct (struct i32)) - ;; CHECK: (type $substruct (struct (field i32) (field f64)) (extends $struct)) - (type $substruct (struct i32 f64) (extends $struct)) + ;; CHECK: (type $substruct (struct_subtype (field i32) (field f64) $struct)) + (type $substruct (struct_subtype i32 f64 $struct)) ;; CHECK: (func $create ;; CHECK-NEXT: (drop @@ -770,12 +770,12 @@ ;; for the shared field, preventing optimization, as a get of the ;; supertype may receive an instance of the subtype. (module - ;; CHECK: (type $struct (struct (field i32))) + ;; CHECK: (type $struct (struct_subtype (field i32) data)) (type $struct (struct i32)) - ;; CHECK: (type $none_=>_none (func)) + ;; CHECK: (type $none_=>_none (func_subtype func)) - ;; CHECK: (type $substruct (struct (field i32) (field f64)) (extends $struct)) - (type $substruct (struct i32 f64) (extends $struct)) + ;; CHECK: (type $substruct (struct_subtype (field i32) (field f64) $struct)) + (type $substruct (struct_subtype i32 f64 $struct)) ;; CHECK: (func $create ;; CHECK-NEXT: (drop @@ -828,12 +828,12 @@ ;; shared between the types, but we only create the substruct with ;; one value, so we can optimize. (module - ;; CHECK: (type $none_=>_none (func)) + ;; CHECK: (type $none_=>_none (func_subtype func)) - ;; CHECK: (type $substruct (struct (field i32) (field f64)) (extends $struct)) - (type $substruct (struct i32 f64) (extends $struct)) + ;; CHECK: (type $substruct (struct_subtype (field i32) (field f64) $struct)) + (type $substruct (struct_subtype i32 f64 $struct)) - ;; CHECK: (type $struct (struct (field i32))) + ;; CHECK: (type $struct (struct_subtype (field i32) data)) (type $struct (struct i32)) ;; CHECK: (func $create @@ -889,13 +889,13 @@ ;; As above, but add a set of $struct. The set prevents the optimization. (module - ;; CHECK: (type $struct (struct (field (mut i32)))) + ;; CHECK: (type $struct (struct_subtype (field (mut i32)) data)) (type $struct (struct (mut i32))) - ;; CHECK: (type $substruct (struct (field (mut i32)) (field f64)) (extends $struct)) - (type $substruct (struct (mut i32) f64) (extends $struct)) + ;; CHECK: (type $substruct (struct_subtype (field (mut i32)) (field f64) $struct)) + (type $substruct (struct_subtype (mut i32) f64 $struct)) - ;; CHECK: (type $none_=>_none (func)) + ;; CHECK: (type $none_=>_none (func_subtype func)) ;; CHECK: (func $create ;; CHECK-NEXT: (drop @@ -954,15 +954,15 @@ ;; Multi-level subtyping, check that we propagate not just to the immediate ;; supertype but all the way as needed. (module - ;; CHECK: (type $struct3 (struct (field i32) (field f64) (field anyref)) (extends $struct2)) - (type $struct3 (struct i32 f64 anyref) (extends $struct2)) + ;; CHECK: (type $struct3 (struct_subtype (field i32) (field f64) (field anyref) $struct2)) + (type $struct3 (struct_subtype i32 f64 anyref $struct2)) - ;; CHECK: (type $none_=>_none (func)) + ;; CHECK: (type $none_=>_none (func_subtype func)) - ;; CHECK: (type $struct2 (struct (field i32) (field f64)) (extends $struct1)) - (type $struct2 (struct i32 f64) (extends $struct1)) + ;; CHECK: (type $struct2 (struct_subtype (field i32) (field f64) $struct1)) + (type $struct2 (struct_subtype i32 f64 $struct1)) - ;; CHECK: (type $struct1 (struct (field i32))) + ;; CHECK: (type $struct1 (struct_subtype (field i32) data)) (type $struct1 (struct i32)) ;; CHECK: (func $create @@ -1089,18 +1089,18 @@ ;; different values in the sub-most type. Create the top and bottom types, but ;; not the middle one. (module - ;; CHECK: (type $struct3 (struct (field i32) (field i32) (field f64) (field f64) (field anyref) (field anyref)) (extends $struct2)) - (type $struct3 (struct i32 i32 f64 f64 anyref anyref) (extends $struct2)) + ;; CHECK: (type $struct3 (struct_subtype (field i32) (field i32) (field f64) (field f64) (field anyref) (field anyref) $struct2)) + (type $struct3 (struct_subtype i32 i32 f64 f64 anyref anyref $struct2)) - ;; CHECK: (type $struct1 (struct (field i32) (field i32))) + ;; CHECK: (type $struct1 (struct_subtype (field i32) (field i32) data)) (type $struct1 (struct i32 i32)) - ;; CHECK: (type $struct2 (struct (field i32) (field i32) (field f64) (field f64)) (extends $struct1)) - (type $struct2 (struct i32 i32 f64 f64) (extends $struct1)) + ;; CHECK: (type $struct2 (struct_subtype (field i32) (field i32) (field f64) (field f64) $struct1)) + (type $struct2 (struct_subtype i32 i32 f64 f64 $struct1)) - ;; CHECK: (type $anyref_=>_none (func (param anyref))) + ;; CHECK: (type $anyref_=>_none (func_subtype (param anyref) func)) - ;; CHECK: (type $none_=>_none (func)) + ;; CHECK: (type $none_=>_none (func_subtype func)) ;; CHECK: (func $create (param $any anyref) ;; CHECK-NEXT: (drop @@ -1323,14 +1323,14 @@ ;; Multi-level subtyping with a different value in the middle of the chain. We ;; can only optimize $struct3. (module - ;; CHECK: (type $struct1 (struct (field (mut i32)))) + ;; CHECK: (type $struct1 (struct_subtype (field (mut i32)) data)) (type $struct1 (struct (mut i32))) - ;; CHECK: (type $struct2 (struct (field (mut i32)) (field f64)) (extends $struct1)) - (type $struct2 (struct (mut i32) f64) (extends $struct1)) - ;; CHECK: (type $none_=>_none (func)) + ;; CHECK: (type $struct2 (struct_subtype (field (mut i32)) (field f64) $struct1)) + (type $struct2 (struct_subtype (mut i32) f64 $struct1)) + ;; CHECK: (type $none_=>_none (func_subtype func)) - ;; CHECK: (type $struct3 (struct (field (mut i32)) (field f64) (field anyref)) (extends $struct2)) - (type $struct3 (struct (mut i32) f64 anyref) (extends $struct2)) + ;; CHECK: (type $struct3 (struct_subtype (field (mut i32)) (field f64) (field anyref) $struct2)) + (type $struct3 (struct_subtype (mut i32) f64 anyref $struct2)) ;; CHECK: (func $create ;; CHECK-NEXT: (drop @@ -1423,16 +1423,16 @@ ;; As above, but add not just a new of the middle class with a different value ;; but also a set. That prevents all optimizations. (module - ;; CHECK: (type $struct2 (struct (field (mut i32)) (field f64)) (extends $struct1)) - (type $struct2 (struct (mut i32) f64) (extends $struct1)) + ;; CHECK: (type $struct2 (struct_subtype (field (mut i32)) (field f64) $struct1)) + (type $struct2 (struct_subtype (mut i32) f64 $struct1)) - ;; CHECK: (type $struct1 (struct (field (mut i32)))) + ;; CHECK: (type $struct1 (struct_subtype (field (mut i32)) data)) (type $struct1 (struct (mut i32))) - ;; CHECK: (type $struct3 (struct (field (mut i32)) (field f64) (field anyref)) (extends $struct2)) - (type $struct3 (struct (mut i32) f64 anyref) (extends $struct2)) + ;; CHECK: (type $struct3 (struct_subtype (field (mut i32)) (field f64) (field anyref) $struct2)) + (type $struct3 (struct_subtype (mut i32) f64 anyref $struct2)) - ;; CHECK: (type $none_=>_none (func)) + ;; CHECK: (type $none_=>_none (func_subtype func)) ;; CHECK: (func $create ;; CHECK-NEXT: (drop @@ -1529,10 +1529,10 @@ ;; Test for a struct with multiple fields, some of which are constant and hence ;; optimizable, and some not. Also test that some have the same type. (module - ;; CHECK: (type $struct (struct (field i32) (field f64) (field i32) (field f64) (field i32))) + ;; CHECK: (type $struct (struct_subtype (field i32) (field f64) (field i32) (field f64) (field i32) data)) (type $struct (struct i32 f64 i32 f64 i32)) - ;; CHECK: (type $none_=>_none (func)) + ;; CHECK: (type $none_=>_none (func_subtype func)) ;; CHECK: (func $create ;; CHECK-NEXT: (drop @@ -1653,20 +1653,20 @@ ;; sets, and the final subtype C has a create and a get. The set to A should ;; apply to it, preventing optimization. (module - ;; CHECK: (type $C (struct (field (mut i32))) (extends $B)) - (type $C (struct (mut i32)) (extends $B)) + ;; CHECK: (type $C (struct_subtype (field (mut i32)) $B)) + (type $C (struct_subtype (mut i32) $B)) - ;; CHECK: (type $A (struct (field (mut i32)))) + ;; CHECK: (type $A (struct_subtype (field (mut i32)) data)) (type $A (struct (mut i32))) - ;; CHECK: (type $none_=>_none (func)) + ;; CHECK: (type $none_=>_none (func_subtype func)) - ;; CHECK: (type $ref|$A|_=>_none (func (param (ref $A)))) + ;; CHECK: (type $ref|$A|_=>_none (func_subtype (param (ref $A)) func)) - ;; CHECK: (type $ref|$C|_=>_none (func (param (ref $C)))) + ;; CHECK: (type $ref|$C|_=>_none (func_subtype (param (ref $C)) func)) - ;; CHECK: (type $B (struct (field (mut i32))) (extends $A)) - (type $B (struct (mut i32)) (extends $A)) + ;; CHECK: (type $B (struct_subtype (field (mut i32)) $A)) + (type $B (struct_subtype (mut i32) $A)) ;; CHECK: (func $create ;; CHECK-NEXT: (drop @@ -1715,10 +1715,10 @@ ;; Copies of a field to itself can be ignored. As a result, we can optimize both ;; of the gets here. (module - ;; CHECK: (type $struct (struct (field (mut i32)))) + ;; CHECK: (type $struct (struct_subtype (field (mut i32)) data)) (type $struct (struct (mut i32))) - ;; CHECK: (type $none_=>_none (func)) + ;; CHECK: (type $none_=>_none (func_subtype func)) ;; CHECK: (func $test ;; CHECK-NEXT: (drop @@ -1773,11 +1773,11 @@ ;; Test of a near-copy, of a similar looking field (same index, and same field ;; type) but in a different struct. (module - ;; CHECK: (type $struct (struct (field (mut f32)) (field (mut i32)))) + ;; CHECK: (type $struct (struct_subtype (field (mut f32)) (field (mut i32)) data)) (type $struct (struct (mut f32) (mut i32))) - ;; CHECK: (type $none_=>_none (func)) + ;; CHECK: (type $none_=>_none (func_subtype func)) - ;; CHECK: (type $other (struct (field (mut f64)) (field (mut i32)))) + ;; CHECK: (type $other (struct_subtype (field (mut f64)) (field (mut i32)) data)) (type $other (struct (mut f64) (mut i32))) ;; CHECK: (func $test @@ -1824,10 +1824,10 @@ ;; Test of a near-copy, of a different index. (module - ;; CHECK: (type $struct (struct (field (mut i32)) (field (mut i32)))) + ;; CHECK: (type $struct (struct_subtype (field (mut i32)) (field (mut i32)) data)) (type $struct (struct (mut i32) (mut i32))) - ;; CHECK: (type $none_=>_none (func)) + ;; CHECK: (type $none_=>_none (func_subtype func)) ;; CHECK: (func $test ;; CHECK-NEXT: (drop diff --git a/test/lit/passes/dae-gc-refine-params.wast b/test/lit/passes/dae-gc-refine-params.wast index f4d4ab056..7c986bd4e 100644 --- a/test/lit/passes/dae-gc-refine-params.wast +++ b/test/lit/passes/dae-gc-refine-params.wast @@ -4,24 +4,24 @@ (module ;; CHECK: (type ${i32} (struct (field i32))) - ;; NOMNL: (type ${i32} (struct (field i32)) (extends ${})) - (type ${i32} (struct (field i32)) (extends ${})) + ;; NOMNL: (type ${i32} (struct_subtype (field i32) ${})) + (type ${i32} (struct_subtype (field i32) ${})) ;; CHECK: (type ${} (struct )) - ;; NOMNL: (type ${} (struct )) + ;; NOMNL: (type ${} (struct_subtype data)) (type ${} (struct)) ;; CHECK: (type ${i32_i64} (struct (field i32) (field i64))) - ;; NOMNL: (type ${i32_i64} (struct (field i32) (field i64)) (extends ${i32})) - (type ${i32_i64} (struct (field i32) (field i64)) (extends ${i32})) + ;; NOMNL: (type ${i32_i64} (struct_subtype (field i32) (field i64) ${i32})) + (type ${i32_i64} (struct_subtype (field i32) (field i64) ${i32})) ;; CHECK: (type ${f64} (struct (field f64))) - ;; NOMNL: (type ${f64} (struct (field f64)) (extends ${})) - (type ${f64} (struct (field f64)) (extends ${})) + ;; NOMNL: (type ${f64} (struct_subtype (field f64) ${})) + (type ${f64} (struct_subtype (field f64) ${})) ;; CHECK: (type ${i32_f32} (struct (field i32) (field f32))) - ;; NOMNL: (type ${i32_f32} (struct (field i32) (field f32)) (extends ${i32})) - (type ${i32_f32} (struct (field i32) (field f32)) (extends ${i32})) + ;; NOMNL: (type ${i32_f32} (struct_subtype (field i32) (field f32) ${i32})) + (type ${i32_f32} (struct_subtype (field i32) (field f32) ${i32})) ;; CHECK: (func $call-various-params-no ;; CHECK-NEXT: (call $various-params-no diff --git a/test/lit/passes/dae-gc-refine-return.wast b/test/lit/passes/dae-gc-refine-return.wast index 73f1d040f..60b340cdc 100644 --- a/test/lit/passes/dae-gc-refine-return.wast +++ b/test/lit/passes/dae-gc-refine-return.wast @@ -4,23 +4,23 @@ (module ;; CHECK: (type $return_{} (func (result (ref ${})))) - ;; NOMNL: (type $return_{} (func (result (ref ${})))) + ;; NOMNL: (type $return_{} (func_subtype (result (ref ${})) func)) (type $return_{} (func (result (ref ${})))) ;; CHECK: (type ${i32_f32} (struct (field i32) (field f32))) - ;; NOMNL: (type ${i32_f32} (struct (field i32) (field f32)) (extends ${i32})) - (type ${i32_f32} (struct (field i32) (field f32)) (extends ${i32})) + ;; NOMNL: (type ${i32_f32} (struct_subtype (field i32) (field f32) ${i32})) + (type ${i32_f32} (struct_subtype (field i32) (field f32) ${i32})) ;; CHECK: (type ${i32_i64} (struct (field i32) (field i64))) - ;; NOMNL: (type ${i32_i64} (struct (field i32) (field i64)) (extends ${i32})) - (type ${i32_i64} (struct (field i32) (field i64)) (extends ${i32})) + ;; NOMNL: (type ${i32_i64} (struct_subtype (field i32) (field i64) ${i32})) + (type ${i32_i64} (struct_subtype (field i32) (field i64) ${i32})) ;; CHECK: (type ${i32} (struct (field i32))) - ;; NOMNL: (type ${i32} (struct (field i32)) (extends ${})) - (type ${i32} (struct (field i32)) (extends ${})) + ;; NOMNL: (type ${i32} (struct_subtype (field i32) ${})) + (type ${i32} (struct_subtype (field i32) ${})) ;; CHECK: (type ${} (struct )) - ;; NOMNL: (type ${} (struct )) + ;; NOMNL: (type ${} (struct_subtype data)) (type ${} (struct)) (table 1 1 funcref) diff --git a/test/lit/passes/dae-gc.wast b/test/lit/passes/dae-gc.wast index 899087e7f..3cc1c8653 100644 --- a/test/lit/passes/dae-gc.wast +++ b/test/lit/passes/dae-gc.wast @@ -1,14 +1,18 @@ ;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. ;; RUN: wasm-opt %s -all --dae -S -o - | filecheck %s -;; RUN: wasm-opt %s -all --dae --nominal -S -o - | filecheck %s +;; RUN: wasm-opt %s -all --dae --nominal -S -o - | filecheck %s --check-prefix=NOMNL (module ;; CHECK: (type ${} (struct )) + ;; NOMNL: (type ${} (struct_subtype data)) (type ${} (struct)) ;; CHECK: (func $foo ;; CHECK-NEXT: (call $bar) ;; CHECK-NEXT: ) + ;; NOMNL: (func $foo + ;; NOMNL-NEXT: (call $bar) + ;; NOMNL-NEXT: ) (func $foo (call $bar (i31.new @@ -31,6 +35,21 @@ ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; NOMNL: (func $bar + ;; NOMNL-NEXT: (local $0 (ref null i31)) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (ref.as_non_null + ;; NOMNL-NEXT: (local.tee $0 + ;; NOMNL-NEXT: (i31.new + ;; NOMNL-NEXT: (i32.const 2) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.tee $0 + ;; NOMNL-NEXT: (unreachable) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) (func $bar (param $0 i31ref) (drop ;; after the parameter is removed, we create a nullable local to replace it, @@ -55,6 +74,9 @@ ;; CHECK: (func $get-rtt (param $0 (rtt ${})) ;; CHECK-NEXT: (nop) ;; CHECK-NEXT: ) + ;; NOMNL: (func $get-rtt (param $0 (rtt ${})) + ;; NOMNL-NEXT: (nop) + ;; NOMNL-NEXT: ) (func $get-rtt (param $0 (rtt ${})) (nop) ) @@ -63,6 +85,11 @@ ;; CHECK-NEXT: (rtt.canon ${}) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; NOMNL: (func $send-rtt + ;; NOMNL-NEXT: (call $get-rtt + ;; NOMNL-NEXT: (rtt.canon ${}) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) (func $send-rtt (call $get-rtt (rtt.canon ${}) diff --git a/test/lit/passes/gto-mutability.wast b/test/lit/passes/gto-mutability.wast index 83b9f4bf5..8610e0760 100644 --- a/test/lit/passes/gto-mutability.wast +++ b/test/lit/passes/gto-mutability.wast @@ -7,13 +7,13 @@ ;; The struct here has three fields, and the second of them has no struct.set ;; which means we can make it immutable. - ;; CHECK: (type $struct (struct (field (mut funcref)) (field funcref) (field (mut funcref)))) + ;; CHECK: (type $struct (struct_subtype (field (mut funcref)) (field funcref) (field (mut funcref)) data)) (type $struct (struct (field (mut funcref)) (field (mut funcref)) (field (mut funcref)))) ;; Test that we update tag types properly. - ;; CHECK: (type $ref|$struct|_=>_none (func (param (ref $struct)))) + ;; CHECK: (type $ref|$struct|_=>_none (func_subtype (param (ref $struct)) func)) - ;; CHECK: (type $none_=>_ref?|$struct| (func (result (ref null $struct)))) + ;; CHECK: (type $none_=>_ref?|$struct| (func_subtype (result (ref null $struct)) func)) ;; CHECK: (tag $tag (param (ref $struct))) (tag $tag (param (ref $struct))) @@ -120,12 +120,12 @@ ;; Test recursion between structs where we only modify one. Specifically $B ;; has no writes to either of its fields. - ;; CHECK: (type $A (struct (field (mut (ref null $B))) (field (mut i32)))) + ;; CHECK: (type $A (struct_subtype (field (mut (ref null $B))) (field (mut i32)) data)) (type $A (struct (field (mut (ref null $B))) (field (mut i32)) )) - ;; CHECK: (type $B (struct (field (ref null $A)) (field f64))) + ;; CHECK: (type $B (struct_subtype (field (ref null $A)) (field f64) data)) (type $B (struct (field (mut (ref null $A))) (field (mut f64)) )) - ;; CHECK: (type $ref|$A|_=>_none (func (param (ref $A)))) + ;; CHECK: (type $ref|$A|_=>_none (func_subtype (param (ref $A)) func)) ;; CHECK: (func $func (param $x (ref $A)) ;; CHECK-NEXT: (struct.set $A 0 @@ -152,13 +152,13 @@ (module ;; As before, but flipped so that $A's fields can become immutable. - ;; CHECK: (type $B (struct (field (mut (ref null $A))) (field (mut f64)))) + ;; CHECK: (type $B (struct_subtype (field (mut (ref null $A))) (field (mut f64)) data)) (type $B (struct (field (mut (ref null $A))) (field (mut f64)) )) - ;; CHECK: (type $A (struct (field (ref null $B)) (field i32))) + ;; CHECK: (type $A (struct_subtype (field (ref null $B)) (field i32) data)) (type $A (struct (field (mut (ref null $B))) (field (mut i32)) )) - ;; CHECK: (type $ref|$B|_=>_none (func (param (ref $B)))) + ;; CHECK: (type $ref|$B|_=>_none (func_subtype (param (ref $B)) func)) ;; CHECK: (func $func (param $x (ref $B)) ;; CHECK-NEXT: (struct.set $B 0 @@ -185,13 +185,13 @@ (module ;; As before, but now one field in each can become immutable. - ;; CHECK: (type $B (struct (field (ref null $A)) (field (mut f64)))) + ;; CHECK: (type $B (struct_subtype (field (ref null $A)) (field (mut f64)) data)) (type $B (struct (field (mut (ref null $A))) (field (mut f64)) )) - ;; CHECK: (type $A (struct (field (mut (ref null $B))) (field i32))) + ;; CHECK: (type $A (struct_subtype (field (mut (ref null $B))) (field i32) data)) (type $A (struct (field (mut (ref null $B))) (field (mut i32)) )) - ;; CHECK: (type $ref|$A|_ref|$B|_=>_none (func (param (ref $A) (ref $B)))) + ;; CHECK: (type $ref|$A|_ref|$B|_=>_none (func_subtype (param (ref $A) (ref $B)) func)) ;; CHECK: (func $func (param $x (ref $A)) (param $y (ref $B)) ;; CHECK-NEXT: (struct.set $A 0 @@ -220,10 +220,10 @@ ;; Field #1 is mutable and can become so. ;; Field #2 is mutable and must remain so. - ;; CHECK: (type $struct (struct (field i32) (field i32) (field (mut i32)))) + ;; CHECK: (type $struct (struct_subtype (field i32) (field i32) (field (mut i32)) data)) (type $struct (struct (field i32) (field (mut i32)) (field (mut i32)))) - ;; CHECK: (type $ref|$struct|_=>_none (func (param (ref $struct)))) + ;; CHECK: (type $ref|$struct|_=>_none (func_subtype (param (ref $struct)) func)) ;; CHECK: (func $func (param $x (ref $struct)) ;; CHECK-NEXT: (struct.set $struct 2 @@ -243,12 +243,12 @@ ;; Subtyping. Without a write in either supertype or subtype, we can ;; optimize the field to be immutable. - ;; CHECK: (type $none_=>_none (func)) + ;; CHECK: (type $none_=>_none (func_subtype func)) - ;; CHECK: (type $super (struct (field i32))) + ;; CHECK: (type $super (struct_subtype (field i32) data)) (type $super (struct (field (mut i32)))) - ;; CHECK: (type $sub (struct (field i32)) (extends $super)) - (type $sub (struct (field (mut i32))) (extends $super)) + ;; CHECK: (type $sub (struct_subtype (field i32) $super)) + (type $sub (struct_subtype (field (mut i32)) $super)) ;; CHECK: (func $func ;; CHECK-NEXT: (drop @@ -280,12 +280,12 @@ (module ;; As above, but add a write in the super, which prevents optimization. - ;; CHECK: (type $super (struct (field (mut i32)))) + ;; CHECK: (type $super (struct_subtype (field (mut i32)) data)) (type $super (struct (field (mut i32)))) - ;; CHECK: (type $ref|$super|_=>_none (func (param (ref $super)))) + ;; CHECK: (type $ref|$super|_=>_none (func_subtype (param (ref $super)) func)) - ;; CHECK: (type $sub (struct (field (mut i32))) (extends $super)) - (type $sub (struct (field (mut i32))) (extends $super)) + ;; CHECK: (type $sub (struct_subtype (field (mut i32)) $super)) + (type $sub (struct_subtype (field (mut i32)) $super)) ;; CHECK: (func $func (param $x (ref $super)) ;; CHECK-NEXT: (drop @@ -325,13 +325,13 @@ (module ;; As above, but add a write in the sub, which prevents optimization. - ;; CHECK: (type $sub (struct (field (mut i32))) (extends $super)) + ;; CHECK: (type $sub (struct_subtype (field (mut i32)) $super)) - ;; CHECK: (type $ref|$sub|_=>_none (func (param (ref $sub)))) + ;; CHECK: (type $ref|$sub|_=>_none (func_subtype (param (ref $sub)) func)) - ;; CHECK: (type $super (struct (field (mut i32)))) + ;; CHECK: (type $super (struct_subtype (field (mut i32)) data)) (type $super (struct (field (mut i32)))) - (type $sub (struct (field (mut i32))) (extends $super)) + (type $sub (struct_subtype (field (mut i32)) $super)) ;; CHECK: (func $func (param $x (ref $sub)) ;; CHECK-NEXT: (struct.set $sub 0 diff --git a/test/lit/passes/heap2local.wast b/test/lit/passes/heap2local.wast index 90ac8a418..0d79cca5b 100644 --- a/test/lit/passes/heap2local.wast +++ b/test/lit/passes/heap2local.wast @@ -2,10 +2,11 @@ ;; (remove-unused-names allows the pass to see that blocks flow values) ;; RUN: wasm-opt %s -all --remove-unused-names --heap2local -S -o - | filecheck %s -;; RUN: wasm-opt %s -all --remove-unused-names --heap2local --nominal -S -o - | filecheck %s +;; RUN: wasm-opt %s -all --remove-unused-names --heap2local --nominal -S -o - | filecheck %s --check-prefix=NOMNL (module ;; CHECK: (type $struct.A (struct (field (mut i32)) (field (mut f64)))) + ;; NOMNL: (type $struct.A (struct_subtype (field (mut i32)) (field (mut f64)) data)) (type $struct.A (struct (field (mut i32)) (field (mut f64)))) ;; CHECK: (type $struct.recursive (struct (field (mut (ref null $struct.recursive))))) @@ -13,9 +14,15 @@ ;; CHECK: (type $struct.nonnullable (struct (field (ref $struct.A)))) ;; CHECK: (type $struct.packed (struct (field (mut i8)))) + ;; NOMNL: (type $struct.recursive (struct_subtype (field (mut (ref null $struct.recursive))) data)) + + ;; NOMNL: (type $struct.nonnullable (struct_subtype (field (ref $struct.A)) data)) + + ;; NOMNL: (type $struct.packed (struct_subtype (field (mut i8)) data)) (type $struct.packed (struct (field (mut i8)))) ;; CHECK: (type $struct.nondefaultable (struct (field (rtt $struct.A)))) + ;; NOMNL: (type $struct.nondefaultable (struct_subtype (field (rtt $struct.A)) data)) (type $struct.nondefaultable (struct (field (rtt $struct.A)))) (type $struct.recursive (struct (field (mut (ref null $struct.recursive))))) @@ -40,6 +47,24 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; NOMNL: (func $simple + ;; NOMNL-NEXT: (local $0 i32) + ;; NOMNL-NEXT: (local $1 f64) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (block (result (ref null $struct.A)) + ;; NOMNL-NEXT: (local.set $0 + ;; NOMNL-NEXT: (i32.const 0) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.set $1 + ;; NOMNL-NEXT: (f64.const 0) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (rtt.canon $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (ref.null $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) (func $simple ;; Other passes can remove such a trivial case of an unused allocation, but ;; we still optimize it. @@ -69,6 +94,25 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; NOMNL: (func $to-local + ;; NOMNL-NEXT: (local $ref (ref null $struct.A)) + ;; NOMNL-NEXT: (local $1 i32) + ;; NOMNL-NEXT: (local $2 f64) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (block (result (ref null $struct.A)) + ;; NOMNL-NEXT: (local.set $1 + ;; NOMNL-NEXT: (i32.const 0) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.set $2 + ;; NOMNL-NEXT: (f64.const 0) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (rtt.canon $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (ref.null $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) (func $to-local (local $ref (ref null $struct.A)) ;; While set to a local, this allocation has no get/set operations. Other @@ -105,6 +149,29 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; NOMNL: (func $one-get + ;; NOMNL-NEXT: (local $0 i32) + ;; NOMNL-NEXT: (local $1 f64) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (block (result i32) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (block (result (ref null $struct.A)) + ;; NOMNL-NEXT: (local.set $0 + ;; NOMNL-NEXT: (i32.const 0) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.set $1 + ;; NOMNL-NEXT: (f64.const 0) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (rtt.canon $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (ref.null $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.get $0) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) (func $one-get ;; An allocation followed by an immediate get of a field. This is a non- ;; escaping allocation, with a use, so we can optimize it out. The @@ -143,6 +210,29 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; NOMNL: (func $one-get-b + ;; NOMNL-NEXT: (local $0 i32) + ;; NOMNL-NEXT: (local $1 f64) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (block (result f64) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (block (result (ref null $struct.A)) + ;; NOMNL-NEXT: (local.set $0 + ;; NOMNL-NEXT: (i32.const 0) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.set $1 + ;; NOMNL-NEXT: (f64.const 0) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (rtt.canon $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (ref.null $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.get $1) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) (func $one-get-b ;; Similar to the above, but using a different field index. (drop @@ -175,6 +265,27 @@ ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; NOMNL: (func $one-set + ;; NOMNL-NEXT: (local $0 i32) + ;; NOMNL-NEXT: (local $1 f64) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (block (result (ref null $struct.A)) + ;; NOMNL-NEXT: (local.set $0 + ;; NOMNL-NEXT: (i32.const 0) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.set $1 + ;; NOMNL-NEXT: (f64.const 0) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (rtt.canon $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (ref.null $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.set $0 + ;; NOMNL-NEXT: (i32.const 1) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) (func $one-set ;; A simple optimizable allocation only used in one set. (struct.set $struct.A 0 @@ -194,6 +305,15 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; NOMNL: (func $packed + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (struct.get_u $struct.packed 0 + ;; NOMNL-NEXT: (struct.new_default_with_rtt $struct.packed + ;; NOMNL-NEXT: (rtt.canon $struct.packed) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) (func $packed ;; We do not optimize packed structs yet. (drop @@ -236,6 +356,37 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; NOMNL: (func $with-init-values + ;; NOMNL-NEXT: (local $0 i32) + ;; NOMNL-NEXT: (local $1 f64) + ;; NOMNL-NEXT: (local $2 i32) + ;; NOMNL-NEXT: (local $3 f64) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (block (result i32) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (block (result (ref null $struct.A)) + ;; NOMNL-NEXT: (local.set $2 + ;; NOMNL-NEXT: (i32.const 2) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.set $3 + ;; NOMNL-NEXT: (f64.const 3.14159) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.set $0 + ;; NOMNL-NEXT: (local.get $2) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.set $1 + ;; NOMNL-NEXT: (local.get $3) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (rtt.canon $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (ref.null $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.get $0) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) (func $with-init-values ;; When we get values to initialize the struct with, assign them to the ;; proper locals. @@ -263,6 +414,19 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; NOMNL: (func $ignore-unreachable + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (block ;; (replaces something unreachable we can't emit) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (block + ;; NOMNL-NEXT: (i32.const 2) + ;; NOMNL-NEXT: (unreachable) + ;; NOMNL-NEXT: (rtt.canon $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) (func $ignore-unreachable ;; An unreachable allocation is not worth trying to process; DCE should ;; remove it. @@ -287,6 +451,16 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; NOMNL: (func $nondefaultable + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (struct.get $struct.nondefaultable 0 + ;; NOMNL-NEXT: (struct.new_with_rtt $struct.nondefaultable + ;; NOMNL-NEXT: (rtt.canon $struct.A) + ;; NOMNL-NEXT: (rtt.canon $struct.nondefaultable) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) (func $nondefaultable ;; We do not optimize structs with nondefaultable types that we cannot ;; handle, like rtts. @@ -327,6 +501,33 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; NOMNL: (func $simple-one-local-set + ;; NOMNL-NEXT: (local $ref (ref null $struct.A)) + ;; NOMNL-NEXT: (local $1 i32) + ;; NOMNL-NEXT: (local $2 f64) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (block (result (ref null $struct.A)) + ;; NOMNL-NEXT: (local.set $1 + ;; NOMNL-NEXT: (i32.const 0) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.set $2 + ;; NOMNL-NEXT: (f64.const 0) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (rtt.canon $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (ref.null $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (block + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (ref.null $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.set $1 + ;; NOMNL-NEXT: (i32.const 1) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) (func $simple-one-local-set (local $ref (ref null $struct.A)) ;; A simple optimizable allocation only used in one set, and also stored @@ -368,6 +569,31 @@ ;; CHECK-NEXT: (local.get $2) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; NOMNL: (func $simple-one-local-get (result f64) + ;; NOMNL-NEXT: (local $ref (ref null $struct.A)) + ;; NOMNL-NEXT: (local $1 i32) + ;; NOMNL-NEXT: (local $2 f64) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (block (result (ref null $struct.A)) + ;; NOMNL-NEXT: (local.set $1 + ;; NOMNL-NEXT: (i32.const 0) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.set $2 + ;; NOMNL-NEXT: (f64.const 0) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (rtt.canon $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (ref.null $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (block (result f64) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (ref.null $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.get $2) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) (func $simple-one-local-get (result f64) (local $ref (ref null $struct.A)) (local.set $ref @@ -384,6 +610,9 @@ ;; CHECK: (func $send-ref (param $0 (ref null $struct.A)) ;; CHECK-NEXT: (nop) ;; CHECK-NEXT: ) + ;; NOMNL: (func $send-ref (param $0 (ref null $struct.A)) + ;; NOMNL-NEXT: (nop) + ;; NOMNL-NEXT: ) (func $send-ref (param (ref null $struct.A)) ) @@ -415,6 +644,34 @@ ;; CHECK-NEXT: (local.get $2) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; NOMNL: (func $safe-to-drop (result f64) + ;; NOMNL-NEXT: (local $ref (ref null $struct.A)) + ;; NOMNL-NEXT: (local $1 i32) + ;; NOMNL-NEXT: (local $2 f64) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (block (result (ref null $struct.A)) + ;; NOMNL-NEXT: (local.set $1 + ;; NOMNL-NEXT: (i32.const 0) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.set $2 + ;; NOMNL-NEXT: (f64.const 0) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (rtt.canon $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (ref.null $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (ref.null $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (block (result f64) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (ref.null $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.get $2) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) (func $safe-to-drop (result f64) (local $ref (ref null $struct.A)) (local.set $ref @@ -445,6 +702,20 @@ ;; CHECK-NEXT: (local.get $ref) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; NOMNL: (func $escape-via-call (result f64) + ;; NOMNL-NEXT: (local $ref (ref null $struct.A)) + ;; NOMNL-NEXT: (local.set $ref + ;; NOMNL-NEXT: (struct.new_default_with_rtt $struct.A + ;; NOMNL-NEXT: (rtt.canon $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (call $send-ref + ;; NOMNL-NEXT: (local.get $ref) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (struct.get $struct.A 1 + ;; NOMNL-NEXT: (local.get $ref) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) (func $escape-via-call (result f64) (local $ref (ref null $struct.A)) (local.set $ref @@ -493,6 +764,38 @@ ;; CHECK-NEXT: (local.get $2) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; NOMNL: (func $safe-to-drop-multiflow (result f64) + ;; NOMNL-NEXT: (local $ref (ref null $struct.A)) + ;; NOMNL-NEXT: (local $1 i32) + ;; NOMNL-NEXT: (local $2 f64) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (block (result (ref null $struct.A)) + ;; NOMNL-NEXT: (local.set $1 + ;; NOMNL-NEXT: (i32.const 0) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.set $2 + ;; NOMNL-NEXT: (f64.const 0) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (rtt.canon $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (ref.null $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (block (result (ref null $struct.A)) + ;; NOMNL-NEXT: (block (result (ref null $struct.A)) + ;; NOMNL-NEXT: (ref.null $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (block (result f64) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (ref.null $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.get $2) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) (func $safe-to-drop-multiflow (result f64) (local $ref (ref null $struct.A)) (local.set $ref @@ -533,6 +836,24 @@ ;; CHECK-NEXT: (local.get $ref) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; NOMNL: (func $escape-after-multiflow (result f64) + ;; NOMNL-NEXT: (local $ref (ref null $struct.A)) + ;; NOMNL-NEXT: (local.set $ref + ;; NOMNL-NEXT: (struct.new_default_with_rtt $struct.A + ;; NOMNL-NEXT: (rtt.canon $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (call $send-ref + ;; NOMNL-NEXT: (block (result (ref null $struct.A)) + ;; NOMNL-NEXT: (block (result (ref null $struct.A)) + ;; NOMNL-NEXT: (local.get $ref) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (struct.get $struct.A 1 + ;; NOMNL-NEXT: (local.get $ref) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) (func $escape-after-multiflow (result f64) (local $ref (ref null $struct.A)) (local.set $ref @@ -572,6 +893,23 @@ ;; CHECK-NEXT: (local.get $ref) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; NOMNL: (func $non-exclusive-set (result f64) + ;; NOMNL-NEXT: (local $ref (ref null $struct.A)) + ;; NOMNL-NEXT: (local.set $ref + ;; NOMNL-NEXT: (select (result (ref $struct.A)) + ;; NOMNL-NEXT: (struct.new_default_with_rtt $struct.A + ;; NOMNL-NEXT: (rtt.canon $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (struct.new_default_with_rtt $struct.A + ;; NOMNL-NEXT: (rtt.canon $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (i32.const 1) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (struct.get $struct.A 1 + ;; NOMNL-NEXT: (local.get $ref) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) (func $non-exclusive-set (result f64) (local $ref (ref null $struct.A)) ;; A set that receives two different allocations, and so we should not try @@ -620,6 +958,34 @@ ;; CHECK-NEXT: (local.get $2) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; NOMNL: (func $local-copies (result f64) + ;; NOMNL-NEXT: (local $ref (ref null $struct.A)) + ;; NOMNL-NEXT: (local $1 i32) + ;; NOMNL-NEXT: (local $2 f64) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (block (result (ref null $struct.A)) + ;; NOMNL-NEXT: (local.set $1 + ;; NOMNL-NEXT: (i32.const 0) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.set $2 + ;; NOMNL-NEXT: (f64.const 0) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (rtt.canon $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (ref.null $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (ref.null $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (block (result f64) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (ref.null $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.get $2) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) (func $local-copies (result f64) (local $ref (ref null $struct.A)) (local.set $ref @@ -675,6 +1041,45 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; NOMNL: (func $local-copies-2 + ;; NOMNL-NEXT: (local $ref (ref null $struct.A)) + ;; NOMNL-NEXT: (local $ref-2 (ref null $struct.A)) + ;; NOMNL-NEXT: (local $2 i32) + ;; NOMNL-NEXT: (local $3 f64) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (block (result (ref null $struct.A)) + ;; NOMNL-NEXT: (local.set $2 + ;; NOMNL-NEXT: (i32.const 0) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.set $3 + ;; NOMNL-NEXT: (f64.const 0) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (rtt.canon $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (ref.null $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (ref.null $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (block (result i32) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (ref.null $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.get $2) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (block (result f64) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (ref.null $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.get $3) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) (func $local-copies-2 (local $ref (ref null $struct.A)) (local $ref-2 (ref null $struct.A)) @@ -731,6 +1136,37 @@ ;; CHECK-NEXT: (local.get $3) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; NOMNL: (func $local-copies-conditional (param $x i32) (result f64) + ;; NOMNL-NEXT: (local $ref (ref null $struct.A)) + ;; NOMNL-NEXT: (local $2 i32) + ;; NOMNL-NEXT: (local $3 f64) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (block (result (ref null $struct.A)) + ;; NOMNL-NEXT: (local.set $2 + ;; NOMNL-NEXT: (i32.const 0) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.set $3 + ;; NOMNL-NEXT: (f64.const 0) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (rtt.canon $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (ref.null $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (if + ;; NOMNL-NEXT: (local.get $x) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (ref.null $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (block (result f64) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (ref.null $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.get $3) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) (func $local-copies-conditional (param $x i32) (result f64) (local $ref (ref null $struct.A)) (local.set $ref @@ -781,6 +1217,36 @@ ;; CHECK-NEXT: (local.get $2) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; NOMNL: (func $block-value (result f64) + ;; NOMNL-NEXT: (local $ref (ref null $struct.A)) + ;; NOMNL-NEXT: (local $1 i32) + ;; NOMNL-NEXT: (local $2 f64) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (block (result (ref null $struct.A)) + ;; NOMNL-NEXT: (local.set $1 + ;; NOMNL-NEXT: (i32.const 0) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.set $2 + ;; NOMNL-NEXT: (f64.const 0) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (rtt.canon $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (ref.null $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (block (result f64) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (block (result (ref null $struct.A)) + ;; NOMNL-NEXT: (call $send-ref + ;; NOMNL-NEXT: (ref.null $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (ref.null $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.get $2) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) (func $block-value (result f64) (local $ref (ref null $struct.A)) (local.set $ref @@ -817,6 +1283,23 @@ ;; CHECK-NEXT: (local.get $ref) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; NOMNL: (func $non-exclusive-get (param $x i32) (result f64) + ;; NOMNL-NEXT: (local $ref (ref null $struct.A)) + ;; NOMNL-NEXT: (local.set $ref + ;; NOMNL-NEXT: (struct.new_default_with_rtt $struct.A + ;; NOMNL-NEXT: (rtt.canon $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (if + ;; NOMNL-NEXT: (local.get $x) + ;; NOMNL-NEXT: (local.set $ref + ;; NOMNL-NEXT: (ref.null $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (struct.get $struct.A 1 + ;; NOMNL-NEXT: (local.get $ref) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) (func $non-exclusive-get (param $x i32) (result f64) (local $ref (ref null $struct.A)) (local.set $ref @@ -856,6 +1339,26 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.get $1) ;; CHECK-NEXT: ) + ;; NOMNL: (func $tee (result i32) + ;; NOMNL-NEXT: (local $ref (ref null $struct.A)) + ;; NOMNL-NEXT: (local $1 i32) + ;; NOMNL-NEXT: (local $2 f64) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (block (result (ref null $struct.A)) + ;; NOMNL-NEXT: (local.set $1 + ;; NOMNL-NEXT: (i32.const 0) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.set $2 + ;; NOMNL-NEXT: (f64.const 0) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (rtt.canon $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (ref.null $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.get $1) + ;; NOMNL-NEXT: ) (func $tee (result i32) (local $ref (ref null $struct.A)) (struct.get $struct.A 0 @@ -886,6 +1389,24 @@ ;; CHECK-NEXT: (ref.null $struct.recursive) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; NOMNL: (func $tee-set + ;; NOMNL-NEXT: (local $ref (ref null $struct.recursive)) + ;; NOMNL-NEXT: (local $1 (ref null $struct.recursive)) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (block (result (ref null $struct.recursive)) + ;; NOMNL-NEXT: (local.set $1 + ;; NOMNL-NEXT: (ref.null $struct.recursive) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (rtt.canon $struct.recursive) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (ref.null $struct.recursive) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.set $1 + ;; NOMNL-NEXT: (ref.null $struct.recursive) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) (func $tee-set (local $ref (ref null $struct.recursive)) ;; As above, but with a set, and also a recursive type. @@ -910,6 +1431,17 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; NOMNL: (func $set-value + ;; NOMNL-NEXT: (local $ref (ref null $struct.recursive)) + ;; NOMNL-NEXT: (struct.set $struct.recursive 0 + ;; NOMNL-NEXT: (ref.null $struct.recursive) + ;; NOMNL-NEXT: (local.tee $ref + ;; NOMNL-NEXT: (struct.new_default_with_rtt $struct.recursive + ;; NOMNL-NEXT: (rtt.canon $struct.recursive) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) (func $set-value (local $ref (ref null $struct.recursive)) (struct.set $struct.recursive 0 @@ -953,6 +1485,35 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; NOMNL: (func $initialize-with-reference + ;; NOMNL-NEXT: (local $0 (ref null $struct.recursive)) + ;; NOMNL-NEXT: (local $1 (ref null $struct.recursive)) + ;; NOMNL-NEXT: (local $2 (ref null $struct.recursive)) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (block (result (ref null $struct.recursive)) + ;; NOMNL-NEXT: (local.set $2 + ;; NOMNL-NEXT: (struct.new_default_with_rtt $struct.recursive + ;; NOMNL-NEXT: (rtt.canon $struct.recursive) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.set $1 + ;; NOMNL-NEXT: (local.get $2) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (rtt.canon $struct.recursive) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (ref.null $struct.recursive) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (block (result (ref null $struct.recursive)) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (ref.null $struct.recursive) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.get $1) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) (func $initialize-with-reference (local $0 (ref null $struct.recursive)) (local.set $0 @@ -990,6 +1551,18 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.get $ref) ;; CHECK-NEXT: ) + ;; NOMNL: (func $escape-flow-out (result anyref) + ;; NOMNL-NEXT: (local $ref (ref null $struct.A)) + ;; NOMNL-NEXT: (struct.set $struct.A 0 + ;; NOMNL-NEXT: (local.tee $ref + ;; NOMNL-NEXT: (struct.new_default_with_rtt $struct.A + ;; NOMNL-NEXT: (rtt.canon $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (i32.const 1) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.get $ref) + ;; NOMNL-NEXT: ) (func $escape-flow-out (result anyref) (local $ref (ref null $struct.A)) (struct.set $struct.A 0 @@ -1018,6 +1591,20 @@ ;; CHECK-NEXT: (local.get $ref) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; NOMNL: (func $escape-return (result anyref) + ;; NOMNL-NEXT: (local $ref (ref null $struct.A)) + ;; NOMNL-NEXT: (struct.set $struct.A 0 + ;; NOMNL-NEXT: (local.tee $ref + ;; NOMNL-NEXT: (struct.new_default_with_rtt $struct.A + ;; NOMNL-NEXT: (rtt.canon $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (i32.const 1) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (return + ;; NOMNL-NEXT: (local.get $ref) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) (func $escape-return (result anyref) (local $ref (ref null $struct.A)) (struct.set $struct.A 0 @@ -1061,6 +1648,33 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; NOMNL: (func $non-nullable (param $a (ref $struct.A)) + ;; NOMNL-NEXT: (local $1 (ref null $struct.A)) + ;; NOMNL-NEXT: (local $2 (ref null $struct.A)) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (block (result (ref $struct.A)) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (block (result (ref null $struct.nonnullable)) + ;; NOMNL-NEXT: (local.set $2 + ;; NOMNL-NEXT: (local.get $a) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.set $1 + ;; NOMNL-NEXT: (ref.as_non_null + ;; NOMNL-NEXT: (local.get $2) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (rtt.canon $struct.nonnullable) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (ref.null $struct.nonnullable) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (ref.as_non_null + ;; NOMNL-NEXT: (local.get $1) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) (func $non-nullable (param $a (ref $struct.A)) (drop ;; An optimizable case where the type is non-nullable, which requires @@ -1171,6 +1785,103 @@ ;; CHECK-NEXT: (br $outer) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; NOMNL: (func $before-loop-use-multi (param $x i32) + ;; NOMNL-NEXT: (local $ref (ref null $struct.A)) + ;; NOMNL-NEXT: (local $2 i32) + ;; NOMNL-NEXT: (local $3 f64) + ;; NOMNL-NEXT: (local $4 i32) + ;; NOMNL-NEXT: (local $5 f64) + ;; NOMNL-NEXT: (loop $outer + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (block (result (ref null $struct.A)) + ;; NOMNL-NEXT: (local.set $4 + ;; NOMNL-NEXT: (i32.const 2) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.set $5 + ;; NOMNL-NEXT: (f64.const 2.1828) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.set $2 + ;; NOMNL-NEXT: (local.get $4) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.set $3 + ;; NOMNL-NEXT: (local.get $5) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (rtt.canon $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (ref.null $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (block (result i32) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (ref.null $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.get $2) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (if + ;; NOMNL-NEXT: (local.get $x) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (block (result f64) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (ref.null $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.get $3) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (block + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (ref.null $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.set $3 + ;; NOMNL-NEXT: (f64.const 42) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (loop $inner + ;; NOMNL-NEXT: (block + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (ref.null $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.set $2 + ;; NOMNL-NEXT: (i32.add + ;; NOMNL-NEXT: (block (result i32) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (ref.null $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.get $2) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (i32.const 1) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (br_if $inner + ;; NOMNL-NEXT: (local.get $x) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (if + ;; NOMNL-NEXT: (local.get $x) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (block (result i32) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (ref.null $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.get $2) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (block (result f64) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (ref.null $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.get $3) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (br $outer) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) (func $before-loop-use-multi (param $x i32) (local $ref (ref null $struct.A)) ;; Allocate in a loop, and use that allocation multiple times in that loop @@ -1294,6 +2005,71 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; NOMNL: (func $multi-separate + ;; NOMNL-NEXT: (local $0 i32) + ;; NOMNL-NEXT: (local $1 f64) + ;; NOMNL-NEXT: (local $2 i32) + ;; NOMNL-NEXT: (local $3 f64) + ;; NOMNL-NEXT: (local $4 i32) + ;; NOMNL-NEXT: (local $5 f64) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (block (result i32) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (block (result (ref null $struct.A)) + ;; NOMNL-NEXT: (local.set $0 + ;; NOMNL-NEXT: (i32.const 0) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.set $1 + ;; NOMNL-NEXT: (f64.const 0) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (rtt.canon $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (ref.null $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.get $0) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (block (result i32) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (block (result (ref null $struct.A)) + ;; NOMNL-NEXT: (local.set $2 + ;; NOMNL-NEXT: (i32.const 0) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.set $3 + ;; NOMNL-NEXT: (f64.const 0) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (rtt.canon $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (ref.null $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.get $2) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (block (result f64) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (block (result (ref null $struct.A)) + ;; NOMNL-NEXT: (local.set $4 + ;; NOMNL-NEXT: (i32.const 0) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.set $5 + ;; NOMNL-NEXT: (f64.const 0) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (rtt.canon $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (ref.null $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.get $5) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) (func $multi-separate ;; Multiple independent things we can optimize. (drop @@ -1370,6 +2146,57 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; NOMNL: (func $multi-separate-same-local-index + ;; NOMNL-NEXT: (local $ref (ref null $struct.A)) + ;; NOMNL-NEXT: (local $1 i32) + ;; NOMNL-NEXT: (local $2 f64) + ;; NOMNL-NEXT: (local $3 i32) + ;; NOMNL-NEXT: (local $4 f64) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (block (result (ref null $struct.A)) + ;; NOMNL-NEXT: (local.set $1 + ;; NOMNL-NEXT: (i32.const 0) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.set $2 + ;; NOMNL-NEXT: (f64.const 0) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (rtt.canon $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (ref.null $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (block (result i32) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (ref.null $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.get $1) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (block (result (ref null $struct.A)) + ;; NOMNL-NEXT: (local.set $3 + ;; NOMNL-NEXT: (i32.const 0) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.set $4 + ;; NOMNL-NEXT: (f64.const 0) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (rtt.canon $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (ref.null $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (block (result i32) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (ref.null $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.get $3) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) (func $multi-separate-same-local-index (local $ref (ref null $struct.A)) ;; Multiple independent things we can optimize that use the same local @@ -1448,6 +2275,58 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; NOMNL: (func $multi-separate-different-local-index-overlapping-lifetimes + ;; NOMNL-NEXT: (local $ref1 (ref null $struct.A)) + ;; NOMNL-NEXT: (local $ref2 (ref null $struct.A)) + ;; NOMNL-NEXT: (local $2 i32) + ;; NOMNL-NEXT: (local $3 f64) + ;; NOMNL-NEXT: (local $4 i32) + ;; NOMNL-NEXT: (local $5 f64) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (block (result (ref null $struct.A)) + ;; NOMNL-NEXT: (local.set $2 + ;; NOMNL-NEXT: (i32.const 0) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.set $3 + ;; NOMNL-NEXT: (f64.const 0) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (rtt.canon $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (ref.null $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (block (result (ref null $struct.A)) + ;; NOMNL-NEXT: (local.set $4 + ;; NOMNL-NEXT: (i32.const 0) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.set $5 + ;; NOMNL-NEXT: (f64.const 0) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (rtt.canon $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (ref.null $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (block (result i32) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (ref.null $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.get $2) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (block (result i32) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (ref.null $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.get $4) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) (func $multi-separate-different-local-index-overlapping-lifetimes (local $ref1 (ref null $struct.A)) (local $ref2 (ref null $struct.A)) @@ -1494,6 +2373,25 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; NOMNL: (func $get-through-block (result f64) + ;; NOMNL-NEXT: (local $0 (ref null $struct.A)) + ;; NOMNL-NEXT: (local.set $0 + ;; NOMNL-NEXT: (struct.new_default_with_rtt $struct.A + ;; NOMNL-NEXT: (rtt.canon $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (struct.get $struct.A 1 + ;; NOMNL-NEXT: (block $block (result (ref null $struct.A)) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (br_if $block + ;; NOMNL-NEXT: (ref.null $struct.A) + ;; NOMNL-NEXT: (i32.const 0) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.get $0) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) (func $get-through-block (result f64) (local $0 (ref null $struct.A)) (local.set $0 @@ -1537,6 +2435,25 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; NOMNL: (func $branch-to-block (result f64) + ;; NOMNL-NEXT: (local $0 (ref null $struct.A)) + ;; NOMNL-NEXT: (local.set $0 + ;; NOMNL-NEXT: (struct.new_default_with_rtt $struct.A + ;; NOMNL-NEXT: (rtt.canon $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (struct.get $struct.A 1 + ;; NOMNL-NEXT: (block $block (result (ref null $struct.A)) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (br_if $block + ;; NOMNL-NEXT: (local.get $0) + ;; NOMNL-NEXT: (i32.const 0) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (ref.null $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) (func $branch-to-block (result f64) (local $0 (ref null $struct.A)) (local.set $0 @@ -1594,6 +2511,41 @@ ;; CHECK-NEXT: (local.get $2) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; NOMNL: (func $branch-to-block-no-fallthrough (result f64) + ;; NOMNL-NEXT: (local $0 (ref null $struct.A)) + ;; NOMNL-NEXT: (local $1 i32) + ;; NOMNL-NEXT: (local $2 f64) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (block (result (ref null $struct.A)) + ;; NOMNL-NEXT: (local.set $1 + ;; NOMNL-NEXT: (i32.const 0) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.set $2 + ;; NOMNL-NEXT: (f64.const 0) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (rtt.canon $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (ref.null $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (block (result f64) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (block $block (result (ref null $struct.A)) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (br_if $block + ;; NOMNL-NEXT: (ref.null $struct.A) + ;; NOMNL-NEXT: (i32.const 0) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (return + ;; NOMNL-NEXT: (f64.const 2.1828) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.get $2) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) (func $branch-to-block-no-fallthrough (result f64) (local $0 (ref null $struct.A)) (local.set $0 @@ -1644,6 +2596,33 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; NOMNL: (func $two-branches (result f64) + ;; NOMNL-NEXT: (local $0 (ref null $struct.A)) + ;; NOMNL-NEXT: (local.set $0 + ;; NOMNL-NEXT: (struct.new_default_with_rtt $struct.A + ;; NOMNL-NEXT: (rtt.canon $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (struct.get $struct.A 1 + ;; NOMNL-NEXT: (block $block (result (ref null $struct.A)) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (br_if $block + ;; NOMNL-NEXT: (local.get $0) + ;; NOMNL-NEXT: (i32.const 0) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (br_if $block + ;; NOMNL-NEXT: (ref.null $struct.A) + ;; NOMNL-NEXT: (i32.const 0) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (return + ;; NOMNL-NEXT: (f64.const 2.1828) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) (func $two-branches (result f64) (local $0 (ref null $struct.A)) (local.set $0 @@ -1699,6 +2678,33 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; NOMNL: (func $two-branches-b (result f64) + ;; NOMNL-NEXT: (local $0 (ref null $struct.A)) + ;; NOMNL-NEXT: (local.set $0 + ;; NOMNL-NEXT: (struct.new_default_with_rtt $struct.A + ;; NOMNL-NEXT: (rtt.canon $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (struct.get $struct.A 1 + ;; NOMNL-NEXT: (block $block (result (ref null $struct.A)) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (br_if $block + ;; NOMNL-NEXT: (local.get $0) + ;; NOMNL-NEXT: (i32.const 0) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (br_if $block + ;; NOMNL-NEXT: (local.get $0) + ;; NOMNL-NEXT: (i32.const 0) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (return + ;; NOMNL-NEXT: (f64.const 2.1828) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) (func $two-branches-b (result f64) (local $0 (ref null $struct.A)) (local.set $0 @@ -1749,6 +2755,27 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; NOMNL: (func $br_if_flow (result f64) + ;; NOMNL-NEXT: (local $0 (ref null $struct.A)) + ;; NOMNL-NEXT: (local.set $0 + ;; NOMNL-NEXT: (struct.new_default_with_rtt $struct.A + ;; NOMNL-NEXT: (rtt.canon $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (struct.get $struct.A 1 + ;; NOMNL-NEXT: (block $block (result (ref null $struct.A)) + ;; NOMNL-NEXT: (call $send-ref + ;; NOMNL-NEXT: (br_if $block + ;; NOMNL-NEXT: (local.get $0) + ;; NOMNL-NEXT: (i32.const 0) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (return + ;; NOMNL-NEXT: (f64.const 2.1828) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) (func $br_if_flow (result f64) (local $0 (ref null $struct.A)) (local.set $0 @@ -1804,6 +2831,38 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; NOMNL: (func $ref-as-non-null + ;; NOMNL-NEXT: (local $ref (ref null $struct.A)) + ;; NOMNL-NEXT: (local $1 i32) + ;; NOMNL-NEXT: (local $2 f64) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (block (result (ref null $struct.A)) + ;; NOMNL-NEXT: (local.set $1 + ;; NOMNL-NEXT: (i32.const 0) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.set $2 + ;; NOMNL-NEXT: (f64.const 0) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (rtt.canon $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (ref.null $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (block + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (ref.null $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.set $1 + ;; NOMNL-NEXT: (i32.const 1) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (ref.as_non_null + ;; NOMNL-NEXT: (ref.null any) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) (func $ref-as-non-null (local $ref (ref null $struct.A)) (local.set $ref @@ -1856,6 +2915,34 @@ ;; CHECK-NEXT: (local.get $1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; NOMNL: (func $ref-as-non-null-through-local (result i32) + ;; NOMNL-NEXT: (local $ref (ref null $struct.A)) + ;; NOMNL-NEXT: (local $1 i32) + ;; NOMNL-NEXT: (local $2 f64) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (block (result (ref null $struct.A)) + ;; NOMNL-NEXT: (local.set $1 + ;; NOMNL-NEXT: (i32.const 0) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.set $2 + ;; NOMNL-NEXT: (f64.const 0) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (rtt.canon $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (ref.null $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (ref.null $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (block (result i32) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (ref.null $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.get $1) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) (func $ref-as-non-null-through-local (result i32) (local $ref (ref null $struct.A)) (local.set $ref @@ -1917,6 +3004,44 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.get $2) ;; CHECK-NEXT: ) + ;; NOMNL: (func $br_if-allocation (result f64) + ;; NOMNL-NEXT: (local $0 (ref null $struct.A)) + ;; NOMNL-NEXT: (local $1 i32) + ;; NOMNL-NEXT: (local $2 f64) + ;; NOMNL-NEXT: (local $3 i32) + ;; NOMNL-NEXT: (local $4 f64) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (block $block (result (ref null $struct.A)) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (br_if $block + ;; NOMNL-NEXT: (block (result (ref null $struct.A)) + ;; NOMNL-NEXT: (local.set $3 + ;; NOMNL-NEXT: (i32.const 42) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.set $4 + ;; NOMNL-NEXT: (f64.const 13.37) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.set $1 + ;; NOMNL-NEXT: (local.get $3) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.set $2 + ;; NOMNL-NEXT: (local.get $4) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (rtt.canon $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (ref.null $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (i32.const 0) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (return + ;; NOMNL-NEXT: (f64.const 2.1828) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.get $2) + ;; NOMNL-NEXT: ) (func $br_if-allocation (result f64) (local $0 (ref null $struct.A)) (struct.get $struct.A 1 @@ -1953,6 +3078,21 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; NOMNL: (func $simple-no-rtt + ;; NOMNL-NEXT: (local $0 i32) + ;; NOMNL-NEXT: (local $1 f64) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (block (result (ref null $struct.A)) + ;; NOMNL-NEXT: (local.set $0 + ;; NOMNL-NEXT: (i32.const 0) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.set $1 + ;; NOMNL-NEXT: (f64.const 0) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (ref.null $struct.A) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) (func $simple-no-rtt (drop ;; This allocation has no rtt, so we have nothing to drop from it when diff --git a/test/lit/passes/inlining_all-features.wast b/test/lit/passes/inlining_all-features.wast index b3089baeb..fce3cc460 100644 --- a/test/lit/passes/inlining_all-features.wast +++ b/test/lit/passes/inlining_all-features.wast @@ -1,7 +1,7 @@ ;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. ;; RUN: foreach %s %t wasm-opt --inlining --all-features -S -o - | filecheck %s -;; RUN: foreach %s %t wasm-opt --inlining --all-features --nominal -S -o - | filecheck %s +;; RUN: foreach %s %t wasm-opt --inlining --all-features --nominal -S -o - | filecheck %s --check-prefix=NOMNL (module ;; CHECK: (type $none_=>_none (func)) @@ -11,6 +11,13 @@ ;; CHECK: (elem declare func $foo) ;; CHECK: (export "ref_func_test" (func $ref_func_test)) + ;; NOMNL: (type $none_=>_none (func_subtype func)) + + ;; NOMNL: (type $none_=>_funcref (func_subtype (result funcref) func)) + + ;; NOMNL: (elem declare func $foo) + + ;; NOMNL: (export "ref_func_test" (func $ref_func_test)) (export "ref_func_test" (func $ref_func_test)) ;; $foo should not be removed after being inlined, because there is 'ref.func' @@ -18,6 +25,9 @@ ;; CHECK: (func $foo ;; CHECK-NEXT: (nop) ;; CHECK-NEXT: ) + ;; NOMNL: (func $foo + ;; NOMNL-NEXT: (nop) + ;; NOMNL-NEXT: ) (func $foo) ;; CHECK: (func $ref_func_test (result funcref) @@ -28,6 +38,14 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (ref.func $foo) ;; CHECK-NEXT: ) + ;; NOMNL: (func $ref_func_test (result funcref) + ;; NOMNL-NEXT: (block + ;; NOMNL-NEXT: (block $__inlined_func$foo + ;; NOMNL-NEXT: (nop) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (ref.func $foo) + ;; NOMNL-NEXT: ) (func $ref_func_test (result funcref) (call $foo) (ref.func $foo) @@ -40,11 +58,17 @@ ;; CHECK: (type $none_=>_i32 (func (result i32))) ;; CHECK: (global $global$0 (mut funcref) (ref.func $0)) + ;; NOMNL: (type $none_=>_i32 (func_subtype (result i32) func)) + + ;; NOMNL: (global $global$0 (mut funcref) (ref.func $0)) (global $global$0 (mut funcref) (ref.func $0)) ;; CHECK: (func $0 (result i32) ;; CHECK-NEXT: (i32.const 1337) ;; CHECK-NEXT: ) + ;; NOMNL: (func $0 (result i32) + ;; NOMNL-NEXT: (i32.const 1337) + ;; NOMNL-NEXT: ) (func $0 (result i32) (i32.const 1337) ) @@ -54,6 +78,11 @@ ;; CHECK-NEXT: (i32.const 1337) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; NOMNL: (func $1 (result i32) + ;; NOMNL-NEXT: (block $__inlined_func$0 (result i32) + ;; NOMNL-NEXT: (i32.const 1337) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) (func $1 (result i32) (call $0) ) @@ -65,11 +94,17 @@ ;; CHECK: (type $none_=>_none (func)) ;; CHECK: (start $0) + ;; NOMNL: (type $none_=>_none (func_subtype func)) + + ;; NOMNL: (start $0) (start $0) ;; CHECK: (func $0 ;; CHECK-NEXT: (nop) ;; CHECK-NEXT: ) + ;; NOMNL: (func $0 + ;; NOMNL-NEXT: (nop) + ;; NOMNL-NEXT: ) (func $0 (nop) ) @@ -79,6 +114,11 @@ ;; CHECK-NEXT: (nop) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; NOMNL: (func $1 + ;; NOMNL-NEXT: (block $__inlined_func$0 + ;; NOMNL-NEXT: (nop) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) (func $1 (call $0) ) @@ -87,9 +127,11 @@ ;; inline a return_call_ref (module ;; CHECK: (type $none_=>_none (func)) + ;; NOMNL: (type $none_=>_none (func_subtype func)) (type $none_=>_none (func)) ;; CHECK: (export "func_36_invoker" (func $1)) + ;; NOMNL: (export "func_36_invoker" (func $1)) (export "func_36_invoker" (func $1)) (func $0 @@ -108,6 +150,17 @@ ;; CHECK-NEXT: (br $__inlined_func$0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; NOMNL: (func $1 + ;; NOMNL-NEXT: (block $__inlined_func$0 + ;; NOMNL-NEXT: (block + ;; NOMNL-NEXT: (call_ref + ;; NOMNL-NEXT: (ref.null $none_=>_none) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (br $__inlined_func$0) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (br $__inlined_func$0) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) (func $1 (call $0) ) @@ -134,6 +187,21 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; NOMNL: (type $none_=>_ref|func| (func_subtype (result (ref func)) func)) + + ;; NOMNL: (elem declare func $1) + + ;; NOMNL: (func $1 (result (ref func)) + ;; NOMNL-NEXT: (local $0 funcref) + ;; NOMNL-NEXT: (block $__inlined_func$0 (result (ref func)) + ;; NOMNL-NEXT: (local.set $0 + ;; NOMNL-NEXT: (ref.func $1) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (ref.as_non_null + ;; NOMNL-NEXT: (local.get $0) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) (func $1 (result (ref func)) (call $0 (ref.func $1) @@ -144,6 +212,7 @@ ;; never inline an rtt parameter, as those cannot be handled as locals (module ;; CHECK: (type $struct (struct )) + ;; NOMNL: (type $struct (struct_subtype data)) (type $struct (struct)) ;; CHECK: (type $rtt_$struct_=>_none (func (param (rtt $struct)))) @@ -152,6 +221,13 @@ ;; CHECK: (func $0 (param $rtt (rtt $struct)) ;; CHECK-NEXT: (nop) ;; CHECK-NEXT: ) + ;; NOMNL: (type $rtt_$struct_=>_none (func_subtype (param (rtt $struct)) func)) + + ;; NOMNL: (type $none_=>_none (func_subtype func)) + + ;; NOMNL: (func $0 (param $rtt (rtt $struct)) + ;; NOMNL-NEXT: (nop) + ;; NOMNL-NEXT: ) (func $0 (param $rtt (rtt $struct)) ) ;; CHECK: (func $1 @@ -159,6 +235,11 @@ ;; CHECK-NEXT: (rtt.canon $struct) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; NOMNL: (func $1 + ;; NOMNL-NEXT: (call $0 + ;; NOMNL-NEXT: (rtt.canon $struct) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) (func $1 (call $0 (rtt.canon $struct) diff --git a/test/lit/passes/instrument-memory-gc.wast b/test/lit/passes/instrument-memory-gc.wast index 1866bdcb8..bbc55ba77 100644 --- a/test/lit/passes/instrument-memory-gc.wast +++ b/test/lit/passes/instrument-memory-gc.wast @@ -1,7 +1,7 @@ ;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. ;; RUN: foreach %s %t wasm-opt --instrument-memory -all -S -o - | filecheck %s -;; RUN: foreach %s %t wasm-opt --instrument-memory --nominal -all -S -o - | filecheck %s +;; RUN: foreach %s %t wasm-opt --instrument-memory --nominal -all -S -o - | filecheck %s --check-prefix=NOMNL (module ;; CHECK: (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) @@ -13,6 +13,15 @@ ;; CHECK: (type $i32_f64_=>_f64 (func (param i32 f64) (result f64))) ;; CHECK: (type $struct (struct (field (mut i32)) (field f32) (field $named f64))) + ;; NOMNL: (type $i32_i32_=>_i32 (func_subtype (param i32 i32) (result i32) func)) + + ;; NOMNL: (type $i32_i64_=>_i64 (func_subtype (param i32 i64) (result i64) func)) + + ;; NOMNL: (type $i32_f32_=>_f32 (func_subtype (param i32 f32) (result f32) func)) + + ;; NOMNL: (type $i32_f64_=>_f64 (func_subtype (param i32 f64) (result f64) func)) + + ;; NOMNL: (type $struct (struct_subtype (field (mut i32)) (field f32) (field $named f64) data)) (type $struct (struct (field (mut i32)) (field f32) @@ -25,6 +34,13 @@ ;; CHECK: (type $ref|$array|_=>_none (func (param (ref $array)))) ;; CHECK: (type $array (array (mut f64))) + ;; NOMNL: (type $i32_i32_i32_i32_=>_i32 (func_subtype (param i32 i32 i32 i32) (result i32) func)) + + ;; NOMNL: (type $ref|$struct|_=>_none (func_subtype (param (ref $struct)) func)) + + ;; NOMNL: (type $ref|$array|_=>_none (func_subtype (param (ref $array)) func)) + + ;; NOMNL: (type $array (array_subtype (mut f64) data)) (type $array (array (mut f64))) ;; CHECK: (import "env" "load_ptr" (func $load_ptr (param i32 i32 i32 i32) (result i32))) @@ -116,6 +132,95 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; NOMNL: (import "env" "load_ptr" (func $load_ptr (param i32 i32 i32 i32) (result i32))) + + ;; NOMNL: (import "env" "load_val_i32" (func $load_val_i32 (param i32 i32) (result i32))) + + ;; NOMNL: (import "env" "load_val_i64" (func $load_val_i64 (param i32 i64) (result i64))) + + ;; NOMNL: (import "env" "load_val_f32" (func $load_val_f32 (param i32 f32) (result f32))) + + ;; NOMNL: (import "env" "load_val_f64" (func $load_val_f64 (param i32 f64) (result f64))) + + ;; NOMNL: (import "env" "store_ptr" (func $store_ptr (param i32 i32 i32 i32) (result i32))) + + ;; NOMNL: (import "env" "store_val_i32" (func $store_val_i32 (param i32 i32) (result i32))) + + ;; NOMNL: (import "env" "store_val_i64" (func $store_val_i64 (param i32 i64) (result i64))) + + ;; NOMNL: (import "env" "store_val_f32" (func $store_val_f32 (param i32 f32) (result f32))) + + ;; NOMNL: (import "env" "store_val_f64" (func $store_val_f64 (param i32 f64) (result f64))) + + ;; NOMNL: (import "env" "struct_get_val_i32" (func $struct_get_val_i32 (param i32 i32) (result i32))) + + ;; NOMNL: (import "env" "struct_get_val_i64" (func $struct_get_val_i64 (param i32 i64) (result i64))) + + ;; NOMNL: (import "env" "struct_get_val_f32" (func $struct_get_val_f32 (param i32 f32) (result f32))) + + ;; NOMNL: (import "env" "struct_get_val_f64" (func $struct_get_val_f64 (param i32 f64) (result f64))) + + ;; NOMNL: (import "env" "struct_set_val_i32" (func $struct_set_val_i32 (param i32 i32) (result i32))) + + ;; NOMNL: (import "env" "struct_set_val_i64" (func $struct_set_val_i64 (param i32 i64) (result i64))) + + ;; NOMNL: (import "env" "struct_set_val_f32" (func $struct_set_val_f32 (param i32 f32) (result f32))) + + ;; NOMNL: (import "env" "struct_set_val_f64" (func $struct_set_val_f64 (param i32 f64) (result f64))) + + ;; NOMNL: (import "env" "array_get_val_i32" (func $array_get_val_i32 (param i32 i32) (result i32))) + + ;; NOMNL: (import "env" "array_get_val_i64" (func $array_get_val_i64 (param i32 i64) (result i64))) + + ;; NOMNL: (import "env" "array_get_val_f32" (func $array_get_val_f32 (param i32 f32) (result f32))) + + ;; NOMNL: (import "env" "array_get_val_f64" (func $array_get_val_f64 (param i32 f64) (result f64))) + + ;; NOMNL: (import "env" "array_set_val_i32" (func $array_set_val_i32 (param i32 i32) (result i32))) + + ;; NOMNL: (import "env" "array_set_val_i64" (func $array_set_val_i64 (param i32 i64) (result i64))) + + ;; NOMNL: (import "env" "array_set_val_f32" (func $array_set_val_f32 (param i32 f32) (result f32))) + + ;; NOMNL: (import "env" "array_set_val_f64" (func $array_set_val_f64 (param i32 f64) (result f64))) + + ;; NOMNL: (import "env" "array_get_index" (func $array_get_index (param i32 i32) (result i32))) + + ;; NOMNL: (import "env" "array_set_index" (func $array_set_index (param i32 i32) (result i32))) + + ;; NOMNL: (func $structs (param $x (ref $struct)) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (call $struct_get_val_i32 + ;; NOMNL-NEXT: (i32.const 0) + ;; NOMNL-NEXT: (struct.get $struct 0 + ;; NOMNL-NEXT: (local.get $x) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (call $struct_get_val_f32 + ;; NOMNL-NEXT: (i32.const 1) + ;; NOMNL-NEXT: (struct.get $struct 1 + ;; NOMNL-NEXT: (local.get $x) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (call $struct_get_val_f64 + ;; NOMNL-NEXT: (i32.const 2) + ;; NOMNL-NEXT: (struct.get $struct $named + ;; NOMNL-NEXT: (local.get $x) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (struct.set $struct 0 + ;; NOMNL-NEXT: (local.get $x) + ;; NOMNL-NEXT: (call $struct_set_val_i32 + ;; NOMNL-NEXT: (i32.const 3) + ;; NOMNL-NEXT: (i32.const 42) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) (func $structs (param $x (ref $struct)) (drop (struct.get $struct 0 (local.get $x)) @@ -154,6 +259,31 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; NOMNL: (func $arrays (param $x (ref $array)) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (call $array_get_val_f64 + ;; NOMNL-NEXT: (i32.const 5) + ;; NOMNL-NEXT: (array.get $array + ;; NOMNL-NEXT: (local.get $x) + ;; NOMNL-NEXT: (call $array_get_index + ;; NOMNL-NEXT: (i32.const 4) + ;; NOMNL-NEXT: (i32.const 10) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (array.set $array + ;; NOMNL-NEXT: (local.get $x) + ;; NOMNL-NEXT: (call $array_set_index + ;; NOMNL-NEXT: (i32.const 6) + ;; NOMNL-NEXT: (i32.const 42) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (call $array_set_val_f64 + ;; NOMNL-NEXT: (i32.const 7) + ;; NOMNL-NEXT: (f64.const 3.14159) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) (func $arrays (param $x (ref $array)) (drop (array.get $array (local.get $x) (i32.const 10)) diff --git a/test/lit/passes/local-subtyping-nn.wast b/test/lit/passes/local-subtyping-nn.wast index bcf13f7c2..290fe032d 100644 --- a/test/lit/passes/local-subtyping-nn.wast +++ b/test/lit/passes/local-subtyping-nn.wast @@ -2,13 +2,15 @@ ;; RUN: wasm-opt %s --local-subtyping -all --enable-gc-nn-locals -S -o - \ ;; RUN: | filecheck %s ;; RUN: wasm-opt %s --local-subtyping -all --enable-gc-nn-locals --nominal -S -o - \ -;; RUN: | filecheck %s +;; RUN: | filecheck %s --check-prefix=NOMNL (module ;; CHECK: (type $struct (struct )) + ;; NOMNL: (type $struct (struct_subtype data)) (type $struct (struct)) ;; CHECK: (import "out" "i32" (func $i32 (result i32))) + ;; NOMNL: (import "out" "i32" (func $i32 (result i32))) (import "out" "i32" (func $i32 (result i32))) ;; CHECK: (func $non-nullable @@ -26,6 +28,21 @@ ;; CHECK-NEXT: (local.get $x) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; NOMNL: (func $non-nullable + ;; NOMNL-NEXT: (local $x (ref $struct)) + ;; NOMNL-NEXT: (local $y (ref $none_=>_i32)) + ;; NOMNL-NEXT: (local.set $x + ;; NOMNL-NEXT: (ref.as_non_null + ;; NOMNL-NEXT: (ref.null $struct) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.set $y + ;; NOMNL-NEXT: (ref.func $i32) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (local.get $x) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) (func $non-nullable (local $x (ref null $struct)) (local $y anyref) @@ -58,6 +75,20 @@ ;; CHECK-NEXT: (local.get $x) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; NOMNL: (func $uses-default (param $i i32) + ;; NOMNL-NEXT: (local $x (ref null $struct)) + ;; NOMNL-NEXT: (if + ;; NOMNL-NEXT: (local.get $i) + ;; NOMNL-NEXT: (local.set $x + ;; NOMNL-NEXT: (ref.as_non_null + ;; NOMNL-NEXT: (ref.null $struct) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (local.get $x) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) (func $uses-default (param $i i32) (local $x (ref null any)) (if diff --git a/test/lit/passes/name-types.wast b/test/lit/passes/name-types.wast index 39cc00423..12fe549ea 100644 --- a/test/lit/passes/name-types.wast +++ b/test/lit/passes/name-types.wast @@ -1,6 +1,6 @@ ;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. ;; RUN: wasm-opt %s -all --name-types -S -o - | filecheck %s -;; RUN: wasm-opt %s -all --name-types --nominal -S -o - | filecheck %s +;; RUN: wasm-opt %s -all --name-types --nominal -S -o - | filecheck %s --check-prefix=NOMNL (module ;; An obnoxious name that will be renamed. @@ -12,11 +12,19 @@ ;; CHECK: (type $type$1 (struct )) ;; CHECK: (type $reasonable-name (struct (field i32))) + ;; NOMNL: (type $type$0 (func_subtype (param (ref $type$1) (ref $reasonable-name)) func)) + + ;; NOMNL: (type $type$1 (struct_subtype data)) + + ;; NOMNL: (type $reasonable-name (struct_subtype (field i32) data)) (type $reasonable-name (struct (field i32))) ;; CHECK: (func $foo (param $x (ref $type$1)) (param $y (ref $reasonable-name)) ;; CHECK-NEXT: (nop) ;; CHECK-NEXT: ) + ;; NOMNL: (func $foo (param $x (ref $type$1)) (param $y (ref $reasonable-name)) + ;; NOMNL-NEXT: (nop) + ;; NOMNL-NEXT: ) (func $foo ;; Use the types to keep them alive. (param $x (ref $obnoxious-super-long-type-name_____________________________1)) diff --git a/test/lit/passes/optimize-instructions-call_ref-roundtrip.wast b/test/lit/passes/optimize-instructions-call_ref-roundtrip.wast index 5bbec4b64..0477abe79 100644 --- a/test/lit/passes/optimize-instructions-call_ref-roundtrip.wast +++ b/test/lit/passes/optimize-instructions-call_ref-roundtrip.wast @@ -10,16 +10,16 @@ ;; distinct nominally. The three tables will use different ones, and the ;; emitted call_indirects should use the corresponding ones. - ;; CHECK: (type $v1 (func)) + ;; CHECK: (type $v1 (func_subtype func)) (type $v1 (func)) - ;; CHECK: (type $v2 (func)) + ;; CHECK: (type $v2 (func_subtype func)) (type $v2 (func)) - ;; CHECK: (type $v3 (func)) + ;; CHECK: (type $v3 (func_subtype func)) (type $v3 (func)) - ;; CHECK: (type $i32_=>_none (func (param i32))) + ;; CHECK: (type $i32_=>_none (func_subtype (param i32) func)) ;; CHECK: (table $table-1 10 (ref null $v1)) (table $table-1 10 (ref null $v1)) diff --git a/test/lit/passes/optimize-instructions-gc-iit.wast b/test/lit/passes/optimize-instructions-gc-iit.wast index d6bb9eb31..9923bf89b 100644 --- a/test/lit/passes/optimize-instructions-gc-iit.wast +++ b/test/lit/passes/optimize-instructions-gc-iit.wast @@ -9,16 +9,16 @@ (module ;; CHECK: (type $parent (struct (field i32))) - ;; NOMNL: (type $parent (struct (field i32))) - ;; NOMNL-TNH: (type $parent (struct (field i32))) + ;; NOMNL: (type $parent (struct_subtype (field i32) data)) + ;; NOMNL-TNH: (type $parent (struct_subtype (field i32) data)) (type $parent (struct (field i32))) ;; CHECK: (type $child (struct (field i32) (field f64))) - ;; NOMNL: (type $child (struct (field i32) (field f64)) (extends $parent)) - ;; NOMNL-TNH: (type $child (struct (field i32) (field f64)) (extends $parent)) - (type $child (struct (field i32) (field f64)) (extends $parent)) + ;; NOMNL: (type $child (struct_subtype (field i32) (field f64) $parent)) + ;; NOMNL-TNH: (type $child (struct_subtype (field i32) (field f64) $parent)) + (type $child (struct_subtype (field i32) (field f64) $parent)) ;; CHECK: (type $other (struct (field i64) (field f32))) - ;; NOMNL: (type $other (struct (field i64) (field f32))) - ;; NOMNL-TNH: (type $other (struct (field i64) (field f32))) + ;; NOMNL: (type $other (struct_subtype (field i64) (field f32) data)) + ;; NOMNL-TNH: (type $other (struct_subtype (field i64) (field f32) data)) (type $other (struct (field i64) (field f32))) ;; CHECK: (func $foo diff --git a/test/lit/passes/optimize-instructions-gc.wast b/test/lit/passes/optimize-instructions-gc.wast index ab973ffae..47d2a17bc 100644 --- a/test/lit/passes/optimize-instructions-gc.wast +++ b/test/lit/passes/optimize-instructions-gc.wast @@ -6,7 +6,7 @@ (module ;; CHECK: (type $struct (struct (field $i8 (mut i8)) (field $i16 (mut i16)) (field $i32 (mut i32)) (field $i64 (mut i64)))) - ;; NOMNL: (type $struct (struct (field $i8 (mut i8)) (field $i16 (mut i16)) (field $i32 (mut i32)) (field $i64 (mut i64)))) + ;; NOMNL: (type $struct (struct_subtype (field $i8 (mut i8)) (field $i16 (mut i16)) (field $i32 (mut i32)) (field $i64 (mut i64)) data)) (type $struct (struct (field $i8 (mut i8)) (field $i16 (mut i16)) @@ -15,28 +15,28 @@ )) ;; CHECK: (type $A (struct (field i32))) - ;; NOMNL: (type $A (struct (field i32))) + ;; NOMNL: (type $A (struct_subtype (field i32) data)) (type $A (struct (field i32))) ;; CHECK: (type $array (array (mut i8))) - ;; NOMNL: (type $array (array (mut i8))) + ;; NOMNL: (type $array (array_subtype (mut i8) data)) (type $array (array (mut i8))) ;; CHECK: (type $B (struct (field i32) (field i32) (field f32))) - ;; NOMNL: (type $B (struct (field i32) (field i32) (field f32)) (extends $A)) - (type $B (struct (field i32) (field i32) (field f32)) (extends $A)) + ;; NOMNL: (type $B (struct_subtype (field i32) (field i32) (field f32) $A)) + (type $B (struct_subtype (field i32) (field i32) (field f32) $A)) ;; CHECK: (type $B-child (struct (field i32) (field i32) (field f32) (field i64))) - ;; NOMNL: (type $B-child (struct (field i32) (field i32) (field f32) (field i64)) (extends $B)) - (type $B-child (struct (field i32) (field i32) (field f32) (field i64)) (extends $B)) + ;; NOMNL: (type $B-child (struct_subtype (field i32) (field i32) (field f32) (field i64) $B)) + (type $B-child (struct_subtype (field i32) (field i32) (field f32) (field i64) $B)) ;; CHECK: (type $empty (struct )) - ;; NOMNL: (type $empty (struct )) + ;; NOMNL: (type $empty (struct_subtype data)) (type $empty (struct)) ;; CHECK: (type $C (struct (field i32) (field i32) (field f64))) - ;; NOMNL: (type $C (struct (field i32) (field i32) (field f64)) (extends $A)) - (type $C (struct (field i32) (field i32) (field f64)) (extends $A)) + ;; NOMNL: (type $C (struct_subtype (field i32) (field i32) (field f64) $A)) + (type $C (struct_subtype (field i32) (field i32) (field f64) $A)) ;; CHECK: (import "env" "get-i32" (func $get-i32 (result i32))) ;; NOMNL: (import "env" "get-i32" (func $get-i32 (result i32))) diff --git a/test/lit/passes/precompute-gc.wast b/test/lit/passes/precompute-gc.wast index c12e86635..2d50fcaa6 100644 --- a/test/lit/passes/precompute-gc.wast +++ b/test/lit/passes/precompute-gc.wast @@ -2,24 +2,29 @@ ;; RUN: wasm-opt %s --remove-unused-names --precompute-propagate --fuzz-exec -all -S -o - \ ;; RUN: | filecheck %s ;; RUN: wasm-opt %s --remove-unused-names --precompute-propagate --fuzz-exec -all --nominal -S -o - \ -;; RUN: | filecheck %s +;; RUN: | filecheck %s --check-prefix=NOMNL (module ;; CHECK: (type $empty (struct )) + ;; NOMNL: (type $empty (struct_subtype data)) + (type $empty (struct)) ;; CHECK: (type $struct (struct (field (mut i32)))) + ;; NOMNL: (type $struct (struct_subtype (field (mut i32)) data)) (type $struct (struct (mut i32))) - (type $empty (struct)) ;; two incompatible struct types (type $A (struct (field (mut f32)))) ;; CHECK: (type $B (struct (field (mut f64)))) + ;; NOMNL: (type $B (struct_subtype (field (mut f64)) data)) (type $B (struct (field (mut f64)))) ;; CHECK: (type $func-return-i32 (func (result i32))) + ;; NOMNL: (type $func-return-i32 (func_subtype (result i32) func)) (type $func-return-i32 (func (result i32))) ;; CHECK: (import "fuzzing-support" "log-i32" (func $log (param i32))) + ;; NOMNL: (import "fuzzing-support" "log-i32" (func $log (param i32))) (import "fuzzing-support" "log-i32" (func $log (param i32))) ;; CHECK: (func $test-fallthrough (result i32) @@ -34,6 +39,18 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) + ;; NOMNL: (func $test-fallthrough (result i32) + ;; NOMNL-NEXT: (local $x funcref) + ;; NOMNL-NEXT: (local.set $x + ;; NOMNL-NEXT: (block (result funcref) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (call $test-fallthrough) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (ref.null func) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (i32.const 1) + ;; NOMNL-NEXT: ) (func $test-fallthrough (result i32) (local $x funcref) (local.set $x @@ -88,6 +105,40 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; NOMNL: (func $load-from-struct + ;; NOMNL-NEXT: (local $x (ref null $struct)) + ;; NOMNL-NEXT: (local.set $x + ;; NOMNL-NEXT: (struct.new_with_rtt $struct + ;; NOMNL-NEXT: (i32.const 1) + ;; NOMNL-NEXT: (rtt.canon $struct) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (call $log + ;; NOMNL-NEXT: (struct.get $struct 0 + ;; NOMNL-NEXT: (local.get $x) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.set $x + ;; NOMNL-NEXT: (struct.new_with_rtt $struct + ;; NOMNL-NEXT: (i32.const 2) + ;; NOMNL-NEXT: (rtt.canon $struct) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (call $log + ;; NOMNL-NEXT: (struct.get $struct 0 + ;; NOMNL-NEXT: (local.get $x) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (struct.set $struct 0 + ;; NOMNL-NEXT: (local.get $x) + ;; NOMNL-NEXT: (i32.const 3) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (call $log + ;; NOMNL-NEXT: (struct.get $struct 0 + ;; NOMNL-NEXT: (local.get $x) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) (func $load-from-struct (local $x (ref null $struct)) (local.set $x @@ -143,6 +194,29 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; NOMNL: (func $load-from-struct-bad-merge (param $i i32) + ;; NOMNL-NEXT: (local $x (ref null $struct)) + ;; NOMNL-NEXT: (if + ;; NOMNL-NEXT: (local.get $i) + ;; NOMNL-NEXT: (local.set $x + ;; NOMNL-NEXT: (struct.new_with_rtt $struct + ;; NOMNL-NEXT: (i32.const 1) + ;; NOMNL-NEXT: (rtt.canon $struct) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.set $x + ;; NOMNL-NEXT: (struct.new_with_rtt $struct + ;; NOMNL-NEXT: (i32.const 2) + ;; NOMNL-NEXT: (rtt.canon $struct) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (call $log + ;; NOMNL-NEXT: (struct.get $struct 0 + ;; NOMNL-NEXT: (local.get $x) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) (func $load-from-struct-bad-merge (param $i i32) (local $x (ref null $struct)) ;; a merge of two different $x values cannot be precomputed @@ -176,6 +250,17 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; NOMNL: (func $modify-gc-heap (param $x (ref null $struct)) + ;; NOMNL-NEXT: (struct.set $struct 0 + ;; NOMNL-NEXT: (local.get $x) + ;; NOMNL-NEXT: (i32.add + ;; NOMNL-NEXT: (struct.get $struct 0 + ;; NOMNL-NEXT: (local.get $x) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (i32.const 1) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) (func $modify-gc-heap (param $x (ref null $struct)) (struct.set $struct 0 (local.get $x) @@ -206,6 +291,23 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; NOMNL: (func $load-from-struct-bad-escape + ;; NOMNL-NEXT: (local $x (ref null $struct)) + ;; NOMNL-NEXT: (local.set $x + ;; NOMNL-NEXT: (struct.new_with_rtt $struct + ;; NOMNL-NEXT: (i32.const 1) + ;; NOMNL-NEXT: (rtt.canon $struct) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (call $modify-gc-heap + ;; NOMNL-NEXT: (local.get $x) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (call $log + ;; NOMNL-NEXT: (struct.get $struct 0 + ;; NOMNL-NEXT: (local.get $x) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) (func $load-from-struct-bad-escape (export "test") (local $x (ref null $struct)) (local.set $x @@ -228,6 +330,13 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; NOMNL: (func $load-from-struct-bad-arrive (param $x (ref null $struct)) + ;; NOMNL-NEXT: (call $log + ;; NOMNL-NEXT: (struct.get $struct 0 + ;; NOMNL-NEXT: (local.get $x) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) (func $load-from-struct-bad-arrive (param $x (ref null $struct)) ;; a parameter cannot be precomputed (call $log @@ -259,6 +368,31 @@ ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; NOMNL: (func $ref-comparisons (param $x (ref null $struct)) (param $y (ref null $struct)) + ;; NOMNL-NEXT: (local $z (ref null $struct)) + ;; NOMNL-NEXT: (local $w (ref null $struct)) + ;; NOMNL-NEXT: (call $log + ;; NOMNL-NEXT: (ref.eq + ;; NOMNL-NEXT: (local.get $x) + ;; NOMNL-NEXT: (local.get $y) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (call $log + ;; NOMNL-NEXT: (ref.eq + ;; NOMNL-NEXT: (local.get $x) + ;; NOMNL-NEXT: (ref.null $struct) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (call $log + ;; NOMNL-NEXT: (ref.eq + ;; NOMNL-NEXT: (local.get $x) + ;; NOMNL-NEXT: (ref.null $struct) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (call $log + ;; NOMNL-NEXT: (i32.const 1) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) (func $ref-comparisons (param $x (ref null $struct)) (param $y (ref null $struct)) @@ -310,6 +444,24 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) + ;; NOMNL: (func $new-ref-comparisons (result i32) + ;; NOMNL-NEXT: (local $x (ref null $struct)) + ;; NOMNL-NEXT: (local $y (ref null $struct)) + ;; NOMNL-NEXT: (local $tempresult i32) + ;; NOMNL-NEXT: (local.set $x + ;; NOMNL-NEXT: (struct.new_with_rtt $struct + ;; NOMNL-NEXT: (i32.const 1) + ;; NOMNL-NEXT: (rtt.canon $struct) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.set $y + ;; NOMNL-NEXT: (local.get $x) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.set $tempresult + ;; NOMNL-NEXT: (i32.const 1) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (i32.const 1) + ;; NOMNL-NEXT: ) (func $new-ref-comparisons (result i32) (local $x (ref null $struct)) (local $y (ref null $struct)) @@ -349,6 +501,21 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) + ;; NOMNL: (func $propagate-equal (result i32) + ;; NOMNL-NEXT: (local $tempresult i32) + ;; NOMNL-NEXT: (local $tempref (ref null $empty)) + ;; NOMNL-NEXT: (local.set $tempresult + ;; NOMNL-NEXT: (ref.eq + ;; NOMNL-NEXT: (local.tee $tempref + ;; NOMNL-NEXT: (struct.new_default_with_rtt $empty + ;; NOMNL-NEXT: (rtt.canon $empty) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.get $tempref) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (i32.const 1) + ;; NOMNL-NEXT: ) (func $propagate-equal (result i32) (local $tempresult i32) (local $tempref (ref null $empty)) @@ -376,6 +543,14 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) + ;; NOMNL: (func $propagate-unequal (result i32) + ;; NOMNL-NEXT: (local $tempresult i32) + ;; NOMNL-NEXT: (local $tempref (ref null $empty)) + ;; NOMNL-NEXT: (local.set $tempresult + ;; NOMNL-NEXT: (i32.const 0) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (i32.const 0) + ;; NOMNL-NEXT: ) (func $propagate-unequal (result i32) (local $tempresult i32) (local $tempref (ref null $empty)) @@ -410,6 +585,19 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.get $tempresult) ;; CHECK-NEXT: ) + ;; NOMNL: (func $propagate-uncertain-param (param $input (ref $empty)) (result i32) + ;; NOMNL-NEXT: (local $tempresult i32) + ;; NOMNL-NEXT: (local $tempref (ref null $empty)) + ;; NOMNL-NEXT: (local.set $tempresult + ;; NOMNL-NEXT: (ref.eq + ;; NOMNL-NEXT: (struct.new_default_with_rtt $empty + ;; NOMNL-NEXT: (rtt.canon $empty) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.get $input) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.get $tempresult) + ;; NOMNL-NEXT: ) (func $propagate-uncertain-param (param $input (ref $empty)) (result i32) (local $tempresult i32) (local $tempref (ref null $empty)) @@ -436,6 +624,16 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.get $tempresult) ;; CHECK-NEXT: ) + ;; NOMNL: (func $propagate-different-params (param $input1 (ref $empty)) (param $input2 (ref $empty)) (result i32) + ;; NOMNL-NEXT: (local $tempresult i32) + ;; NOMNL-NEXT: (local.set $tempresult + ;; NOMNL-NEXT: (ref.eq + ;; NOMNL-NEXT: (local.get $input1) + ;; NOMNL-NEXT: (local.get $input2) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.get $tempresult) + ;; NOMNL-NEXT: ) (func $propagate-different-params (param $input1 (ref $empty)) (param $input2 (ref $empty)) (result i32) (local $tempresult i32) (local.set $tempresult @@ -458,6 +656,16 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.get $tempresult) ;; CHECK-NEXT: ) + ;; NOMNL: (func $propagate-same-param (param $input (ref $empty)) (result i32) + ;; NOMNL-NEXT: (local $tempresult i32) + ;; NOMNL-NEXT: (local.set $tempresult + ;; NOMNL-NEXT: (ref.eq + ;; NOMNL-NEXT: (local.get $input) + ;; NOMNL-NEXT: (local.get $input) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.get $tempresult) + ;; NOMNL-NEXT: ) (func $propagate-same-param (param $input (ref $empty)) (result i32) (local $tempresult i32) (local.set $tempresult @@ -501,6 +709,36 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.get $tempresult) ;; CHECK-NEXT: ) + ;; NOMNL: (func $propagate-uncertain-local (result i32) + ;; NOMNL-NEXT: (local $tempresult i32) + ;; NOMNL-NEXT: (local $tempref (ref null $empty)) + ;; NOMNL-NEXT: (local $stashedref (ref null $empty)) + ;; NOMNL-NEXT: (local.set $tempref + ;; NOMNL-NEXT: (struct.new_default_with_rtt $empty + ;; NOMNL-NEXT: (rtt.canon $empty) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.set $stashedref + ;; NOMNL-NEXT: (local.get $tempref) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (if + ;; NOMNL-NEXT: (call $helper + ;; NOMNL-NEXT: (i32.const 0) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.set $tempref + ;; NOMNL-NEXT: (struct.new_default_with_rtt $empty + ;; NOMNL-NEXT: (rtt.canon $empty) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.set $tempresult + ;; NOMNL-NEXT: (ref.eq + ;; NOMNL-NEXT: (local.get $tempref) + ;; NOMNL-NEXT: (local.get $stashedref) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.get $tempresult) + ;; NOMNL-NEXT: ) (func $propagate-uncertain-local (result i32) (local $tempresult i32) (local $tempref (ref null $empty)) @@ -565,6 +803,37 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; NOMNL: (func $propagate-uncertain-loop + ;; NOMNL-NEXT: (local $tempresult i32) + ;; NOMNL-NEXT: (local $tempref (ref null $empty)) + ;; NOMNL-NEXT: (local $stashedref (ref null $empty)) + ;; NOMNL-NEXT: (local.set $tempref + ;; NOMNL-NEXT: (struct.new_default_with_rtt $empty + ;; NOMNL-NEXT: (rtt.canon $empty) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.set $stashedref + ;; NOMNL-NEXT: (local.get $tempref) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (loop $loop + ;; NOMNL-NEXT: (local.set $tempresult + ;; NOMNL-NEXT: (ref.eq + ;; NOMNL-NEXT: (local.get $tempref) + ;; NOMNL-NEXT: (local.get $stashedref) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.set $tempref + ;; NOMNL-NEXT: (struct.new_default_with_rtt $empty + ;; NOMNL-NEXT: (rtt.canon $empty) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (br_if $loop + ;; NOMNL-NEXT: (call $helper + ;; NOMNL-NEXT: (local.get $tempresult) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) (func $propagate-uncertain-loop (local $tempresult i32) (local $tempref (ref null $empty)) @@ -622,6 +891,29 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; NOMNL: (func $propagate-certain-loop + ;; NOMNL-NEXT: (local $tempresult i32) + ;; NOMNL-NEXT: (local $tempref (ref null $empty)) + ;; NOMNL-NEXT: (local $stashedref (ref null $empty)) + ;; NOMNL-NEXT: (local.set $tempref + ;; NOMNL-NEXT: (struct.new_default_with_rtt $empty + ;; NOMNL-NEXT: (rtt.canon $empty) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.set $stashedref + ;; NOMNL-NEXT: (local.get $tempref) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (loop $loop + ;; NOMNL-NEXT: (local.set $tempresult + ;; NOMNL-NEXT: (i32.const 1) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (br_if $loop + ;; NOMNL-NEXT: (call $helper + ;; NOMNL-NEXT: (i32.const 1) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) (func $propagate-certain-loop (local $tempresult i32) (local $tempref (ref null $empty)) @@ -674,6 +966,29 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; NOMNL: (func $propagate-certain-loop-2 + ;; NOMNL-NEXT: (local $tempresult i32) + ;; NOMNL-NEXT: (local $tempref (ref null $empty)) + ;; NOMNL-NEXT: (local $stashedref (ref null $empty)) + ;; NOMNL-NEXT: (loop $loop + ;; NOMNL-NEXT: (local.set $tempref + ;; NOMNL-NEXT: (struct.new_default_with_rtt $empty + ;; NOMNL-NEXT: (rtt.canon $empty) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.set $stashedref + ;; NOMNL-NEXT: (local.get $tempref) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.set $tempresult + ;; NOMNL-NEXT: (i32.const 1) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (br_if $loop + ;; NOMNL-NEXT: (call $helper + ;; NOMNL-NEXT: (i32.const 1) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) (func $propagate-certain-loop-2 (local $tempresult i32) (local $tempref (ref null $empty)) @@ -734,6 +1049,37 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; NOMNL: (func $propagate-possibly-certain-loop + ;; NOMNL-NEXT: (local $tempresult i32) + ;; NOMNL-NEXT: (local $tempref (ref null $empty)) + ;; NOMNL-NEXT: (local $stashedref (ref null $empty)) + ;; NOMNL-NEXT: (loop $loop + ;; NOMNL-NEXT: (if + ;; NOMNL-NEXT: (call $helper + ;; NOMNL-NEXT: (i32.const 0) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.set $tempref + ;; NOMNL-NEXT: (struct.new_default_with_rtt $empty + ;; NOMNL-NEXT: (rtt.canon $empty) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.set $stashedref + ;; NOMNL-NEXT: (local.get $tempref) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.set $tempresult + ;; NOMNL-NEXT: (ref.eq + ;; NOMNL-NEXT: (local.get $tempref) + ;; NOMNL-NEXT: (local.get $stashedref) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (br_if $loop + ;; NOMNL-NEXT: (call $helper + ;; NOMNL-NEXT: (local.get $tempresult) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) (func $propagate-possibly-certain-loop (local $tempresult i32) (local $tempref (ref null $empty)) @@ -773,6 +1119,9 @@ ;; CHECK: (func $helper (param $0 i32) (result i32) ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) + ;; NOMNL: (func $helper (param $0 i32) (result i32) + ;; NOMNL-NEXT: (unreachable) + ;; NOMNL-NEXT: ) (func $helper (param i32) (result i32) (unreachable) ) @@ -788,6 +1137,17 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; NOMNL: (func $odd-cast-and-get + ;; NOMNL-NEXT: (local $temp (ref null $B)) + ;; NOMNL-NEXT: (local.set $temp + ;; NOMNL-NEXT: (ref.null $B) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (struct.get $B 0 + ;; NOMNL-NEXT: (ref.null $B) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) (func $odd-cast-and-get (local $temp (ref null $B)) ;; Try to cast a null of A to B. While the types are incompatible, ref.cast @@ -823,6 +1183,20 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; NOMNL: (func $odd-cast-and-get-tuple + ;; NOMNL-NEXT: (local $temp ((ref null $B) i32)) + ;; NOMNL-NEXT: (local.set $temp + ;; NOMNL-NEXT: (tuple.make + ;; NOMNL-NEXT: (ref.null $B) + ;; NOMNL-NEXT: (i32.const 10) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (struct.get $B 0 + ;; NOMNL-NEXT: (ref.null $B) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) (func $odd-cast-and-get-tuple (local $temp ((ref null $B) i32)) ;; As above, but with a tuple. @@ -847,6 +1221,9 @@ ;; CHECK: (func $receive-f64 (param $0 f64) ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) + ;; NOMNL: (func $receive-f64 (param $0 f64) + ;; NOMNL-NEXT: (unreachable) + ;; NOMNL-NEXT: ) (func $receive-f64 (param f64) (unreachable) ) @@ -864,6 +1241,19 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; NOMNL: (func $odd-cast-and-get-non-null (param $temp (ref $func-return-i32)) + ;; NOMNL-NEXT: (local.set $temp + ;; NOMNL-NEXT: (ref.cast + ;; NOMNL-NEXT: (ref.func $receive-f64) + ;; NOMNL-NEXT: (rtt.canon $func-return-i32) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (call_ref + ;; NOMNL-NEXT: (local.get $temp) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) (func $odd-cast-and-get-non-null (param $temp (ref $func-return-i32)) ;; Try to cast a function to an incompatible type. (local.set $temp @@ -889,6 +1279,14 @@ ;; CHECK-NEXT: (rtt.canon $struct) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; NOMNL: (func $new_block_unreachable (result anyref) + ;; NOMNL-NEXT: (block + ;; NOMNL-NEXT: (block + ;; NOMNL-NEXT: (unreachable) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (rtt.canon $struct) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) (func $new_block_unreachable (result anyref) (struct.new_with_rtt $struct ;; The value is a block with an unreachable. precompute will get rid of the @@ -914,6 +1312,19 @@ ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; NOMNL: (func $br_on_cast-on-creation-rtt (result (ref $empty)) + ;; NOMNL-NEXT: (block $label (result (ref $empty)) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (br_on_cast $label + ;; NOMNL-NEXT: (struct.new_default_with_rtt $empty + ;; NOMNL-NEXT: (rtt.canon $empty) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (rtt.canon $empty) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (unreachable) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) (func $br_on_cast-on-creation-rtt (result (ref $empty)) (block $label (result (ref $empty)) (drop @@ -941,6 +1352,16 @@ ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; NOMNL: (func $br_on_cast-on-creation-nortt (result (ref $empty)) + ;; NOMNL-NEXT: (block $label (result (ref $empty)) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (br_on_cast_static $label $empty + ;; NOMNL-NEXT: (struct.new_default $empty) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (unreachable) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) (func $br_on_cast-on-creation-nortt (result (ref $empty)) (block $label (result (ref $empty)) (drop @@ -985,6 +1406,38 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; NOMNL: (func $ref.is_null (param $param i32) + ;; NOMNL-NEXT: (local $ref (ref null $empty)) + ;; NOMNL-NEXT: (local.set $ref + ;; NOMNL-NEXT: (struct.new_default $empty) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (call $helper + ;; NOMNL-NEXT: (i32.const 0) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.set $ref + ;; NOMNL-NEXT: (ref.null $empty) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (call $helper + ;; NOMNL-NEXT: (i32.const 1) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (if + ;; NOMNL-NEXT: (local.get $param) + ;; NOMNL-NEXT: (local.set $ref + ;; NOMNL-NEXT: (struct.new_default $empty) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (call $helper + ;; NOMNL-NEXT: (ref.is_null + ;; NOMNL-NEXT: (local.get $ref) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) (func $ref.is_null (param $param i32) (local $ref (ref null $empty)) ;; Test ref.null on references, and also test that we can infer multiple diff --git a/test/lit/passes/roundtrip-gc-types.wast b/test/lit/passes/roundtrip-gc-types.wast index c5ed84d54..d14415f3b 100644 --- a/test/lit/passes/roundtrip-gc-types.wast +++ b/test/lit/passes/roundtrip-gc-types.wast @@ -8,19 +8,19 @@ (module ;; CHECK: (type $A (struct (field (ref $C)))) - ;; NOMNL: (type $A (struct (field (ref $C)))) + ;; NOMNL: (type $A (struct_subtype (field (ref $C)) data)) (type $A (struct (field (ref $C)))) ;; CHECK: (type $C (struct (field (mut (ref $B))))) ;; CHECK: (type $B (func (param (ref $A)) (result (ref $B)))) - ;; NOMNL: (type $C (struct (field (mut (ref $B))))) + ;; NOMNL: (type $C (struct_subtype (field (mut (ref $B))) data)) - ;; NOMNL: (type $B (func (param (ref $A)) (result (ref $B)))) + ;; NOMNL: (type $B (func_subtype (param (ref $A)) (result (ref $B)) func)) (type $B (func (param (ref $A)) (result (ref $B)))) (type $C (struct (field (mut (ref $B))))) ;; CHECK: (type $D (struct (field (ref $C)) (field (ref $A)))) - ;; NOMNL: (type $D (struct (field (ref $C)) (field (ref $A))) (extends $A)) - (type $D (struct (field (ref $C)) (field (ref $A))) (extends $A)) + ;; NOMNL: (type $D (struct_subtype (field (ref $C)) (field (ref $A)) $A)) + (type $D (struct_subtype (field (ref $C)) (field (ref $A)) $A)) ;; CHECK: (global $g0 (rtt 0 $A) (rtt.canon $A)) ;; NOMNL: (global $g0 (rtt 0 $A) (rtt.canon $A)) (global $g0 (rtt 0 $A) (rtt.canon $A)) diff --git a/test/lit/passes/simplify-locals-gc.wast b/test/lit/passes/simplify-locals-gc.wast index 97891aca4..380bcc16b 100644 --- a/test/lit/passes/simplify-locals-gc.wast +++ b/test/lit/passes/simplify-locals-gc.wast @@ -2,13 +2,15 @@ ;; RUN: wasm-opt %s --simplify-locals -all -S -o - \ ;; RUN: | filecheck %s ;; RUN: wasm-opt %s --simplify-locals -all --nominal -S -o - \ -;; RUN: | filecheck %s +;; RUN: | filecheck %s --check-prefix=NOMNL (module ;; CHECK: (type $struct (struct (field (mut i32)))) + ;; NOMNL: (type $struct (struct_subtype (field (mut i32)) data)) (type $struct (struct (field (mut i32)))) ;; CHECK: (type $struct-immutable (struct (field i32))) + ;; NOMNL: (type $struct-immutable (struct_subtype (field i32) data)) (type $struct-immutable (struct (field i32))) ;; Writes to heap objects cannot be reordered with reads. @@ -25,6 +27,19 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.get $temp) ;; CHECK-NEXT: ) + ;; NOMNL: (func $no-reorder-past-write (param $x (ref $struct)) (result i32) + ;; NOMNL-NEXT: (local $temp i32) + ;; NOMNL-NEXT: (local.set $temp + ;; NOMNL-NEXT: (struct.get $struct 0 + ;; NOMNL-NEXT: (local.get $x) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (struct.set $struct 0 + ;; NOMNL-NEXT: (local.get $x) + ;; NOMNL-NEXT: (i32.const 42) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.get $temp) + ;; NOMNL-NEXT: ) (func $no-reorder-past-write (param $x (ref $struct)) (result i32) (local $temp i32) (local.set $temp @@ -50,6 +65,17 @@ ;; CHECK-NEXT: (local.get $y) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; NOMNL: (func $reorder-past-write-if-immutable (param $x (ref $struct)) (param $y (ref $struct-immutable)) (result i32) + ;; NOMNL-NEXT: (local $temp i32) + ;; NOMNL-NEXT: (nop) + ;; NOMNL-NEXT: (struct.set $struct 0 + ;; NOMNL-NEXT: (local.get $x) + ;; NOMNL-NEXT: (i32.const 42) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (struct.get $struct-immutable 0 + ;; NOMNL-NEXT: (local.get $y) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) (func $reorder-past-write-if-immutable (param $x (ref $struct)) (param $y (ref $struct-immutable)) (result i32) (local $temp i32) (local.set $temp @@ -79,6 +105,21 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.get $temp) ;; CHECK-NEXT: ) + ;; NOMNL: (func $unreachable-struct.get (param $x (ref $struct)) (param $y (ref $struct-immutable)) (result i32) + ;; NOMNL-NEXT: (local $temp i32) + ;; NOMNL-NEXT: (local.tee $temp + ;; NOMNL-NEXT: (block ;; (replaces something unreachable we can't emit) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (unreachable) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (struct.set $struct 0 + ;; NOMNL-NEXT: (local.get $x) + ;; NOMNL-NEXT: (i32.const 42) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.get $temp) + ;; NOMNL-NEXT: ) (func $unreachable-struct.get (param $x (ref $struct)) (param $y (ref $struct-immutable)) (result i32) (local $temp i32) ;; As above, but the get's ref is unreachable. This tests we do not hit an @@ -119,6 +160,28 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; NOMNL: (func $no-block-values-if-br_on + ;; NOMNL-NEXT: (local $temp anyref) + ;; NOMNL-NEXT: (block $block + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (br_on_null $block + ;; NOMNL-NEXT: (ref.null any) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (local.set $temp + ;; NOMNL-NEXT: (ref.null any) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (br $block) + ;; NOMNL-NEXT: (local.set $temp + ;; NOMNL-NEXT: (ref.null any) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (ref.as_non_null + ;; NOMNL-NEXT: (local.get $temp) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) (func $no-block-values-if-br_on (local $temp (ref null any)) (block $block |