;; 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)
    )
   )
  )
 )
)