| ;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. |
| ;; NOTE: This test was ported using port_passes_tests_to_lit.py and could be cleaned up. |
| |
| ;; RUN: foreach %s %t wasm-opt --vacuum --all-features -S -o - | filecheck %s |
| |
| (module |
| (memory 256 256) |
| ;; CHECK: (type $0 (func)) |
| (type $0 (func)) |
| ;; CHECK: (type $3 (func (result i32))) |
| |
| ;; CHECK: (type $1 (func (param i32))) |
| (type $1 (func (param i32))) |
| ;; CHECK: (type $2 (func (result f32))) |
| (type $2 (func (result f32))) |
| (type $3 (func (result i32))) |
| ;; CHECK: (type $4 (func (param i32 f64 i32 i32))) |
| (type $4 (func (param i32 f64 i32 i32))) |
| (import $int "env" "int" (result i32)) |
| ;; CHECK: (type $i32_=>_i32 (func (param i32) (result i32))) |
| |
| ;; CHECK: (type $none_=>_f64 (func (result f64))) |
| |
| ;; CHECK: (import "env" "int" (func $int (result i32))) |
| |
| ;; CHECK: (global $Int i32 (i32.const 0)) |
| (global $Int i32 (i32.const 0)) |
| ;; CHECK: (memory $0 256 256) |
| |
| ;; CHECK: (func $b (type $0) |
| ;; CHECK-NEXT: (nop) |
| ;; CHECK-NEXT: ) |
| (func $b (type $0) |
| (drop |
| (i32.const 50) |
| ) |
| (nop) |
| (drop |
| (i32.const 51) |
| ) |
| (nop) |
| (nop) |
| (drop |
| (i32.const 52) |
| ) |
| (block $waka1 |
| (drop |
| (i32.const 53) |
| ) |
| (br $waka1) |
| (drop |
| (i32.const 54) |
| ) |
| ) |
| (block $waka2 |
| (nop) |
| (br $waka2) |
| (drop |
| (i32.const 56) |
| ) |
| ) |
| (block $waka3 |
| (br_table $waka3 $waka3 $waka3 |
| (i32.const 57) |
| ) |
| (drop |
| (i32.const 58) |
| ) |
| ) |
| (if |
| (i32.const 100) |
| (nop) |
| (drop |
| (i32.const 101) |
| ) |
| ) |
| (if |
| (i32.const 102) |
| (drop |
| (i32.const 103) |
| ) |
| (nop) |
| ) |
| (if |
| (i32.const 104) |
| (nop) |
| (nop) |
| ) |
| ) |
| ;; CHECK: (func $l (type $3) (result i32) |
| ;; CHECK-NEXT: (local $x i32) |
| ;; CHECK-NEXT: (local $y i32) |
| ;; CHECK-NEXT: (local.set $x |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.set $x |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.set $x |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| (func $l (result i32) |
| (local $x i32) |
| (local $y i32) |
| (drop |
| (local.get $x) |
| ) |
| (local.set $x |
| (local.get $x) |
| ) |
| (block $in-a-block |
| (drop |
| (local.get $x) |
| ) |
| ) |
| (block $two-in-a-block |
| (drop |
| (local.get $x) |
| ) |
| (drop |
| (local.get $y) |
| ) |
| ) |
| (local.set $x |
| (block $result-used (result i32) |
| (local.get $x) |
| ) |
| ) |
| (local.set $x |
| (block $two-and-result-used (result i32) |
| (drop |
| (local.get $x) |
| ) |
| (local.get $y) |
| ) |
| ) |
| (local.get $x) |
| ) |
| ;; CHECK: (func $loopy (type $1) (param $0 i32) |
| ;; CHECK-NEXT: (nop) |
| ;; CHECK-NEXT: ) |
| (func $loopy (type $1) (param $0 i32) |
| (loop $loop-in1 |
| (nop) |
| ) |
| (loop $loop-in3 |
| (nop) |
| (nop) |
| ) |
| (drop |
| (loop $loop-in5 (result i32) |
| (drop |
| (local.get $0) |
| ) |
| (i32.const 20) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $unary (type $2) (result f32) |
| ;; CHECK-NEXT: (f32.abs |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $unary (type $2) (result f32) |
| (drop |
| (f32.abs |
| (f32.const 1) |
| ) |
| ) |
| (f32.abs |
| (unreachable) |
| ) |
| (f32.abs |
| (f32.const 2) |
| ) |
| ) |
| ;; CHECK: (func $binary (type $2) (result f32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.add |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: (f32.const 3) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $binary (type $2) (result f32) |
| (drop |
| (f32.add |
| (f32.const 1) |
| (f32.const 2) |
| ) |
| ) |
| (drop |
| (f32.add |
| (unreachable) |
| (f32.const 3) |
| ) |
| ) |
| (drop |
| (f32.add |
| (f32.const 4) |
| (unreachable) |
| ) |
| ) |
| (f32.add |
| (unreachable) |
| (unreachable) |
| ) |
| (f32.add |
| (f32.const 5) |
| (f32.const 6) |
| ) |
| ) |
| ;; CHECK: (func $select (type $3) (result i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (select |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: (i32.const 4) |
| ;; CHECK-NEXT: (i32.const 5) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $select (type $3) (result i32) |
| (drop |
| (select |
| (i32.const 1) |
| (i32.const 2) |
| (i32.const 3) |
| ) |
| ) |
| (drop |
| (select |
| (unreachable) |
| (i32.const 4) |
| (i32.const 5) |
| ) |
| ) |
| (drop |
| (select |
| (i32.const 6) |
| (unreachable) |
| (i32.const 7) |
| ) |
| ) |
| (drop |
| (select |
| (i32.const 8) |
| (i32.const 9) |
| (unreachable) |
| ) |
| ) |
| (select |
| (unreachable) |
| (unreachable) |
| (i32.const 10) |
| ) |
| (drop |
| (select |
| (unreachable) |
| (i32.const 11) |
| (unreachable) |
| ) |
| ) |
| (drop |
| (select |
| (i32.const 12) |
| (unreachable) |
| (unreachable) |
| ) |
| ) |
| (select |
| (unreachable) |
| (unreachable) |
| (unreachable) |
| ) |
| (select |
| (i32.const 13) |
| (i32.const 14) |
| (i32.const 15) |
| ) |
| ) |
| ;; CHECK: (func $block-to-one (type $0) |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: ) |
| (func $block-to-one (type $0) |
| (block $block0 |
| (nop) |
| (nop) |
| ) |
| (block $block1 |
| (nop) |
| (unreachable) |
| ) |
| (block $block2 |
| (nop) |
| (unreachable) |
| (nop) |
| ) |
| (block $block3 |
| (unreachable) |
| (nop) |
| ) |
| (block $block4 |
| (unreachable) |
| ) |
| ) |
| ;; CHECK: (func $recurse (type $0) |
| ;; CHECK-NEXT: (nop) |
| ;; CHECK-NEXT: ) |
| (func $recurse (type $0) |
| (nop) |
| (drop |
| (f32.abs |
| (f32.abs |
| (f32.abs |
| (f32.abs |
| (f32.abs |
| (f32.abs |
| (f32.const 1) |
| ) |
| ) |
| ) |
| ) |
| ) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $func-block (type $0) |
| ;; CHECK-NEXT: (nop) |
| ;; CHECK-NEXT: ) |
| (func $func-block (type $0) |
| (drop |
| (f32.abs |
| (f32.abs |
| (f32.abs |
| (f32.abs |
| (f32.abs |
| (f32.abs |
| (f32.const 1) |
| ) |
| ) |
| ) |
| ) |
| ) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $Gu (type $4) (param $b i32) (param $e f64) (param $l i32) (param $d i32) |
| ;; CHECK-NEXT: (if |
| ;; CHECK-NEXT: (if (result i32) |
| ;; CHECK-NEXT: (local.get $d) |
| ;; CHECK-NEXT: (f64.ne |
| ;; CHECK-NEXT: (f64.promote_f32 |
| ;; CHECK-NEXT: (f32.load |
| ;; CHECK-NEXT: (local.tee $l |
| ;; CHECK-NEXT: (i32.add |
| ;; CHECK-NEXT: (local.get $b) |
| ;; CHECK-NEXT: (i32.const 60) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.get $e) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $Gu (type $4) (param $b i32) (param $e f64) (param $l i32) (param $d i32) |
| (if |
| (if (result i32) |
| (local.get $d) |
| (block $block1 (result i32) |
| (nop) |
| (f64.ne |
| (f64.promote_f32 |
| (f32.load |
| (local.tee $l |
| (i32.add |
| (local.get $b) |
| (i32.const 60) |
| ) |
| ) |
| ) |
| ) |
| (local.get $e) |
| ) |
| ) |
| (i32.const 0) |
| ) |
| (unreachable) |
| ) |
| ) |
| ;; CHECK: (func $if-drop (type $3) (result i32) |
| ;; CHECK-NEXT: (block $out |
| ;; CHECK-NEXT: (if |
| ;; CHECK-NEXT: (call $if-drop) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (call $int) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (br $out) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (if |
| ;; CHECK-NEXT: (call $if-drop) |
| ;; CHECK-NEXT: (br $out) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (call $int) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| (func $if-drop (result i32) |
| (block $out |
| (drop |
| (if (result i32) |
| (call $if-drop) |
| (call $int) |
| (br $out) |
| ) |
| ) |
| (drop |
| (if (result i32) |
| (call $if-drop) |
| (br $out) |
| (call $int) |
| ) |
| ) |
| ) |
| (i32.const 1) |
| ) |
| ;; CHECK: (func $drop-silly (type $0) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (call $int) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (call $int) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (call $int) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (block |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (call $int) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (call $int) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $drop-silly |
| (drop |
| (i32.eqz |
| (i32.eqz |
| (i32.const 1) |
| ) |
| ) |
| ) |
| (drop |
| (i32.eqz |
| (i32.eqz |
| (call $int) |
| ) |
| ) |
| ) |
| (drop |
| (i32.add |
| (i32.const 2) |
| (i32.const 3) |
| ) |
| ) |
| (drop |
| (i32.add |
| (i32.const 4) |
| (call $int) |
| ) |
| ) |
| (drop |
| (i32.add |
| (call $int) |
| (i32.const 5) |
| ) |
| ) |
| (drop |
| (i32.add |
| (call $int) |
| (call $int) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $drop-get-global (type $0) |
| ;; CHECK-NEXT: (call $drop-get-global) |
| ;; CHECK-NEXT: ) |
| (func $drop-get-global |
| (drop |
| (block (result i32) |
| (call $drop-get-global) |
| (global.get $Int) ;; this is not needed due to the block being drop'd, but make sure the call is not then dropped either |
| ) |
| ) |
| ) |
| ;; CHECK: (func $relooperJumpThreading1 (type $0) |
| ;; CHECK-NEXT: (local $$vararg_ptr5 i32) |
| ;; CHECK-NEXT: (local $$11 i32) |
| ;; CHECK-NEXT: (nop) |
| ;; CHECK-NEXT: ) |
| (func $relooperJumpThreading1 |
| (local $$vararg_ptr5 i32) |
| (local $$11 i32) |
| (loop $while-in$1 |
| (drop |
| (block $jumpthreading$outer$8 (result i32) |
| (block $jumpthreading$inner$8 |
| (br $jumpthreading$outer$8 ;; the rest is dead in the outer block, but be careful to leave the return value! |
| (i32.const 0) |
| ) |
| ) |
| (i32.store |
| (local.get $$vararg_ptr5) |
| (local.get $$11) |
| ) |
| (i32.const 0) |
| ) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $relooperJumpThreading2 (type $0) |
| ;; CHECK-NEXT: (nop) |
| ;; CHECK-NEXT: ) |
| (func $relooperJumpThreading2 |
| (loop $while-in$1 |
| (drop |
| (block $jumpthreading$outer$8 (result i32) |
| (block $jumpthreading$inner$8 |
| (br $jumpthreading$outer$8 |
| (i32.const 0) |
| ) |
| ) |
| (i32.const 0) |
| ) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $relooperJumpThreading3 (type $0) |
| ;; CHECK-NEXT: (nop) |
| ;; CHECK-NEXT: ) |
| (func $relooperJumpThreading3 |
| (loop $while-in$1 |
| (drop |
| (block $jumpthreading$outer$8 (result i32) |
| (br $jumpthreading$outer$8 ;; code after this is dead, can kill it, but preserve the return value at the end! |
| (i32.const 0) |
| ) |
| (drop (i32.const 3)) |
| (drop (i32.const 2)) |
| (drop (i32.const 1)) |
| (i32.const 0) |
| ) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $if2drops (type $3) (result i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (if (result i32) |
| ;; CHECK-NEXT: (call $if2drops) |
| ;; CHECK-NEXT: (call $if2drops) |
| ;; CHECK-NEXT: (call $if2drops) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 2) |
| ;; CHECK-NEXT: ) |
| (func $if2drops (result i32) |
| (if |
| (call $if2drops) |
| (drop |
| (call $if2drops) |
| ) |
| (drop |
| (call $if2drops) |
| ) |
| ) |
| (i32.const 2) |
| ) |
| ;; CHECK: (func $if2drops-different (type $3) (result i32) |
| ;; CHECK-NEXT: (if |
| ;; CHECK-NEXT: (call $if2drops) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (call $if2drops) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (call $unary) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 2) |
| ;; CHECK-NEXT: ) |
| (func $if2drops-different (result i32) |
| (if |
| (call $if2drops) |
| (drop |
| (call $if2drops) ;; i32 |
| ) |
| (drop |
| (call $unary) ;; f32! |
| ) |
| ) |
| (i32.const 2) |
| ) |
| ;; CHECK: (func $if-const (type $1) (param $x i32) |
| ;; CHECK-NEXT: (call $if-const |
| ;; CHECK-NEXT: (i32.const 3) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (call $if-const |
| ;; CHECK-NEXT: (i32.const 5) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (call $if-const |
| ;; CHECK-NEXT: (i32.const 7) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $if-const (param $x i32) |
| (if (i32.const 0) (call $if-const (i32.const 1))) |
| (if (i32.const 2) (call $if-const (i32.const 3))) |
| (if (i32.const 0) (call $if-const (i32.const 4)) (call $if-const (i32.const 5))) |
| (if (i32.const 6) (call $if-const (i32.const 7)) (call $if-const (i32.const 8))) |
| ) |
| ;; CHECK: (func $drop-if-both-unreachable (type $1) (param $0 i32) |
| ;; CHECK-NEXT: (block $out |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (if |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: (br $out) |
| ;; CHECK-NEXT: (br $out) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (if |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $drop-if-both-unreachable (param $0 i32) |
| (block $out |
| (drop |
| (if (result i32) |
| (local.get $0) |
| (br $out) |
| (br $out) |
| ) |
| ) |
| ) |
| (drop |
| (if (result i32) |
| (local.get $0) |
| (unreachable) |
| (unreachable) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $if-1-block (type $i32_=>_i32) (param $x i32) (result i32) |
| ;; CHECK-NEXT: (block $out |
| ;; CHECK-NEXT: (if |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (block |
| ;; CHECK-NEXT: (local.set $x |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (br $out) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| (func $if-1-block (param $x i32) (result i32) |
| (block $out |
| (if |
| (local.get $x) |
| (block |
| (if |
| (i32.const 1) |
| (block |
| (local.set $x |
| (local.get $x) |
| ) |
| (br $out) |
| ) |
| ) |
| ) |
| ) |
| ) |
| (local.get $x) |
| ) |
| ;; CHECK: (func $block-resize-br-gone (type $0) |
| ;; CHECK-NEXT: (block $out |
| ;; CHECK-NEXT: (block $in |
| ;; CHECK-NEXT: (call $block-resize-br-gone) |
| ;; CHECK-NEXT: (br $in) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (return) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (block $out2 |
| ;; CHECK-NEXT: (block $in2 |
| ;; CHECK-NEXT: (br $in2) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (return) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $block-resize-br-gone |
| (block $out |
| (block $in |
| (call $block-resize-br-gone) |
| (br $in) |
| (br $out) |
| ) |
| (return) |
| ) |
| ;; The second br will be removed. (The entire expression after us can also |
| ;; be removed, which will be done by --remove-unused-brs --vacuum.) |
| (block $out2 |
| (block $in2 |
| (br $in2) |
| (br $out2) |
| ) |
| (return) |
| ) |
| ) |
| ;; CHECK: (func $block-unreachable-but-last-element-concrete (type $0) |
| ;; CHECK-NEXT: (local $2 i32) |
| ;; CHECK-NEXT: (nop) |
| ;; CHECK-NEXT: ) |
| (func $block-unreachable-but-last-element-concrete |
| (local $2 i32) |
| (block $label$0 |
| (drop |
| (block (result i32) |
| (br $label$0) |
| (local.get $2) |
| ) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $a (type $0) |
| ;; CHECK-NEXT: (i32.store |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: (i32.const 2) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (f64.div |
| ;; CHECK-NEXT: (f64.const -nan:0xfffffffffa361) |
| ;; CHECK-NEXT: (loop $label$1 |
| ;; CHECK-NEXT: (br $label$1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $a |
| (block |
| (i32.store (i32.const 1) (i32.const 2)) |
| (f64.div |
| (f64.const -nan:0xfffffffffa361) |
| (loop $label$1 ;; unreachable, so the div is too. keep |
| (br $label$1) |
| ) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $leave-block-even-if-br-not-taken (type $none_=>_f64) (result f64) |
| ;; CHECK-NEXT: (block $label$0 |
| ;; CHECK-NEXT: (f64.store align=1 |
| ;; CHECK-NEXT: (i32.const 879179022) |
| ;; CHECK-NEXT: (block |
| ;; CHECK-NEXT: (loop $label$9 |
| ;; CHECK-NEXT: (br $label$9) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.const 677803374) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $leave-block-even-if-br-not-taken (result f64) |
| (block $label$0 (result f64) |
| (f64.store align=1 |
| (i32.const 879179022) |
| (br_if $label$0 |
| ;; This loop never exits, so it is unreachable. We don't have much to |
| ;; optimize here, but we can remove the br_if and leave an unreachable |
| ;; block with the other contents for dce to clean up. |
| (loop $label$9 |
| (br $label$9) |
| ) |
| (i32.const 677803374) |
| ) |
| ) |
| (f64.const 2097914503796645752267195e31) |
| ) |
| ) |
| ;; CHECK: (func $executed-if-in-block (type $0) |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: ) |
| (func $executed-if-in-block |
| (block $label$0 |
| (if |
| (i32.const 170996275) |
| (unreachable) |
| (br $label$0) |
| ) |
| ) |
| (unreachable) |
| ) |
| ;; CHECK: (func $executed-if-in-block2 (type $0) |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: ) |
| (func $executed-if-in-block2 |
| (block $label$0 |
| (if |
| (i32.const 170996275) |
| (nop) |
| (br $label$0) |
| ) |
| ) |
| (unreachable) |
| ) |
| ;; CHECK: (func $executed-if-in-block3 (type $0) |
| ;; CHECK-NEXT: (block $label$0 |
| ;; CHECK-NEXT: (br $label$0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: ) |
| (func $executed-if-in-block3 |
| (block $label$0 |
| (if |
| (i32.const 170996275) |
| (br $label$0) |
| (nop) |
| ) |
| ) |
| (unreachable) |
| ) |
| ;; CHECK: (func $load-may-have-side-effects (type $3) (result i32) |
| ;; CHECK-NEXT: (i64.ge_s |
| ;; CHECK-NEXT: (block (result i64) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.load32_s |
| ;; CHECK-NEXT: (i32.const 678585719) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i64.const 2912825531628789796) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i64.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $load-may-have-side-effects (result i32) |
| (i64.ge_s |
| (block (result i64) |
| (drop |
| (i64.eq |
| (i64.load32_s |
| (i32.const 678585719) |
| ) |
| (i64.const 8097879367757079605) |
| ) |
| ) |
| (i64.const 2912825531628789796) |
| ) |
| (i64.const 0) |
| ) |
| ) |
| ;; CHECK: (func $unary-binary-may-trap (type $0) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.trunc_f32_u |
| ;; CHECK-NEXT: (f32.const 70847791997969805621592064) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $unary-binary-may-trap |
| (drop |
| (i64.div_s |
| (i64.const -1) |
| (i64.const 729618461987467893) |
| ) |
| ) |
| (drop |
| (i64.trunc_f32_u |
| (f32.const 70847791997969805621592064) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $unreachable-if-with-nop-arm-that-leaves-a-concrete-value-if-nop-is-removed (type $0) |
| ;; CHECK-NEXT: (block $label$0 |
| ;; CHECK-NEXT: (loop $label$1 |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (br_if $label$0 |
| ;; CHECK-NEXT: (loop $label$9 |
| ;; CHECK-NEXT: (br $label$9) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $unreachable-if-with-nop-arm-that-leaves-a-concrete-value-if-nop-is-removed |
| (block $label$0 |
| (loop $label$1 |
| (drop |
| (if (result i32) |
| (br_if $label$0 |
| (loop $label$9 |
| (br $label$9) |
| ) |
| ) |
| (unreachable) |
| (i32.const 1920103026) |
| ) |
| ) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $if-arm-vanishes (type $3) (result i32) |
| ;; CHECK-NEXT: (block $label$0 (result i32) |
| ;; CHECK-NEXT: (br $label$0 |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $if-arm-vanishes (result i32) |
| (block $label$0 (result i32) |
| (block $label$1 |
| (if |
| (br $label$0 |
| (i32.const 1) |
| ) |
| (br $label$1) |
| ) |
| ) |
| (i32.const 1579493952) |
| ) |
| ) |
| ;; CHECK: (func $if-arm-vanishes-2 (type $3) (result i32) |
| ;; CHECK-NEXT: (block $label$0 (result i32) |
| ;; CHECK-NEXT: (br $label$0 |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $if-arm-vanishes-2 (result i32) |
| (block $label$0 (result i32) |
| (block $label$1 |
| (if |
| (br $label$0 |
| (i32.const 1) |
| ) |
| (br $label$1) |
| ) |
| ) |
| (i32.const 1579493952) |
| ) |
| ) |
| ;; CHECK: (func $nop-if-type-changes (type $0) |
| ;; CHECK-NEXT: (local $0 i32) |
| ;; CHECK-NEXT: (nop) |
| ;; CHECK-NEXT: ) |
| (func $nop-if-type-changes (type $0) |
| (local $0 i32) |
| (block $label$0 |
| (if |
| (i32.eqz |
| (local.get $0) |
| ) |
| (block $label$1 |
| (block |
| (if ;; we nop this if, which has a type change for block $label$1, no more brs to it |
| (i32.const 0) |
| (br_if $label$1 |
| (i32.const 1717966400) |
| ) |
| ) |
| (drop |
| (br $label$0) |
| ) |
| ) |
| ) |
| ) |
| ) |
| ) |
| ) |
| (module ;; a child with a different type, cannot simply replace the parent with it |
| ;; CHECK: (type $0 (func (param i64))) |
| (type $0 (func (param i64))) |
| ;; CHECK: (type $1 (func (param f32 i32) (result i32))) |
| (type $1 (func (param f32 i32) (result i32))) |
| ;; CHECK: (func $0 (type $0) (param $0 i64) |
| ;; CHECK-NEXT: (nop) |
| ;; CHECK-NEXT: ) |
| (func $0 (; 0 ;) (type $0) (param $0 i64) |
| (nop) |
| ) |
| ;; CHECK: (func $1 (type $1) (param $0 f32) (param $1 i32) (result i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (block $label$2 (result i64) |
| ;; CHECK-NEXT: (call $0 |
| ;; CHECK-NEXT: (br_if $label$2 |
| ;; CHECK-NEXT: (i64.const -137438953472) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: ) |
| (func $1 (; 1 ;) (type $1) (param $0 f32) (param $1 i32) (result i32) |
| (drop |
| (block $label$1 (result i32) |
| (i32.wrap_i64 |
| (block $label$2 (result i64) |
| (call $0 |
| (br_if $label$2 |
| (i64.const -137438953472) |
| (i32.const 1) |
| ) |
| ) |
| (unreachable) |
| ) |
| ) |
| ) |
| ) |
| (unreachable) |
| ) |
| ) |
| (module ;; vacuum away a drop on an if where both arms can be vacuumed |
| (memory 1 1) |
| ;; CHECK: (type $i32_=>_i32 (func (param i32) (result i32))) |
| |
| ;; CHECK: (type $i32_i32_i32_=>_none (func (param i32 i32 i32))) |
| |
| ;; CHECK: (global $global$1 (mut i32) (i32.const 0)) |
| (global $global$1 (mut i32) (i32.const 0)) |
| ;; CHECK: (memory $0 1 1) |
| |
| ;; CHECK: (export "compress" (func $3)) |
| |
| ;; CHECK: (func $_deflate (type $i32_=>_i32) (param $0 i32) (result i32) |
| ;; CHECK-NEXT: (call $_deflate |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $_deflate (param i32) (result i32) |
| (call $_deflate (local.get $0)) |
| ) |
| ;; CHECK: (func $_deflateInit2_ (type $i32_=>_i32) (param $0 i32) (result i32) |
| ;; CHECK-NEXT: (call $_deflateInit2_ |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $_deflateInit2_ (param i32) (result i32) |
| (call $_deflateInit2_ (local.get $0)) |
| ) |
| ;; CHECK: (func $_deflateEnd (type $i32_=>_i32) (param $0 i32) (result i32) |
| ;; CHECK-NEXT: (call $_deflateEnd |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $_deflateEnd (param i32) (result i32) |
| (call $_deflateEnd (local.get $0)) |
| ) |
| (func "compress" (param $0 i32) (param $1 i32) (param $2 i32) |
| (local $3 i32) |
| (local.set $3 |
| (global.get $global$1) |
| ) |
| (global.set $global$1 |
| (i32.sub |
| (global.get $global$1) |
| (i32.const -64) |
| ) |
| ) |
| (i32.store |
| (local.get $3) |
| (local.get $2) |
| ) |
| (i32.store offset=4 |
| (local.get $3) |
| (i32.const 100000) |
| ) |
| (i32.store offset=12 |
| (local.get $3) |
| (local.get $0) |
| ) |
| (i32.store offset=16 |
| (local.get $3) |
| (i32.load |
| (local.get $1) |
| ) |
| ) |
| (i32.store offset=32 |
| (local.get $3) |
| (i32.const 0) |
| ) |
| (i32.store offset=36 |
| (local.get $3) |
| (i32.const 0) |
| ) |
| (i32.store offset=40 |
| (local.get $3) |
| (i32.const 0) |
| ) |
| (if |
| (call $_deflateInit2_ |
| (local.get $3) |
| ) |
| (block |
| (global.set $global$1 |
| (local.get $3) |
| ) |
| (return) |
| ) |
| ) |
| (drop |
| (if (result i32) |
| (i32.eq |
| (local.tee $0 |
| (call $_deflate |
| (local.get $3) |
| ) |
| ) |
| (i32.const 1) |
| ) |
| (block (result i32) |
| (i32.store |
| (local.get $1) |
| (i32.load offset=20 |
| (local.get $3) |
| ) |
| ) |
| (local.set $0 |
| (call $_deflateEnd |
| (local.get $3) |
| ) |
| ) |
| (global.set $global$1 |
| (local.get $3) |
| ) |
| (local.get $0) |
| ) |
| (block (result i32) |
| (drop |
| (call $_deflateEnd |
| (local.get $3) |
| ) |
| ) |
| (global.set $global$1 |
| (local.get $3) |
| ) |
| (select |
| (local.get $0) |
| (i32.const -5) |
| (local.get $0) |
| ) |
| ) |
| ) |
| ) |
| ) |
| ) |
| |
| ;; CHECK: (func $3 (type $i32_i32_i32_=>_none) (param $0 i32) (param $1 i32) (param $2 i32) |
| ;; CHECK-NEXT: (local $3 i32) |
| ;; CHECK-NEXT: (local.set $3 |
| ;; CHECK-NEXT: (global.get $global$1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (global.set $global$1 |
| ;; CHECK-NEXT: (i32.sub |
| ;; CHECK-NEXT: (global.get $global$1) |
| ;; CHECK-NEXT: (i32.const -64) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.store |
| ;; CHECK-NEXT: (local.get $3) |
| ;; CHECK-NEXT: (local.get $2) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.store offset=4 |
| ;; CHECK-NEXT: (local.get $3) |
| ;; CHECK-NEXT: (i32.const 100000) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.store offset=12 |
| ;; CHECK-NEXT: (local.get $3) |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.store offset=16 |
| ;; CHECK-NEXT: (local.get $3) |
| ;; CHECK-NEXT: (i32.load |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.store offset=32 |
| ;; CHECK-NEXT: (local.get $3) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.store offset=36 |
| ;; CHECK-NEXT: (local.get $3) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.store offset=40 |
| ;; CHECK-NEXT: (local.get $3) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (if |
| ;; CHECK-NEXT: (call $_deflateInit2_ |
| ;; CHECK-NEXT: (local.get $3) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (block |
| ;; CHECK-NEXT: (global.set $global$1 |
| ;; CHECK-NEXT: (local.get $3) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (return) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (if (result i32) |
| ;; CHECK-NEXT: (i32.eq |
| ;; CHECK-NEXT: (local.tee $0 |
| ;; CHECK-NEXT: (call $_deflate |
| ;; CHECK-NEXT: (local.get $3) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (block (result i32) |
| ;; CHECK-NEXT: (i32.store |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: (i32.load offset=20 |
| ;; CHECK-NEXT: (local.get $3) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.set $0 |
| ;; CHECK-NEXT: (call $_deflateEnd |
| ;; CHECK-NEXT: (local.get $3) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (global.set $global$1 |
| ;; CHECK-NEXT: (local.get $3) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (block (result i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (call $_deflateEnd |
| ;; CHECK-NEXT: (local.get $3) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (global.set $global$1 |
| ;; CHECK-NEXT: (local.get $3) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (module |
| (type $A (struct (field (mut i32)))) |
| ;; CHECK: (type $none_=>_none (func)) |
| |
| ;; CHECK: (func $foo (type $none_=>_none) |
| ;; CHECK-NEXT: (nop) |
| ;; CHECK-NEXT: ) |
| (func $foo |
| (drop |
| (block (result structref) |
| ;; this dropped item can be vacuumed out in principle, but it is a non- |
| ;; nullable reference type and we don't have a type to put in its place, so |
| ;; don't try to replace it. (later operations will remove all the body of |
| ;; this function; this test verifies we don't crash along the way) |
| (struct.new_default $A) |
| ) |
| ) |
| ) |
| ) |
| (module |
| ;; CHECK: (type $none_=>_none (func)) |
| |
| ;; CHECK: (global $global$0 (mut i32) (i32.const 10)) |
| (global $global$0 (mut i32) (i32.const 10)) |
| ;; CHECK: (func $1 (type $none_=>_none) |
| ;; CHECK-NEXT: (nop) |
| ;; CHECK-NEXT: ) |
| (func $1 |
| (drop |
| (block $block (result funcref i32) |
| ;; we can vaccum out all parts of this block: the br_if is not taken, there |
| ;; is a nop, and the tuple at the end goes to a dropped block anyhow. this |
| ;; test specifically verifies handling of tuples containing non-nullable |
| ;; types, for which we try to create a zero in an intermediate step along |
| ;; the way. |
| (drop |
| (br_if $block |
| (tuple.make |
| (ref.func $1) |
| (i32.const 0) |
| ) |
| (i32.const 0) |
| ) |
| ) |
| (nop) |
| (tuple.make |
| (ref.func $1) |
| (i32.const 1) |
| ) |
| ) |
| ) |
| ) |
| ) |