| (module |
| (global $global$0 (mut i32) (i32.const 1)) |
| (func $basics (param $x i32) |
| (local $y i32) |
| (local $z f32) |
| (local $w i64) |
| (local $t f64) |
| (drop (local.get $x)) ;; keep as param get |
| (drop (local.get $y)) ;; turn into get of 0-init |
| (drop (local.get $z)) |
| (drop (local.get $w)) |
| (drop (local.get $t)) |
| (local.set $x (i32.const 100)) ;; overwrite param |
| (drop (local.get $x)) ;; no longer a param! |
| (local.set $t (f64.const 2)) ;; overwrite local |
| (drop (local.get $t)) |
| (local.set $t (f64.const 33)) ;; overwrite local AGAIN |
| (drop (local.get $t)) |
| (drop (local.get $t)) ;; use twice |
| ) |
| (func $if (param $p i32) |
| (local $x i32) |
| (local $y i32) |
| (drop |
| (if (result i32) |
| (i32.const 1) |
| (then |
| (local.get $x) |
| ) |
| (else |
| (local.get $y) |
| ) |
| ) |
| ) |
| (if |
| (i32.const 1) |
| (then |
| (local.set $x (i32.const 1)) |
| ) |
| ) |
| (drop (local.get $x)) |
| ;; same but with param |
| (if |
| (i32.const 1) |
| (then |
| (local.set $p (i32.const 1)) |
| ) |
| ) |
| (drop (local.get $p)) |
| ;; if-else |
| (if |
| (i32.const 1) |
| (then |
| (local.set $x (i32.const 2)) |
| ) |
| (else |
| (nop) |
| ) |
| ) |
| (drop (local.get $x)) |
| (if |
| (i32.const 1) |
| (then |
| (nop) |
| ) |
| (else |
| (local.set $x (i32.const 3)) |
| ) |
| ) |
| (drop (local.get $x)) |
| (if |
| (i32.const 1) |
| (then |
| (local.set $x (i32.const 4)) |
| ) |
| (else |
| (local.set $x (i32.const 5)) |
| ) |
| ) |
| (drop (local.get $x)) |
| (if |
| (i32.const 1) |
| (then |
| (local.set $x (i32.const 6)) |
| ) |
| (else |
| (block |
| (local.set $x (i32.const 7)) |
| (local.set $x (i32.const 8)) |
| ) |
| ) |
| ) |
| (drop (local.get $x)) |
| ) |
| (func $if2 (param $x i32) |
| (if |
| (i32.const 1) |
| (then |
| (block |
| (local.set $x (i32.const 1)) |
| (drop (local.get $x)) ;; use between phi set and use |
| ) |
| ) |
| ) |
| (drop (local.get $x)) |
| ) |
| (func $block (param $x i32) |
| (block $out |
| (br_if $out (i32.const 2)) |
| (local.set $x (i32.const 1)) |
| ) |
| (drop (local.get $x)) |
| ) |
| (func $block2 (param $x i32) |
| (block $out |
| (local.set $x (i32.const 1)) |
| (drop (local.get $x)) |
| (br_if $out (i32.const 2)) |
| (drop (local.get $x)) |
| (if (i32.const 3) |
| (then |
| (block |
| (local.set $x (i32.const 1)) |
| (drop (local.get $x)) |
| (br $out) |
| ) |
| ) |
| ) |
| (drop (local.get $x)) |
| (local.set $x (i32.const 4)) |
| (drop (local.get $x)) |
| (if (i32.const 5) |
| (then |
| (br $out) |
| ) |
| ) |
| (drop (local.get $x)) |
| (if (i32.const 6) |
| (then |
| (nop) |
| ) |
| ) |
| (if (i32.const 7) |
| (then |
| (nop) |
| ) |
| (else |
| (nop) |
| ) |
| ) |
| ;; finally, switching |
| (block $in |
| (local.set $x (i32.const 8)) |
| (drop (local.get $x)) |
| (br_table $in $out (i32.const 9)) |
| ) |
| (drop (local.get $x)) |
| (block $in2 |
| (local.set $x (i32.const 10)) |
| (drop (local.get $x)) |
| (br_table $out $in2 (i32.const 11)) |
| ) |
| (drop (local.get $x)) |
| ) |
| (drop (local.get $x)) |
| ) |
| (func $loop (param $x i32) |
| (drop (local.get $x)) |
| (loop $moar |
| (drop (local.get $x)) |
| (local.set $x (i32.const 1)) |
| (br_if $moar (i32.const 2)) |
| ) |
| (drop (local.get $x)) |
| ) |
| (func $loop2 (param $x i32) |
| (drop (local.get $x)) |
| (loop $moar |
| (drop (local.get $x)) |
| (local.set $x (i32.const 1)) |
| (drop (local.get $x)) |
| (local.set $x (i32.const 123)) |
| (drop (local.get $x)) |
| (br_if $moar (i32.const 2)) |
| (drop (local.get $x)) ;; add use in loop before it ends, we should update this to the phi |
| (local.set $x (i32.const 3)) |
| (drop (local.get $x)) ;; another use, but should *not* be phi'd |
| ) |
| (drop (local.get $x)) |
| ) |
| (func $loop2-zeroinit |
| (local $x i32) |
| (drop (local.get $x)) |
| (loop $moar |
| (drop (local.get $x)) |
| (local.set $x (i32.const 1)) |
| (drop (local.get $x)) |
| (local.set $x (i32.const 123)) |
| (drop (local.get $x)) |
| (br_if $moar (i32.const 2)) |
| (drop (local.get $x)) ;; add use in loop before it ends, we should update this to the phi |
| (local.set $x (i32.const 3)) |
| (drop (local.get $x)) ;; another use, but should *not* be phi'd |
| ) |
| (drop (local.get $x)) |
| ) |
| (func $real-loop |
| (param $param i32) |
| (local $loopvar i32) |
| (local $inc i32) |
| (local.set $loopvar |
| (local.get $param) |
| ) |
| (loop $more |
| (block $stop |
| (if |
| (i32.const 1) |
| (then |
| (br $stop) |
| ) |
| ) |
| (local.set $inc |
| (i32.add |
| (local.get $loopvar) ;; this var should be written to from before the loop and the inc at the end |
| (i32.const 1) |
| ) |
| ) |
| (local.set $loopvar |
| (local.get $inc) |
| ) |
| (br $more) |
| ) |
| ) |
| (drop (local.get $loopvar)) |
| ) |
| (func $real-loop-outblock |
| (param $param i32) |
| (local $loopvar i32) |
| (local $inc i32) |
| (local.set $loopvar |
| (local.get $param) |
| ) |
| (block $stop |
| (loop $more |
| (if |
| (i32.const 1) |
| (then |
| (br $stop) |
| ) |
| ) |
| (local.set $inc |
| (i32.add |
| (local.get $loopvar) ;; this var should be written to from before the loop and the inc at the end |
| (i32.const 1) |
| ) |
| ) |
| (local.set $loopvar |
| (local.get $inc) |
| ) |
| (br $more) |
| ) |
| ) |
| (drop (local.get $loopvar)) |
| ) |
| (func $loop-loop-param |
| (param $param i32) |
| (loop $loop1 |
| (block $out1 |
| (if |
| (local.get $param) |
| (then |
| (br $out1) |
| ) |
| ) |
| (local.set $param (i32.const 1)) |
| (br $loop1) |
| ) |
| ) |
| (loop $loop2 |
| (block $out2 |
| (if |
| (local.get $param) |
| (then |
| (br $out2) |
| ) |
| ) |
| (local.set $param (i32.const 2)) |
| (br $loop2) |
| ) |
| ) |
| ) |
| (func $loop-loop-param-nomerge |
| (param $param i32) |
| (loop $loop1 |
| (block $out1 |
| (local.set $param (i32.const 1)) |
| (if |
| (local.get $param) |
| (then |
| (br $out1) |
| ) |
| ) |
| (br $loop1) |
| ) |
| ) |
| (loop $loop2 |
| (block $out2 |
| (if |
| (local.get $param) |
| (then |
| (br $out2) |
| ) |
| ) |
| (local.set $param (i32.const 2)) |
| (br $loop2) |
| ) |
| ) |
| ) |
| (func $loop-nesting |
| (param $x i32) |
| (block $out |
| (loop $loop1 |
| (if |
| (local.get $x) |
| (then |
| (br $out) |
| ) |
| ) |
| (loop $loop2 |
| (if |
| (local.get $x) |
| (then |
| (br $out) |
| ) |
| ) |
| (local.set $x (i32.const 1)) |
| (br $loop2) |
| ) |
| (local.set $x (i32.const 2)) |
| (br $loop1) |
| ) |
| ) |
| (drop (local.get $x)) ;; can receive from either set, or input param |
| ) |
| (func $loop-nesting-2 |
| (param $x i32) |
| (block $out |
| (loop $loop1 |
| (if |
| (local.get $x) |
| (then |
| (br $out) |
| ) |
| ) |
| (loop $loop2 |
| (if |
| (local.get $x) |
| (then |
| (br $out) |
| ) |
| ) |
| (local.set $x (i32.const 1)) |
| (br_if $loop2 (i32.const 3)) ;; add fallthrough |
| ) |
| (local.set $x (i32.const 2)) |
| (br $loop1) |
| ) |
| ) |
| (drop (local.get $x)) ;; can receive from either set, or input param |
| ) |
| (func $func_6 (result i32) |
| (local $result i32) |
| (local $zero i32) |
| (loop $label$1 |
| (if |
| (i32.eqz |
| (global.get $global$0) |
| ) |
| (then |
| (return |
| (local.get $result) ;; we eventually reach here |
| ) |
| ) |
| ) |
| (global.set $global$0 |
| (i32.const 0) ;; tell next iteration to return |
| ) |
| (local.set $result |
| (i32.const 1) ;; set the return value to 1, temporarily |
| ) |
| (br_if $label$1 |
| (i32.const 0) ;; don't do anything here |
| ) |
| (local.set $result |
| (local.get $zero) ;; set it to zero instead |
| ) |
| (br $label$1) ;; back to the top, where we will return the zero |
| ) |
| ) |
| (func $ssa-merge-tricky (result i32) |
| (local $var$0 i32) |
| (local $var$1 i32) |
| (local.set $var$1 |
| (local.tee $var$0 |
| (i32.const 0) ;; both vars start out identical |
| ) |
| ) |
| (loop $label$1 |
| (if |
| (i32.eqz |
| (global.get $global$0) |
| ) |
| (then |
| (return |
| (i32.const 12345) |
| ) |
| ) |
| ) |
| (global.set $global$0 |
| (i32.const 0) |
| ) |
| (if |
| (i32.eqz |
| (local.get $var$0) ;; check $0 here. this will get a phi var |
| ) |
| (then |
| (br_if $label$1 |
| (i32.eqz |
| (local.tee $var$0 ;; set $0 to 1. here the two diverge. for the phi, we'll get a set here and above |
| (i32.const 1) |
| ) |
| ) |
| ) |
| ) |
| ) |
| (br_if $label$1 |
| (i32.eqz ;; indeed equal, enter loop again, and then hang prevention kicks in |
| (local.tee $var$1 ;; set them all to 0 |
| (local.tee $var$0 |
| (local.get $var$1) ;; this must get $1, not the phis, as even though the sets appear in both sources, we only execute 1. |
| ) |
| ) |
| ) |
| ) |
| ) |
| (i32.const -54) |
| ) |
| ) |