summaryrefslogtreecommitdiff
path: root/test/passes
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2017-06-28 22:05:05 -0700
committerGitHub <noreply@github.com>2017-06-28 22:05:05 -0700
commite488da5adbef2613c08fe205db5b79b1765a4af3 (patch)
treee3cab840dcbf7d8d4ccf1f47a742fbfc41e1d5ef /test/passes
parente2c08d42ab0ffc05d980ae2d34fee0e77b201134 (diff)
downloadbinaryen-e488da5adbef2613c08fe205db5b79b1765a4af3.tar.gz
binaryen-e488da5adbef2613c08fe205db5b79b1765a4af3.tar.bz2
binaryen-e488da5adbef2613c08fe205db5b79b1765a4af3.zip
Code folding (#1076)
Adds a pass that folds code, i.e. merges it when possible. See details in comment in the pass implementation cpp. This is enabled by default in -Os and -Oz. Seems risky to enable anywhere else, as it does add branches - likely predictable ones so maybe no slowdown, but still some risk. Code size numbers: wasm-backend: 196331 + binaryen -Os (before): 182598 + binaryen -Os (with folding): 181943 asm2wasm -Os (before): 172463 asm2wasm -Os (with folding): 168774 So this reduces wasm-backend output by an additional 0.5% than it could before. Mainly this is because the wasm backend already has code folding, whereas on asm2wasm output, where we didn't have folding before, this saves over 2%. The 0.5% improvement on the wasm backend's output might be because this can fold more types of code than LLVM can (it can fold nested control flow, in particular).
Diffstat (limited to 'test/passes')
-rw-r--r--test/passes/remove-unused-names_code-folding.txt1681
-rw-r--r--test/passes/remove-unused-names_code-folding.wast1176
2 files changed, 2857 insertions, 0 deletions
diff --git a/test/passes/remove-unused-names_code-folding.txt b/test/passes/remove-unused-names_code-folding.txt
new file mode 100644
index 000000000..0ad10704f
--- /dev/null
+++ b/test/passes/remove-unused-names_code-folding.txt
@@ -0,0 +1,1681 @@
+(module
+ (type $0 (func))
+ (type $1 (func (param i32 i32) (result i32)))
+ (type $2 (func (result i32)))
+ (memory $0 0)
+ (func $ifs (type $0)
+ (if
+ (i32.const 0)
+ (nop)
+ )
+ (block
+ (drop
+ (i32.const 0)
+ )
+ (nop)
+ )
+ (if
+ (i32.const 0)
+ (nop)
+ (unreachable)
+ )
+ (drop
+ (block (result i32)
+ (drop
+ (i32.const 0)
+ )
+ (i32.add
+ (i32.const 1)
+ (i32.const 2)
+ )
+ )
+ )
+ (drop
+ (if (result i32)
+ (i32.const 0)
+ (i32.add
+ (i32.const 1)
+ (i32.const 2)
+ )
+ (i32.add
+ (i32.const 1)
+ (i32.const 333333333)
+ )
+ )
+ )
+ )
+ (func $ifs-blocks (type $0)
+ (block
+ (drop
+ (i32.const 0)
+ )
+ (block
+ (nop)
+ )
+ )
+ (block
+ (if
+ (i32.const 0)
+ (unreachable)
+ (block
+ )
+ )
+ (nop)
+ )
+ (block
+ (if
+ (i32.const 0)
+ (block
+ )
+ (unreachable)
+ )
+ (nop)
+ )
+ (if
+ (i32.const 0)
+ (block
+ (nop)
+ (unreachable)
+ )
+ (nop)
+ )
+ (if
+ (i32.const 0)
+ (nop)
+ (block
+ (nop)
+ (unreachable)
+ )
+ )
+ )
+ (func $ifs-blocks-big (type $0)
+ (block
+ (drop
+ (i32.const 0)
+ )
+ (block
+ (drop
+ (i32.add
+ (i32.const 1)
+ (i32.const 2)
+ )
+ )
+ )
+ )
+ (block
+ (if
+ (i32.const 0)
+ (unreachable)
+ (block
+ )
+ )
+ (drop
+ (i32.add
+ (i32.const 1)
+ (i32.const 2)
+ )
+ )
+ )
+ (block
+ (if
+ (i32.const 0)
+ (block
+ )
+ (unreachable)
+ )
+ (drop
+ (i32.add
+ (i32.const 1)
+ (i32.const 2)
+ )
+ )
+ )
+ (if
+ (i32.const 0)
+ (block
+ (drop
+ (i32.add
+ (i32.const 1)
+ (i32.const 2)
+ )
+ )
+ (unreachable)
+ )
+ (drop
+ (i32.add
+ (i32.const 1)
+ (i32.const 2)
+ )
+ )
+ )
+ (if
+ (i32.const 0)
+ (drop
+ (i32.add
+ (i32.const 1)
+ (i32.const 2)
+ )
+ )
+ (block
+ (drop
+ (i32.add
+ (i32.const 1)
+ (i32.const 2)
+ )
+ )
+ (unreachable)
+ )
+ )
+ )
+ (func $ifs-blocks-long (type $0)
+ (block
+ (if
+ (i32.const 1)
+ (block
+ (drop
+ (i32.const -1234)
+ )
+ (drop
+ (i32.const -1000)
+ )
+ )
+ (drop
+ (i32.const 999)
+ )
+ )
+ (drop
+ (i32.const 1)
+ )
+ (nop)
+ (unreachable)
+ )
+ (drop
+ (block (result i32)
+ (if
+ (i32.const 2)
+ (block
+ (drop
+ (i32.const -1234)
+ )
+ (drop
+ (i32.const -1000)
+ )
+ )
+ (drop
+ (i32.const 999)
+ )
+ )
+ (drop
+ (i32.const 1)
+ )
+ (nop)
+ (unreachable)
+ (i32.const 2)
+ )
+ )
+ (drop
+ (block (result i32)
+ (if
+ (i32.const 3)
+ (block
+ (drop
+ (i32.const -1234)
+ )
+ (drop
+ (i32.const -1000)
+ )
+ )
+ (drop
+ (i32.const 999)
+ )
+ )
+ (drop
+ (i32.const 1)
+ )
+ (nop)
+ (i32.const 2)
+ )
+ )
+ )
+ (func $if-worth-it-i-dunno (type $0)
+ (block $folding-inner0
+ (block
+ (if
+ (i32.const 0)
+ (if
+ (i32.const 0)
+ (block
+ (drop
+ (i32.const -1234)
+ )
+ (drop
+ (i32.const -1000)
+ )
+ (br $folding-inner0)
+ )
+ (block
+ (drop
+ (i32.const 999)
+ )
+ (drop
+ (i32.const 1)
+ )
+ (br $folding-inner0)
+ )
+ )
+ )
+ (if
+ (i32.const 0)
+ (block
+ (if
+ (i32.const 0)
+ (block
+ (drop
+ (i32.const -1234)
+ )
+ (drop
+ (i32.const -1000)
+ )
+ )
+ (block
+ (drop
+ (i32.const 999)
+ )
+ (drop
+ (i32.const 1)
+ )
+ )
+ )
+ (unreachable)
+ (br $folding-inner0)
+ )
+ )
+ (if
+ (i32.const 0)
+ (block
+ (if
+ (i32.const 0)
+ (block
+ )
+ (block
+ (drop
+ (i32.const 999)
+ )
+ (drop
+ (i32.const 1)
+ )
+ )
+ )
+ (br $folding-inner0)
+ )
+ )
+ (if
+ (i32.const 0)
+ (block
+ (if
+ (i32.const 0)
+ (block
+ (drop
+ (i32.const -1234)
+ )
+ (drop
+ (i32.const -1000)
+ )
+ )
+ (block
+ )
+ )
+ (br $folding-inner0)
+ )
+ )
+ (block
+ (block
+ (if
+ (i32.const 9999)
+ (block
+ (drop
+ (i32.const -51234)
+ )
+ (drop
+ (i32.const -51000)
+ )
+ )
+ (block
+ (drop
+ (i32.const 5999)
+ )
+ (drop
+ (i32.const 51)
+ )
+ )
+ )
+ (br $folding-inner0)
+ )
+ )
+ (drop
+ (block (result i32)
+ (block (result i32)
+ (if
+ (i32.const 9999)
+ (block
+ (drop
+ (i32.const -51234)
+ )
+ (drop
+ (i32.const -51000)
+ )
+ )
+ (block
+ (drop
+ (i32.const 5999)
+ )
+ (drop
+ (i32.const 51)
+ )
+ )
+ )
+ (unreachable)
+ (i32.const 10)
+ )
+ )
+ )
+ (block
+ (drop
+ (if (result i32)
+ (i32.const 9999)
+ (block (result i32)
+ (drop
+ (i32.const -51234)
+ )
+ (drop
+ (i32.const -51000)
+ )
+ (unreachable)
+ (i32.const 10)
+ )
+ (block (result i32)
+ (drop
+ (i32.const 5999)
+ )
+ (drop
+ (i32.const 51)
+ )
+ (unreachable)
+ (i32.const 10)
+ )
+ )
+ )
+ )
+ )
+ )
+ (unreachable)
+ (unreachable)
+ )
+ (func $no-grandparent (type $0)
+ (if
+ (i32.const 9999)
+ (block
+ (drop
+ (i32.const -51234)
+ )
+ (drop
+ (i32.const -51000)
+ )
+ (unreachable)
+ (unreachable)
+ )
+ (block
+ (drop
+ (i32.const 5999)
+ )
+ (drop
+ (i32.const 51)
+ )
+ (unreachable)
+ (unreachable)
+ )
+ )
+ )
+ (func $yes-grandparent (type $0)
+ (block
+ (if
+ (i32.const 9999)
+ (block
+ (drop
+ (i32.const -51234)
+ )
+ (drop
+ (i32.const -51000)
+ )
+ )
+ (block
+ (drop
+ (i32.const 5999)
+ )
+ (drop
+ (i32.const 51)
+ )
+ )
+ )
+ (unreachable)
+ (unreachable)
+ )
+ )
+ (func $ifs-named-block (type $1) (param $x i32) (param $y i32) (result i32)
+ (block $out
+ (block $out2
+ (block
+ (drop
+ (get_local $x)
+ )
+ (block
+ (br_if $out
+ (get_local $y)
+ )
+ (nop)
+ )
+ )
+ (block
+ (if
+ (get_local $x)
+ (br_if $out
+ (get_local $y)
+ )
+ (br_if $out2
+ (get_local $y)
+ )
+ )
+ (nop)
+ )
+ (if
+ (i32.const 1234)
+ (if
+ (get_local $x)
+ (block
+ (nop)
+ (br_if $out
+ (get_local $y)
+ )
+ (nop)
+ )
+ (block
+ (nop)
+ (br_if $out2
+ (get_local $y)
+ )
+ (nop)
+ )
+ )
+ )
+ (if
+ (get_local $x)
+ (block $left
+ (br_if $left
+ (get_local $y)
+ )
+ (nop)
+ )
+ (block
+ (br_if $out
+ (get_local $y)
+ )
+ (nop)
+ )
+ )
+ (if
+ (get_local $x)
+ (block
+ (br_if $out
+ (get_local $y)
+ )
+ (nop)
+ )
+ (block $right
+ (br_if $right
+ (get_local $y)
+ )
+ (nop)
+ )
+ )
+ )
+ (return
+ (i32.const 10)
+ )
+ )
+ (return
+ (i32.const 20)
+ )
+ )
+ (func $block (type $0)
+ (block $x
+ (if
+ (i32.const 0)
+ (br $x)
+ )
+ (if
+ (i32.const 0)
+ (br $x)
+ )
+ (br $x)
+ )
+ (drop
+ (i32.const 1)
+ )
+ (drop
+ (i32.const 2)
+ )
+ )
+ (func $block2 (type $0)
+ (block $x
+ (if
+ (i32.const 0)
+ (block
+ (drop
+ (i32.const 1)
+ )
+ (drop
+ (i32.const 333333)
+ )
+ (br $x)
+ )
+ )
+ (if
+ (i32.const 0)
+ (block
+ (drop
+ (i32.const 1)
+ )
+ (drop
+ (i32.const 2)
+ )
+ (br $x)
+ )
+ )
+ (drop
+ (i32.const 1)
+ )
+ (drop
+ (i32.const 2)
+ )
+ (br $x)
+ )
+ )
+ (func $block3 (type $0)
+ (block $x
+ (if
+ (i32.const 0)
+ (block
+ (drop
+ (i32.const 1000)
+ )
+ (br $x)
+ )
+ )
+ (if
+ (i32.const 0)
+ (block
+ (drop
+ (i32.const 2000)
+ )
+ (drop
+ (i32.const 3000)
+ )
+ (br $x)
+ )
+ )
+ (drop
+ (i32.const 4000)
+ )
+ (drop
+ (i32.const 5000)
+ )
+ (drop
+ (i32.const 6000)
+ )
+ (br $x)
+ )
+ (drop
+ (i32.const 1)
+ )
+ (drop
+ (i32.const 2)
+ )
+ )
+ (func $mixture (type $0)
+ (block $out
+ (block
+ (drop
+ (i32.const 1)
+ )
+ (block
+ (drop
+ (i32.const 2)
+ )
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (br $out)
+ )
+ )
+ )
+ (block $out2
+ (block
+ (if
+ (i32.const 1)
+ (drop
+ (i32.const 3)
+ )
+ (block
+ (drop
+ (i32.const 4)
+ )
+ (drop
+ (i32.const 5)
+ )
+ )
+ )
+ (drop
+ (i32.const 2)
+ )
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (br $out2)
+ )
+ )
+ (block
+ (block $out3
+ (block
+ (drop
+ (i32.const 1)
+ )
+ (block
+ (br $out3)
+ )
+ )
+ (block
+ (drop
+ (i32.const 1)
+ )
+ (block
+ (br $out3)
+ )
+ )
+ (br $out3)
+ )
+ (drop
+ (i32.const 2)
+ )
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ )
+ )
+ (func $block-corners (type $0)
+ (block
+ (block $x
+ (if
+ (i32.const 0)
+ (br $x)
+ )
+ )
+ (drop
+ (i32.const 1)
+ )
+ (drop
+ (i32.const 2)
+ )
+ )
+ (drop
+ (block $y (result i32)
+ (if
+ (i32.const 0)
+ (block
+ (drop
+ (i32.const 1)
+ )
+ (drop
+ (i32.const 2)
+ )
+ (br $y
+ (i32.const 3)
+ )
+ )
+ )
+ (drop
+ (i32.const 1)
+ )
+ (drop
+ (i32.const 2)
+ )
+ (br $y
+ (i32.const 3)
+ )
+ )
+ )
+ (drop
+ (block $z (result i32)
+ (if
+ (i32.const 0)
+ (block
+ (drop
+ (i32.const 1)
+ )
+ (drop
+ (i32.const 2)
+ )
+ (br $z
+ (i32.const 2)
+ )
+ )
+ )
+ (drop
+ (i32.const 1)
+ )
+ (drop
+ (i32.const 2)
+ )
+ (i32.const 3)
+ )
+ )
+ (block $w
+ (if
+ (i32.const 0)
+ (block
+ (drop
+ (i32.const 1)
+ )
+ (drop
+ (i32.const 2)
+ )
+ (br_if $w
+ (i32.const 3)
+ )
+ )
+ )
+ (drop
+ (i32.const 1)
+ )
+ (drop
+ (i32.const 2)
+ )
+ )
+ (block $x1
+ (if
+ (i32.const 0)
+ (block
+ (drop
+ (i32.const 1)
+ )
+ (drop
+ (i32.const 2)
+ )
+ (br $x1)
+ (nop)
+ )
+ )
+ (drop
+ (i32.const 1)
+ )
+ (drop
+ (i32.const 2)
+ )
+ )
+ (block $side
+ (block $x2
+ (br_table $x2 $side
+ (i32.const 0)
+ )
+ (if
+ (i32.const 0)
+ (block
+ (drop
+ (i32.const 1)
+ )
+ (drop
+ (i32.const 2)
+ )
+ (br $x2)
+ )
+ )
+ (drop
+ (i32.const 1)
+ )
+ (drop
+ (i32.const 2)
+ )
+ )
+ (block $x3
+ (br_table $side $x3
+ (i32.const 0)
+ )
+ (if
+ (i32.const 0)
+ (block
+ (drop
+ (i32.const 1)
+ )
+ (drop
+ (i32.const 2)
+ )
+ (br $x3)
+ )
+ )
+ (drop
+ (i32.const 1)
+ )
+ (drop
+ (i32.const 2)
+ )
+ )
+ )
+ )
+ (func $terminating (type $0)
+ (block $folding-inner0
+ (block
+ (if
+ (i32.const 1)
+ (br $folding-inner0)
+ )
+ (if
+ (i32.const 2)
+ (br $folding-inner0)
+ )
+ (if
+ (i32.const 3)
+ (br $folding-inner0)
+ )
+ )
+ (return)
+ )
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (unreachable)
+ )
+ (func $terminating-unreachable (type $0)
+ (block $folding-inner0
+ (block
+ (if
+ (i32.const 1)
+ (br $folding-inner0)
+ )
+ (if
+ (i32.const 2)
+ (br $folding-inner0)
+ )
+ (if
+ (i32.const 3)
+ (br $folding-inner0)
+ )
+ (unreachable)
+ )
+ )
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (unreachable)
+ )
+ (func $terminating-value (type $2) (result i32)
+ (block $folding-inner0
+ (return
+ (block (result i32)
+ (if
+ (i32.const 1)
+ (br $folding-inner0)
+ )
+ (if
+ (i32.const 2)
+ (br $folding-inner0)
+ )
+ (if
+ (i32.const 3)
+ (br $folding-inner0)
+ )
+ (i32.const 4)
+ )
+ )
+ )
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (unreachable)
+ )
+ (func $terminating-just-2 (type $0)
+ (block $folding-inner0
+ (block
+ (if
+ (i32.const 1)
+ (br $folding-inner0)
+ )
+ (if
+ (i32.const 2)
+ (br $folding-inner0)
+ )
+ (if
+ (i32.const 3)
+ (block
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (drop
+ (i32.const 10)
+ )
+ (unreachable)
+ )
+ )
+ )
+ (return)
+ )
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (unreachable)
+ )
+ (func $terminating-shortness (type $0)
+ (block $folding-inner1
+ (block
+ (block $folding-inner0
+ (block
+ (if
+ (i32.const 1)
+ (br $folding-inner0)
+ )
+ (if
+ (i32.const 2)
+ (br $folding-inner1)
+ )
+ (if
+ (i32.const 3)
+ (block
+ (drop
+ (i32.const 10)
+ )
+ (br $folding-inner0)
+ )
+ )
+ )
+ (return)
+ )
+ (nop)
+ (br $folding-inner1)
+ )
+ )
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (unreachable)
+ )
+ (func $terminating-multiple-separate (type $0)
+ (block $folding-inner1
+ (block
+ (block $folding-inner0
+ (block
+ (if
+ (i32.const 1)
+ (br $folding-inner0)
+ )
+ (if
+ (i32.const 1)
+ (br $folding-inner0)
+ )
+ (if
+ (i32.const 1)
+ (br $folding-inner1)
+ )
+ (if
+ (i32.const 1)
+ (br $folding-inner1)
+ )
+ )
+ (return)
+ )
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (drop
+ (i32.const 1)
+ )
+ (unreachable)
+ )
+ )
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (drop
+ (i32.const 2)
+ )
+ (unreachable)
+ )
+ (func $terminating-just-worth-it (type $0)
+ (block $folding-inner0
+ (block
+ (if
+ (i32.const 1)
+ (br $folding-inner0)
+ )
+ (if
+ (i32.const 2)
+ (br $folding-inner0)
+ )
+ (if
+ (i32.const 3)
+ (br $folding-inner0)
+ )
+ )
+ (return)
+ )
+ (nop)
+ (nop)
+ (nop)
+ (unreachable)
+ )
+ (func $terminating-not-worth-it (type $0)
+ (if
+ (i32.const 1)
+ (block
+ (nop)
+ (nop)
+ (unreachable)
+ )
+ )
+ (if
+ (i32.const 2)
+ (block
+ (nop)
+ (nop)
+ (unreachable)
+ )
+ )
+ (if
+ (i32.const 3)
+ (block
+ (nop)
+ (nop)
+ (unreachable)
+ )
+ )
+ )
+ (func $terminating-return (type $0)
+ (block $folding-inner0
+ (block
+ (if
+ (i32.const 1)
+ (br $folding-inner0)
+ )
+ (if
+ (i32.const 2)
+ (br $folding-inner0)
+ )
+ (if
+ (i32.const 3)
+ (br $folding-inner0)
+ )
+ )
+ (return)
+ )
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (nop)
+ (return)
+ )
+ (func $terminating-return-value (type $2) (result i32)
+ (block $folding-inner0
+ (block
+ (if
+ (i32.const 1)
+ (br $folding-inner0)
+ )
+ (if
+ (i32.const 2)
+ (br $folding-inner0)
+ )
+ (if
+ (i32.const 3)
+ (br $folding-inner0)
+ )
+ (if
+ (i32.const 3)
+ (block
+ (nop)
+ (return
+ (i32.add
+ (i32.const 111111111)
+ (i32.const 2222222)
+ )
+ )
+ )
+ )
+ (return
+ (i32.const 1234)
+ )
+ )
+ )
+ (nop)
+ (return
+ (i32.add
+ (i32.const 1)
+ (i32.const 2)
+ )
+ )
+ )
+ (func $terminating-fallthrough-value (type $2) (result i32)
+ (block $folding-inner0
+ (return
+ (block (result i32)
+ (if
+ (i32.const 1)
+ (br $folding-inner0)
+ )
+ (if
+ (i32.const 2)
+ (br $folding-inner0)
+ )
+ (if
+ (i32.const 3)
+ (br $folding-inner0)
+ )
+ (if
+ (i32.const 3)
+ (block
+ (nop)
+ (return
+ (i32.add
+ (i32.const 111111111)
+ (i32.const 2222222)
+ )
+ )
+ )
+ )
+ (i32.const 1234)
+ )
+ )
+ )
+ (nop)
+ (return
+ (i32.add
+ (i32.const 1)
+ (i32.const 2)
+ )
+ )
+ )
+ (func $big-return (type $2) (result i32)
+ (block $folding-inner0
+ (block
+ (if
+ (i32.const 1)
+ (br $folding-inner0)
+ )
+ (if
+ (i32.const 2)
+ (br $folding-inner0)
+ )
+ (if
+ (i32.const 3)
+ (br $folding-inner0)
+ )
+ (if
+ (i32.const 4)
+ (br $folding-inner0)
+ )
+ (if
+ (i32.const 5)
+ (br $folding-inner0)
+ )
+ (if
+ (i32.const 6)
+ (br $folding-inner0)
+ )
+ (unreachable)
+ )
+ )
+ (return
+ (i32.add
+ (i32.const 1)
+ (i32.const 2)
+ )
+ )
+ )
+ (func $return-mix (type $2) (result i32)
+ (block $folding-inner0
+ (block
+ (if
+ (i32.const 1)
+ (br $folding-inner0)
+ )
+ (if
+ (i32.const 2)
+ (br $folding-inner0)
+ )
+ (if
+ (i32.const 3)
+ (br $folding-inner0)
+ )
+ (if
+ (i32.const 4)
+ (br $folding-inner0)
+ )
+ (if
+ (i32.const 3)
+ (return
+ (i32.add
+ (i32.const 1)
+ (i32.const 234567)
+ )
+ )
+ )
+ (br $folding-inner0)
+ )
+ )
+ (return
+ (i32.add
+ (i32.const 1)
+ (i32.const 2)
+ )
+ )
+ )
+ (func $just-unreachable (type $0)
+ (unreachable)
+ )
+ (func $just-return (type $2) (result i32)
+ (return
+ (i32.add
+ (i32.const 1)
+ (i32.const 2)
+ )
+ )
+ )
+ (func $drop-if-with-value-but-unreachable (type $0)
+ (if
+ (i32.const 0)
+ (nop)
+ )
+ (block
+ (drop
+ (i32.const 0)
+ )
+ (block
+ (nop)
+ )
+ )
+ (if
+ (i32.const 0)
+ (nop)
+ (unreachable)
+ )
+ (nop)
+ (drop
+ (block (result i32)
+ (drop
+ (unreachable)
+ )
+ (block (result i32)
+ (i32.add
+ (i32.const 1)
+ (i32.const 2)
+ )
+ )
+ )
+ )
+ (drop
+ (if (result i32)
+ (i32.const 0)
+ (i32.add
+ (i32.const 1)
+ (i32.const 2)
+ )
+ (i32.add
+ (i32.const 1)
+ (i32.const 333333333)
+ )
+ )
+ )
+ )
+ (func $nested-control-flow (type $0)
+ (block $out
+ (block
+ (block $x
+ (if
+ (i32.const 0)
+ (br $x)
+ )
+ (if
+ (i32.const 0)
+ (br $x)
+ )
+ (br $x)
+ )
+ (if
+ (i32.const 1)
+ (br $out)
+ )
+ (drop
+ (i32.const 1)
+ )
+ (drop
+ (i32.const 2)
+ )
+ )
+ (drop
+ (i32.const 3)
+ )
+ )
+ )
+ (func $nested-control-flow-dangerous (type $0)
+ (block $folding-inner0
+ (block $out
+ (block
+ (if
+ (i32.const 0)
+ (block
+ (if
+ (i32.const 1)
+ (br $out)
+ )
+ (br $folding-inner0)
+ )
+ )
+ (if
+ (i32.const 0)
+ (block
+ (if
+ (i32.const 1)
+ (br $out)
+ )
+ (br $folding-inner0)
+ )
+ )
+ (if
+ (i32.const 1)
+ (br $out)
+ )
+ (br $folding-inner0)
+ )
+ (drop
+ (i32.const 3)
+ )
+ )
+ (return)
+ )
+ (drop
+ (i32.const 1)
+ )
+ (drop
+ (i32.const 2)
+ )
+ (return)
+ )
+ (func $nested-control-flow-dangerous-but-ok (type $0)
+ (block $folding-inner0
+ (block
+ (block $middle
+ (block
+ (if
+ (i32.const 0)
+ (block
+ (if
+ (i32.add
+ (i32.const 0)
+ (i32.const 1)
+ )
+ (br $middle)
+ )
+ (br $folding-inner0)
+ )
+ )
+ (if
+ (i32.const 0)
+ (block
+ (if
+ (i32.add
+ (i32.const 0)
+ (i32.const 1)
+ )
+ (br $middle)
+ )
+ (br $folding-inner0)
+ )
+ )
+ (if
+ (i32.add
+ (i32.const 0)
+ (i32.const 1)
+ )
+ (br $middle)
+ )
+ (br $folding-inner0)
+ )
+ )
+ (drop
+ (i32.const 3)
+ )
+ )
+ (return)
+ )
+ (drop
+ (i32.const 1)
+ )
+ (drop
+ (i32.const 2)
+ )
+ (return)
+ )
+ (func $nested-control-flow-dangerous-but-ok-b (type $0)
+ (block $out
+ (block $middle
+ (block
+ (if
+ (i32.const 0)
+ (block
+ (if
+ (i32.add
+ (i32.const 0)
+ (i32.const 1)
+ )
+ (br $middle)
+ )
+ (br $out)
+ )
+ )
+ (if
+ (i32.const 0)
+ (block
+ (if
+ (i32.add
+ (i32.const 0)
+ (i32.const 1)
+ )
+ (br $middle)
+ )
+ (br $out)
+ )
+ )
+ (if
+ (i32.add
+ (i32.const 0)
+ (i32.const 1)
+ )
+ (br $middle)
+ )
+ )
+ )
+ (unreachable)
+ )
+ (drop
+ (i32.const 1)
+ )
+ (drop
+ (i32.const 2)
+ )
+ (drop
+ (i32.const 3)
+ )
+ (drop
+ (i32.const 4)
+ )
+ (drop
+ (i32.const 1)
+ )
+ (drop
+ (i32.const 2)
+ )
+ (drop
+ (i32.const 3)
+ )
+ (drop
+ (i32.const 4)
+ )
+ )
+ (func $nested-control-flow-dangerous-but-ok-c (type $0)
+ (block $x
+ (block
+ (block $out
+ (block
+ (if
+ (i32.const 0)
+ (br $out)
+ )
+ (if
+ (i32.const 0)
+ (br $out)
+ )
+ (br $out)
+ )
+ (unreachable)
+ )
+ (if
+ (i32.add
+ (i32.const 0)
+ (i32.const 1)
+ )
+ (br $x)
+ )
+ (drop
+ (i32.const 1)
+ )
+ (drop
+ (i32.const 2)
+ )
+ )
+ (unreachable)
+ )
+ (drop
+ (i32.const 5)
+ )
+ )
+ (func $nested-control-flow-dangerous-but-ok-d (type $0)
+ (block
+ (block $out
+ (block
+ (if
+ (i32.const 0)
+ (br $out)
+ )
+ (if
+ (i32.const 0)
+ (br $out)
+ )
+ (br $out)
+ )
+ )
+ (block $x
+ (if
+ (i32.add
+ (i32.const 0)
+ (i32.const 1)
+ )
+ (br $x)
+ )
+ )
+ (drop
+ (i32.const 1)
+ )
+ (drop
+ (i32.const 2)
+ )
+ )
+ (drop
+ (i32.const 3)
+ )
+ )
+)
diff --git a/test/passes/remove-unused-names_code-folding.wast b/test/passes/remove-unused-names_code-folding.wast
new file mode 100644
index 000000000..35d95ba90
--- /dev/null
+++ b/test/passes/remove-unused-names_code-folding.wast
@@ -0,0 +1,1176 @@
+(module
+ (func $ifs
+ (if (i32.const 0) (nop))
+ (if (i32.const 0) (nop) (nop))
+ (if (i32.const 0) (nop) (unreachable))
+ (drop
+ (if (result i32) (i32.const 0)
+ (i32.add (i32.const 1) (i32.const 2))
+ (i32.add (i32.const 1) (i32.const 2))
+ )
+ )
+ (drop
+ (if (result i32) (i32.const 0)
+ (i32.add (i32.const 1) (i32.const 2))
+ (i32.add (i32.const 1) (i32.const 333333333))
+ )
+ )
+ )
+ (func $ifs-blocks
+ (if (i32.const 0)
+ (block
+ (nop)
+ )
+ (block
+ (nop)
+ )
+ )
+ (if (i32.const 0)
+ (block
+ (unreachable)
+ (nop)
+ )
+ (block
+ (nop)
+ )
+ )
+ (if (i32.const 0)
+ (block
+ (nop)
+ )
+ (block
+ (unreachable)
+ (nop)
+ )
+ )
+ (if (i32.const 0)
+ (block
+ (nop)
+ (unreachable)
+ )
+ (block
+ (nop)
+ )
+ )
+ (if (i32.const 0)
+ (block
+ (nop)
+ )
+ (block
+ (nop)
+ (unreachable)
+ )
+ )
+ )
+ (func $ifs-blocks-big
+ (if (i32.const 0)
+ (block
+ (drop (i32.add (i32.const 1) (i32.const 2)))
+ )
+ (block
+ (drop (i32.add (i32.const 1) (i32.const 2)))
+ )
+ )
+ (if (i32.const 0)
+ (block
+ (unreachable)
+ (drop (i32.add (i32.const 1) (i32.const 2)))
+ )
+ (block
+ (drop (i32.add (i32.const 1) (i32.const 2)))
+ )
+ )
+ (if (i32.const 0)
+ (block
+ (drop (i32.add (i32.const 1) (i32.const 2)))
+ )
+ (block
+ (unreachable)
+ (drop (i32.add (i32.const 1) (i32.const 2)))
+ )
+ )
+ (if (i32.const 0)
+ (block
+ (drop (i32.add (i32.const 1) (i32.const 2)))
+ (unreachable)
+ )
+ (block
+ (drop (i32.add (i32.const 1) (i32.const 2)))
+ )
+ )
+ (if (i32.const 0)
+ (block
+ (drop (i32.add (i32.const 1) (i32.const 2)))
+ )
+ (block
+ (drop (i32.add (i32.const 1) (i32.const 2)))
+ (unreachable)
+ )
+ )
+ )
+ (func $ifs-blocks-long
+ (if (i32.const 1)
+ (block
+ (drop (i32.const -1234))
+ (drop (i32.const -1000))
+ (drop (i32.const 1))
+ (nop)
+ (unreachable)
+ )
+ (block
+ (drop (i32.const 999))
+ (drop (i32.const 1))
+ (nop)
+ (unreachable)
+ )
+ )
+ (drop
+ (if (result i32) (i32.const 2)
+ (block (result i32)
+ (drop (i32.const -1234))
+ (drop (i32.const -1000))
+ (drop (i32.const 1))
+ (nop)
+ (unreachable)
+ (i32.const 2)
+ )
+ (block (result i32)
+ (drop (i32.const 999))
+ (drop (i32.const 1))
+ (nop)
+ (unreachable)
+ (i32.const 2)
+ )
+ )
+ )
+ (drop
+ (if (result i32) (i32.const 3)
+ (block (result i32)
+ (drop (i32.const -1234))
+ (drop (i32.const -1000))
+ (drop (i32.const 1))
+ (nop)
+ (i32.const 2)
+ )
+ (block (result i32)
+ (drop (i32.const 999))
+ (drop (i32.const 1))
+ (nop)
+ (i32.const 2)
+ )
+ )
+ )
+ )
+ (func $if-worth-it-i-dunno
+ ;; just 2, so not worth it
+ (if (i32.const 0) ;; (put them in ifs, so no block outside which would make us more confident in creating a block in hopes it would vanish)
+ (if (i32.const 0)
+ (block
+ (drop (i32.const -1234))
+ (drop (i32.const -1000))
+ (unreachable)
+ (unreachable)
+ )
+ (block
+ (drop (i32.const 999))
+ (drop (i32.const 1))
+ (unreachable)
+ (unreachable)
+ )
+ )
+ )
+ ;; 3, so why not
+ (if (i32.const 0) ;; (put them in ifs, so no block outside which would make us more confident in creating a block in hopes it would vanish)
+ (if (i32.const 0)
+ (block
+ (drop (i32.const -1234))
+ (drop (i32.const -1000))
+ (unreachable)
+ (unreachable)
+ (unreachable)
+ )
+ (block
+ (drop (i32.const 999))
+ (drop (i32.const 1))
+ (unreachable)
+ (unreachable)
+ (unreachable)
+ )
+ )
+ )
+ ;; just 2, but we'll empty out a block
+ (if (i32.const 0) ;; (put them in ifs, so no block outside which would make us more confident in creating a block in hopes it would vanish)
+ (if (i32.const 0)
+ (block
+ (unreachable)
+ (unreachable)
+ )
+ (block
+ (drop (i32.const 999))
+ (drop (i32.const 1))
+ (unreachable)
+ (unreachable)
+ )
+ )
+ )
+ ;; just 2, but we'll empty out a block
+ (if (i32.const 0) ;; (put them in ifs, so no block outside which would make us more confident in creating a block in hopes it would vanish)
+ (if (i32.const 0)
+ (block
+ (drop (i32.const -1234))
+ (drop (i32.const -1000))
+ (unreachable)
+ (unreachable)
+ )
+ (block
+ (unreachable)
+ (unreachable)
+ )
+ )
+ )
+ ;; just two, but on a block, so we hope to merge, and can optimize here
+ (block $a-holding-block
+ (if (i32.const 9999)
+ (block
+ (drop (i32.const -51234))
+ (drop (i32.const -51000))
+ (unreachable)
+ (unreachable)
+ )
+ (block
+ (drop (i32.const 5999))
+ (drop (i32.const 51))
+ (unreachable)
+ (unreachable)
+ )
+ )
+ )
+ ;; with value
+ (drop
+ (block $b-holding-block (result i32)
+ (if (result i32) (i32.const 9999)
+ (block (result i32)
+ (drop (i32.const -51234))
+ (drop (i32.const -51000))
+ (unreachable)
+ (i32.const 10)
+ )
+ (block (result i32)
+ (drop (i32.const 5999))
+ (drop (i32.const 51))
+ (unreachable)
+ (i32.const 10)
+ )
+ )
+ )
+ )
+ ;; oops, something in between
+ (block $c-holding-block
+ (drop
+ (if (result i32) (i32.const 9999)
+ (block (result i32)
+ (drop (i32.const -51234))
+ (drop (i32.const -51000))
+ (unreachable)
+ (i32.const 10)
+ )
+ (block (result i32)
+ (drop (i32.const 5999))
+ (drop (i32.const 51))
+ (unreachable)
+ (i32.const 10)
+ )
+ )
+ )
+ )
+ )
+ (func $no-grandparent
+ ;; if we had a parent block, we might optimize this
+ (if (i32.const 9999)
+ (block
+ (drop (i32.const -51234))
+ (drop (i32.const -51000))
+ (unreachable)
+ (unreachable)
+ )
+ (block
+ (drop (i32.const 5999))
+ (drop (i32.const 51))
+ (unreachable)
+ (unreachable)
+ )
+ )
+ )
+ (func $yes-grandparent
+ (block
+ (if (i32.const 9999)
+ (block
+ (drop (i32.const -51234))
+ (drop (i32.const -51000))
+ (unreachable)
+ (unreachable)
+ )
+ (block
+ (drop (i32.const 5999))
+ (drop (i32.const 51))
+ (unreachable)
+ (unreachable)
+ )
+ )
+ )
+ )
+ (func $ifs-named-block (param $x i32) (param $y i32) (result i32)
+ (block $out
+ (block $out2
+ (if (get_local $x)
+ (block
+ (br_if $out (get_local $y i32))
+ (nop)
+ )
+ (block
+ (br_if $out (get_local $y i32))
+ (nop)
+ )
+ )
+ (if (get_local $x)
+ (block
+ (br_if $out (get_local $y i32))
+ (nop)
+ )
+ (block
+ (br_if $out2 (get_local $y i32))
+ (nop)
+ )
+ )
+ (if (i32.const 1234)
+ (if (get_local $x)
+ (block
+ (nop)
+ (br_if $out (get_local $y i32))
+ (nop)
+ )
+ (block
+ (nop)
+ (br_if $out2 (get_local $y i32))
+ (nop)
+ )
+ )
+ )
+ (if (get_local $x)
+ (block $left
+ (br_if $left (get_local $y i32))
+ (nop)
+ )
+ (block
+ (br_if $out (get_local $y i32))
+ (nop)
+ )
+ )
+ (if (get_local $x)
+ (block
+ (br_if $out (get_local $y i32))
+ (nop)
+ )
+ (block $right
+ (br_if $right (get_local $y i32))
+ (nop)
+ )
+ )
+ )
+ (return (i32.const 10))
+ )
+ (return (i32.const 20))
+ )
+ (func $block
+ (block $x
+ (if (i32.const 0)
+ (block
+ (drop (i32.const 1))
+ (drop (i32.const 2))
+ (br $x)
+ )
+ )
+ (if (i32.const 0)
+ (block
+ (drop (i32.const 1))
+ (drop (i32.const 2))
+ (br $x)
+ )
+ )
+ ;; no fallthrough, another thing to merge
+ (drop (i32.const 1))
+ (drop (i32.const 2))
+ (br $x)
+ )
+ )
+ (func $block2
+ (block $x
+ (if (i32.const 0)
+ (block
+ (drop (i32.const 1))
+ (drop (i32.const 333333))
+ (br $x)
+ )
+ )
+ (if (i32.const 0)
+ (block
+ (drop (i32.const 1))
+ (drop (i32.const 2))
+ (br $x)
+ )
+ )
+ ;; no fallthrough, another thing to merge
+ (drop (i32.const 1))
+ (drop (i32.const 2))
+ (br $x)
+ )
+ )
+ (func $block3
+ (block $x
+ (if (i32.const 0)
+ (block
+ (drop (i32.const 1000))
+ (drop (i32.const 1))
+ (drop (i32.const 2))
+ (br $x)
+ )
+ )
+ (if (i32.const 0)
+ (block
+ (drop (i32.const 2000))
+ (drop (i32.const 3000))
+ (drop (i32.const 1))
+ (drop (i32.const 2))
+ (br $x)
+ )
+ )
+ (drop (i32.const 4000))
+ (drop (i32.const 5000))
+ (drop (i32.const 6000))
+ ;; no fallthrough, another thing to merge
+ (drop (i32.const 1))
+ (drop (i32.const 2))
+ (br $x)
+ )
+ )
+ (func $mixture
+ (block $out ;; then we reach the block, and the tail infos are stale, should ignore
+ (if (i32.const 1) ;; then we optimize the if, pushing those brs outside!
+ (block
+ (drop (i32.const 2)) ;; first we note the block tails for $out
+ (nop) (nop) (nop) (nop) (nop) (nop) ;; totally worth it
+ (br $out)
+ )
+ (block
+ (drop (i32.const 2))
+ (nop) (nop) (nop) (nop) (nop) (nop)
+ (br $out)
+ )
+ )
+ )
+ (block $out2
+ (if (i32.const 1)
+ (block
+ (drop (i32.const 3)) ;; leave something
+ (drop (i32.const 2))
+ (nop) (nop) (nop) (nop) (nop) (nop)
+ (br $out2)
+ )
+ (block
+ (drop (i32.const 4)) ;; leave something
+ (drop (i32.const 5)) ;; leave something
+ (drop (i32.const 2))
+ (nop) (nop) (nop) (nop) (nop) (nop)
+ (br $out2)
+ )
+ )
+ )
+ ;; now a case where do **do** want to fold for the block (which we can only do in a later pass)
+ (block $out3
+ (if (i32.const 1)
+ (block
+ (drop (i32.const 2))
+ (nop) (nop) (nop) (nop) (nop) (nop)
+ (br $out3)
+ )
+ (block
+ (drop (i32.const 2))
+ (nop) (nop) (nop) (nop) (nop) (nop)
+ (br $out3)
+ )
+ )
+ (if (i32.const 1)
+ (block
+ (drop (i32.const 2))
+ (nop) (nop) (nop) (nop) (nop) (nop)
+ (br $out3)
+ )
+ (block
+ (drop (i32.const 2))
+ (nop) (nop) (nop) (nop) (nop) (nop)
+ (br $out3)
+ )
+ )
+ (drop (i32.const 2))
+ (nop) (nop) (nop) (nop) (nop) (nop)
+ (br $out3)
+ )
+ )
+ (func $block-corners
+ ;; these should be merged
+ (block $x
+ (if (i32.const 0)
+ (block
+ (drop (i32.const 1))
+ (drop (i32.const 2))
+ (br $x)
+ )
+ )
+ (drop (i32.const 1))
+ (drop (i32.const 2))
+ )
+ ;; these should not
+ ;; values
+ (drop
+ (block $y (result i32)
+ (if (i32.const 0)
+ (block
+ (drop (i32.const 1))
+ (drop (i32.const 2))
+ (br $y (i32.const 3))
+ )
+ )
+ (drop (i32.const 1))
+ (drop (i32.const 2))
+ (br $y (i32.const 3))
+ )
+ )
+ (drop
+ (block $z (result i32)
+ (if (i32.const 0)
+ (block
+ (drop (i32.const 1))
+ (drop (i32.const 2))
+ (br $z (i32.const 2))
+ )
+ )
+ (drop (i32.const 1))
+ (drop (i32.const 2))
+ (i32.const 3)
+ )
+ )
+ ;; condition
+ (block $w
+ (if (i32.const 0)
+ (block
+ (drop (i32.const 1))
+ (drop (i32.const 2))
+ (br_if $w (i32.const 3))
+ )
+ )
+ (drop (i32.const 1))
+ (drop (i32.const 2))
+ )
+ ;; not at the end
+ (block $x1
+ (if (i32.const 0)
+ (block
+ (drop (i32.const 1))
+ (drop (i32.const 2))
+ (br $x1)
+ (nop)
+ )
+ )
+ (drop (i32.const 1))
+ (drop (i32.const 2))
+ )
+ ;; switches
+ (block $side
+ (block $x2
+ (br_table $x2 $side (i32.const 0))
+ (if (i32.const 0)
+ (block
+ (drop (i32.const 1))
+ (drop (i32.const 2))
+ (br $x2)
+ )
+ )
+ (drop (i32.const 1))
+ (drop (i32.const 2))
+ )
+ (block $x3
+ (br_table $side $x3 (i32.const 0))
+ (if (i32.const 0)
+ (block
+ (drop (i32.const 1))
+ (drop (i32.const 2))
+ (br $x3)
+ )
+ )
+ (drop (i32.const 1))
+ (drop (i32.const 2))
+ )
+ )
+ )
+ (func $terminating
+ (if (i32.const 1)
+ (block
+ (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop)
+ (unreachable)
+ )
+ )
+ (if (i32.const 2)
+ (block
+ (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop)
+ (unreachable)
+ )
+ )
+ (if (i32.const 3)
+ (block
+ (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop)
+ (unreachable)
+ )
+ )
+ )
+ (func $terminating-unreachable
+ (if (i32.const 1)
+ (block
+ (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop)
+ (unreachable)
+ )
+ )
+ (if (i32.const 2)
+ (block
+ (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop)
+ (unreachable)
+ )
+ )
+ (if (i32.const 3)
+ (block
+ (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop)
+ (unreachable)
+ )
+ )
+ (unreachable)
+ )
+ (func $terminating-value (result i32)
+ (if (i32.const 1)
+ (block
+ (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop)
+ (unreachable)
+ )
+ )
+ (if (i32.const 2)
+ (block
+ (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop)
+ (unreachable)
+ )
+ )
+ (if (i32.const 3)
+ (block
+ (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop)
+ (unreachable)
+ )
+ )
+ (i32.const 4)
+ )
+ (func $terminating-just-2
+ (if (i32.const 1)
+ (block
+ (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop)
+ (unreachable)
+ )
+ )
+ (if (i32.const 2)
+ (block
+ (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop)
+ (unreachable)
+ )
+ )
+ (if (i32.const 3)
+ (block
+ (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop)
+ (drop (i32.const 10))
+ (unreachable)
+ )
+ )
+ )
+ (func $terminating-shortness
+ (if (i32.const 1)
+ (block
+ (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop)
+ (unreachable)
+ )
+ )
+ (if (i32.const 2)
+ (block
+ (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) ;; shorter. we do the two long ones greedily, then the merged one and this can also be opted
+ (unreachable)
+ )
+ )
+ (if (i32.const 3)
+ (block
+ (drop (i32.const 10))
+ (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop)
+ (unreachable)
+ )
+ )
+ )
+ (func $terminating-multiple-separate
+ (if (i32.const 1)
+ (block
+ (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop)
+ (drop (i32.const 1))
+ (unreachable)
+ )
+ )
+ (if (i32.const 1)
+ (block
+ (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop)
+ (drop (i32.const 1))
+ (unreachable)
+ )
+ )
+ (if (i32.const 1)
+ (block
+ (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop)
+ (drop (i32.const 2))
+ (unreachable)
+ )
+ )
+ (if (i32.const 1)
+ (block
+ (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop)
+ (drop (i32.const 2))
+ (unreachable)
+ )
+ )
+ )
+ (func $terminating-just-worth-it
+ (if (i32.const 1)
+ (block
+ (nop) (nop) (nop)
+ (unreachable)
+ )
+ )
+ (if (i32.const 2)
+ (block
+ (nop) (nop) (nop)
+ (unreachable)
+ )
+ )
+ (if (i32.const 3)
+ (block
+ (nop) (nop) (nop)
+ (unreachable)
+ )
+ )
+ )
+ (func $terminating-not-worth-it
+ (if (i32.const 1)
+ (block
+ (nop) (nop)
+ (unreachable)
+ )
+ )
+ (if (i32.const 2)
+ (block
+ (nop) (nop)
+ (unreachable)
+ )
+ )
+ (if (i32.const 3)
+ (block
+ (nop) (nop)
+ (unreachable)
+ )
+ )
+ )
+ (func $terminating-return
+ (if (i32.const 1)
+ (block
+ (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop)
+ (return)
+ )
+ )
+ (if (i32.const 2)
+ (block
+ (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop)
+ (return)
+ )
+ )
+ (if (i32.const 3)
+ (block
+ (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop)
+ (return)
+ )
+ )
+ )
+ (func $terminating-return-value (result i32)
+ (if (i32.const 1)
+ (block
+ (nop)
+ (return (i32.add (i32.const 1) (i32.const 2)))
+ )
+ )
+ (if (i32.const 2)
+ (block
+ (nop)
+ (return (i32.add (i32.const 1) (i32.const 2)))
+ )
+ )
+ (if (i32.const 3)
+ (block
+ (nop)
+ (return (i32.add (i32.const 1) (i32.const 2)))
+ )
+ )
+ (if (i32.const 3)
+ (block
+ (nop)
+ (return (i32.add (i32.const 111111111) (i32.const 2222222)))
+ )
+ )
+ (return (i32.const 1234))
+ )
+ (func $terminating-fallthrough-value (result i32)
+ (if (i32.const 1)
+ (block
+ (nop)
+ (return (i32.add (i32.const 1) (i32.const 2)))
+ )
+ )
+ (if (i32.const 2)
+ (block
+ (nop)
+ (return (i32.add (i32.const 1) (i32.const 2)))
+ )
+ )
+ (if (i32.const 3)
+ (block
+ (nop)
+ (return (i32.add (i32.const 1) (i32.const 2)))
+ )
+ )
+ (if (i32.const 3)
+ (block
+ (nop)
+ (return (i32.add (i32.const 111111111) (i32.const 2222222)))
+ )
+ )
+ (i32.const 1234)
+ )
+ (func $big-return (result i32)
+ (if (i32.const 1) (return (i32.add (i32.const 1) (i32.const 2))))
+ (if (i32.const 2) (return (i32.add (i32.const 1) (i32.const 2))))
+ (if (i32.const 3) (return (i32.add (i32.const 1) (i32.const 2))))
+ (if (i32.const 4) (return (i32.add (i32.const 1) (i32.const 2))))
+ (if (i32.const 5) (return (i32.add (i32.const 1) (i32.const 2))))
+ (if (i32.const 6) (return (i32.add (i32.const 1) (i32.const 2))))
+ (unreachable)
+ )
+ (func $return-mix (result i32)
+ (if (i32.const 1) (return (i32.add (i32.const 1) (i32.const 2))))
+ (if (i32.const 2) (return (i32.add (i32.const 1) (i32.const 2))))
+ (if (i32.const 3) (return (i32.add (i32.const 1) (i32.const 2))))
+ (if (i32.const 4) (return (i32.add (i32.const 1) (i32.const 2))))
+ (if (i32.const 3) (return (i32.add (i32.const 1) (i32.const 234567))))
+ (return (i32.add (i32.const 1) (i32.const 2))) ;; on a block, and the toplevel in fact
+ )
+ (func $just-unreachable
+ (unreachable)
+ )
+ (func $just-return (result i32)
+ (return (i32.add (i32.const 1) (i32.const 2))) ;; on a block, and the toplevel in fact
+ )
+ (func $drop-if-with-value-but-unreachable
+ (block $label$0
+ (if
+ (i32.const 0)
+ (block $label$1
+ (nop)
+ )
+ )
+ (if
+ (i32.const 0)
+ (block $label$2
+ (nop)
+ )
+ (block $label$3
+ (nop)
+ )
+ )
+ (if
+ (i32.const 0)
+ (block $label$4
+ (nop)
+ )
+ (block $label$5
+ (unreachable)
+ )
+ )
+ (nop)
+ (drop
+ (if (result i32) ;; we replace this if, must replace with same type!
+ (unreachable)
+ (block $label$6 (result i32)
+ (i32.add
+ (i32.const 1)
+ (i32.const 2)
+ )
+ )
+ (block $label$7 (result i32)
+ (i32.add
+ (i32.const 1)
+ (i32.const 2)
+ )
+ )
+ )
+ )
+ (drop
+ (if (result i32)
+ (i32.const 0)
+ (block $label$8 (result i32)
+ (i32.add
+ (i32.const 1)
+ (i32.const 2)
+ )
+ )
+ (block $label$9 (result i32)
+ (i32.add
+ (i32.const 1)
+ (i32.const 333333333)
+ )
+ )
+ )
+ )
+ )
+ )
+ (func $nested-control-flow
+ (block $out
+ (block $x
+ (if (i32.const 0)
+ (block
+ (if (i32.const 1)
+ (br $out)
+ )
+ (drop (i32.const 1))
+ (drop (i32.const 2))
+ (br $x)
+ )
+ )
+ (if (i32.const 0)
+ (block
+ (if (i32.const 1)
+ (br $out)
+ )
+ (drop (i32.const 1))
+ (drop (i32.const 2))
+ (br $x)
+ )
+ )
+ ;; no fallthrough, another thing to merge
+ (if (i32.const 1)
+ (br $out)
+ )
+ (drop (i32.const 1))
+ (drop (i32.const 2))
+ (br $x)
+ )
+ (drop (i32.const 3))
+ )
+ )
+ (func $nested-control-flow-dangerous
+ (block $out
+ (block $x
+ (if (i32.const 0)
+ (block
+ (if (i32.const 1)
+ (br $out) ;; this br cannot be moved out of the $out block!
+ )
+ (drop (i32.const 1))
+ (drop (i32.const 2))
+ (return)
+ )
+ )
+ (if (i32.const 0)
+ (block
+ (if (i32.const 1)
+ (br $out)
+ )
+ (drop (i32.const 1))
+ (drop (i32.const 2))
+ (return)
+ )
+ )
+ ;; no fallthrough, another thing to merge
+ (if (i32.const 1)
+ (br $out)
+ )
+ (drop (i32.const 1))
+ (drop (i32.const 2))
+ (return)
+ )
+ (drop (i32.const 3))
+ )
+ )
+ (func $nested-control-flow-dangerous-but-ok
+ (block $out
+ (block $middle
+ (block $x
+ (if (i32.const 0)
+ (block
+ (if (i32.add (i32.const 0) (i32.const 1))
+ (br $middle)
+ )
+ (drop (i32.const 1))
+ (drop (i32.const 2))
+ (return)
+ )
+ )
+ (if (i32.const 0)
+ (block
+ (if (i32.add (i32.const 0) (i32.const 1))
+ (br $middle)
+ )
+ (drop (i32.const 1))
+ (drop (i32.const 2))
+ (return)
+ )
+ )
+ ;; no fallthrough, another thing to merge
+ (if (i32.add (i32.const 0) (i32.const 1))
+ (br $middle)
+ )
+ (drop (i32.const 1))
+ (drop (i32.const 2))
+ (return)
+ )
+ )
+ (drop (i32.const 3))
+ )
+ )
+ (func $nested-control-flow-dangerous-but-ok-b
+ (block $out
+ (block $middle
+ (block $x
+ (if (i32.const 0)
+ (block
+ (if (i32.add (i32.const 0) (i32.const 1))
+ (br $middle) ;; this is dangerous - we branch to middle with is inside out, so we can't move this out of out
+ )
+ (drop (i32.const 1))
+ (drop (i32.const 2))
+ (drop (i32.const 3))
+ (drop (i32.const 4))
+ (drop (i32.const 1))
+ (drop (i32.const 2))
+ (drop (i32.const 3))
+ (drop (i32.const 4))
+ (br $out)
+ )
+ )
+ (if (i32.const 0)
+ (block
+ (if (i32.add (i32.const 0) (i32.const 1))
+ (br $middle)
+ )
+ (drop (i32.const 1))
+ (drop (i32.const 2))
+ (drop (i32.const 3))
+ (drop (i32.const 4))
+ (drop (i32.const 1))
+ (drop (i32.const 2))
+ (drop (i32.const 3))
+ (drop (i32.const 4))
+ (br $out)
+ )
+ )
+ ;; no fallthrough, another thing to merge
+ (if (i32.add (i32.const 0) (i32.const 1))
+ (br $middle)
+ )
+ )
+ )
+ (unreachable) ;; no fallthrough
+ )
+ )
+ (func $nested-control-flow-dangerous-but-ok-c
+ (block $x
+ (block $out
+ (block $middle
+ (if (i32.const 0)
+ (block
+ (if (i32.add (i32.const 0) (i32.const 1))
+ (br $x) ;; this is ok - we branch to x which is outside of out
+ )
+ (drop (i32.const 1))
+ (drop (i32.const 2))
+ (br $out)
+ )
+ )
+ (if (i32.const 0)
+ (block
+ (if (i32.add (i32.const 0) (i32.const 1))
+ (br $x)
+ )
+ (drop (i32.const 1))
+ (drop (i32.const 2))
+ (br $out)
+ )
+ )
+ ;; no fallthrough, another thing to merge
+ (if (i32.add (i32.const 0) (i32.const 1))
+ (br $x)
+ )
+ (drop (i32.const 1))
+ (drop (i32.const 2))
+ (br $out)
+ )
+ (unreachable) ;; no fallthrough
+ )
+ (unreachable) ;; no fallthrough
+ )
+ (drop (i32.const 5))
+ )
+ (func $nested-control-flow-dangerous-but-ok-d
+ (block $out
+ (block $middle
+ (if (i32.const 0)
+ (block
+ (block $x
+ (if (i32.add (i32.const 0) (i32.const 1))
+ (br $x) ;; this is ok - we branch to x which is nested in us
+ )
+ )
+ (drop (i32.const 1))
+ (drop (i32.const 2))
+ (br $out)
+ )
+ )
+ (if (i32.const 0)
+ (block
+ (block $x
+ (if (i32.add (i32.const 0) (i32.const 1))
+ (br $x) ;; this is ok - we branch to x which is nested in us
+ )
+ )
+ (drop (i32.const 1))
+ (drop (i32.const 2))
+ (br $out)
+ )
+ )
+ ;; no fallthrough, another thing to merge
+ (block $x
+ (if (i32.add (i32.const 0) (i32.const 1))
+ (br $x) ;; this is ok - we branch to x which is nested in us
+ )
+ )
+ (drop (i32.const 1))
+ (drop (i32.const 2))
+ (br $out)
+ )
+ )
+ (drop (i32.const 3))
+ )
+)