summaryrefslogtreecommitdiff
path: root/test/passes/remove-unused-names_code-folding_all-features.wast
diff options
context:
space:
mode:
Diffstat (limited to 'test/passes/remove-unused-names_code-folding_all-features.wast')
-rw-r--r--test/passes/remove-unused-names_code-folding_all-features.wast1244
1 files changed, 1244 insertions, 0 deletions
diff --git a/test/passes/remove-unused-names_code-folding_all-features.wast b/test/passes/remove-unused-names_code-folding_all-features.wast
new file mode 100644
index 000000000..ad803864e
--- /dev/null
+++ b/test/passes/remove-unused-names_code-folding_all-features.wast
@@ -0,0 +1,1244 @@
+(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 (local.get $x)
+ (block
+ (br_if $out (local.get $y i32))
+ (nop)
+ )
+ (block
+ (br_if $out (local.get $y i32))
+ (nop)
+ )
+ )
+ (if (local.get $x)
+ (block
+ (br_if $out (local.get $y i32))
+ (nop)
+ )
+ (block
+ (br_if $out2 (local.get $y i32))
+ (nop)
+ )
+ )
+ (if (i32.const 1234)
+ (if (local.get $x)
+ (block
+ (nop)
+ (br_if $out (local.get $y i32))
+ (nop)
+ )
+ (block
+ (nop)
+ (br_if $out2 (local.get $y i32))
+ (nop)
+ )
+ )
+ )
+ (if (local.get $x)
+ (block $left
+ (br_if $left (local.get $y i32))
+ (nop)
+ )
+ (block
+ (br_if $out (local.get $y i32))
+ (nop)
+ )
+ )
+ (if (local.get $x)
+ (block
+ (br_if $out (local.get $y i32))
+ (nop)
+ )
+ (block $right
+ (br_if $right (local.get $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))
+ )
+ (func $if-suffix (param $x i32) (result i32)
+ (if
+ (local.get $x)
+ (local.set $x (i32.const 1))
+ (block
+ (drop (call $if-suffix (i32.const -1)))
+ (local.set $x (i32.const 1))
+ )
+ )
+ (if (result i32)
+ (local.get $x)
+ (i32.const 2)
+ (block (result i32)
+ (drop (call $if-suffix (i32.const -2)))
+ (i32.const 2)
+ )
+ )
+ )
+
+ (func $exnref_pop_test (local $exn exnref)
+ (try
+ (try
+ (catch
+ ;; Expressions containing exnref.pop should NOT be taken out and
+ ;; folded.
+ (local.set $exn (exnref.pop))
+ (drop (i32.const 111))
+ (drop (i32.const 222))
+ (drop (i32.const 333))
+ (unreachable)
+ )
+ )
+ (catch
+ (local.set $exn (exnref.pop))
+ (drop (i32.const 111))
+ (drop (i32.const 222))
+ (drop (i32.const 333))
+ (unreachable)
+ )
+ )
+ )
+
+ (event $e (attr 0)) ;; exception with no param
+ (func $br_on_exn_target_block (local $exn exnref)
+ ;; Here this block $x is targeted by br_on_exn, so code folding out of this
+ ;; block should NOT happen.
+ (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)
+ )
+ )
+ (drop (br_on_exn $x $e (local.get $exn)))
+ ;; no fallthrough, another thing to merge
+ (drop (i32.const 1))
+ (drop (i32.const 2))
+ (br $x)
+ )
+ )
+)