summaryrefslogtreecommitdiff
path: root/test/lit/passes
diff options
context:
space:
mode:
authorAlon Zakai <azakai@google.com>2021-04-21 19:54:38 -0700
committerGitHub <noreply@github.com>2021-04-21 19:54:38 -0700
commit0e0147dd18a3875bde24f418b23230d454942c4a (patch)
tree8ecb81e690058954e22ea3bd813b3ead0a9b4db3 /test/lit/passes
parentcb776da297a845e15171405b7f7518619122d7aa (diff)
downloadbinaryen-0e0147dd18a3875bde24f418b23230d454942c4a.tar.gz
binaryen-0e0147dd18a3875bde24f418b23230d454942c4a.tar.bz2
binaryen-0e0147dd18a3875bde24f418b23230d454942c4a.zip
Generalize moving of identical code from if/select arms (#3833)
Effects are fine in the moved code, if we are doing so on an if (which runs just one arm anyhow). Allow unreachable, which lets us hoist returns for example. Allow none, which lets us hoist drop and call for example. For this we also need to be careful with subtyping, as at least drop is polymorphic, so the child types may not have an LUB (see example in code). Adds a small ShallowEffectAnalyzer child of EffectAnalyzer that calls visit to just do a shallow analysis (instead of walk which walks the children).
Diffstat (limited to 'test/lit/passes')
-rw-r--r--test/lit/passes/optimize-instructions-gc.wast30
-rw-r--r--test/lit/passes/optimize-instructions.wast161
2 files changed, 166 insertions, 25 deletions
diff --git a/test/lit/passes/optimize-instructions-gc.wast b/test/lit/passes/optimize-instructions-gc.wast
index 3ae0e1d91..c0474a823 100644
--- a/test/lit/passes/optimize-instructions-gc.wast
+++ b/test/lit/passes/optimize-instructions-gc.wast
@@ -849,7 +849,7 @@
)
)
)
- ;; CHECK: (func $ternary-identical-arms-but-side-effect (param $x (ref null $struct)) (param $y (ref null $struct)) (param $z i32)
+ ;; CHECK: (func $select-identical-arms-but-side-effect (param $x (ref null $struct)) (param $y (ref null $struct)) (param $z i32)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (select
;; CHECK-NEXT: (struct.get_u $struct $i8
@@ -862,7 +862,7 @@
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
- (func $ternary-identical-arms-but-side-effect (param $x (ref null $struct)) (param $y (ref null $struct)) (param $z i32)
+ (func $select-identical-arms-but-side-effect (param $x (ref null $struct)) (param $y (ref null $struct)) (param $z i32)
(drop
(select
;; the arms are equal but have side effects
@@ -901,4 +901,30 @@
)
)
)
+ ;; CHECK: (func $if-identical-arms-with-side-effect (param $x (ref null $struct)) (param $y (ref null $struct)) (param $z i32)
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (struct.get_u $struct $i8
+ ;; CHECK-NEXT: (if (result (ref null $struct))
+ ;; CHECK-NEXT: (local.get $z)
+ ;; CHECK-NEXT: (local.get $x)
+ ;; CHECK-NEXT: (local.get $y)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $if-identical-arms-with-side-effect (param $x (ref null $struct)) (param $y (ref null $struct)) (param $z i32)
+ (drop
+ (if (result i32)
+ (local.get $z)
+ ;; the arms are equal and have side effects, but that is ok with an if
+ ;; which only executes one side anyhow
+ (struct.get_u $struct 0
+ (local.get $x)
+ )
+ (struct.get_u $struct 0
+ (local.get $y)
+ )
+ )
+ )
+ )
)
diff --git a/test/lit/passes/optimize-instructions.wast b/test/lit/passes/optimize-instructions.wast
index 7150fc839..3ed0b3115 100644
--- a/test/lit/passes/optimize-instructions.wast
+++ b/test/lit/passes/optimize-instructions.wast
@@ -101,12 +101,10 @@
)
)
;; CHECK: (func $if-eqz-two-arms (param $i1 i32)
- ;; CHECK-NEXT: (if
- ;; CHECK-NEXT: (local.get $i1)
- ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (if (result i32)
+ ;; CHECK-NEXT: (local.get $i1)
;; CHECK-NEXT: (i32.const 12)
- ;; CHECK-NEXT: )
- ;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 11)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
@@ -125,14 +123,12 @@
)
)
;; CHECK: (func $if-eqz-two-arms-i64 (param $i2 i64)
- ;; CHECK-NEXT: (if
- ;; CHECK-NEXT: (i64.eqz
- ;; CHECK-NEXT: (local.get $i2)
- ;; CHECK-NEXT: )
- ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (if (result i32)
+ ;; CHECK-NEXT: (i64.eqz
+ ;; CHECK-NEXT: (local.get $i2)
+ ;; CHECK-NEXT: )
;; CHECK-NEXT: (i32.const 11)
- ;; CHECK-NEXT: )
- ;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 12)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
@@ -11928,29 +11924,44 @@
)
)
)
- ;; CHECK: (func $ternary-identical-arms-but-type-is-none (param $x i32) (param $y i32) (param $z i32)
- ;; CHECK-NEXT: (if
- ;; CHECK-NEXT: (local.get $z)
- ;; CHECK-NEXT: (drop
- ;; CHECK-NEXT: (i32.eqz
+ ;; CHECK: (func $ternary-identical-arms-and-type-is-none (param $x i32) (param $y i32) (param $z i32)
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (i32.eqz
+ ;; CHECK-NEXT: (if (result i32)
+ ;; CHECK-NEXT: (local.get $z)
;; CHECK-NEXT: (local.get $x)
- ;; CHECK-NEXT: )
- ;; CHECK-NEXT: )
- ;; CHECK-NEXT: (drop
- ;; CHECK-NEXT: (i32.eqz
;; CHECK-NEXT: (local.get $y)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
- (func $ternary-identical-arms-but-type-is-none (param $x i32) (param $y i32) (param $z i32)
+ (func $ternary-identical-arms-and-type-is-none (param $x i32) (param $y i32) (param $z i32)
(if
(local.get $z)
- ;; identical arms, but type is none
(drop (i32.eqz (local.get $x)))
(drop (i32.eqz (local.get $y)))
)
)
+ ;; CHECK: (func $ternary-identical-arms-and-type-is-none-child-types-mismatch (param $x i32) (param $y i32) (param $z i32)
+ ;; CHECK-NEXT: (if
+ ;; CHECK-NEXT: (local.get $z)
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (f64.const 2.34)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $ternary-identical-arms-and-type-is-none-child-types-mismatch (param $x i32) (param $y i32) (param $z i32)
+ (if
+ (local.get $z)
+ ;; the drop cannot be hoisted out, since the children's type mismatch
+ ;; would not allow us to give a proper type to the if.
+ (drop (i32.const 1))
+ (drop (f64.const 2.34))
+ )
+ )
;; CHECK: (func $ternary-identical-arms-but-block (param $x i32) (param $y i32) (param $z i32)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (select
@@ -12013,4 +12024,108 @@
)
)
)
+ ;; CHECK: (func $ternary-identical-arms-br_if-same (param $x i32) (param $y i32) (param $z i32)
+ ;; CHECK-NEXT: (block $block
+ ;; CHECK-NEXT: (br_if $block
+ ;; CHECK-NEXT: (if (result i32)
+ ;; CHECK-NEXT: (local.get $z)
+ ;; CHECK-NEXT: (local.get $x)
+ ;; CHECK-NEXT: (local.get $y)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $ternary-identical-arms-br_if-same (param $x i32) (param $y i32) (param $z i32)
+ (block $block
+ (if
+ (local.get $z)
+ ;; two br_ifs with the same target are shallowly identical
+ (br_if $block
+ (local.get $x)
+ )
+ (br_if $block
+ (local.get $y)
+ )
+ )
+ )
+ )
+ ;; CHECK: (func $ternary-identical-arms-br_if-different (param $x i32) (param $y i32) (param $z i32)
+ ;; CHECK-NEXT: (block $block1
+ ;; CHECK-NEXT: (block $block2
+ ;; CHECK-NEXT: (if
+ ;; CHECK-NEXT: (local.get $z)
+ ;; CHECK-NEXT: (br_if $block1
+ ;; CHECK-NEXT: (local.get $x)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (br_if $block2
+ ;; CHECK-NEXT: (local.get $y)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $ternary-identical-arms-br_if-different (param $x i32) (param $y i32) (param $z i32)
+ (block $block1
+ (block $block2
+ (if
+ (local.get $z)
+ ;; two br_ifs with different targets are not shallowly identical
+ (br_if $block1
+ (local.get $x)
+ )
+ (br_if $block2
+ (local.get $y)
+ )
+ )
+ )
+ )
+ )
+ ;; CHECK: (func $ternary-identical-arms-return (param $x i32) (param $y i32) (param $z i32) (result i32)
+ ;; CHECK-NEXT: (block $block
+ ;; CHECK-NEXT: (return
+ ;; CHECK-NEXT: (if (result i32)
+ ;; CHECK-NEXT: (local.get $z)
+ ;; CHECK-NEXT: (local.get $x)
+ ;; CHECK-NEXT: (local.get $y)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $ternary-identical-arms-return (param $x i32) (param $y i32) (param $z i32) (result i32)
+ (block $block
+ (if
+ (local.get $z)
+ (return
+ (local.get $x)
+ )
+ (return
+ (local.get $y)
+ )
+ )
+ )
+ )
+ ;; CHECK: (func $send-i32 (param $0 i32)
+ ;; CHECK-NEXT: (nop)
+ ;; CHECK-NEXT: )
+ (func $send-i32 (param i32))
+ ;; CHECK: (func $ternary-identical-arms-call (param $x i32) (param $y i32) (param $z i32)
+ ;; CHECK-NEXT: (call $send-i32
+ ;; CHECK-NEXT: (if (result i32)
+ ;; CHECK-NEXT: (local.get $z)
+ ;; CHECK-NEXT: (local.get $x)
+ ;; CHECK-NEXT: (local.get $y)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $ternary-identical-arms-call (param $x i32) (param $y i32) (param $z i32)
+ (if
+ (local.get $z)
+ (call $send-i32
+ (local.get $x)
+ )
+ (call $send-i32
+ (local.get $y)
+ )
+ )
+ )
)