;; 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 ;; 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))) ;; CHECK: (type $5 (func (param i32) (result i32))) ;; CHECK: (type $6 (func (result f64))) ;; CHECK: (import "env" "int" (func $int (type $3) (result i32))) (import "env" "int" (func $int (result i32))) ;; CHECK: (global $Int i32 (i32.const 0)) (global $Int i32 (i32.const 0)) (memory 256 256) ;; 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) (then (nop) ) (else (drop (i32.const 101) ) ) ) (if (i32.const 102) (then (drop (i32.const 103) ) ) (else (nop) ) ) (if (i32.const 104) (then (nop) ) (else (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: (then ;; 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: ) ;; CHECK-NEXT: (else ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (then ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) ;; 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) (then (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) ) ) ) (else (i32.const 0) ) ) (then (unreachable) ) ) ) ;; CHECK: (func $if-drop (type $3) (result i32) ;; CHECK-NEXT: (block $out ;; CHECK-NEXT: (if ;; CHECK-NEXT: (call $if-drop) ;; CHECK-NEXT: (then ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (call $int) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (else ;; CHECK-NEXT: (br $out) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (if ;; CHECK-NEXT: (call $if-drop) ;; CHECK-NEXT: (then ;; CHECK-NEXT: (br $out) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (else ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (call $int) ;; CHECK-NEXT: ) ;; 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) (then (call $int) ) (else (br $out) ) ) ) (drop (if (result i32) (call $if-drop) (then (br $out) ) (else (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: (then ;; CHECK-NEXT: (call $if2drops) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (else ;; CHECK-NEXT: (call $if2drops) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (i32.const 2) ;; CHECK-NEXT: ) (func $if2drops (result i32) (if (call $if2drops) (then (drop (call $if2drops) ) ) (else (drop (call $if2drops) ) ) ) (i32.const 2) ) ;; CHECK: (func $if2drops-different (type $3) (result i32) ;; CHECK-NEXT: (if ;; CHECK-NEXT: (call $if2drops) ;; CHECK-NEXT: (then ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (call $if2drops) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (else ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (call $unary) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (i32.const 2) ;; CHECK-NEXT: ) (func $if2drops-different (result i32) (if (call $if2drops) (then (drop (call $if2drops) ;; i32 ) ) (else (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) (then (call $if-const (i32.const 1)))) (if (i32.const 2) (then (call $if-const (i32.const 3)))) (if (i32.const 0) (then (call $if-const (i32.const 4)) )(else (call $if-const (i32.const 5)))) (if (i32.const 6) (then (call $if-const (i32.const 7)) )(else (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: (then ;; CHECK-NEXT: (br $out) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (else ;; CHECK-NEXT: (br $out) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (if ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: (then ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (else ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $drop-if-both-unreachable (param $0 i32) (block $out (drop (if (result i32) (local.get $0) (then (br $out) ) (else (br $out) ) ) ) ) (drop (if (result i32) (local.get $0) (then (unreachable) ) (else (unreachable) ) ) ) ) ;; CHECK: (func $if-1-block (type $5) (param $x i32) (result i32) ;; CHECK-NEXT: (block $out ;; CHECK-NEXT: (if ;; CHECK-NEXT: (local.get $x) ;; CHECK-NEXT: (then ;; 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) (then (block (if (i32.const 1) (then (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 $6) (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) (then (unreachable) ) (else (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) (then (nop) ) (else (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) (then (br $label$0) ) (else (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) ) ) (then (unreachable) ) (else (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) ) (then (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) ) (then (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) ) (then (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) (then (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 $0 (func (param i32) (result i32))) ;; CHECK: (type $1 (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 $compress)) ;; CHECK: (func $_deflate (type $0) (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 $0) (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 $0) (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)) ) ;; CHECK: (func $compress (type $1) (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: (then ;; 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: (then ;; 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: (else ;; 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: ) (func $compress (export "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) ) (then (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) ) (then (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) ) ) (else (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) ) ) ) ) ) ) ) (module (type $A (struct (field (mut i32)))) ;; CHECK: (type $0 (func)) ;; CHECK: (func $foo (type $0) ;; 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 $0 (func)) ;; CHECK: (global $global$0 (mut i32) (i32.const 10)) (global $global$0 (mut i32) (i32.const 10)) ;; CHECK: (func $1 (type $0) ;; CHECK-NEXT: (nop) ;; CHECK-NEXT: ) (func $1 (tuple.drop 2 (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. (tuple.drop 2 (br_if $block (tuple.make 2 (ref.func $1) (i32.const 0) ) (i32.const 0) ) ) (nop) (tuple.make 2 (ref.func $1) (i32.const 1) ) ) ) ) )