summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorAlon Zakai <azakai@google.com>2024-06-03 14:19:50 -0700
committerGitHub <noreply@github.com>2024-06-03 14:19:50 -0700
commitea4d9e45e1b9a929a38fbca9a6c316b0b918b12e (patch)
treeb5bf325352e34021e488cf83907ed064730f0b8f /test
parent9347a223fcc1b6c297805b3c37fe1e7473158720 (diff)
downloadbinaryen-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.wast376
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)
)
)
)