summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2017-06-13 16:05:01 -0700
committerGitHub <noreply@github.com>2017-06-13 16:05:01 -0700
commitb5b40c9ab0c35ed74e97a6491e15651382091b2e (patch)
treed2ec6c2006089d8385b850a730af4be936874314 /test
parent61b409bc845f385f1d7ea7ac81d1649b63435828 (diff)
downloadbinaryen-b5b40c9ab0c35ed74e97a6491e15651382091b2e.tar.gz
binaryen-b5b40c9ab0c35ed74e97a6491e15651382091b2e.tar.bz2
binaryen-b5b40c9ab0c35ed74e97a6491e15651382091b2e.zip
SSA pass (#1049)
* Add SSA pass which ensures a single assign for each local, except for merged locals where we ensure exactly a single assign from one of the paths leading to that use * Also add InstrumentLocals pass, useful for debugging locals (similar to InstrumentMemory but for locals) * Fix a PickLoadSigns bug with tees not being ignored, which was not noticed until now because we ran it on flatter output by default, but the ssa pass uncovered the bug
Diffstat (limited to 'test')
-rw-r--r--test/passes/instrument-locals.txt118
-rw-r--r--test/passes/instrument-locals.wast29
-rw-r--r--test/passes/pick-load-signs.txt16
-rw-r--r--test/passes/pick-load-signs.wast16
-rw-r--r--test/passes/ssa.txt694
-rw-r--r--test/passes/ssa.wast315
6 files changed, 1188 insertions, 0 deletions
diff --git a/test/passes/instrument-locals.txt b/test/passes/instrument-locals.txt
new file mode 100644
index 000000000..5cc8a98fe
--- /dev/null
+++ b/test/passes/instrument-locals.txt
@@ -0,0 +1,118 @@
+(module
+ (type $0 (func))
+ (type $FUNCSIG$iiii (func (param i32 i32 i32) (result i32)))
+ (type $FUNCSIG$jiij (func (param i32 i32 i64) (result i64)))
+ (type $FUNCSIG$fiif (func (param i32 i32 f32) (result f32)))
+ (type $FUNCSIG$diid (func (param i32 i32 f64) (result f64)))
+ (import "instrument" "get_i32" (func $get_i32 (param i32 i32 i32) (result i32)))
+ (import "instrument" "get_i64" (func $get_i64 (param i32 i32 i64) (result i64)))
+ (import "instrument" "get_f32" (func $get_f32 (param i32 i32 f32) (result f32)))
+ (import "instrument" "get_f64" (func $get_f64 (param i32 i32 f64) (result f64)))
+ (import "instrument" "set_i32" (func $set_i32 (param i32 i32 i32) (result i32)))
+ (import "instrument" "set_i64" (func $set_i64 (param i32 i32 i64) (result i64)))
+ (import "instrument" "set_f32" (func $set_f32 (param i32 i32 f32) (result f32)))
+ (import "instrument" "set_f64" (func $set_f64 (param i32 i32 f64) (result f64)))
+ (memory $0 0)
+ (func $A (type $0)
+ (local $x i32)
+ (local $y i64)
+ (local $z f32)
+ (local $w f64)
+ (drop
+ (call $get_i32
+ (i32.const 0)
+ (i32.const 0)
+ (get_local $x)
+ )
+ )
+ (drop
+ (get_local $y)
+ )
+ (drop
+ (call $get_f32
+ (i32.const 1)
+ (i32.const 2)
+ (get_local $z)
+ )
+ )
+ (drop
+ (call $get_f64
+ (i32.const 2)
+ (i32.const 3)
+ (get_local $w)
+ )
+ )
+ (drop
+ (call $get_i32
+ (i32.const 3)
+ (i32.const 0)
+ (get_local $x)
+ )
+ )
+ (drop
+ (get_local $y)
+ )
+ (drop
+ (call $get_f32
+ (i32.const 4)
+ (i32.const 2)
+ (get_local $z)
+ )
+ )
+ (drop
+ (call $get_f64
+ (i32.const 5)
+ (i32.const 3)
+ (get_local $w)
+ )
+ )
+ (set_local $x
+ (call $set_i32
+ (i32.const 6)
+ (i32.const 0)
+ (i32.const 1)
+ )
+ )
+ (set_local $y
+ (i64.const 2)
+ )
+ (set_local $z
+ (call $set_f32
+ (i32.const 7)
+ (i32.const 2)
+ (f32.const 3.2100000381469727)
+ )
+ )
+ (set_local $w
+ (call $set_f64
+ (i32.const 8)
+ (i32.const 3)
+ (f64.const 4.321)
+ )
+ )
+ (set_local $x
+ (call $set_i32
+ (i32.const 9)
+ (i32.const 0)
+ (i32.const 11)
+ )
+ )
+ (set_local $y
+ (i64.const 22)
+ )
+ (set_local $z
+ (call $set_f32
+ (i32.const 10)
+ (i32.const 2)
+ (f32.const 33.209999084472656)
+ )
+ )
+ (set_local $w
+ (call $set_f64
+ (i32.const 11)
+ (i32.const 3)
+ (f64.const 44.321)
+ )
+ )
+ )
+)
diff --git a/test/passes/instrument-locals.wast b/test/passes/instrument-locals.wast
new file mode 100644
index 000000000..b7e34c6d6
--- /dev/null
+++ b/test/passes/instrument-locals.wast
@@ -0,0 +1,29 @@
+(module
+ (func $A
+ (local $x i32)
+ (local $y i64)
+ (local $z f32)
+ (local $w f64)
+
+ (drop (get_local $x))
+ (drop (get_local $y))
+ (drop (get_local $z))
+ (drop (get_local $w))
+
+ (drop (get_local $x))
+ (drop (get_local $y))
+ (drop (get_local $z))
+ (drop (get_local $w))
+
+ (set_local $x (i32.const 1))
+ (set_local $y (i64.const 2))
+ (set_local $z (f32.const 3.21))
+ (set_local $w (f64.const 4.321))
+
+ (set_local $x (i32.const 11))
+ (set_local $y (i64.const 22))
+ (set_local $z (f32.const 33.21))
+ (set_local $w (f64.const 44.321))
+ )
+)
+
diff --git a/test/passes/pick-load-signs.txt b/test/passes/pick-load-signs.txt
index 707bb50e9..e8507fa29 100644
--- a/test/passes/pick-load-signs.txt
+++ b/test/passes/pick-load-signs.txt
@@ -260,4 +260,20 @@
(i32.const 1024)
)
)
+ (func $tees (type $0)
+ (local $y i32)
+ (drop
+ (tee_local $y
+ (i32.load8_s
+ (i32.const 1024)
+ )
+ )
+ )
+ (drop
+ (i32.and
+ (get_local $y)
+ (i32.const 255)
+ )
+ )
+ )
)
diff --git a/test/passes/pick-load-signs.wast b/test/passes/pick-load-signs.wast
index 49105e497..33f814926 100644
--- a/test/passes/pick-load-signs.wast
+++ b/test/passes/pick-load-signs.wast
@@ -257,4 +257,20 @@
(i32.const 1024)
)
)
+ (func $tees
+ (local $y i32)
+ (drop ;; a "use", so we can't alter the value
+ (tee_local $y
+ (i32.load8_s
+ (i32.const 1024)
+ )
+ )
+ )
+ (drop
+ (i32.and
+ (get_local $y)
+ (i32.const 255)
+ )
+ )
+ )
)
diff --git a/test/passes/ssa.txt b/test/passes/ssa.txt
new file mode 100644
index 000000000..3d410057c
--- /dev/null
+++ b/test/passes/ssa.txt
@@ -0,0 +1,694 @@
+(module
+ (type $0 (func (param i32)))
+ (type $1 (func))
+ (memory $0 0)
+ (func $basics (type $0) (param $x i32)
+ (local $y i32)
+ (local $z f32)
+ (local $w i64)
+ (local $t f64)
+ (local $5 i32)
+ (local $6 f64)
+ (local $7 f64)
+ (drop
+ (get_local $x)
+ )
+ (drop
+ (i32.const 0)
+ )
+ (drop
+ (f32.const 0)
+ )
+ (drop
+ (i64.const 0)
+ )
+ (drop
+ (f64.const 0)
+ )
+ (set_local $5
+ (i32.const 100)
+ )
+ (drop
+ (get_local $5)
+ )
+ (set_local $6
+ (f64.const 2)
+ )
+ (drop
+ (get_local $6)
+ )
+ (set_local $7
+ (f64.const 33)
+ )
+ (drop
+ (get_local $7)
+ )
+ (drop
+ (get_local $7)
+ )
+ )
+ (func $if (type $0) (param $p i32)
+ (local $x i32)
+ (local $y i32)
+ (local $3 i32)
+ (local $4 i32)
+ (local $5 i32)
+ (local $6 i32)
+ (local $7 i32)
+ (local $8 i32)
+ (local $9 i32)
+ (local $10 i32)
+ (local $11 i32)
+ (local $12 i32)
+ (local $13 i32)
+ (local $14 i32)
+ (local $15 i32)
+ (local $16 i32)
+ (local $17 i32)
+ (set_local $13
+ (get_local $p)
+ )
+ (block
+ (drop
+ (if i32
+ (i32.const 1)
+ (i32.const 0)
+ (i32.const 0)
+ )
+ )
+ (if
+ (i32.const 1)
+ (set_local $3
+ (tee_local $15
+ (tee_local $14
+ (tee_local $12
+ (i32.const 1)
+ )
+ )
+ )
+ )
+ )
+ (drop
+ (get_local $12)
+ )
+ (if
+ (i32.const 1)
+ (set_local $4
+ (tee_local $13
+ (i32.const 1)
+ )
+ )
+ )
+ (drop
+ (get_local $13)
+ )
+ (if
+ (i32.const 1)
+ (set_local $5
+ (tee_local $15
+ (tee_local $14
+ (i32.const 2)
+ )
+ )
+ )
+ (nop)
+ )
+ (drop
+ (get_local $14)
+ )
+ (if
+ (i32.const 1)
+ (nop)
+ (set_local $6
+ (tee_local $15
+ (i32.const 3)
+ )
+ )
+ )
+ (drop
+ (get_local $15)
+ )
+ (if
+ (i32.const 1)
+ (set_local $7
+ (tee_local $16
+ (i32.const 4)
+ )
+ )
+ (set_local $8
+ (tee_local $16
+ (i32.const 5)
+ )
+ )
+ )
+ (drop
+ (get_local $16)
+ )
+ (if
+ (i32.const 1)
+ (set_local $9
+ (tee_local $17
+ (i32.const 6)
+ )
+ )
+ (block $block
+ (set_local $10
+ (i32.const 7)
+ )
+ (set_local $11
+ (tee_local $17
+ (i32.const 8)
+ )
+ )
+ )
+ )
+ (drop
+ (get_local $17)
+ )
+ )
+ )
+ (func $if2 (type $0) (param $x i32)
+ (local $1 i32)
+ (local $2 i32)
+ (set_local $2
+ (get_local $x)
+ )
+ (block
+ (if
+ (i32.const 1)
+ (block $block
+ (set_local $1
+ (tee_local $2
+ (i32.const 1)
+ )
+ )
+ (drop
+ (get_local $1)
+ )
+ )
+ )
+ (drop
+ (get_local $2)
+ )
+ )
+ )
+ (func $block (type $0) (param $x i32)
+ (local $1 i32)
+ (local $2 i32)
+ (set_local $2
+ (get_local $x)
+ )
+ (block
+ (block $out
+ (br_if $out
+ (i32.const 2)
+ )
+ (set_local $1
+ (tee_local $2
+ (i32.const 1)
+ )
+ )
+ )
+ (drop
+ (get_local $2)
+ )
+ )
+ )
+ (func $block2 (type $0) (param $x i32)
+ (local $1 i32)
+ (local $2 i32)
+ (local $3 i32)
+ (local $4 i32)
+ (local $5 i32)
+ (local $6 i32)
+ (block $out
+ (set_local $1
+ (tee_local $6
+ (i32.const 1)
+ )
+ )
+ (drop
+ (get_local $1)
+ )
+ (br_if $out
+ (i32.const 2)
+ )
+ (drop
+ (get_local $1)
+ )
+ (if
+ (i32.const 3)
+ (block $block
+ (set_local $2
+ (tee_local $6
+ (i32.const 1)
+ )
+ )
+ (drop
+ (get_local $2)
+ )
+ (br $out)
+ )
+ )
+ (drop
+ (get_local $1)
+ )
+ (set_local $3
+ (tee_local $6
+ (i32.const 4)
+ )
+ )
+ (drop
+ (get_local $3)
+ )
+ (if
+ (i32.const 5)
+ (br $out)
+ )
+ (drop
+ (get_local $3)
+ )
+ (if
+ (i32.const 6)
+ (nop)
+ )
+ (if
+ (i32.const 7)
+ (nop)
+ (nop)
+ )
+ (block $in
+ (set_local $4
+ (tee_local $6
+ (i32.const 8)
+ )
+ )
+ (drop
+ (get_local $4)
+ )
+ (br_table $in $out
+ (i32.const 9)
+ )
+ )
+ (drop
+ (get_local $4)
+ )
+ (block $in2
+ (set_local $5
+ (tee_local $6
+ (i32.const 10)
+ )
+ )
+ (drop
+ (get_local $5)
+ )
+ (br_table $out $in2
+ (i32.const 11)
+ )
+ )
+ (drop
+ (get_local $5)
+ )
+ )
+ (drop
+ (get_local $6)
+ )
+ )
+ (func $loop (type $0) (param $x i32)
+ (local $1 i32)
+ (local $2 i32)
+ (set_local $2
+ (get_local $x)
+ )
+ (block
+ (drop
+ (get_local $x)
+ )
+ (loop $moar
+ (drop
+ (get_local $2)
+ )
+ (set_local $1
+ (tee_local $2
+ (i32.const 1)
+ )
+ )
+ (br_if $moar
+ (i32.const 2)
+ )
+ )
+ (drop
+ (get_local $1)
+ )
+ )
+ )
+ (func $loop2 (type $0) (param $x i32)
+ (local $1 i32)
+ (local $2 i32)
+ (local $3 i32)
+ (local $4 i32)
+ (set_local $4
+ (get_local $x)
+ )
+ (block
+ (drop
+ (get_local $x)
+ )
+ (loop $moar
+ (drop
+ (get_local $4)
+ )
+ (set_local $1
+ (i32.const 1)
+ )
+ (drop
+ (get_local $1)
+ )
+ (set_local $2
+ (tee_local $4
+ (i32.const 123)
+ )
+ )
+ (drop
+ (get_local $2)
+ )
+ (br_if $moar
+ (i32.const 2)
+ )
+ (drop
+ (get_local $2)
+ )
+ (set_local $3
+ (i32.const 3)
+ )
+ (drop
+ (get_local $3)
+ )
+ )
+ (drop
+ (get_local $3)
+ )
+ )
+ )
+ (func $loop2-zeroinit (type $1)
+ (local $x i32)
+ (local $1 i32)
+ (local $2 i32)
+ (local $3 i32)
+ (local $4 i32)
+ (drop
+ (i32.const 0)
+ )
+ (loop $moar
+ (drop
+ (get_local $4)
+ )
+ (set_local $1
+ (i32.const 1)
+ )
+ (drop
+ (get_local $1)
+ )
+ (set_local $2
+ (tee_local $4
+ (i32.const 123)
+ )
+ )
+ (drop
+ (get_local $2)
+ )
+ (br_if $moar
+ (i32.const 2)
+ )
+ (drop
+ (get_local $2)
+ )
+ (set_local $3
+ (i32.const 3)
+ )
+ (drop
+ (get_local $3)
+ )
+ )
+ (drop
+ (get_local $3)
+ )
+ )
+ (func $real-loop (type $0) (param $param i32)
+ (local $loopvar i32)
+ (local $inc i32)
+ (local $3 i32)
+ (local $4 i32)
+ (local $5 i32)
+ (local $6 i32)
+ (set_local $3
+ (tee_local $6
+ (get_local $param)
+ )
+ )
+ (loop $more
+ (block $stop
+ (if
+ (i32.const 1)
+ (br $stop)
+ )
+ (set_local $4
+ (i32.add
+ (get_local $6)
+ (i32.const 1)
+ )
+ )
+ (set_local $5
+ (tee_local $6
+ (get_local $4)
+ )
+ )
+ (br $more)
+ )
+ )
+ (drop
+ (get_local $6)
+ )
+ )
+ (func $real-loop-outblock (type $0) (param $param i32)
+ (local $loopvar i32)
+ (local $inc i32)
+ (local $3 i32)
+ (local $4 i32)
+ (local $5 i32)
+ (local $6 i32)
+ (set_local $3
+ (tee_local $6
+ (get_local $param)
+ )
+ )
+ (block $stop
+ (loop $more
+ (if
+ (i32.const 1)
+ (br $stop)
+ )
+ (set_local $4
+ (i32.add
+ (get_local $6)
+ (i32.const 1)
+ )
+ )
+ (set_local $5
+ (tee_local $6
+ (get_local $4)
+ )
+ )
+ (br $more)
+ )
+ )
+ (drop
+ (get_local $6)
+ )
+ )
+ (func $loop-loop-param (type $0) (param $param i32)
+ (local $1 i32)
+ (local $2 i32)
+ (local $3 i32)
+ (local $4 i32)
+ (set_local $3
+ (get_local $param)
+ )
+ (set_local $4
+ (get_local $param)
+ )
+ (block
+ (loop $loop1
+ (block $out1
+ (if
+ (get_local $3)
+ (br $out1)
+ )
+ (set_local $1
+ (tee_local $4
+ (tee_local $3
+ (i32.const 1)
+ )
+ )
+ )
+ (br $loop1)
+ )
+ )
+ (loop $loop2
+ (block $out2
+ (if
+ (get_local $4)
+ (br $out2)
+ )
+ (set_local $2
+ (tee_local $4
+ (i32.const 2)
+ )
+ )
+ (br $loop2)
+ )
+ )
+ )
+ )
+ (func $loop-loop-param-nomerge (type $0) (param $param i32)
+ (local $1 i32)
+ (local $2 i32)
+ (local $3 i32)
+ (loop $loop1
+ (block $out1
+ (set_local $1
+ (tee_local $3
+ (i32.const 1)
+ )
+ )
+ (if
+ (get_local $1)
+ (br $out1)
+ )
+ (br $loop1)
+ )
+ )
+ (loop $loop2
+ (block $out2
+ (if
+ (get_local $3)
+ (br $out2)
+ )
+ (set_local $2
+ (tee_local $3
+ (i32.const 2)
+ )
+ )
+ (br $loop2)
+ )
+ )
+ )
+ (func $loop-nesting (type $0) (param $x i32)
+ (local $1 i32)
+ (local $2 i32)
+ (local $3 i32)
+ (local $4 i32)
+ (local $5 i32)
+ (set_local $3
+ (get_local $x)
+ )
+ (set_local $4
+ (get_local $x)
+ )
+ (set_local $5
+ (get_local $x)
+ )
+ (block
+ (block $out
+ (loop $loop1
+ (if
+ (get_local $3)
+ (br $out)
+ )
+ (loop $loop2
+ (if
+ (get_local $4)
+ (br $out)
+ )
+ (set_local $1
+ (tee_local $5
+ (tee_local $4
+ (i32.const 1)
+ )
+ )
+ )
+ (br $loop2)
+ )
+ (set_local $2
+ (tee_local $5
+ (tee_local $4
+ (tee_local $3
+ (i32.const 2)
+ )
+ )
+ )
+ )
+ (br $loop1)
+ )
+ )
+ (drop
+ (get_local $5)
+ )
+ )
+ )
+ (func $loop-nesting-2 (type $0) (param $x i32)
+ (local $1 i32)
+ (local $2 i32)
+ (local $3 i32)
+ (local $4 i32)
+ (local $5 i32)
+ (set_local $3
+ (get_local $x)
+ )
+ (set_local $4
+ (get_local $x)
+ )
+ (set_local $5
+ (get_local $x)
+ )
+ (block
+ (block $out
+ (loop $loop1
+ (if
+ (get_local $3)
+ (br $out)
+ )
+ (loop $loop2
+ (if
+ (get_local $4)
+ (br $out)
+ )
+ (set_local $1
+ (tee_local $5
+ (tee_local $4
+ (i32.const 1)
+ )
+ )
+ )
+ (br_if $loop2
+ (i32.const 3)
+ )
+ )
+ (set_local $2
+ (tee_local $5
+ (tee_local $4
+ (tee_local $3
+ (i32.const 2)
+ )
+ )
+ )
+ )
+ (br $loop1)
+ )
+ )
+ (drop
+ (get_local $5)
+ )
+ )
+ )
+)
diff --git a/test/passes/ssa.wast b/test/passes/ssa.wast
new file mode 100644
index 000000000..fe78aecb5
--- /dev/null
+++ b/test/passes/ssa.wast
@@ -0,0 +1,315 @@
+(module
+ (func $basics (param $x i32)
+ (local $y i32)
+ (local $z f32)
+ (local $w i64)
+ (local $t f64)
+ (drop (get_local $x)) ;; keep as param get
+ (drop (get_local $y)) ;; turn into get of 0-init
+ (drop (get_local $z))
+ (drop (get_local $w))
+ (drop (get_local $t))
+ (set_local $x (i32.const 100)) ;; overwrite param
+ (drop (get_local $x)) ;; no longer a param!
+ (set_local $t (f64.const 2)) ;; overwrite local
+ (drop (get_local $t))
+ (set_local $t (f64.const 33)) ;; overwrite local AGAIN
+ (drop (get_local $t))
+ (drop (get_local $t)) ;; use twice
+ )
+ (func $if (param $p i32)
+ (local $x i32)
+ (local $y i32)
+ (drop
+ (if i32
+ (i32.const 1)
+ (get_local $x)
+ (get_local $y)
+ )
+ )
+ (if
+ (i32.const 1)
+ (set_local $x (i32.const 1))
+ )
+ (drop (get_local $x))
+ ;; same but with param
+ (if
+ (i32.const 1)
+ (set_local $p (i32.const 1))
+ )
+ (drop (get_local $p))
+ ;; if-else
+ (if
+ (i32.const 1)
+ (set_local $x (i32.const 2))
+ (nop)
+ )
+ (drop (get_local $x))
+ (if
+ (i32.const 1)
+ (nop)
+ (set_local $x (i32.const 3))
+ )
+ (drop (get_local $x))
+ (if
+ (i32.const 1)
+ (set_local $x (i32.const 4))
+ (set_local $x (i32.const 5))
+ )
+ (drop (get_local $x))
+ (if
+ (i32.const 1)
+ (set_local $x (i32.const 6))
+ (block
+ (set_local $x (i32.const 7))
+ (set_local $x (i32.const 8))
+ )
+ )
+ (drop (get_local $x))
+ )
+ (func $if2 (param $x i32)
+ (if
+ (i32.const 1)
+ (block
+ (set_local $x (i32.const 1))
+ (drop (get_local $x)) ;; use between phi set and use
+ )
+ )
+ (drop (get_local $x))
+ )
+ (func $block (param $x i32)
+ (block $out
+ (br_if $out (i32.const 2))
+ (set_local $x (i32.const 1))
+ )
+ (drop (get_local $x))
+ )
+ (func $block2 (param $x i32)
+ (block $out
+ (set_local $x (i32.const 1))
+ (drop (get_local $x))
+ (br_if $out (i32.const 2))
+ (drop (get_local $x))
+ (if (i32.const 3)
+ (block
+ (set_local $x (i32.const 1))
+ (drop (get_local $x))
+ (br $out)
+ )
+ )
+ (drop (get_local $x))
+ (set_local $x (i32.const 4))
+ (drop (get_local $x))
+ (if (i32.const 5)
+ (br $out)
+ )
+ (drop (get_local $x))
+ (if (i32.const 6)
+ (nop)
+ )
+ (if (i32.const 7)
+ (nop)
+ (nop)
+ )
+ ;; finally, switching
+ (block $in
+ (set_local $x (i32.const 8))
+ (drop (get_local $x))
+ (br_table $in $out (i32.const 9))
+ )
+ (drop (get_local $x))
+ (block $in2
+ (set_local $x (i32.const 10))
+ (drop (get_local $x))
+ (br_table $out $in2 (i32.const 11))
+ )
+ (drop (get_local $x))
+ )
+ (drop (get_local $x))
+ )
+ (func $loop (param $x i32)
+ (drop (get_local $x))
+ (loop $moar
+ (drop (get_local $x))
+ (set_local $x (i32.const 1))
+ (br_if $moar (i32.const 2))
+ )
+ (drop (get_local $x))
+ )
+ (func $loop2 (param $x i32)
+ (drop (get_local $x))
+ (loop $moar
+ (drop (get_local $x))
+ (set_local $x (i32.const 1))
+ (drop (get_local $x))
+ (set_local $x (i32.const 123))
+ (drop (get_local $x))
+ (br_if $moar (i32.const 2))
+ (drop (get_local $x)) ;; add use in loop before it ends, we should update this to the phi
+ (set_local $x (i32.const 3))
+ (drop (get_local $x)) ;; another use, but should *not* be phi'd
+ )
+ (drop (get_local $x))
+ )
+ (func $loop2-zeroinit
+ (local $x i32)
+ (drop (get_local $x))
+ (loop $moar
+ (drop (get_local $x))
+ (set_local $x (i32.const 1))
+ (drop (get_local $x))
+ (set_local $x (i32.const 123))
+ (drop (get_local $x))
+ (br_if $moar (i32.const 2))
+ (drop (get_local $x)) ;; add use in loop before it ends, we should update this to the phi
+ (set_local $x (i32.const 3))
+ (drop (get_local $x)) ;; another use, but should *not* be phi'd
+ )
+ (drop (get_local $x))
+ )
+ (func $real-loop
+ (param $param i32)
+ (local $loopvar i32)
+ (local $inc i32)
+ (set_local $loopvar
+ (get_local $param)
+ )
+ (loop $more
+ (block $stop
+ (if
+ (i32.const 1)
+ (br $stop)
+ )
+ (set_local $inc
+ (i32.add
+ (get_local $loopvar) ;; this var should be written to from before the loop and the inc at the end
+ (i32.const 1)
+ )
+ )
+ (set_local $loopvar
+ (get_local $inc)
+ )
+ (br $more)
+ )
+ )
+ (drop (get_local $loopvar))
+ )
+ (func $real-loop-outblock
+ (param $param i32)
+ (local $loopvar i32)
+ (local $inc i32)
+ (set_local $loopvar
+ (get_local $param)
+ )
+ (block $stop
+ (loop $more
+ (if
+ (i32.const 1)
+ (br $stop)
+ )
+ (set_local $inc
+ (i32.add
+ (get_local $loopvar) ;; this var should be written to from before the loop and the inc at the end
+ (i32.const 1)
+ )
+ )
+ (set_local $loopvar
+ (get_local $inc)
+ )
+ (br $more)
+ )
+ )
+ (drop (get_local $loopvar))
+ )
+ (func $loop-loop-param
+ (param $param i32)
+ (loop $loop1
+ (block $out1
+ (if
+ (get_local $param)
+ (br $out1)
+ )
+ (set_local $param (i32.const 1))
+ (br $loop1)
+ )
+ )
+ (loop $loop2
+ (block $out2
+ (if
+ (get_local $param)
+ (br $out2)
+ )
+ (set_local $param (i32.const 2))
+ (br $loop2)
+ )
+ )
+ )
+ (func $loop-loop-param-nomerge
+ (param $param i32)
+ (loop $loop1
+ (block $out1
+ (set_local $param (i32.const 1))
+ (if
+ (get_local $param)
+ (br $out1)
+ )
+ (br $loop1)
+ )
+ )
+ (loop $loop2
+ (block $out2
+ (if
+ (get_local $param)
+ (br $out2)
+ )
+ (set_local $param (i32.const 2))
+ (br $loop2)
+ )
+ )
+ )
+ (func $loop-nesting
+ (param $x i32)
+ (block $out
+ (loop $loop1
+ (if
+ (get_local $x)
+ (br $out)
+ )
+ (loop $loop2
+ (if
+ (get_local $x)
+ (br $out)
+ )
+ (set_local $x (i32.const 1))
+ (br $loop2)
+ )
+ (set_local $x (i32.const 2))
+ (br $loop1)
+ )
+ )
+ (drop (get_local $x)) ;; can receive from either set, or input param
+ )
+ (func $loop-nesting-2
+ (param $x i32)
+ (block $out
+ (loop $loop1
+ (if
+ (get_local $x)
+ (br $out)
+ )
+ (loop $loop2
+ (if
+ (get_local $x)
+ (br $out)
+ )
+ (set_local $x (i32.const 1))
+ (br_if $loop2 (i32.const 3)) ;; add fallthrough
+ )
+ (set_local $x (i32.const 2))
+ (br $loop1)
+ )
+ )
+ (drop (get_local $x)) ;; can receive from either set, or input param
+ )
+)
+