;; 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 --coalesce-locals -S -o - | filecheck %s

(module
  ;; CHECK:      (type $2 (func))

  ;; CHECK:      (type $1 (func (result i32)))

  ;; CHECK:      (type $4 (func (param i32)))

  ;; CHECK:      (type $FUNCSIG$iii (func (param i32 i32) (result i32)))

  ;; CHECK:      (type $5 (func (param f64 i32) (result i64)))

  ;; CHECK:      (type $3 (func (param i32 f32)))

  ;; CHECK:      (type $FUNCSIG$iiii (func (param i32 i32 i32) (result i32)))
  (type $FUNCSIG$iiii (func (param i32 i32 i32) (result i32)))
  (type $FUNCSIG$iii (func (param i32 i32) (result i32)))
  (type $2 (func))
  (type $3 (func (param i32 f32)))
  (type $4 (func (param i32)))
  ;; CHECK:      (type $8 (func (param i32) (result i32)))

  ;; CHECK:      (type $9 (func (param i32 i32)))

  ;; CHECK:      (type $10 (func (result f64)))

  ;; CHECK:      (import "env" "_emscripten_autodebug_i32" (func $_emscripten_autodebug_i32 (param i32 i32) (result i32)))
  (import "env" "_emscripten_autodebug_i32" (func $_emscripten_autodebug_i32 (param i32 i32) (result i32)))
  ;; CHECK:      (import "env" "get" (func $get (result i32)))
  (import "env" "get" (func $get (result i32)))
  ;; CHECK:      (import "env" "set" (func $set (param i32)))
  (import "env" "set" (func $set (param i32)))

  (memory 10)

  ;; CHECK:      (memory $0 10)

  ;; CHECK:      (func $nothing-to-do
  ;; CHECK-NEXT:  (local $0 i32)
  ;; CHECK-NEXT:  (nop)
  ;; CHECK-NEXT: )
  (func $nothing-to-do (type $2)
    (local $x i32)
    (nop)
  )
  ;; CHECK:      (func $merge
  ;; CHECK-NEXT:  (local $0 i32)
  ;; CHECK-NEXT:  (nop)
  ;; CHECK-NEXT: )
  (func $merge (type $2)
    (local $x i32)
    (local $y i32)
    (nop)
  )
  ;; CHECK:      (func $leave-type
  ;; CHECK-NEXT:  (local $0 i32)
  ;; CHECK-NEXT:  (local $1 f32)
  ;; CHECK-NEXT:  (nop)
  ;; CHECK-NEXT: )
  (func $leave-type (type $2)
    (local $x i32)
    (local $y f32)
    (nop)
  )
  ;; CHECK:      (func $leave-interfere
  ;; CHECK-NEXT:  (local $0 i32)
  ;; CHECK-NEXT:  (local $1 i32)
  ;; CHECK-NEXT:  (local.set $0
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (local.set $1
  ;; CHECK-NEXT:   (i32.const 1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $leave-interfere (type $2)
    (local $x i32)
    (local $y i32)
    (local.set $x
      (i32.const 0)
    )
    (local.set $y
      (i32.const 1)
    )
    (drop
      (local.get $x)
    )
    (drop
      (local.get $y)
    )
  )
  ;; CHECK:      (func $almost-interfere
  ;; CHECK-NEXT:  (local $0 i32)
  ;; CHECK-NEXT:  (local.set $0
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (local.set $0
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $almost-interfere (type $2)
    (local $x i32)
    (local $y i32)
    (local.set $x
      (i32.const 0)
    )
    (drop
      (local.get $x)
    )
    (local.set $y
      (i32.const 0)
    )
    (drop
      (local.get $y)
    )
  )
  ;; CHECK:      (func $redundant-copy
  ;; CHECK-NEXT:  (local $0 i32)
  ;; CHECK-NEXT:  (local.set $0
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (nop)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $redundant-copy (type $2)
    (local $x i32)
    (local $y i32)
    (local.set $x
      (i32.const 0)
    )
    (local.set $y
      (local.get $x)
    )
    (drop
      (local.get $y)
    )
  )
  ;; CHECK:      (func $ineffective-store
  ;; CHECK-NEXT:  (local $0 i32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (local.set $0
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $ineffective-store (type $2)
    (local $x i32)
    (local.set $x
      (i32.const 0)
    )
    (local.set $x
      (i32.const 0)
    )
    (drop
      (local.get $x)
    )
  )
  ;; CHECK:      (func $block
  ;; CHECK-NEXT:  (local $0 i32)
  ;; CHECK-NEXT:  (block $block0
  ;; CHECK-NEXT:   (local.set $0
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $block (type $2)
    (local $x i32)
    (block $block0
      (local.set $x
        (i32.const 0)
      )
    )
    (drop
      (local.get $x)
    )
  )
  ;; CHECK:      (func $see-both-sides
  ;; CHECK-NEXT:  (local $0 i32)
  ;; CHECK-NEXT:  (local $1 i32)
  ;; CHECK-NEXT:  (local.set $0
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (block $block0
  ;; CHECK-NEXT:   (local.set $1
  ;; CHECK-NEXT:    (i32.const 1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $see-both-sides (type $2)
    (local $x i32)
    (local $y i32)
    (local.set $x
      (i32.const 0)
    )
    (block $block0
      (local.set $y
        (i32.const 1)
      )
    )
    (drop
      (local.get $x)
    )
    (drop
      (local.get $y)
    )
  )
  ;; CHECK:      (func $see-br-and-ignore-dead
  ;; CHECK-NEXT:  (local $0 i32)
  ;; CHECK-NEXT:  (local.set $0
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (block $block
  ;; CHECK-NEXT:   (br $block)
  ;; CHECK-NEXT:   (drop
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (drop
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (drop
  ;; CHECK-NEXT:    (i32.const -1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $see-br-and-ignore-dead (type $2)
    (local $x i32)
    (local $y i32)
    (local.set $x
      (i32.const 0)
    )
    (block $block
      (br $block)
      (local.set $y
        (i32.const 0)
      )
      (drop
        (local.get $y)
      )
      (local.set $x
        (i32.const -1)
      )
    )
    (drop
      (local.get $x)
    )
  )
  ;; CHECK:      (func $see-block-body
  ;; CHECK-NEXT:  (local $0 i32)
  ;; CHECK-NEXT:  (local $1 i32)
  ;; CHECK-NEXT:  (local.set $0
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (block $block
  ;; CHECK-NEXT:   (local.set $1
  ;; CHECK-NEXT:    (i32.const 1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (drop
  ;; CHECK-NEXT:    (local.get $1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (br $block)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $see-block-body (type $2)
    (local $x i32)
    (local $y i32)
    (local.set $x
      (i32.const 0)
    )
    (block $block
      (local.set $y
        (i32.const 1)
      )
      (drop
        (local.get $y)
      )
      (br $block)
    )
    (drop
      (local.get $x)
    )
  )
  ;; CHECK:      (func $zero-init
  ;; CHECK-NEXT:  (local $0 i32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $zero-init (type $2)
    (local $x i32)
    (local $y i32)
    (drop
      (local.get $x)
    )
    (drop
      (local.get $y)
    )
  )
  ;; CHECK:      (func $multi
  ;; CHECK-NEXT:  (local $0 i32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $multi (type $2)
    (local $x i32)
    (local $y i32)
    (local $z i32)
    (drop
      (local.get $y)
    )
    (drop
      (local.get $z)
    )
  )
  ;; CHECK:      (func $if-else
  ;; CHECK-NEXT:  (local $0 i32)
  ;; CHECK-NEXT:  (if
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:   (then
  ;; CHECK-NEXT:    (drop
  ;; CHECK-NEXT:     (local.get $0)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (else
  ;; CHECK-NEXT:    (drop
  ;; CHECK-NEXT:     (local.get $0)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $if-else (type $2)
    (local $x i32)
    (local $y i32)
    (if
      (i32.const 0)
      (then
        (drop
          (local.get $x)
        )
      )
      (else
        (drop
          (local.get $y)
        )
      )
    )
  )
  ;; CHECK:      (func $if-else-parallel
  ;; CHECK-NEXT:  (local $0 i32)
  ;; CHECK-NEXT:  (if
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:   (then
  ;; CHECK-NEXT:    (block $block1
  ;; CHECK-NEXT:     (local.set $0
  ;; CHECK-NEXT:      (i32.const 0)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (drop
  ;; CHECK-NEXT:      (local.get $0)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (else
  ;; CHECK-NEXT:    (block $block3
  ;; CHECK-NEXT:     (local.set $0
  ;; CHECK-NEXT:      (i32.const 1)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (drop
  ;; CHECK-NEXT:      (local.get $0)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $if-else-parallel (type $2)
    (local $x i32)
    (local $y i32)
    (if
      (i32.const 0)
      (then
        (block $block1
          (local.set $x
            (i32.const 0)
          )
          (drop
            (local.get $x)
          )
        )
      )
      (else
        (block $block3
          (local.set $y
            (i32.const 1)
          )
          (drop
            (local.get $y)
          )
        )
      )
    )
  )
  ;; CHECK:      (func $if-else-after
  ;; CHECK-NEXT:  (local $0 i32)
  ;; CHECK-NEXT:  (local $1 i32)
  ;; CHECK-NEXT:  (if
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:   (then
  ;; CHECK-NEXT:    (local.set $0
  ;; CHECK-NEXT:     (i32.const 0)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (else
  ;; CHECK-NEXT:    (local.set $1
  ;; CHECK-NEXT:     (i32.const 1)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $if-else-after (type $2)
    (local $x i32)
    (local $y i32)
    (if
      (i32.const 0)
      (then
        (local.set $x
          (i32.const 0)
        )
      )
      (else
        (local.set $y
          (i32.const 1)
        )
      )
    )
    (drop
      (local.get $x)
    )
    (drop
      (local.get $y)
    )
  )
  ;; CHECK:      (func $if-else-through
  ;; CHECK-NEXT:  (local $0 i32)
  ;; CHECK-NEXT:  (local $1 i32)
  ;; CHECK-NEXT:  (local.set $0
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (local.set $1
  ;; CHECK-NEXT:   (i32.const 1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (if
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:   (then
  ;; CHECK-NEXT:    (drop
  ;; CHECK-NEXT:     (i32.const 1)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (else
  ;; CHECK-NEXT:    (drop
  ;; CHECK-NEXT:     (i32.const 2)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $if-else-through (type $2)
    (local $x i32)
    (local $y i32)
    (local.set $x
      (i32.const 0)
    )
    (local.set $y
      (i32.const 1)
    )
    (if
      (i32.const 0)
      (then
        (drop
          (i32.const 1)
        )
      )
      (else
        (drop
          (i32.const 2)
        )
      )
    )
    (drop
      (local.get $x)
    )
    (drop
      (local.get $y)
    )
  )
  ;; CHECK:      (func $if-through
  ;; CHECK-NEXT:  (local $0 i32)
  ;; CHECK-NEXT:  (local $1 i32)
  ;; CHECK-NEXT:  (local.set $0
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (local.set $1
  ;; CHECK-NEXT:   (i32.const 1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (if
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:   (then
  ;; CHECK-NEXT:    (drop
  ;; CHECK-NEXT:     (i32.const 1)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $if-through (type $2)
    (local $x i32)
    (local $y i32)
    (local.set $x
      (i32.const 0)
    )
    (local.set $y
      (i32.const 1)
    )
    (if
      (i32.const 0)
      (then
        (drop
          (i32.const 1)
        )
      )
    )
    (drop
      (local.get $x)
    )
    (drop
      (local.get $y)
    )
  )
  ;; CHECK:      (func $if-through2
  ;; CHECK-NEXT:  (local $0 i32)
  ;; CHECK-NEXT:  (local $1 i32)
  ;; CHECK-NEXT:  (local.set $0
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (if
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:   (then
  ;; CHECK-NEXT:    (local.set $1
  ;; CHECK-NEXT:     (i32.const 1)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $if-through2 (type $2)
    (local $x i32)
    (local $y i32)
    (local.set $x
      (i32.const 0)
    )
    (if
      (i32.const 0)
      (then
        (local.set $y
          (i32.const 1)
        )
      )
    )
    (drop
      (local.get $x)
    )
    (drop
      (local.get $y)
    )
  )
  ;; CHECK:      (func $if-through3
  ;; CHECK-NEXT:  (local $0 i32)
  ;; CHECK-NEXT:  (local $1 i32)
  ;; CHECK-NEXT:  (local.set $0
  ;; CHECK-NEXT:   (i32.const 1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (if
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:   (then
  ;; CHECK-NEXT:    (block $block1
  ;; CHECK-NEXT:     (drop
  ;; CHECK-NEXT:      (local.get $0)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (drop
  ;; CHECK-NEXT:      (local.get $1)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $if-through3 (type $2)
    (local $x i32)
    (local $y i32)
    (local.set $x
      (i32.const 1)
    )
    (if
      (i32.const 0)
      (then
        (block $block1
          (drop
            (local.get $x)
          )
          (drop
            (local.get $y)
          )
        )
      )
    )
  )
  ;; CHECK:      (func $if2
  ;; CHECK-NEXT:  (local $0 i32)
  ;; CHECK-NEXT:  (local $1 i32)
  ;; CHECK-NEXT:  (if
  ;; CHECK-NEXT:   (local.tee $0
  ;; CHECK-NEXT:    (i32.const 1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (then
  ;; CHECK-NEXT:    (block $block1
  ;; CHECK-NEXT:     (drop
  ;; CHECK-NEXT:      (local.get $0)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (drop
  ;; CHECK-NEXT:      (local.get $1)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $if2 (type $2)
    (local $x i32)
    (local $y i32)
    (if
      (local.tee $x
        (i32.const 1)
      )
      (then
        (block $block1
          (drop
            (local.get $x)
          )
          (drop
            (local.get $y)
          )
        )
      )
    )
  )
  ;; CHECK:      (func $if3
  ;; CHECK-NEXT:  (local $0 i32)
  ;; CHECK-NEXT:  (local $1 i32)
  ;; CHECK-NEXT:  (if
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:   (then
  ;; CHECK-NEXT:    (block $block1
  ;; CHECK-NEXT:     (local.set $0
  ;; CHECK-NEXT:      (i32.const 0)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (drop
  ;; CHECK-NEXT:      (local.get $0)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $if3 (type $2)
    (local $x i32)
    (local $y i32)
    (if
      (i32.const 0)
      (then
        (block $block1
          (local.set $x
            (i32.const 0)
          )
          (drop
            (local.get $x)
          )
        )
      )
    )
    (drop
      (local.get $y)
    )
  )
  ;; CHECK:      (func $if4
  ;; CHECK-NEXT:  (local $0 i32)
  ;; CHECK-NEXT:  (if
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:   (then
  ;; CHECK-NEXT:    (block $block1
  ;; CHECK-NEXT:     (local.set $0
  ;; CHECK-NEXT:      (i32.const 0)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (drop
  ;; CHECK-NEXT:      (local.get $0)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (local.set $0
  ;; CHECK-NEXT:      (i32.const 1)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $if4 (type $2)
    (local $x i32)
    (local $y i32)
    (if
      (i32.const 0)
      (then
        (block $block1
          (local.set $x
            (i32.const 0)
          )
          (drop
            (local.get $x)
          )
          (local.set $y
            (i32.const 1)
          )
        )
      )
    )
    (drop
      (local.get $y)
    )
  )
  ;; CHECK:      (func $if5
  ;; CHECK-NEXT:  (local $0 i32)
  ;; CHECK-NEXT:  (if
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:   (then
  ;; CHECK-NEXT:    (block $block1
  ;; CHECK-NEXT:     (drop
  ;; CHECK-NEXT:      (local.get $0)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (local.set $0
  ;; CHECK-NEXT:      (i32.const 1)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $if5 (type $2)
    (local $x i32)
    (local $y i32)
    (if
      (i32.const 0)
      (then
        (block $block1
          ;; These locals can be coalesced together: $x's live range ends here,
          ;; and $y's begins right after it, so they do not have an overlap with
          ;; a different value.
          (drop
            (local.get $x)
          )
          (local.set $y
            (i32.const 1)
          )
        )
      )
    )
    (drop
      (local.get $y)
    )
  )
  ;; CHECK:      (func $if5-flip
  ;; CHECK-NEXT:  (local $0 i32)
  ;; CHECK-NEXT:  (local $1 i32)
  ;; CHECK-NEXT:  (if
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:   (then
  ;; CHECK-NEXT:    (block $block1
  ;; CHECK-NEXT:     (local.set $1
  ;; CHECK-NEXT:      (i32.const 1)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (drop
  ;; CHECK-NEXT:      (local.get $0)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $if5-flip (type $2)
    (local $x i32)
    (local $y i32)
    (if
      (i32.const 0)
      (then
        (block $block1
          ;; As above, but flipping these two instructions causes a conflict.
          (local.set $y
            (i32.const 1)
          )
          (drop
            (local.get $x)
          )
        )
      )
    )
    (drop
      (local.get $y)
    )
  )
  ;; CHECK:      (func $loop
  ;; CHECK-NEXT:  (local $0 i32)
  ;; CHECK-NEXT:  (local $1 i32)
  ;; CHECK-NEXT:  (loop $in
  ;; CHECK-NEXT:   (drop
  ;; CHECK-NEXT:    (local.get $0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (local.set $0
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (drop
  ;; CHECK-NEXT:    (local.get $1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (br $in)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $loop (type $2)
    (local $x i32)
    (local $y i32)
    (loop $in
      (drop
        (local.get $x)
      )
      (local.set $x
        (i32.const 0)
      )
      (drop
        (local.get $y)
      )
      (br $in)
    )
  )
  ;; CHECK:      (func $interfere-in-dead
  ;; CHECK-NEXT:  (local $0 i32)
  ;; CHECK-NEXT:  (block $block
  ;; CHECK-NEXT:   (br $block)
  ;; CHECK-NEXT:   (drop
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (drop
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $interfere-in-dead (type $2)
    (local $x i32)
    (local $y i32)
    (block $block
      (br $block)
      (drop
        (local.get $x)
      )
      (drop
        (local.get $y)
      )
    )
  )
  ;; CHECK:      (func $interfere-in-dead2
  ;; CHECK-NEXT:  (local $0 i32)
  ;; CHECK-NEXT:  (block $block
  ;; CHECK-NEXT:   (unreachable)
  ;; CHECK-NEXT:   (drop
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (drop
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $interfere-in-dead2 (type $2)
    (local $x i32)
    (local $y i32)
    (block $block
      (unreachable)
      (drop
        (local.get $x)
      )
      (drop
        (local.get $y)
      )
    )
  )
  ;; CHECK:      (func $interfere-in-dead3
  ;; CHECK-NEXT:  (local $0 i32)
  ;; CHECK-NEXT:  (block $block
  ;; CHECK-NEXT:   (return)
  ;; CHECK-NEXT:   (drop
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (drop
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $interfere-in-dead3 (type $2)
    (local $x i32)
    (local $y i32)
    (block $block
      (return)
      (drop
        (local.get $x)
      )
      (drop
        (local.get $y)
      )
    )
  )
  ;; CHECK:      (func $params (param $0 i32) (param $1 f32)
  ;; CHECK-NEXT:  (local $2 i32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $2)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $2)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $2)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $params (type $3) (param $p i32) (param $q f32)
    (local $x i32)
    (local $y i32)
    (local $z i32)
    (local $w i32)
    (drop
      (local.get $y)
    )
    (drop
      (local.get $z)
    )
    (drop
      (local.get $w)
    )
  )
  ;; CHECK:      (func $interfere-in-dead4
  ;; CHECK-NEXT:  (local $0 i32)
  ;; CHECK-NEXT:  (block $block
  ;; CHECK-NEXT:   (br_if $block
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (drop
  ;; CHECK-NEXT:    (local.get $0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (drop
  ;; CHECK-NEXT:    (local.get $0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $interfere-in-dead4 (type $2)
    (local $x i32)
    (local $y i32)
    (block $block
      (br_if $block
        (i32.const 0)
      )
      (drop
        (local.get $x)
      )
      (drop
        (local.get $y)
      )
    )
  )
  ;; CHECK:      (func $switch
  ;; CHECK-NEXT:  (local $0 i32)
  ;; CHECK-NEXT:  (block $switch$def
  ;; CHECK-NEXT:   (block $switch-case$1
  ;; CHECK-NEXT:    (block $switch-case$2
  ;; CHECK-NEXT:     (br_table $switch-case$1 $switch-case$2 $switch-case$1 $switch-case$1 $switch$def
  ;; CHECK-NEXT:      (i32.const 100)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (drop
  ;; CHECK-NEXT:      (i32.const 0)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (drop
  ;; CHECK-NEXT:     (local.get $0)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (drop
  ;; CHECK-NEXT:    (local.get $0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $switch (type $2)
    (local $x i32)
    (local $y i32)
    (local $z i32)
    (local $w i32)
    (block $switch$def
      (block $switch-case$1
        (block $switch-case$2
          (br_table $switch-case$1 $switch-case$2 $switch-case$1 $switch-case$1 $switch$def
            (i32.const 100)
          )
          (drop
            (local.get $x)
          )
        )
        (drop
          (local.get $y)
        )
      )
      (drop
        (local.get $z)
      )
    )
    (drop
      (local.get $w)
    )
  )
  ;; CHECK:      (func $greedy-can-be-happy
  ;; CHECK-NEXT:  (local $0 i32)
  ;; CHECK-NEXT:  (local $1 i32)
  ;; CHECK-NEXT:  (if
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:   (then
  ;; CHECK-NEXT:    (if
  ;; CHECK-NEXT:     (i32.const 1)
  ;; CHECK-NEXT:     (then
  ;; CHECK-NEXT:      (if
  ;; CHECK-NEXT:       (i32.const 2)
  ;; CHECK-NEXT:       (then
  ;; CHECK-NEXT:        (block $block3
  ;; CHECK-NEXT:         (local.set $0
  ;; CHECK-NEXT:          (i32.const 100)
  ;; CHECK-NEXT:         )
  ;; CHECK-NEXT:         (local.set $1
  ;; CHECK-NEXT:          (i32.const 101)
  ;; CHECK-NEXT:         )
  ;; CHECK-NEXT:         (drop
  ;; CHECK-NEXT:          (local.get $0)
  ;; CHECK-NEXT:         )
  ;; CHECK-NEXT:         (drop
  ;; CHECK-NEXT:          (local.get $1)
  ;; CHECK-NEXT:         )
  ;; CHECK-NEXT:        )
  ;; CHECK-NEXT:       )
  ;; CHECK-NEXT:       (else
  ;; CHECK-NEXT:        (block $block5
  ;; CHECK-NEXT:         (local.set $0
  ;; CHECK-NEXT:          (i32.const 102)
  ;; CHECK-NEXT:         )
  ;; CHECK-NEXT:         (local.set $1
  ;; CHECK-NEXT:          (i32.const 103)
  ;; CHECK-NEXT:         )
  ;; CHECK-NEXT:         (drop
  ;; CHECK-NEXT:          (local.get $0)
  ;; CHECK-NEXT:         )
  ;; CHECK-NEXT:         (drop
  ;; CHECK-NEXT:          (local.get $1)
  ;; CHECK-NEXT:         )
  ;; CHECK-NEXT:        )
  ;; CHECK-NEXT:       )
  ;; CHECK-NEXT:      )
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (else
  ;; CHECK-NEXT:      (if
  ;; CHECK-NEXT:       (i32.const 3)
  ;; CHECK-NEXT:       (then
  ;; CHECK-NEXT:        (block $block8
  ;; CHECK-NEXT:         (local.set $0
  ;; CHECK-NEXT:          (i32.const 104)
  ;; CHECK-NEXT:         )
  ;; CHECK-NEXT:         (local.set $1
  ;; CHECK-NEXT:          (i32.const 105)
  ;; CHECK-NEXT:         )
  ;; CHECK-NEXT:         (drop
  ;; CHECK-NEXT:          (local.get $0)
  ;; CHECK-NEXT:         )
  ;; CHECK-NEXT:         (drop
  ;; CHECK-NEXT:          (local.get $1)
  ;; CHECK-NEXT:         )
  ;; CHECK-NEXT:        )
  ;; CHECK-NEXT:       )
  ;; CHECK-NEXT:       (else
  ;; CHECK-NEXT:        (block $block10
  ;; CHECK-NEXT:         (local.set $0
  ;; CHECK-NEXT:          (i32.const 106)
  ;; CHECK-NEXT:         )
  ;; CHECK-NEXT:         (local.set $1
  ;; CHECK-NEXT:          (i32.const 107)
  ;; CHECK-NEXT:         )
  ;; CHECK-NEXT:         (drop
  ;; CHECK-NEXT:          (local.get $0)
  ;; CHECK-NEXT:         )
  ;; CHECK-NEXT:         (drop
  ;; CHECK-NEXT:          (local.get $1)
  ;; CHECK-NEXT:         )
  ;; CHECK-NEXT:        )
  ;; CHECK-NEXT:       )
  ;; CHECK-NEXT:      )
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (else
  ;; CHECK-NEXT:    (if
  ;; CHECK-NEXT:     (i32.const 4)
  ;; CHECK-NEXT:     (then
  ;; CHECK-NEXT:      (block $block13
  ;; CHECK-NEXT:       (local.set $0
  ;; CHECK-NEXT:        (i32.const 108)
  ;; CHECK-NEXT:       )
  ;; CHECK-NEXT:       (local.set $1
  ;; CHECK-NEXT:        (i32.const 109)
  ;; CHECK-NEXT:       )
  ;; CHECK-NEXT:       (drop
  ;; CHECK-NEXT:        (local.get $0)
  ;; CHECK-NEXT:       )
  ;; CHECK-NEXT:       (drop
  ;; CHECK-NEXT:        (local.get $1)
  ;; CHECK-NEXT:       )
  ;; CHECK-NEXT:      )
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (else
  ;; CHECK-NEXT:      (block $block15
  ;; CHECK-NEXT:       (local.set $0
  ;; CHECK-NEXT:        (i32.const 110)
  ;; CHECK-NEXT:       )
  ;; CHECK-NEXT:       (local.set $1
  ;; CHECK-NEXT:        (i32.const 111)
  ;; CHECK-NEXT:       )
  ;; CHECK-NEXT:       (drop
  ;; CHECK-NEXT:        (local.get $0)
  ;; CHECK-NEXT:       )
  ;; CHECK-NEXT:       (drop
  ;; CHECK-NEXT:        (local.get $1)
  ;; CHECK-NEXT:       )
  ;; CHECK-NEXT:      )
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $greedy-can-be-happy (type $2)
    (local $x1 i32)
    (local $x2 i32)
    (local $x3 i32)
    (local $y1 i32)
    (local $y2 i32)
    (local $y3 i32)
    (if
      (i32.const 0)
      (then
        (if
          (i32.const 1)
          (then
            (if
              (i32.const 2)
              (then
                (block $block3
                  (local.set $x1
                    (i32.const 100)
                  )
                  (local.set $y2
                    (i32.const 101)
                  )
                  (drop
                    (local.get $x1)
                  )
                  (drop
                    (local.get $y2)
                  )
                )
              )
              (else
                (block $block5
                  (local.set $x1
                    (i32.const 102)
                  )
                  (local.set $y3
                    (i32.const 103)
                  )
                  (drop
                    (local.get $x1)
                  )
                  (drop
                    (local.get $y3)
                  )
                )
              )
            )
          )
          (else
            (if
              (i32.const 3)
              (then
                (block $block8
                  (local.set $x2
                    (i32.const 104)
                  )
                  (local.set $y1
                    (i32.const 105)
                  )
                  (drop
                    (local.get $x2)
                  )
                  (drop
                    (local.get $y1)
                  )
                )
              )
              (else
                (block $block10
                  (local.set $x2
                    (i32.const 106)
                  )
                  (local.set $y3
                    (i32.const 107)
                  )
                  (drop
                    (local.get $x2)
                  )
                  (drop
                    (local.get $y3)
                  )
                )
              )
            )
          )
        )
      )
      (else
        (if
          (i32.const 4)
          (then
            (block $block13
              (local.set $x3
                (i32.const 108)
              )
              (local.set $y1
                (i32.const 109)
              )
              (drop
                (local.get $x3)
              )
              (drop
                (local.get $y1)
              )
            )
          )
          (else
            (block $block15
              (local.set $x3
                (i32.const 110)
              )
              (local.set $y2
                (i32.const 111)
              )
              (drop
                (local.get $x3)
              )
              (drop
                (local.get $y2)
              )
            )
          )
        )
      )
    )
  )
  ;; CHECK:      (func $greedy-can-be-sad
  ;; CHECK-NEXT:  (local $0 i32)
  ;; CHECK-NEXT:  (local $1 i32)
  ;; CHECK-NEXT:  (local $2 i32)
  ;; CHECK-NEXT:  (if
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:   (then
  ;; CHECK-NEXT:    (if
  ;; CHECK-NEXT:     (i32.const 1)
  ;; CHECK-NEXT:     (then
  ;; CHECK-NEXT:      (if
  ;; CHECK-NEXT:       (i32.const 2)
  ;; CHECK-NEXT:       (then
  ;; CHECK-NEXT:        (block $block3
  ;; CHECK-NEXT:         (local.set $0
  ;; CHECK-NEXT:          (i32.const 100)
  ;; CHECK-NEXT:         )
  ;; CHECK-NEXT:         (local.set $1
  ;; CHECK-NEXT:          (i32.const 101)
  ;; CHECK-NEXT:         )
  ;; CHECK-NEXT:         (drop
  ;; CHECK-NEXT:          (local.get $0)
  ;; CHECK-NEXT:         )
  ;; CHECK-NEXT:         (drop
  ;; CHECK-NEXT:          (local.get $1)
  ;; CHECK-NEXT:         )
  ;; CHECK-NEXT:        )
  ;; CHECK-NEXT:       )
  ;; CHECK-NEXT:       (else
  ;; CHECK-NEXT:        (block $block5
  ;; CHECK-NEXT:         (local.set $0
  ;; CHECK-NEXT:          (i32.const 102)
  ;; CHECK-NEXT:         )
  ;; CHECK-NEXT:         (local.set $2
  ;; CHECK-NEXT:          (i32.const 103)
  ;; CHECK-NEXT:         )
  ;; CHECK-NEXT:         (drop
  ;; CHECK-NEXT:          (local.get $0)
  ;; CHECK-NEXT:         )
  ;; CHECK-NEXT:         (drop
  ;; CHECK-NEXT:          (local.get $2)
  ;; CHECK-NEXT:         )
  ;; CHECK-NEXT:        )
  ;; CHECK-NEXT:       )
  ;; CHECK-NEXT:      )
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (else
  ;; CHECK-NEXT:      (if
  ;; CHECK-NEXT:       (i32.const 3)
  ;; CHECK-NEXT:       (then
  ;; CHECK-NEXT:        (block $block8
  ;; CHECK-NEXT:         (local.set $1
  ;; CHECK-NEXT:          (i32.const 104)
  ;; CHECK-NEXT:         )
  ;; CHECK-NEXT:         (local.set $0
  ;; CHECK-NEXT:          (i32.const 105)
  ;; CHECK-NEXT:         )
  ;; CHECK-NEXT:         (drop
  ;; CHECK-NEXT:          (local.get $1)
  ;; CHECK-NEXT:         )
  ;; CHECK-NEXT:         (drop
  ;; CHECK-NEXT:          (local.get $0)
  ;; CHECK-NEXT:         )
  ;; CHECK-NEXT:        )
  ;; CHECK-NEXT:       )
  ;; CHECK-NEXT:       (else
  ;; CHECK-NEXT:        (block $block10
  ;; CHECK-NEXT:         (local.set $1
  ;; CHECK-NEXT:          (i32.const 106)
  ;; CHECK-NEXT:         )
  ;; CHECK-NEXT:         (local.set $2
  ;; CHECK-NEXT:          (i32.const 107)
  ;; CHECK-NEXT:         )
  ;; CHECK-NEXT:         (drop
  ;; CHECK-NEXT:          (local.get $1)
  ;; CHECK-NEXT:         )
  ;; CHECK-NEXT:         (drop
  ;; CHECK-NEXT:          (local.get $2)
  ;; CHECK-NEXT:         )
  ;; CHECK-NEXT:        )
  ;; CHECK-NEXT:       )
  ;; CHECK-NEXT:      )
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (else
  ;; CHECK-NEXT:    (if
  ;; CHECK-NEXT:     (i32.const 4)
  ;; CHECK-NEXT:     (then
  ;; CHECK-NEXT:      (block $block13
  ;; CHECK-NEXT:       (local.set $2
  ;; CHECK-NEXT:        (i32.const 108)
  ;; CHECK-NEXT:       )
  ;; CHECK-NEXT:       (local.set $0
  ;; CHECK-NEXT:        (i32.const 109)
  ;; CHECK-NEXT:       )
  ;; CHECK-NEXT:       (drop
  ;; CHECK-NEXT:        (local.get $2)
  ;; CHECK-NEXT:       )
  ;; CHECK-NEXT:       (drop
  ;; CHECK-NEXT:        (local.get $0)
  ;; CHECK-NEXT:       )
  ;; CHECK-NEXT:      )
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (else
  ;; CHECK-NEXT:      (block $block15
  ;; CHECK-NEXT:       (local.set $2
  ;; CHECK-NEXT:        (i32.const 110)
  ;; CHECK-NEXT:       )
  ;; CHECK-NEXT:       (local.set $1
  ;; CHECK-NEXT:        (i32.const 111)
  ;; CHECK-NEXT:       )
  ;; CHECK-NEXT:       (drop
  ;; CHECK-NEXT:        (local.get $2)
  ;; CHECK-NEXT:       )
  ;; CHECK-NEXT:       (drop
  ;; CHECK-NEXT:        (local.get $1)
  ;; CHECK-NEXT:       )
  ;; CHECK-NEXT:      )
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $greedy-can-be-sad (type $2)
    (local $x1 i32)
    (local $y1 i32)
    (local $x2 i32)
    (local $y2 i32)
    (local $x3 i32)
    (local $y3 i32)
    (if
      (i32.const 0)
      (then
        (if
          (i32.const 1)
          (then
            (if
              (i32.const 2)
              (then
                (block $block3
                  (local.set $x1
                    (i32.const 100)
                  )
                  (local.set $y2
                    (i32.const 101)
                  )
                  (drop
                    (local.get $x1)
                  )
                  (drop
                    (local.get $y2)
                  )
                )
              )
              (else
                (block $block5
                  (local.set $x1
                    (i32.const 102)
                  )
                  (local.set $y3
                    (i32.const 103)
                  )
                  (drop
                    (local.get $x1)
                  )
                  (drop
                    (local.get $y3)
                  )
                )
              )
            )
          )
          (else
            (if
              (i32.const 3)
              (then
                (block $block8
                  (local.set $x2
                    (i32.const 104)
                  )
                  (local.set $y1
                    (i32.const 105)
                  )
                  (drop
                    (local.get $x2)
                  )
                  (drop
                    (local.get $y1)
                  )
                )
              )
              (else
                (block $block10
                  (local.set $x2
                    (i32.const 106)
                  )
                  (local.set $y3
                    (i32.const 107)
                  )
                  (drop
                    (local.get $x2)
                  )
                  (drop
                    (local.get $y3)
                  )
                )
              )
            )
          )
        )
      )
      (else
        (if
          (i32.const 4)
          (then
            (block $block13
              (local.set $x3
                (i32.const 108)
              )
              (local.set $y1
                (i32.const 109)
              )
              (drop
                (local.get $x3)
              )
              (drop
                (local.get $y1)
              )
            )
          )
          (else
            (block $block15
              (local.set $x3
                (i32.const 110)
              )
              (local.set $y2
                (i32.const 111)
              )
              (drop
                (local.get $x3)
              )
              (drop
                (local.get $y2)
              )
            )
          )
        )
      )
    )
  )
  ;; CHECK:      (func $_memcpy (param $0 i32) (param $1 i32) (param $2 i32) (result i32)
  ;; CHECK-NEXT:  (local $3 i32)
  ;; CHECK-NEXT:  (if
  ;; CHECK-NEXT:   (i32.ge_s
  ;; CHECK-NEXT:    (local.get $2)
  ;; CHECK-NEXT:    (i32.const 4096)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (then
  ;; CHECK-NEXT:    (drop
  ;; CHECK-NEXT:     (local.get $0)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (local.set $3
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (if
  ;; CHECK-NEXT:   (i32.eq
  ;; CHECK-NEXT:    (i32.and
  ;; CHECK-NEXT:     (local.get $0)
  ;; CHECK-NEXT:     (i32.const 3)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (i32.and
  ;; CHECK-NEXT:     (local.get $1)
  ;; CHECK-NEXT:     (i32.const 3)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (then
  ;; CHECK-NEXT:    (block $block2
  ;; CHECK-NEXT:     (block $while-out$0
  ;; CHECK-NEXT:      (loop $while-in$1
  ;; CHECK-NEXT:       (if
  ;; CHECK-NEXT:        (i32.eqz
  ;; CHECK-NEXT:         (i32.and
  ;; CHECK-NEXT:          (local.get $0)
  ;; CHECK-NEXT:          (i32.const 3)
  ;; CHECK-NEXT:         )
  ;; CHECK-NEXT:        )
  ;; CHECK-NEXT:        (then
  ;; CHECK-NEXT:         (br $while-out$0)
  ;; CHECK-NEXT:        )
  ;; CHECK-NEXT:       )
  ;; CHECK-NEXT:       (block $block4
  ;; CHECK-NEXT:        (if
  ;; CHECK-NEXT:         (i32.eqz
  ;; CHECK-NEXT:          (local.get $2)
  ;; CHECK-NEXT:         )
  ;; CHECK-NEXT:         (then
  ;; CHECK-NEXT:          (return
  ;; CHECK-NEXT:           (local.get $3)
  ;; CHECK-NEXT:          )
  ;; CHECK-NEXT:         )
  ;; CHECK-NEXT:        )
  ;; CHECK-NEXT:        (i32.store8
  ;; CHECK-NEXT:         (local.get $0)
  ;; CHECK-NEXT:         (i32.load8_s
  ;; CHECK-NEXT:          (local.get $1)
  ;; CHECK-NEXT:         )
  ;; CHECK-NEXT:        )
  ;; CHECK-NEXT:        (local.set $0
  ;; CHECK-NEXT:         (i32.add
  ;; CHECK-NEXT:          (local.get $0)
  ;; CHECK-NEXT:          (i32.const 1)
  ;; CHECK-NEXT:         )
  ;; CHECK-NEXT:        )
  ;; CHECK-NEXT:        (local.set $1
  ;; CHECK-NEXT:         (i32.add
  ;; CHECK-NEXT:          (local.get $1)
  ;; CHECK-NEXT:          (i32.const 1)
  ;; CHECK-NEXT:         )
  ;; CHECK-NEXT:        )
  ;; CHECK-NEXT:        (local.set $2
  ;; CHECK-NEXT:         (i32.sub
  ;; CHECK-NEXT:          (local.get $2)
  ;; CHECK-NEXT:          (i32.const 1)
  ;; CHECK-NEXT:         )
  ;; CHECK-NEXT:        )
  ;; CHECK-NEXT:       )
  ;; CHECK-NEXT:       (br $while-in$1)
  ;; CHECK-NEXT:      )
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (block $while-out$2
  ;; CHECK-NEXT:      (loop $while-in$3
  ;; CHECK-NEXT:       (if
  ;; CHECK-NEXT:        (i32.eqz
  ;; CHECK-NEXT:         (i32.ge_s
  ;; CHECK-NEXT:          (local.get $2)
  ;; CHECK-NEXT:          (i32.const 4)
  ;; CHECK-NEXT:         )
  ;; CHECK-NEXT:        )
  ;; CHECK-NEXT:        (then
  ;; CHECK-NEXT:         (br $while-out$2)
  ;; CHECK-NEXT:        )
  ;; CHECK-NEXT:       )
  ;; CHECK-NEXT:       (block $block7
  ;; CHECK-NEXT:        (i32.store
  ;; CHECK-NEXT:         (local.get $0)
  ;; CHECK-NEXT:         (i32.load
  ;; CHECK-NEXT:          (local.get $1)
  ;; CHECK-NEXT:         )
  ;; CHECK-NEXT:        )
  ;; CHECK-NEXT:        (local.set $0
  ;; CHECK-NEXT:         (i32.add
  ;; CHECK-NEXT:          (local.get $0)
  ;; CHECK-NEXT:          (i32.const 4)
  ;; CHECK-NEXT:         )
  ;; CHECK-NEXT:        )
  ;; CHECK-NEXT:        (local.set $1
  ;; CHECK-NEXT:         (i32.add
  ;; CHECK-NEXT:          (local.get $1)
  ;; CHECK-NEXT:          (i32.const 4)
  ;; CHECK-NEXT:         )
  ;; CHECK-NEXT:        )
  ;; CHECK-NEXT:        (local.set $2
  ;; CHECK-NEXT:         (i32.sub
  ;; CHECK-NEXT:          (local.get $2)
  ;; CHECK-NEXT:          (i32.const 4)
  ;; CHECK-NEXT:         )
  ;; CHECK-NEXT:        )
  ;; CHECK-NEXT:       )
  ;; CHECK-NEXT:       (br $while-in$3)
  ;; CHECK-NEXT:      )
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (block $while-out$4
  ;; CHECK-NEXT:   (loop $while-in$5
  ;; CHECK-NEXT:    (if
  ;; CHECK-NEXT:     (i32.eqz
  ;; CHECK-NEXT:      (i32.gt_s
  ;; CHECK-NEXT:       (local.get $2)
  ;; CHECK-NEXT:       (i32.const 0)
  ;; CHECK-NEXT:      )
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (then
  ;; CHECK-NEXT:      (br $while-out$4)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (block $block9
  ;; CHECK-NEXT:     (i32.store8
  ;; CHECK-NEXT:      (local.get $0)
  ;; CHECK-NEXT:      (i32.load8_s
  ;; CHECK-NEXT:       (local.get $1)
  ;; CHECK-NEXT:      )
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (local.set $0
  ;; CHECK-NEXT:      (i32.add
  ;; CHECK-NEXT:       (local.get $0)
  ;; CHECK-NEXT:       (i32.const 1)
  ;; CHECK-NEXT:      )
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (local.set $1
  ;; CHECK-NEXT:      (i32.add
  ;; CHECK-NEXT:       (local.get $1)
  ;; CHECK-NEXT:       (i32.const 1)
  ;; CHECK-NEXT:      )
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (local.set $2
  ;; CHECK-NEXT:      (i32.sub
  ;; CHECK-NEXT:       (local.get $2)
  ;; CHECK-NEXT:       (i32.const 1)
  ;; CHECK-NEXT:      )
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (br $while-in$5)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (return
  ;; CHECK-NEXT:   (local.get $3)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $_memcpy (type $FUNCSIG$iiii) (param $i1 i32) (param $i2 i32) (param $i3 i32) (result i32)
    (local $i4 i32)
    (if
      (i32.ge_s
        (local.get $i3)
        (i32.const 4096)
      )
      (then
        (drop
          (local.get $i1)
        )
      )
    )
    (local.set $i4
      (local.get $i1)
    )
    (if
      (i32.eq
        (i32.and
          (local.get $i1)
          (i32.const 3)
        )
        (i32.and
          (local.get $i2)
          (i32.const 3)
        )
      )
      (then
        (block $block2
          (block $while-out$0
            (loop $while-in$1
              (if
                (i32.eqz
                  (i32.and
                    (local.get $i1)
                    (i32.const 3)
                  )
                )
                (then
                  (br $while-out$0)
                )
              )
              (block $block4
                (if
                  (i32.eqz
                    (local.get $i3)
                  )
                  (then
                    (return
                      (local.get $i4)
                    )
                  )
                )
                (i32.store8
                  (local.get $i1)
                  (i32.load8_s
                    (local.get $i2)
                  )
                )
                (local.set $i1
                  (i32.add
                    (local.get $i1)
                    (i32.const 1)
                  )
                )
                (local.set $i2
                  (i32.add
                    (local.get $i2)
                    (i32.const 1)
                  )
                )
                (local.set $i3
                  (i32.sub
                    (local.get $i3)
                    (i32.const 1)
                  )
                )
              )
              (br $while-in$1)
            )
          )
          (block $while-out$2
            (loop $while-in$3
              (if
                (i32.eqz
                  (i32.ge_s
                    (local.get $i3)
                    (i32.const 4)
                  )
                )
                (then
                  (br $while-out$2)
                )
              )
              (block $block7
                (i32.store
                  (local.get $i1)
                  (i32.load
                    (local.get $i2)
                  )
                )
                (local.set $i1
                  (i32.add
                    (local.get $i1)
                    (i32.const 4)
                  )
                )
                (local.set $i2
                  (i32.add
                    (local.get $i2)
                    (i32.const 4)
                  )
                )
                (local.set $i3
                  (i32.sub
                    (local.get $i3)
                    (i32.const 4)
                  )
                )
              )
              (br $while-in$3)
            )
          )
        )
      )
    )
    (block $while-out$4
      (loop $while-in$5
        (if
          (i32.eqz
            (i32.gt_s
              (local.get $i3)
              (i32.const 0)
            )
          )
          (then
            (br $while-out$4)
          )
        )
        (block $block9
          (i32.store8
            (local.get $i1)
            (i32.load8_s
              (local.get $i2)
            )
          )
          (local.set $i1
            (i32.add
              (local.get $i1)
              (i32.const 1)
            )
          )
          (local.set $i2
            (i32.add
              (local.get $i2)
              (i32.const 1)
            )
          )
          (local.set $i3
            (i32.sub
              (local.get $i3)
              (i32.const 1)
            )
          )
        )
        (br $while-in$5)
      )
    )
    (return
      (local.get $i4)
    )
  )
  ;; CHECK:      (func $this-is-effective-i-tell-you (param $0 i32)
  ;; CHECK-NEXT:  (if
  ;; CHECK-NEXT:   (i32.const -1)
  ;; CHECK-NEXT:   (then
  ;; CHECK-NEXT:    (block $block1
  ;; CHECK-NEXT:     (if
  ;; CHECK-NEXT:      (i32.const 0)
  ;; CHECK-NEXT:      (then
  ;; CHECK-NEXT:       (nop)
  ;; CHECK-NEXT:      )
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (local.set $0
  ;; CHECK-NEXT:      (i32.const 1)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (else
  ;; CHECK-NEXT:    (nop)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $this-is-effective-i-tell-you (type $4) (param $x i32)
    (if
      (i32.const -1)
      (then
        (block $block1
          (if
            (i32.const 0)
            (then
              (nop)
            )
          )
          (local.set $x
            (i32.const 1)
          )
        )
      )
      (else
        (nop)
      )
    )
    (drop
      (local.get $x)
    )
  )
  ;; CHECK:      (func $prefer-remove-copies1
  ;; CHECK-NEXT:  (local $0 i32)
  ;; CHECK-NEXT:  (local $1 i32)
  ;; CHECK-NEXT:  (local.set $0
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (nop)
  ;; CHECK-NEXT:  (local.set $1
  ;; CHECK-NEXT:   (i32.const 1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $prefer-remove-copies1 (type $2)
    (local $y i32)
    (local $z i32)
    (local $x i32)
    (local.set $x
      (i32.const 0)
    )
    (local.set $y
      (local.get $x)
    )
    (local.set $z
      (i32.const 1)
    )
    (drop
      (local.get $y)
    )
    (drop
      (local.get $z)
    )
  )
  ;; CHECK:      (func $prefer-remove-copies2
  ;; CHECK-NEXT:  (local $0 i32)
  ;; CHECK-NEXT:  (local $1 i32)
  ;; CHECK-NEXT:  (local.set $0
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (nop)
  ;; CHECK-NEXT:  (local.set $1
  ;; CHECK-NEXT:   (i32.const 1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $prefer-remove-copies2 (type $2)
    (local $y i32)
    (local $z i32)
    (local $x i32)
    (local.set $x
      (i32.const 0)
    )
    (local.set $z
      (local.get $x)
    )
    (local.set $y
      (i32.const 1)
    )
    (drop
      (local.get $y)
    )
    (drop
      (local.get $z)
    )
  )
  ;; CHECK:      (func $in-unreachable
  ;; CHECK-NEXT:  (local $0 i32)
  ;; CHECK-NEXT:  (block $x
  ;; CHECK-NEXT:   (return)
  ;; CHECK-NEXT:   (drop
  ;; CHECK-NEXT:    (i32.const 1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (drop
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (drop
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (block $y
  ;; CHECK-NEXT:   (unreachable)
  ;; CHECK-NEXT:   (drop
  ;; CHECK-NEXT:    (i32.const 1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (drop
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (drop
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (block $z
  ;; CHECK-NEXT:   (br $z)
  ;; CHECK-NEXT:   (drop
  ;; CHECK-NEXT:    (i32.const 1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (drop
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (drop
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (block $z0
  ;; CHECK-NEXT:   (br_table $z0 $z0
  ;; CHECK-NEXT:    (i32.const 100)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (drop
  ;; CHECK-NEXT:    (i32.const 1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (drop
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (drop
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $in-unreachable
    (local $a i32)
    (block $x
      (return)
      (local.set $a (i32.const 1))
      (drop (local.get $a))
      (local.set $a (local.get $a))
    )
    (block $y
      (unreachable)
      (local.set $a (i32.const 1))
      (drop (local.get $a))
      (local.set $a (local.get $a))
    )
    (block $z
      (br $z)
      (local.set $a (i32.const 1))
      (drop (local.get $a))
      (local.set $a (local.get $a))
    )
    (block $z
      (br_table $z $z
        (i32.const 100)
      )
      (local.set $a (i32.const 1))
      (drop (local.get $a))
      (local.set $a (local.get $a))
    )
  )
  ;; CHECK:      (func $nop-in-unreachable
  ;; CHECK-NEXT:  (local $0 i32)
  ;; CHECK-NEXT:  (unreachable)
  ;; CHECK-NEXT:  (i32.store
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $nop-in-unreachable
    (local $x i32)
    (block
      (unreachable)
      (i32.store
        (local.get $x)
        (local.tee $x (i32.const 0))
      )
    )
  )
  ;; CHECK:      (func $loop-backedge
  ;; CHECK-NEXT:  (local $0 i32)
  ;; CHECK-NEXT:  (local $1 i32)
  ;; CHECK-NEXT:  (local.set $0
  ;; CHECK-NEXT:   (i32.const 2)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (block $out
  ;; CHECK-NEXT:   (loop $while-in7
  ;; CHECK-NEXT:    (local.set $1
  ;; CHECK-NEXT:     (i32.const 0)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (call $set
  ;; CHECK-NEXT:     (local.get $1)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (local.set $0
  ;; CHECK-NEXT:     (i32.add
  ;; CHECK-NEXT:      (local.get $0)
  ;; CHECK-NEXT:      (i32.const 1)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (if
  ;; CHECK-NEXT:     (call $get)
  ;; CHECK-NEXT:     (then
  ;; CHECK-NEXT:      (local.set $1
  ;; CHECK-NEXT:       (local.get $0)
  ;; CHECK-NEXT:      )
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (br_if $out
  ;; CHECK-NEXT:     (local.get $1)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (local.set $0
  ;; CHECK-NEXT:     (i32.const 100)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (nop)
  ;; CHECK-NEXT:    (br $while-in7)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $loop-backedge
    (local $0 i32) ;; loop phi
    (local $1 i32) ;; value for next loop iteration
    (local $2 i32) ;; a local that might be merged with with $1, perhaps making us prefer it to removing a backedge copy
    (local.set $0
      (i32.const 2)
    )
    (block $out
      (loop $while-in7
        (local.set $2 (i32.const 0)) ;; 2 interferes with 0
        (call $set (local.get $2))
        (local.set $1
          (i32.add
            (local.get $0)
            (i32.const 1)
          )
        )
        (if (call $get)
          (then
            (local.set $2 (local.get $1)) ;; copy for 1/2
          )
        )
        (br_if $out (local.get $2))
        (local.set $1 (i32.const 100))
        (local.set $0 (local.get $1)) ;; copy for 1/0, with extra weight should win the tie
        (br $while-in7)
      )
    )
  )
  ;; CHECK:      (func $if-copy1
  ;; CHECK-NEXT:  (local $0 i32)
  ;; CHECK-NEXT:  (local $1 i32)
  ;; CHECK-NEXT:  (loop $top
  ;; CHECK-NEXT:   (local.set $0
  ;; CHECK-NEXT:    (if (result i32)
  ;; CHECK-NEXT:     (i32.const 1)
  ;; CHECK-NEXT:     (then
  ;; CHECK-NEXT:      (local.get $0)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (else
  ;; CHECK-NEXT:      (local.get $1)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (drop
  ;; CHECK-NEXT:    (local.get $0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (drop
  ;; CHECK-NEXT:    (local.get $1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (br $top)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $if-copy1
    (local $x i32)
    (local $y i32)
    (loop $top
      (local.set $x
        (if (result i32)
          (i32.const 1)
          (then
            (local.get $x)
          )
          (else
            (local.get $y)
          )
        )
      )
      (drop (local.get $x))
      (drop (local.get $y))
      (br $top)
    )
  )
  ;; CHECK:      (func $if-copy2
  ;; CHECK-NEXT:  (local $0 i32)
  ;; CHECK-NEXT:  (local $1 i32)
  ;; CHECK-NEXT:  (loop $top
  ;; CHECK-NEXT:   (local.set $1
  ;; CHECK-NEXT:    (if (result i32)
  ;; CHECK-NEXT:     (i32.const 1)
  ;; CHECK-NEXT:     (then
  ;; CHECK-NEXT:      (local.get $0)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (else
  ;; CHECK-NEXT:      (local.get $1)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (drop
  ;; CHECK-NEXT:    (local.get $1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (drop
  ;; CHECK-NEXT:    (local.get $0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (br $top)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $if-copy2
    (local $x i32)
    (local $y i32)
    (loop $top
      (local.set $x
        (if (result i32)
          (i32.const 1)
          (then
            (local.get $y)
          )
          (else
            (local.get $x)
          )
        )
      )
      (drop (local.get $x))
      (drop (local.get $y))
      (br $top)
    )
  )
  ;; CHECK:      (func $if-copy3
  ;; CHECK-NEXT:  (local $0 i32)
  ;; CHECK-NEXT:  (local $1 i32)
  ;; CHECK-NEXT:  (loop $top
  ;; CHECK-NEXT:   (local.set $0
  ;; CHECK-NEXT:    (if (result i32)
  ;; CHECK-NEXT:     (i32.const 1)
  ;; CHECK-NEXT:     (then
  ;; CHECK-NEXT:      (unreachable)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (else
  ;; CHECK-NEXT:      (local.get $0)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (drop
  ;; CHECK-NEXT:    (local.get $0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (drop
  ;; CHECK-NEXT:    (local.get $1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (br $top)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $if-copy3
    (local $x i32)
    (local $y i32)
    (loop $top
      (local.set $x
        (if (result i32)
          (i32.const 1)
          (then
            (unreachable)
          )
          (else
            (local.get $x)
          )
        )
      )
      (drop (local.get $x))
      (drop (local.get $y))
      (br $top)
    )
  )
  ;; CHECK:      (func $if-copy4
  ;; CHECK-NEXT:  (local $0 i32)
  ;; CHECK-NEXT:  (local $1 i32)
  ;; CHECK-NEXT:  (loop $top
  ;; CHECK-NEXT:   (local.set $1
  ;; CHECK-NEXT:    (if (result i32)
  ;; CHECK-NEXT:     (i32.const 1)
  ;; CHECK-NEXT:     (then
  ;; CHECK-NEXT:      (unreachable)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (else
  ;; CHECK-NEXT:      (local.get $0)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (drop
  ;; CHECK-NEXT:    (local.get $1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (drop
  ;; CHECK-NEXT:    (local.get $0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (br $top)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $if-copy4
    (local $x i32)
    (local $y i32)
    (loop $top
      (local.set $x
        (if (result i32)
          (i32.const 1)
          (then
            (unreachable)
          )
          (else
            (local.get $y)
          )
        )
      )
      (drop (local.get $x))
      (drop (local.get $y))
      (br $top)
    )
  )
  ;; CHECK:      (func $if-copy-tee
  ;; CHECK-NEXT:  (local $0 i32)
  ;; CHECK-NEXT:  (local $1 i32)
  ;; CHECK-NEXT:  (loop $top
  ;; CHECK-NEXT:   (drop
  ;; CHECK-NEXT:    (local.tee $0
  ;; CHECK-NEXT:     (if (result i32)
  ;; CHECK-NEXT:      (i32.const 1)
  ;; CHECK-NEXT:      (then
  ;; CHECK-NEXT:       (local.get $0)
  ;; CHECK-NEXT:      )
  ;; CHECK-NEXT:      (else
  ;; CHECK-NEXT:       (i32.const 2)
  ;; CHECK-NEXT:      )
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (drop
  ;; CHECK-NEXT:    (local.get $0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (drop
  ;; CHECK-NEXT:    (local.get $1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (br $top)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $if-copy-tee
    (local $x i32)
    (local $y i32)
    (loop $top
      (drop
        (local.tee $x
          (if (result i32)
            (i32.const 1)
            (then
              (local.get $x)
            )
            (else
              (i32.const 2)
            )
          )
        )
      )
      (drop (local.get $x))
      (drop (local.get $y))
      (br $top)
    )
  )
  ;; CHECK:      (func $tee_br (param $0 i32) (result i32)
  ;; CHECK-NEXT:  (block $b
  ;; CHECK-NEXT:   (return
  ;; CHECK-NEXT:    (br $b)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (i32.const 1)
  ;; CHECK-NEXT: )
  (func $tee_br (param $x i32) (result i32)
    (block $b
      (return
        (local.tee $x
          (br $b)
        )
      )
    )
    (i32.const 1)
  )
  ;; CHECK:      (func $unused-tee-with-child-if-no-else (param $0 i32)
  ;; CHECK-NEXT:  (loop $label$0
  ;; CHECK-NEXT:   (drop
  ;; CHECK-NEXT:    (if
  ;; CHECK-NEXT:     (br $label$0)
  ;; CHECK-NEXT:     (then
  ;; CHECK-NEXT:      (nop)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $unused-tee-with-child-if-no-else (param $0 i32)
   (loop $label$0
    (drop
     (local.tee $0
      (if
       (br $label$0)
       (then
        (nop)
       )
      )
     )
    )
   )
  )
  ;; CHECK:      (func $tee_if_with_unreachable_else (param $0 f64) (param $1 i32) (result i64)
  ;; CHECK-NEXT:  (call $tee_if_with_unreachable_else
  ;; CHECK-NEXT:   (local.tee $0
  ;; CHECK-NEXT:    (if (result f64)
  ;; CHECK-NEXT:     (local.get $1)
  ;; CHECK-NEXT:     (then
  ;; CHECK-NEXT:      (local.get $0)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (else
  ;; CHECK-NEXT:      (unreachable)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (f64.lt
  ;; CHECK-NEXT:    (f64.const -128)
  ;; CHECK-NEXT:    (local.get $0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $tee_if_with_unreachable_else (param $0 f64) (param $1 i32) (result i64)
    (call $tee_if_with_unreachable_else
     (local.tee $0
      (if (result f64)
       (local.get $1)
       (then
        (local.get $0)
       )
       (else
        (unreachable)
       )
      )
     )
     (f64.lt
      (f64.const -128)
      (local.get $0)
     )
    )
  )
  ;; CHECK:      (func $tee_if_with_unreachable_true (param $0 f64) (param $1 i32) (result i64)
  ;; CHECK-NEXT:  (call $tee_if_with_unreachable_else
  ;; CHECK-NEXT:   (local.tee $0
  ;; CHECK-NEXT:    (if (result f64)
  ;; CHECK-NEXT:     (local.get $1)
  ;; CHECK-NEXT:     (then
  ;; CHECK-NEXT:      (unreachable)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (else
  ;; CHECK-NEXT:      (local.get $0)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (f64.lt
  ;; CHECK-NEXT:    (f64.const -128)
  ;; CHECK-NEXT:    (local.get $0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $tee_if_with_unreachable_true (param $0 f64) (param $1 i32) (result i64)
    (call $tee_if_with_unreachable_else
     (local.tee $0
      (if (result f64)
       (local.get $1)
       (then
        (unreachable)
       )
       (else
        (local.get $0)
       )
      )
     )
     (f64.lt
      (f64.const -128)
      (local.get $0)
     )
    )
  )
  ;; CHECK:      (func $pick
  ;; CHECK-NEXT:  (local $0 i32)
  ;; CHECK-NEXT:  (nop)
  ;; CHECK-NEXT:  (if
  ;; CHECK-NEXT:   (i32.const 1)
  ;; CHECK-NEXT:   (then
  ;; CHECK-NEXT:    (drop
  ;; CHECK-NEXT:     (i32.const 1)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (nop)
  ;; CHECK-NEXT:  (nop)
  ;; CHECK-NEXT: )
  (func $pick
   (local $x i32)
   (local $y i32)
   (local.set $x (local.get $y))
   (if (i32.const 1)
    (then
     (local.set $x (i32.const 1))
    )
   )
   (local.set $x (local.get $y))
   (local.set $x (local.get $y))
  )
  ;; CHECK:      (func $pick-2
  ;; CHECK-NEXT:  (local $0 i32)
  ;; CHECK-NEXT:  (nop)
  ;; CHECK-NEXT:  (if
  ;; CHECK-NEXT:   (i32.const 1)
  ;; CHECK-NEXT:   (then
  ;; CHECK-NEXT:    (drop
  ;; CHECK-NEXT:     (i32.const 1)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (nop)
  ;; CHECK-NEXT:  (nop)
  ;; CHECK-NEXT: )
  (func $pick-2
   (local $x i32)
   (local $y i32)
   (local.set $y (local.get $x))
   (if (i32.const 1)
    (then
     (local.set $y (i32.const 1))
    )
   )
   (local.set $y (local.get $x))
   (local.set $y (local.get $x))
  )
  ;; CHECK:      (func $many
  ;; CHECK-NEXT:  (local $0 i32)
  ;; CHECK-NEXT:  (nop)
  ;; CHECK-NEXT:  (nop)
  ;; CHECK-NEXT:  (nop)
  ;; CHECK-NEXT:  (nop)
  ;; CHECK-NEXT:  (if
  ;; CHECK-NEXT:   (i32.const 1)
  ;; CHECK-NEXT:   (then
  ;; CHECK-NEXT:    (drop
  ;; CHECK-NEXT:     (i32.const 1)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (nop)
  ;; CHECK-NEXT:  (if
  ;; CHECK-NEXT:   (i32.const 1)
  ;; CHECK-NEXT:   (then
  ;; CHECK-NEXT:    (drop
  ;; CHECK-NEXT:     (i32.const 1)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (nop)
  ;; CHECK-NEXT:  (nop)
  ;; CHECK-NEXT:  (nop)
  ;; CHECK-NEXT:  (local.set $0
  ;; CHECK-NEXT:   (i32.const 2)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (nop)
  ;; CHECK-NEXT:  (if
  ;; CHECK-NEXT:   (i32.const 1)
  ;; CHECK-NEXT:   (then
  ;; CHECK-NEXT:    (drop
  ;; CHECK-NEXT:     (i32.const 1)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (nop)
  ;; CHECK-NEXT:  (nop)
  ;; CHECK-NEXT:  (nop)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (i32.const 2)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (nop)
  ;; CHECK-NEXT: )
  (func $many
   (local $x i32)
   (local $y i32)
   (local $z i32)
   (local $w i32)
   (local.set $y (local.get $x))
   (local.set $z (local.get $y))
   (local.set $w (local.get $z))
   (local.set $x (local.get $z))
   (if (i32.const 1)
    (then
     (local.set $y (i32.const 1))
    )
   )
   (local.set $x (local.get $z))
   (if (i32.const 1)
    (then
     (local.set $y (i32.const 1))
    )
   )
   (local.set $y (local.get $x))
   (local.set $z (local.get $y))
   (local.set $w (local.get $z))
   (local.set $z (i32.const 2))
   (local.set $x (local.get $z))
   (if (i32.const 1)
    (then
     (local.set $y (i32.const 1))
    )
   )
   (local.set $y (local.get $x))
   (local.set $z (local.get $y))
   (local.set $w (local.get $z))
   (local.set $z (i32.const 2))
   (local.set $x (local.get $w))
  )
  ;; CHECK:      (func $loop-copies (param $0 i32) (param $1 i32)
  ;; CHECK-NEXT:  (loop $loop
  ;; CHECK-NEXT:   (local.set $0
  ;; CHECK-NEXT:    (local.get $1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (local.set $1
  ;; CHECK-NEXT:    (local.get $0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (br_if $loop
  ;; CHECK-NEXT:    (local.get $0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $loop-copies (param $x i32) (param $y i32)
   (loop $loop
    (local.set $x (local.get $y))
    (local.set $y (local.get $x))
    (br_if $loop (local.get $x))
   )
  )
  ;; CHECK:      (func $proper-type (result f64)
  ;; CHECK-NEXT:  (local $0 f64)
  ;; CHECK-NEXT:  (local $1 i32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (select
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:    (i32.const 1)
  ;; CHECK-NEXT:    (local.get $1)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (local.get $0)
  ;; CHECK-NEXT: )
  (func $proper-type (result f64)
   (local $var$0 i32)
   (local $var$2 f64)
   (local.set $var$0
    (select
     (i32.const 0)
     (i32.const 1)
     (local.get $var$0)
    )
   )
   (local.tee $var$2 ;; the locals will be reordered, this should be the f64
    (local.get $var$2)
   )
  )
  ;; CHECK:      (func $reuse-param (param $0 i32) (param $1 i32) (result i32)
  ;; CHECK-NEXT:  (i32.add
  ;; CHECK-NEXT:   (local.tee $0
  ;; CHECK-NEXT:    (i32.xor
  ;; CHECK-NEXT:     (i32.shr_s
  ;; CHECK-NEXT:      (i32.shl
  ;; CHECK-NEXT:       (local.get $0)
  ;; CHECK-NEXT:       (i32.const 16)
  ;; CHECK-NEXT:      )
  ;; CHECK-NEXT:      (i32.const 16)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:     (i32.shr_s
  ;; CHECK-NEXT:      (i32.shl
  ;; CHECK-NEXT:       (local.get $1)
  ;; CHECK-NEXT:       (i32.const 16)
  ;; CHECK-NEXT:      )
  ;; CHECK-NEXT:      (i32.const 16)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $reuse-param (param $x i32) (param $y i32) (result i32)
   (local $temp i32)
   (i32.add
    (local.tee $temp
     (i32.xor
      (i32.shr_s
       (i32.shl
        (local.get $x) ;; $x and $temp do not interfere
        (i32.const 16)
       )
      (i32.const 16)
     )
     (i32.shr_s
      (i32.shl
        (local.get $y)
        (i32.const 16)
       )
       (i32.const 16)
      )
     )
    )
    (local.get $temp)
   )
  )

  ;; CHECK:      (func $copies-do-not-interfere (result i32)
  ;; CHECK-NEXT:  (local $0 i32)
  ;; CHECK-NEXT:  (local.set $0
  ;; CHECK-NEXT:   (i32.const 100)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (nop)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (local.get $0)
  ;; CHECK-NEXT: )
  (func $copies-do-not-interfere (result i32)
   (local $0 i32)
   (local $1 i32)
   (local.set $0
    (i32.const 100)
   )
   ;; The two locals are copies, and so they do not interfere, even though
   ;; their live ranges overlap and there is a set of one of them in that
   ;; overlap. We can coalesce them together to a single local.
   (local.set $1
    (local.get $0)
   )
   (drop
    (local.get $0)
   )
   (local.get $1)
  )

  ;; CHECK:      (func $tee-copies-do-not-interfere (result i32)
  ;; CHECK-NEXT:  (local $0 i32)
  ;; CHECK-NEXT:  (local.set $0
  ;; CHECK-NEXT:   (i32.const 100)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (local.get $0)
  ;; CHECK-NEXT: )
  (func $tee-copies-do-not-interfere (result i32)
   (local $0 i32)
   (local $1 i32)
   ;; Similar to the above, but now the copying is done using a tee.
   (local.set $1
    (local.tee $0
     (i32.const 100)
    )
   )
   (drop
    (local.get $0)
   )
   (local.get $1)
  )

  ;; CHECK:      (func $multiple-tee-copies-do-not-interfere (result i32)
  ;; CHECK-NEXT:  (local $0 i32)
  ;; CHECK-NEXT:  (local.set $0
  ;; CHECK-NEXT:   (i32.const 100)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (local.get $0)
  ;; CHECK-NEXT: )
  (func $multiple-tee-copies-do-not-interfere (result i32)
   (local $0 i32)
   (local $1 i32)
   (local $2 i32)
   ;; Similar to the above, but a chain of 3 items.
   (local.set $2
    (local.tee $1
     (local.tee $0
      (i32.const 100)
     )
    )
   )
   (drop
    (local.get $0)
   )
   (drop
    (local.get $1)
   )
   (local.get $2)
  )

  ;; CHECK:      (func $copies-and-then-interfere (result i32)
  ;; CHECK-NEXT:  (local $0 i32)
  ;; CHECK-NEXT:  (local $1 i32)
  ;; CHECK-NEXT:  (local.set $1
  ;; CHECK-NEXT:   (i32.const 100)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (local.set $0
  ;; CHECK-NEXT:   (local.get $1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (local.set $0
  ;; CHECK-NEXT:   (i32.const 123)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (local.get $0)
  ;; CHECK-NEXT: )
  (func $copies-and-then-interfere (result i32)
   (local $0 i32)
   (local $1 i32)
   (local.set $0
    (i32.const 100)
   )
   (local.set $1
    (local.get $0)
   )
   (drop
    (local.get $0)
   )
   (drop
    (local.get $1)
   )
   ;; The copy before this set should not confuse us - this set causes a
   ;; divergence on the overlapping live ranges, and we cannot coalesce these
   ;; two locals.
   (local.set $1
    (i32.const 123)
   )
   (drop
    (local.get $0)
   )
   (local.get $1)
  )

  ;; CHECK:      (func $copies-and-then-set-without-interfering (result i32)
  ;; CHECK-NEXT:  (local $0 i32)
  ;; CHECK-NEXT:  (local.set $0
  ;; CHECK-NEXT:   (i32.const 100)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (nop)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (local.set $0
  ;; CHECK-NEXT:   (i32.const 123)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (local.get $0)
  ;; CHECK-NEXT: )
  (func $copies-and-then-set-without-interfering (result i32)
   (local $0 i32)
   (local $1 i32)
   (local.set $0
    (i32.const 100)
   )
   (local.set $1
    (local.get $0)
   )
   (drop
    (local.get $0)
   )
   (drop
    (local.get $1)
   )
   ;; Similar to the above, but now $0's live range has ended (there is no get
   ;; of it at the point of this set), and so there is no interference, and
   ;; these locals can be coalesced.
   (local.set $1
    (i32.const 123)
   )
   (local.get $1)
  )

  ;; CHECK:      (func $copy-third-party (result i32)
  ;; CHECK-NEXT:  (local $0 i32)
  ;; CHECK-NEXT:  (local.set $0
  ;; CHECK-NEXT:   (i32.const 100)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (nop)
  ;; CHECK-NEXT:  (nop)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (local.get $0)
  ;; CHECK-NEXT: )
  (func $copy-third-party (result i32)
   (local $0 i32)
   (local $1 i32)
   (local $2 i32)
   ;; $2 begins with a value, which is copied to $0 and $1. None of these
   ;; interfere and they can all be coalesced.
   (local.set $2
    (i32.const 100)
   )
   (local.set $1
    (local.get $2)
   )
   (local.set $0
    (local.get $2)
   )
   (drop
    (local.get $0)
   )
   (drop
    (local.get $1)
   )
   (local.get $2)
  )

  ;; CHECK:      (func $ineffective-set (result i32)
  ;; CHECK-NEXT:  (local $0 i32)
  ;; CHECK-NEXT:  (local $1 i32)
  ;; CHECK-NEXT:  (local.set $0
  ;; CHECK-NEXT:   (i32.const 100)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (local.get $1)
  ;; CHECK-NEXT: )
  (func $ineffective-set (result i32)
   (local $0 i32)
   (local $1 i32)
   (local $2 i32)
   (local.set $0
    ;; This set of $2 is ineffective in that there are no gets of $2, but the
    ;; value does flow through to the outer set, and we must notice that. In
    ;; particular, we must see that $0 and $1 conflict, and cannot be coalesced
    ;; together ($1 is alive from the zero init to the very end, and so $0's
    ;; set means it diverges).
    (local.tee $2
     (i32.const 100)
    )
   )
   (drop
    (local.get $0)
   )
   (local.get $1)
  )

  ;; CHECK:      (func $inter-block-copy (result i32)
  ;; CHECK-NEXT:  (local $0 i32)
  ;; CHECK-NEXT:  (local $1 i32)
  ;; CHECK-NEXT:  (local.set $0
  ;; CHECK-NEXT:   (i32.const 100)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (nop)
  ;; CHECK-NEXT:  (nop)
  ;; CHECK-NEXT:  (if
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:   (then
  ;; CHECK-NEXT:    (local.set $1
  ;; CHECK-NEXT:     (local.get $0)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (else
  ;; CHECK-NEXT:    (local.set $1
  ;; CHECK-NEXT:     (local.get $0)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (local.get $1)
  ;; CHECK-NEXT: )
  (func $inter-block-copy (result i32)
   (local $0 i32)
   (local $1 i32)
   (local $2 i32)
   (local $3 i32)
   (local.set $0
    (i32.const 100)
   )
   (local.set $1
    (local.get $0)
   )
   (local.set $2
    (local.get $0)
   )
   ;; At this point $1 is equal to $2, as they are both copies of $0. Then the
   ;; if assigns one of them to $3, which means that $3 is also equal to them
   ;; all. However, we only analyze copied values *inside* blocks, which means
   ;; that in each of the if arms we see that $3 is assigned either the value
   ;; of $1 or $2, but we don't know that those values are both equal to $0. As
   ;; a result, we will infer that $3 interfers with $0, as their live ranges
   ;; overlap and $3 is assigned a value that looks different than $0. This
   ;; will prevent $3 being coalesced with all the others. (However, see the
   ;; next testcase for more on this.)
   (if
    (local.get $0)
    (then
     (local.set $3
      (local.get $1)
     )
    )
    (else
     (local.set $3
      (local.get $2)
     )
    )
   )
   (drop
    (local.get $0)
   )
   (drop
    (local.get $1)
   )
   (drop
    (local.get $2)
   )
   (local.get $3)
  )

  ;; CHECK:      (func $inter-block-copy-second-pass (result i32)
  ;; CHECK-NEXT:  (local $0 i32)
  ;; CHECK-NEXT:  (local.set $0
  ;; CHECK-NEXT:   (i32.const 100)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (nop)
  ;; CHECK-NEXT:  (nop)
  ;; CHECK-NEXT:  (if
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:   (then
  ;; CHECK-NEXT:    (nop)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (else
  ;; CHECK-NEXT:    (nop)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (local.get $0)
  ;; CHECK-NEXT: )
  (func $inter-block-copy-second-pass (result i32)
   (local $0 i32)
   (local $1 i32)
   ;; This function contains the output of the previous testcase
   ;; $inter-block-copy, and shows what running a second pass results in. After
   ;; the first pass we have coalesced the original $0, $1, and $2 into a single
   ;; local ($0), and renamed the original $3 into $1. At this point the
   ;; algorithm can see that $0 and $1 do not interfere: there are no copies in
   ;; the middle, and in both if arms when we assign a value to $1 it is the
   ;; value already in $0, and there is no other assignment of either one that
   ;; appears in their overlapping live ranges, so they will be coalesced into
   ;; a single local.
   (local.set $0
    (i32.const 100)
   )
   (nop)
   (nop)
   (if
    (local.get $0)
    (then
     (local.set $1
      (local.get $0)
     )
    )
    (else
     (local.set $1
      (local.get $0)
     )
    )
   )
   (drop
    (local.get $0)
   )
   (drop
    (local.get $0)
   )
   (drop
    (local.get $0)
   )
   (local.get $1)
  )

  ;; CHECK:      (func $equal-constants-zeroinit
  ;; CHECK-NEXT:  (local $0 i32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $equal-constants-zeroinit
    (local $x i32)
    (local $y i32)
    ;; $x and $y both have the zero init value, which is identical, and they do
    ;; not interfere.
    (drop
      (local.get $x)
    )
    (drop
      (local.get $y)
    )
  )

  ;; CHECK:      (func $equal-constants
  ;; CHECK-NEXT:  (local $0 i32)
  ;; CHECK-NEXT:  (local.set $0
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $equal-constants
    (local $x i32)
    (local $y i32)
    ;; $x is written the same value as $y, so they do not interfere.
    (local.set $x
      (i32.const 0)
    )
    (drop
      (local.get $x)
    )
    (drop
      (local.get $y)
    )
  )

  ;; CHECK:      (func $different-constants
  ;; CHECK-NEXT:  (local $0 i32)
  ;; CHECK-NEXT:  (local $1 i32)
  ;; CHECK-NEXT:  (local.set $0
  ;; CHECK-NEXT:   (i32.const 1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $different-constants
    (local $x i32)
    (local $y i32)
    ;; $x is written a different value, so they do interfere.
    (local.set $x
      (i32.const 1)
    )
    (drop
      (local.get $x)
    )
    (drop
      (local.get $y)
    )
  )

  ;; CHECK:      (func $equal-constants-nonzero
  ;; CHECK-NEXT:  (local $0 i32)
  ;; CHECK-NEXT:  (local.set $0
  ;; CHECK-NEXT:   (i32.const 42)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (local.set $0
  ;; CHECK-NEXT:   (i32.const 42)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $equal-constants-nonzero
    (local $x i32)
    (local $y i32)
    (local.set $x
      (i32.const 42)
    )
    (local.set $y
      (i32.const 42)
    )
    (drop
      (local.get $x)
    )
    (drop
      (local.get $y)
    )
  )

  ;; CHECK:      (func $different-constants-nonzero
  ;; CHECK-NEXT:  (local $0 i32)
  ;; CHECK-NEXT:  (local $1 i32)
  ;; CHECK-NEXT:  (local.set $0
  ;; CHECK-NEXT:   (i32.const 42)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (local.set $1
  ;; CHECK-NEXT:   (i32.const 1337)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (local.get $1)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $different-constants-nonzero
    (local $x i32)
    (local $y i32)
    (local.set $x
      (i32.const 42)
    )
    (local.set $y
      (i32.const 1337)
    )
    (drop
      (local.get $x)
    )
    (drop
      (local.get $y)
    )
  )
)
