;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited.
;; RUN: wasm-opt -all --coalesce-locals %s -S -o - | filecheck %s

(module
 ;; CHECK:      (type $function (func))
 (type $function (func))
 ;; CHECK:      (type $cont (cont $function))
 (type $cont (cont $function))
 ;; CHECK:      (type $function_2 (func (param (ref $cont))))
 (type $function_2 (func (param (ref $cont))))
 ;; CHECK:      (type $cont_2 (cont $function_2))
 (type $cont_2 (cont $function_2))

 ;; CHECK:      (tag $tag (type $function))
 (tag $tag)
 ;; CHECK:      (tag $exn (type $5) (param i32))
 (tag $exn (param i32))

 ;; CHECK:      (func $resume (type $2) (param $0 (ref $cont)) (result i32)
 ;; CHECK-NEXT:  (local $1 i32)
 ;; CHECK-NEXT:  (local.set $1
 ;; CHECK-NEXT:   (block $handle_exn (result i32)
 ;; CHECK-NEXT:    (try_table (catch $exn $handle_exn)
 ;; CHECK-NEXT:     (local.set $0
 ;; CHECK-NEXT:      (block $handle_effect (result (ref $cont))
 ;; CHECK-NEXT:       (resume $cont (on $tag $handle_effect)
 ;; CHECK-NEXT:        (local.get $0)
 ;; CHECK-NEXT:       )
 ;; CHECK-NEXT:       (return
 ;; CHECK-NEXT:        (i32.const 0)
 ;; CHECK-NEXT:       )
 ;; CHECK-NEXT:      )
 ;; CHECK-NEXT:     )
 ;; CHECK-NEXT:     (return_call $resume
 ;; CHECK-NEXT:      (local.get $0)
 ;; CHECK-NEXT:     )
 ;; CHECK-NEXT:    )
 ;; CHECK-NEXT:    (return
 ;; CHECK-NEXT:     (i32.const 0)
 ;; CHECK-NEXT:    )
 ;; CHECK-NEXT:   )
 ;; CHECK-NEXT:  )
 ;; CHECK-NEXT:  (local.get $1)
 ;; CHECK-NEXT: )
 (func $resume (param $c (ref $cont)) (result i32)
  (local $x i32)
  (local $y (ref $cont))
  ;; resume can raise an exception, so this local.set should not be
  ;; optimized away
  (local.set $x
   (block $handle_exn (result i32)
    (try_table (catch $exn $handle_exn)
     ;; this local.set is reachable, so it should not be optimized away
     (local.set $y
      (block $handle_effect (result (ref $cont))
       (resume $cont (on $tag $handle_effect)
        (local.get $c)
       )
       (return
        (i32.const 0)
       )
      )
     )
     (return_call $resume
      (local.get $y)
     )
    )
    (return
     (i32.const 0)
    )
   )
  )
  (local.get $x)
 )

 ;; CHECK:      (func $resume_throw (type $2) (param $0 (ref $cont)) (result i32)
 ;; CHECK-NEXT:  (local $1 i32)
 ;; CHECK-NEXT:  (local.set $1
 ;; CHECK-NEXT:   (block $handle_exn (result i32)
 ;; CHECK-NEXT:    (try_table (catch $exn $handle_exn)
 ;; CHECK-NEXT:     (local.set $0
 ;; CHECK-NEXT:      (block $handle_effect (result (ref $cont))
 ;; CHECK-NEXT:       (resume_throw $cont $tag (on $tag $handle_effect)
 ;; CHECK-NEXT:        (local.get $0)
 ;; CHECK-NEXT:       )
 ;; CHECK-NEXT:       (return
 ;; CHECK-NEXT:        (i32.const 0)
 ;; CHECK-NEXT:       )
 ;; CHECK-NEXT:      )
 ;; CHECK-NEXT:     )
 ;; CHECK-NEXT:     (return_call $resume
 ;; CHECK-NEXT:      (local.get $0)
 ;; CHECK-NEXT:     )
 ;; CHECK-NEXT:    )
 ;; CHECK-NEXT:    (return
 ;; CHECK-NEXT:     (i32.const 0)
 ;; CHECK-NEXT:    )
 ;; CHECK-NEXT:   )
 ;; CHECK-NEXT:  )
 ;; CHECK-NEXT:  (local.get $1)
 ;; CHECK-NEXT: )
 (func $resume_throw (param $c (ref $cont)) (result i32)
  (local $x i32)
  (local $y (ref $cont))
  ;; resume can raise an exception, so this local.set should not be
  ;; optimized away
  (local.set $x
   (block $handle_exn (result i32)
    (try_table (catch $exn $handle_exn)
     ;; this local.set is reachable, so it should not be optimized away
     (local.set $y
      (block $handle_effect (result (ref $cont))
       (resume_throw $cont $tag (on $tag $handle_effect)
        (local.get $c)
       )
       (return
        (i32.const 0)
       )
      )
     )
     (return_call $resume
      (local.get $y)
     )
    )
    (return
     (i32.const 0)
    )
   )
  )
  (local.get $x)
 )

 ;; CHECK:      (func $suspend (type $6) (result i32)
 ;; CHECK-NEXT:  (local $0 i32)
 ;; CHECK-NEXT:  (local.set $0
 ;; CHECK-NEXT:   (block $handle_exn (result i32)
 ;; CHECK-NEXT:    (try_table (catch $exn $handle_exn)
 ;; CHECK-NEXT:     (suspend $tag)
 ;; CHECK-NEXT:    )
 ;; CHECK-NEXT:    (return
 ;; CHECK-NEXT:     (i32.const 0)
 ;; CHECK-NEXT:    )
 ;; CHECK-NEXT:   )
 ;; CHECK-NEXT:  )
 ;; CHECK-NEXT:  (local.get $0)
 ;; CHECK-NEXT: )
 (func $suspend (result i32)
  (local $x i32)
  ;; suspend can raise an exception, so this local.set should not be
  ;; optimized away
  (local.set $x
   (block $handle_exn (result i32)
    (try_table (catch $exn $handle_exn)
     (suspend $tag)
    )
    (return
     (i32.const 0)
    )
   )
  )
  (local.get $x)
 )

 ;; CHECK:      (func $switch (type $7) (param $0 (ref $cont_2)) (result i32)
 ;; CHECK-NEXT:  (local $1 i32)
 ;; CHECK-NEXT:  (local.set $1
 ;; CHECK-NEXT:   (block $handle_exn (result i32)
 ;; CHECK-NEXT:    (try_table (catch $exn $handle_exn)
 ;; CHECK-NEXT:     (switch $cont_2 $tag
 ;; CHECK-NEXT:      (local.get $0)
 ;; CHECK-NEXT:     )
 ;; CHECK-NEXT:    )
 ;; CHECK-NEXT:    (return
 ;; CHECK-NEXT:     (i32.const 0)
 ;; CHECK-NEXT:    )
 ;; CHECK-NEXT:   )
 ;; CHECK-NEXT:  )
 ;; CHECK-NEXT:  (local.get $1)
 ;; CHECK-NEXT: )
 (func $switch (param $c (ref $cont_2)) (result i32)
  (local $x i32)
  ;; switch can raise an exception, so this local.set should not be
  ;; optimized away
  (local.set $x
   (block $handle_exn (result i32)
    (try_table (catch $exn $handle_exn)
     (switch $cont_2 $tag
      (local.get $c)
     )
    )
    (return
     (i32.const 0)
    )
   )
  )
  (local.get $x)
 )
)
