diff options
author | Alon Zakai <azakai@google.com> | 2024-06-03 14:19:50 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-06-03 14:19:50 -0700 |
commit | ea4d9e45e1b9a929a38fbca9a6c316b0b918b12e (patch) | |
tree | b5bf325352e34021e488cf83907ed064730f0b8f /test | |
parent | 9347a223fcc1b6c297805b3c37fe1e7473158720 (diff) | |
download | binaryen-ea4d9e45e1b9a929a38fbca9a6c316b0b918b12e.tar.gz binaryen-ea4d9e45e1b9a929a38fbca9a6c316b0b918b12e.tar.bz2 binaryen-ea4d9e45e1b9a929a38fbca9a6c316b0b918b12e.zip |
Effects: Add missing combining logic for MayNotReturn (#6635)
Without that logic we could end up dropping that particular effect. This actually
made a test pass when it should not: the modified test here has a function with
effects that are ok to remove, but it had a loop which adds MayNotReturn which
we should actually not remove, so it was removed erroneously.
To fix the test, add other effects there (local ones) that we can see are removable.
Also add a function with a loop to test that we do not remove an infinite loop,
which adds coverage for the fix here.
Diffstat (limited to 'test')
-rw-r--r-- | test/lit/passes/global-effects-O.wast | 376 |
1 files changed, 295 insertions, 81 deletions
diff --git a/test/lit/passes/global-effects-O.wast b/test/lit/passes/global-effects-O.wast index c7ba06781..ef2cf62e0 100644 --- a/test/lit/passes/global-effects-O.wast +++ b/test/lit/passes/global-effects-O.wast @@ -11,31 +11,38 @@ (module ;; CHECK_0: (type $0 (func)) - ;; CHECK_0: (type $1 (func (result i32))) + ;; CHECK_0: (type $1 (func (param i32) (result i32))) ;; CHECK_0: (export "main" (func $main)) ;; CHECK_1: (type $0 (func)) - ;; CHECK_1: (type $1 (func (result i32))) + ;; CHECK_1: (type $1 (func (param i32) (result i32))) ;; CHECK_1: (export "main" (func $main)) ;; CHECK_3: (type $0 (func)) - ;; CHECK_3: (type $1 (func (result i32))) + ;; CHECK_3: (type $1 (func (param i32) (result i32))) ;; CHECK_3: (export "main" (func $main)) ;; CHECK_s: (type $0 (func)) - ;; CHECK_s: (type $1 (func (result i32))) + ;; CHECK_s: (type $1 (func (param i32) (result i32))) ;; CHECK_s: (export "main" (func $main)) ;; CHECK_O: (type $0 (func)) - ;; CHECK_O: (type $1 (func (result i32))) + ;; CHECK_O: (type $1 (func (param i32) (result i32))) ;; CHECK_O: (export "main" (func $main)) (export "main" (func $main)) + ;; CHECK_0: (export "main-infinite" (func $main-infinite)) + ;; CHECK_1: (export "main-infinite" (func $main-infinite)) + ;; CHECK_3: (export "main-infinite" (func $main-infinite)) + ;; CHECK_s: (export "main-infinite" (func $main-infinite)) + ;; CHECK_O: (export "main-infinite" (func $main-infinite)) + (export "main-infinite" (func $main-infinite)) + ;; CHECK_0: (export "pointless-work" (func $pointless-work)) ;; CHECK_1: (export "pointless-work" (func $pointless-work)) ;; CHECK_3: (export "pointless-work" (func $pointless-work)) @@ -45,10 +52,14 @@ ;; CHECK_0: (func $main (type $0) ;; CHECK_0-NEXT: (if - ;; CHECK_0-NEXT: (call $pointless-work) + ;; CHECK_0-NEXT: (call $pointless-work + ;; CHECK_0-NEXT: (i32.const 0) + ;; CHECK_0-NEXT: ) ;; CHECK_0-NEXT: (then ;; CHECK_0-NEXT: (drop - ;; CHECK_0-NEXT: (call $pointless-work) + ;; CHECK_0-NEXT: (call $pointless-work + ;; CHECK_0-NEXT: (i32.const 1) + ;; CHECK_0-NEXT: ) ;; CHECK_0-NEXT: ) ;; CHECK_0-NEXT: ) ;; CHECK_0-NEXT: ) @@ -70,17 +81,248 @@ ;; effects we can see that it is pointless and remove this entire if (except ;; for -O0). (if - (call $pointless-work) + (call $pointless-work + (i32.const 0) + ) (then (drop - (call $pointless-work) + (call $pointless-work + (i32.const 1) + ) ) ) ) ) - ;; CHECK_0: (func $pointless-work (type $1) (result i32) - ;; CHECK_0-NEXT: (local $x i32) + ;; CHECK_0: (func $main-infinite (type $0) + ;; CHECK_0-NEXT: (if + ;; CHECK_0-NEXT: (call $infinite-work + ;; CHECK_0-NEXT: (i32.const 0) + ;; CHECK_0-NEXT: ) + ;; CHECK_0-NEXT: (then + ;; CHECK_0-NEXT: (drop + ;; CHECK_0-NEXT: (call $infinite-work + ;; CHECK_0-NEXT: (i32.const 1) + ;; CHECK_0-NEXT: ) + ;; CHECK_0-NEXT: ) + ;; CHECK_0-NEXT: ) + ;; CHECK_0-NEXT: ) + ;; CHECK_0-NEXT: ) + ;; CHECK_1: (func $main-infinite (type $0) + ;; CHECK_1-NEXT: (if + ;; CHECK_1-NEXT: (call $infinite-work + ;; CHECK_1-NEXT: (i32.const 0) + ;; CHECK_1-NEXT: ) + ;; CHECK_1-NEXT: (then + ;; CHECK_1-NEXT: (drop + ;; CHECK_1-NEXT: (call $infinite-work + ;; CHECK_1-NEXT: (i32.const 1) + ;; CHECK_1-NEXT: ) + ;; CHECK_1-NEXT: ) + ;; CHECK_1-NEXT: ) + ;; CHECK_1-NEXT: ) + ;; CHECK_1-NEXT: ) + ;; CHECK_3: (func $main-infinite (type $0) + ;; CHECK_3-NEXT: (if + ;; CHECK_3-NEXT: (call $infinite-work + ;; CHECK_3-NEXT: (i32.const 0) + ;; CHECK_3-NEXT: ) + ;; CHECK_3-NEXT: (then + ;; CHECK_3-NEXT: (drop + ;; CHECK_3-NEXT: (call $infinite-work + ;; CHECK_3-NEXT: (i32.const 1) + ;; CHECK_3-NEXT: ) + ;; CHECK_3-NEXT: ) + ;; CHECK_3-NEXT: ) + ;; CHECK_3-NEXT: ) + ;; CHECK_3-NEXT: ) + ;; CHECK_s: (func $main-infinite (type $0) + ;; CHECK_s-NEXT: (if + ;; CHECK_s-NEXT: (call $infinite-work + ;; CHECK_s-NEXT: (i32.const 0) + ;; CHECK_s-NEXT: ) + ;; CHECK_s-NEXT: (then + ;; CHECK_s-NEXT: (drop + ;; CHECK_s-NEXT: (call $infinite-work + ;; CHECK_s-NEXT: (i32.const 1) + ;; CHECK_s-NEXT: ) + ;; CHECK_s-NEXT: ) + ;; CHECK_s-NEXT: ) + ;; CHECK_s-NEXT: ) + ;; CHECK_s-NEXT: ) + ;; CHECK_O: (func $main-infinite (type $0) + ;; CHECK_O-NEXT: (if + ;; CHECK_O-NEXT: (call $infinite-work + ;; CHECK_O-NEXT: (i32.const 0) + ;; CHECK_O-NEXT: ) + ;; CHECK_O-NEXT: (then + ;; CHECK_O-NEXT: (drop + ;; CHECK_O-NEXT: (call $infinite-work + ;; CHECK_O-NEXT: (i32.const 1) + ;; CHECK_O-NEXT: ) + ;; CHECK_O-NEXT: ) + ;; CHECK_O-NEXT: ) + ;; CHECK_O-NEXT: ) + ;; CHECK_O-NEXT: ) + (func $main-infinite + ;; We cannot remove in this case as the pointless work may have an infinite + ;; loop, which we do not eliminate. + (if + (call $infinite-work + (i32.const 0) + ) + (then + (drop + (call $infinite-work + (i32.const 1) + ) + ) + ) + ) + ) + + ;; CHECK_0: (func $pointless-work (type $1) (param $x i32) (result i32) + ;; CHECK_0-NEXT: (local.set $x + ;; CHECK_0-NEXT: (i32.add + ;; CHECK_0-NEXT: (local.get $x) + ;; CHECK_0-NEXT: (i32.const 1) + ;; CHECK_0-NEXT: ) + ;; CHECK_0-NEXT: ) + ;; CHECK_0-NEXT: (if + ;; CHECK_0-NEXT: (i32.ge_u + ;; CHECK_0-NEXT: (local.get $x) + ;; CHECK_0-NEXT: (i32.const 12345678) + ;; CHECK_0-NEXT: ) + ;; CHECK_0-NEXT: (then + ;; CHECK_0-NEXT: (local.set $x + ;; CHECK_0-NEXT: (i32.add + ;; CHECK_0-NEXT: (local.get $x) + ;; CHECK_0-NEXT: (i32.const 1) + ;; CHECK_0-NEXT: ) + ;; CHECK_0-NEXT: ) + ;; CHECK_0-NEXT: ) + ;; CHECK_0-NEXT: ) + ;; CHECK_0-NEXT: (return + ;; CHECK_0-NEXT: (local.get $x) + ;; CHECK_0-NEXT: ) + ;; CHECK_0-NEXT: ) + ;; CHECK_1: (func $pointless-work (type $1) (param $0 i32) (result i32) + ;; CHECK_1-NEXT: (if (result i32) + ;; CHECK_1-NEXT: (i32.ge_u + ;; CHECK_1-NEXT: (local.tee $0 + ;; CHECK_1-NEXT: (i32.add + ;; CHECK_1-NEXT: (local.get $0) + ;; CHECK_1-NEXT: (i32.const 1) + ;; CHECK_1-NEXT: ) + ;; CHECK_1-NEXT: ) + ;; CHECK_1-NEXT: (i32.const 12345678) + ;; CHECK_1-NEXT: ) + ;; CHECK_1-NEXT: (then + ;; CHECK_1-NEXT: (i32.add + ;; CHECK_1-NEXT: (local.get $0) + ;; CHECK_1-NEXT: (i32.const 1) + ;; CHECK_1-NEXT: ) + ;; CHECK_1-NEXT: ) + ;; CHECK_1-NEXT: (else + ;; CHECK_1-NEXT: (local.get $0) + ;; CHECK_1-NEXT: ) + ;; CHECK_1-NEXT: ) + ;; CHECK_1-NEXT: ) + ;; CHECK_3: (func $pointless-work (type $1) (param $0 i32) (result i32) + ;; CHECK_3-NEXT: (if (result i32) + ;; CHECK_3-NEXT: (i32.ge_u + ;; CHECK_3-NEXT: (local.tee $0 + ;; CHECK_3-NEXT: (i32.add + ;; CHECK_3-NEXT: (local.get $0) + ;; CHECK_3-NEXT: (i32.const 1) + ;; CHECK_3-NEXT: ) + ;; CHECK_3-NEXT: ) + ;; CHECK_3-NEXT: (i32.const 12345678) + ;; CHECK_3-NEXT: ) + ;; CHECK_3-NEXT: (then + ;; CHECK_3-NEXT: (i32.add + ;; CHECK_3-NEXT: (local.get $0) + ;; CHECK_3-NEXT: (i32.const 1) + ;; CHECK_3-NEXT: ) + ;; CHECK_3-NEXT: ) + ;; CHECK_3-NEXT: (else + ;; CHECK_3-NEXT: (local.get $0) + ;; CHECK_3-NEXT: ) + ;; CHECK_3-NEXT: ) + ;; CHECK_3-NEXT: ) + ;; CHECK_s: (func $pointless-work (type $1) (param $0 i32) (result i32) + ;; CHECK_s-NEXT: (if (result i32) + ;; CHECK_s-NEXT: (i32.ge_u + ;; CHECK_s-NEXT: (local.tee $0 + ;; CHECK_s-NEXT: (i32.add + ;; CHECK_s-NEXT: (local.get $0) + ;; CHECK_s-NEXT: (i32.const 1) + ;; CHECK_s-NEXT: ) + ;; CHECK_s-NEXT: ) + ;; CHECK_s-NEXT: (i32.const 12345678) + ;; CHECK_s-NEXT: ) + ;; CHECK_s-NEXT: (then + ;; CHECK_s-NEXT: (i32.add + ;; CHECK_s-NEXT: (local.get $0) + ;; CHECK_s-NEXT: (i32.const 1) + ;; CHECK_s-NEXT: ) + ;; CHECK_s-NEXT: ) + ;; CHECK_s-NEXT: (else + ;; CHECK_s-NEXT: (local.get $0) + ;; CHECK_s-NEXT: ) + ;; CHECK_s-NEXT: ) + ;; CHECK_s-NEXT: ) + ;; CHECK_O: (func $pointless-work (type $1) (param $0 i32) (result i32) + ;; CHECK_O-NEXT: (if (result i32) + ;; CHECK_O-NEXT: (i32.ge_u + ;; CHECK_O-NEXT: (local.tee $0 + ;; CHECK_O-NEXT: (i32.add + ;; CHECK_O-NEXT: (local.get $0) + ;; CHECK_O-NEXT: (i32.const 1) + ;; CHECK_O-NEXT: ) + ;; CHECK_O-NEXT: ) + ;; CHECK_O-NEXT: (i32.const 12345678) + ;; CHECK_O-NEXT: ) + ;; CHECK_O-NEXT: (then + ;; CHECK_O-NEXT: (i32.add + ;; CHECK_O-NEXT: (local.get $0) + ;; CHECK_O-NEXT: (i32.const 1) + ;; CHECK_O-NEXT: ) + ;; CHECK_O-NEXT: ) + ;; CHECK_O-NEXT: (else + ;; CHECK_O-NEXT: (local.get $0) + ;; CHECK_O-NEXT: ) + ;; CHECK_O-NEXT: ) + ;; CHECK_O-NEXT: ) + (func $pointless-work (param $x i32) (result i32) + ;; Some pointless work, with no side effects, that cannot be inlined. (The + ;; changes here are not important for this test.) + (local.set $x + (i32.add + (local.get $x) + (i32.const 1) + ) + ) + (if + (i32.ge_u + (local.get $x) + (i32.const 12345678) + ) + (then + (local.set $x + (i32.add + (local.get $x) + (i32.const 1) + ) + ) + ) + ) + (return + (local.get $x) + ) + ) + + ;; CHECK_0: (func $infinite-work (type $1) (param $x i32) (result i32) ;; CHECK_0-NEXT: (loop $loop ;; CHECK_0-NEXT: (local.set $x ;; CHECK_0-NEXT: (i32.add @@ -88,92 +330,70 @@ ;; CHECK_0-NEXT: (i32.const 1) ;; CHECK_0-NEXT: ) ;; CHECK_0-NEXT: ) - ;; CHECK_0-NEXT: (if - ;; CHECK_0-NEXT: (i32.ge_u - ;; CHECK_0-NEXT: (local.get $x) - ;; CHECK_0-NEXT: (i32.const 12345678) - ;; CHECK_0-NEXT: ) - ;; CHECK_0-NEXT: (then - ;; CHECK_0-NEXT: (return - ;; CHECK_0-NEXT: (local.get $x) - ;; CHECK_0-NEXT: ) - ;; CHECK_0-NEXT: ) + ;; CHECK_0-NEXT: (br_if $loop + ;; CHECK_0-NEXT: (local.get $x) ;; CHECK_0-NEXT: ) - ;; CHECK_0-NEXT: (br $loop) + ;; CHECK_0-NEXT: ) + ;; CHECK_0-NEXT: (return + ;; CHECK_0-NEXT: (local.get $x) ;; CHECK_0-NEXT: ) ;; CHECK_0-NEXT: ) - ;; CHECK_1: (func $pointless-work (type $1) (result i32) - ;; CHECK_1-NEXT: (local $0 i32) - ;; CHECK_1-NEXT: (loop $loop (result i32) + ;; CHECK_1: (func $infinite-work (type $1) (param $0 i32) (result i32) + ;; CHECK_1-NEXT: (loop $loop ;; CHECK_1-NEXT: (br_if $loop - ;; CHECK_1-NEXT: (i32.lt_u - ;; CHECK_1-NEXT: (local.tee $0 - ;; CHECK_1-NEXT: (i32.add - ;; CHECK_1-NEXT: (local.get $0) - ;; CHECK_1-NEXT: (i32.const 1) - ;; CHECK_1-NEXT: ) + ;; CHECK_1-NEXT: (local.tee $0 + ;; CHECK_1-NEXT: (i32.add + ;; CHECK_1-NEXT: (local.get $0) + ;; CHECK_1-NEXT: (i32.const 1) ;; CHECK_1-NEXT: ) - ;; CHECK_1-NEXT: (i32.const 12345678) ;; CHECK_1-NEXT: ) ;; CHECK_1-NEXT: ) - ;; CHECK_1-NEXT: (local.get $0) ;; CHECK_1-NEXT: ) + ;; CHECK_1-NEXT: (local.get $0) ;; CHECK_1-NEXT: ) - ;; CHECK_3: (func $pointless-work (type $1) (result i32) - ;; CHECK_3-NEXT: (local $0 i32) - ;; CHECK_3-NEXT: (loop $loop (result i32) + ;; CHECK_3: (func $infinite-work (type $1) (param $0 i32) (result i32) + ;; CHECK_3-NEXT: (loop $loop ;; CHECK_3-NEXT: (br_if $loop - ;; CHECK_3-NEXT: (i32.lt_u - ;; CHECK_3-NEXT: (local.tee $0 - ;; CHECK_3-NEXT: (i32.add - ;; CHECK_3-NEXT: (local.get $0) - ;; CHECK_3-NEXT: (i32.const 1) - ;; CHECK_3-NEXT: ) + ;; CHECK_3-NEXT: (local.tee $0 + ;; CHECK_3-NEXT: (i32.add + ;; CHECK_3-NEXT: (local.get $0) + ;; CHECK_3-NEXT: (i32.const 1) ;; CHECK_3-NEXT: ) - ;; CHECK_3-NEXT: (i32.const 12345678) ;; CHECK_3-NEXT: ) ;; CHECK_3-NEXT: ) - ;; CHECK_3-NEXT: (local.get $0) ;; CHECK_3-NEXT: ) + ;; CHECK_3-NEXT: (local.get $0) ;; CHECK_3-NEXT: ) - ;; CHECK_s: (func $pointless-work (type $1) (result i32) - ;; CHECK_s-NEXT: (local $0 i32) - ;; CHECK_s-NEXT: (loop $loop (result i32) + ;; CHECK_s: (func $infinite-work (type $1) (param $0 i32) (result i32) + ;; CHECK_s-NEXT: (loop $loop ;; CHECK_s-NEXT: (br_if $loop - ;; CHECK_s-NEXT: (i32.lt_u - ;; CHECK_s-NEXT: (local.tee $0 - ;; CHECK_s-NEXT: (i32.add - ;; CHECK_s-NEXT: (local.get $0) - ;; CHECK_s-NEXT: (i32.const 1) - ;; CHECK_s-NEXT: ) + ;; CHECK_s-NEXT: (local.tee $0 + ;; CHECK_s-NEXT: (i32.add + ;; CHECK_s-NEXT: (local.get $0) + ;; CHECK_s-NEXT: (i32.const 1) ;; CHECK_s-NEXT: ) - ;; CHECK_s-NEXT: (i32.const 12345678) ;; CHECK_s-NEXT: ) ;; CHECK_s-NEXT: ) - ;; CHECK_s-NEXT: (local.get $0) ;; CHECK_s-NEXT: ) + ;; CHECK_s-NEXT: (local.get $0) ;; CHECK_s-NEXT: ) - ;; CHECK_O: (func $pointless-work (type $1) (result i32) - ;; CHECK_O-NEXT: (local $0 i32) - ;; CHECK_O-NEXT: (loop $loop (result i32) + ;; CHECK_O: (func $infinite-work (type $1) (param $0 i32) (result i32) + ;; CHECK_O-NEXT: (loop $loop ;; CHECK_O-NEXT: (br_if $loop - ;; CHECK_O-NEXT: (i32.lt_u - ;; CHECK_O-NEXT: (local.tee $0 - ;; CHECK_O-NEXT: (i32.add - ;; CHECK_O-NEXT: (local.get $0) - ;; CHECK_O-NEXT: (i32.const 1) - ;; CHECK_O-NEXT: ) + ;; CHECK_O-NEXT: (local.tee $0 + ;; CHECK_O-NEXT: (i32.add + ;; CHECK_O-NEXT: (local.get $0) + ;; CHECK_O-NEXT: (i32.const 1) ;; CHECK_O-NEXT: ) - ;; CHECK_O-NEXT: (i32.const 12345678) ;; CHECK_O-NEXT: ) ;; CHECK_O-NEXT: ) - ;; CHECK_O-NEXT: (local.get $0) ;; CHECK_O-NEXT: ) + ;; CHECK_O-NEXT: (local.get $0) ;; CHECK_O-NEXT: ) - (func $pointless-work (result i32) - (local $x i32) - ;; Some pointless work, with no side effects, that cannot be inlined. (The - ;; changes here are not important for this test.) + (func $infinite-work (param $x i32) (result i32) + ;; Some work with no side effects aside from that it appears to potentially + ;; do infinite work, due to a loop. (The changes here are not important for + ;; this test.) (loop $loop (local.set $x (i32.add @@ -181,18 +401,12 @@ (i32.const 1) ) ) - (if - (i32.ge_u - (local.get $x) - (i32.const 12345678) - ) - (then - (return - (local.get $x) - ) - ) + (br_if $loop + (local.get $x) ) - (br $loop) + ) + (return + (local.get $x) ) ) ) |