;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited.
;; RUN: foreach %s %t wasm-opt -all --type-ssa --preserve-type-order -S -o - | filecheck %s

(module
  (rec
    ;; Casts
    ;; CHECK:      (rec
    ;; CHECK-NEXT:  (type $used-in-ref-test (sub (struct (field anyref))))
    (type $used-in-ref-test (sub (struct (field anyref))))
    ;; CHECK:       (type $used-in-ref-cast (sub (struct (field anyref))))
    (type $used-in-ref-cast (sub (struct (field anyref))))
    ;; CHECK:       (type $used-in-br-on-cast (sub (struct (field anyref))))
    (type $used-in-br-on-cast (sub (struct (field anyref))))
    ;; CHECK:       (type $used-in-br-on-cast-fail (sub (struct (field anyref))))
    (type $used-in-br-on-cast-fail (sub (struct (field anyref))))

    ;; Control flow structures
    ;; CHECK:       (type $used-in-block (sub (struct (field anyref))))
    (type $used-in-block (sub (struct (field anyref))))
    ;; CHECK:       (type $used-in-loop (sub (struct (field anyref))))
    (type $used-in-loop (sub (struct (field anyref))))
    ;; CHECK:       (type $used-in-if (sub (struct (field anyref))))
    (type $used-in-if (sub (struct (field anyref))))
    ;; CHECK:       (type $used-in-try (sub (struct (field anyref))))
    (type $used-in-try (sub (struct (field anyref))))
    ;; CHECK:       (type $used-in-try-table (sub (struct (field anyref))))
    (type $used-in-try-table (sub (struct (field anyref))))

    ;; Other expressions
    ;; CHECK:       (type $used-in-branch (sub (struct (field anyref))))
    (type $used-in-branch (sub (struct (field anyref))))
    ;; CHECK:       (type $used-in-br-table (sub (struct (field anyref))))
    (type $used-in-br-table (sub (struct (field anyref))))
    ;; CHECK:       (type $used-in-return (sub (struct (field anyref))))
    (type $used-in-return (sub (struct (field anyref))))
    ;; CHECK:       (type $used-in-return-ok (sub (struct (field anyref))))
    (type $used-in-return-ok (sub (struct (field anyref))))
    ;; CHECK:       (type $used-in-call (sub (struct (field anyref))))
    (type $used-in-call (sub (struct (field anyref))))
    ;; CHECK:       (type $used-in-call-ok (sub (struct (field anyref))))
    (type $used-in-call-ok (sub (struct (field anyref))))
    ;; CHECK:       (type $used-in-call-indirect (sub (struct (field anyref))))
    (type $used-in-call-indirect (sub (struct (field anyref))))
    ;; CHECK:       (type $used-in-call-indirect-ok (sub (struct (field anyref))))
    (type $used-in-call-indirect-ok (sub (struct (field anyref))))
    ;; CHECK:       (type $used-in-call-ref (sub (struct (field anyref))))
    (type $used-in-call-ref (sub (struct (field anyref))))
    ;; CHECK:       (type $used-in-call-ref-ok (sub (struct (field anyref))))
    (type $used-in-call-ref-ok (sub (struct (field anyref))))
    ;; CHECK:       (type $used-in-call-ref-unreachable (sub (struct (field anyref))))
    (type $used-in-call-ref-unreachable (sub (struct (field anyref))))
    ;; CHECK:       (type $used-in-call-ref-bot (sub (struct (field anyref))))
    (type $used-in-call-ref-bot (sub (struct (field anyref))))
    ;; CHECK:       (type $used-in-ret-call (sub (struct (field anyref))))
    (type $used-in-ret-call (sub (struct (field anyref))))
    ;; CHECK:       (type $used-in-ret-call-ok (sub (struct (field anyref))))
    (type $used-in-ret-call-ok (sub (struct (field anyref))))
    ;; CHECK:       (type $used-in-ret-call-unreachable (sub (struct (field anyref))))
    (type $used-in-ret-call-unreachable (sub (struct (field anyref))))
    ;; CHECK:       (type $used-in-throw (sub (struct (field anyref))))
    (type $used-in-throw (sub (struct (field anyref))))
    ;; CHECK:       (type $used-in-throw-ok (sub (struct (field anyref))))
    (type $used-in-throw-ok (sub (struct (field anyref))))
    ;; TODO: resume, suspend, and switch
    ;; CHECK:       (type $used-in-local-set (sub (struct (field anyref))))
    (type $used-in-local-set (sub (struct (field anyref))))
    ;; CHECK:       (type $used-in-local-set-ok (sub (struct (field anyref))))
    (type $used-in-local-set-ok (sub (struct (field anyref))))
    ;; CHECK:       (type $used-in-local-set-tuple (sub (struct (field anyref))))
    (type $used-in-local-set-tuple (sub (struct (field anyref))))
    ;; CHECK:       (type $used-in-local-set-tuple-ok (sub (struct (field anyref))))
    (type $used-in-local-set-tuple-ok (sub (struct (field anyref))))
    ;; CHECK:       (type $used-in-global-set (sub (struct (field anyref))))
    (type $used-in-global-set (sub (struct (field anyref))))
    ;; CHECK:       (type $used-in-global-set-ok (sub (struct (field anyref))))
    (type $used-in-global-set-ok (sub (struct (field anyref))))
    ;; CHECK:       (type $used-in-table-set (sub (struct (field anyref))))
    (type $used-in-table-set (sub (struct (field anyref))))
    ;; CHECK:       (type $used-in-table-set-ok (sub (struct (field anyref))))
    (type $used-in-table-set-ok (sub (struct (field anyref))))
    ;; CHECK:       (type $used-in-struct-new (sub (struct (field anyref))))
    (type $used-in-struct-new (sub (struct (field anyref))))
    ;; CHECK:       (type $used-in-struct-new-ok (sub (struct (field anyref))))
    (type $used-in-struct-new-ok (sub (struct (field anyref))))
    ;; TODO: Struct.new with descriptor
    ;; CHECK:       (type $used-in-struct-set (sub (struct (field anyref))))
    (type $used-in-struct-set (sub (struct (field anyref))))
    ;; CHECK:       (type $used-in-struct-set-ok (sub (struct (field anyref))))
    (type $used-in-struct-set-ok (sub (struct (field anyref))))
    ;; CHECK:       (type $used-in-array-new (sub (struct (field anyref))))
    (type $used-in-array-new (sub (struct (field anyref))))
    ;; CHECK:       (type $used-in-array-new-ok (sub (struct (field anyref))))
    (type $used-in-array-new-ok (sub (struct (field anyref))))
    ;; CHECK:       (type $used-in-array-new-fixed (sub (struct (field anyref))))
    (type $used-in-array-new-fixed (sub (struct (field anyref))))
    ;; CHECK:       (type $used-in-array-new-fixed-ok (sub (struct (field anyref))))
    (type $used-in-array-new-fixed-ok (sub (struct (field anyref))))
    ;; CHECK:       (type $used-in-array-set (sub (struct (field anyref))))
    (type $used-in-array-set (sub (struct (field anyref))))
    ;; CHECK:       (type $used-in-array-set-ok (sub (struct (field anyref))))
    (type $used-in-array-set-ok (sub (struct (field anyref))))
    ;; CHECK:       (type $used-in-array-fill (sub (struct (field anyref))))
    (type $used-in-array-fill (sub (struct (field anyref))))
    ;; CHECK:       (type $used-in-array-fill-ok (sub (struct (field anyref))))
    (type $used-in-array-fill-ok (sub (struct (field anyref))))
    ;; CHECK:       (type $used-in-array-copy-ok (sub (struct (field anyref))))
    (type $used-in-array-copy-ok (sub (struct (field anyref))))
    ;; TODO: Array atomic accessors
    ;; TODO: cont.new and cont.bind

    ;; Module fields
    ;; CHECK:       (type $used-in-func (sub (struct (field anyref))))
    (type $used-in-func (sub (struct (field anyref))))
    ;; CHECK:       (type $used-in-global (sub (struct (field anyref))))
    (type $used-in-global (sub (struct (field anyref))))
    ;; CHECK:       (type $used-in-segment (sub (struct (field anyref))))
    (type $used-in-segment (sub (struct (field anyref))))
  )

  ;; CHECK:      (type $call-ref-exact (func (param (ref (exact $used-in-call-ref)))))
  (type $call-ref-exact (func (param (ref (exact $used-in-call-ref)))))
  ;; CHECK:      (type $call-ref-inexact (func (param (ref $used-in-call-ref-ok))))
  (type $call-ref-inexact (func (param (ref $used-in-call-ref-ok))))
  ;; CHECK:      (type $call-ref-unreachable (func (param (ref (exact $used-in-call-ref-unreachable)))))
  (type $call-ref-unreachable (func (param (ref (exact $used-in-call-ref-unreachable)))))
  ;; CHECK:      (type $call-ref-bot (func (param (ref (exact $used-in-call-ref-bot)))))
  (type $call-ref-bot (func (param (ref (exact $used-in-call-ref-bot)))))

  ;; CHECK:      (type $struct-new-exact (struct (field (ref (exact $used-in-struct-new))) (field anyref)))
  (type $struct-new-exact (struct (field (ref (exact $used-in-struct-new)) anyref)))
  ;; CHECK:      (type $struct-new-inexact (struct (field (ref $used-in-struct-new-ok)) (field anyref)))
  (type $struct-new-inexact (struct (field (ref $used-in-struct-new-ok) anyref)))

  ;; CHECK:      (type $struct-set-exact (struct (field (mut (ref (exact $used-in-struct-set))))))
  (type $struct-set-exact (struct (field (mut (ref (exact $used-in-struct-set))))))
  ;; CHECK:      (type $struct-set-inexact (struct (field (mut (ref $used-in-struct-set-ok)))))
  (type $struct-set-inexact (struct (field (mut (ref $used-in-struct-set-ok)))))

  ;; CHECK:      (type $array-new-exact (sub (array (ref null (exact $used-in-array-new)))))
  (type $array-new-exact (sub (array (field (ref null (exact $used-in-array-new))))))
  ;; CHECK:      (type $array-new-inexact (sub (array (ref null $used-in-array-new-ok))))
  (type $array-new-inexact (sub (array (field (ref null $used-in-array-new-ok)))))

  ;; CHECK:      (type $array-new-fixed-exact (sub (array (ref null (exact $used-in-array-new-fixed)))))
  (type $array-new-fixed-exact (sub (array (field (ref null (exact $used-in-array-new-fixed))))))
  ;; CHECK:      (type $array-new-fixed-inexact (sub (array (ref null $used-in-array-new-fixed-ok))))
  (type $array-new-fixed-inexact (sub (array (field (ref null $used-in-array-new-fixed-ok)))))

  ;; CHECK:      (type $array-set-exact (sub (array (mut (ref (exact $used-in-array-set))))))
  (type $array-set-exact (sub (array (field (mut (ref (exact $used-in-array-set)))))))
  ;; CHECK:      (type $array-set-inexact (sub (array (mut (ref $used-in-array-set-ok)))))
  (type $array-set-inexact (sub (array (field (mut (ref $used-in-array-set-ok))))))

  ;; CHECK:      (type $array-fill-exact (sub (array (mut (ref (exact $used-in-array-fill))))))
  (type $array-fill-exact (sub (array (field (mut (ref (exact $used-in-array-fill)))))))
  ;; CHECK:      (type $array-fill-inexact (sub (array (mut (ref $used-in-array-fill-ok)))))
  (type $array-fill-inexact (sub (array (field (mut (ref $used-in-array-fill-ok))))))

  ;; CHECK:      (type $array-copy-exact (sub (array (mut (ref (exact $used-in-array-copy-ok))))))
  (type $array-copy-exact (sub (array (field (mut (ref (exact $used-in-array-copy-ok)))))))

  ;; CHECK:      (type $67 (func (param (ref (exact $used-in-throw)))))

  ;; CHECK:      (type $68 (func (param (ref $used-in-throw-ok))))

  ;; CHECK:      (type $69 (func (param (ref (exact $used-in-ref-test)))))

  ;; CHECK:      (type $70 (func (param (ref (exact $used-in-ref-cast)))))

  ;; CHECK:      (type $71 (func (param (ref (exact $used-in-br-on-cast)))))

  ;; CHECK:      (type $72 (func (param (ref (exact $used-in-br-on-cast-fail)))))

  ;; CHECK:      (type $73 (func (param (ref (exact $used-in-block)))))

  ;; CHECK:      (type $74 (func (param (ref (exact $used-in-loop)))))

  ;; CHECK:      (type $75 (func (param (ref (exact $used-in-if)))))

  ;; CHECK:      (type $76 (func (param (ref (exact $used-in-try)))))

  ;; CHECK:      (type $77 (func (param (ref (exact $used-in-try-table)))))

  ;; CHECK:      (type $78 (func (param (ref (exact $used-in-branch)))))

  ;; CHECK:      (type $79 (func (param (ref (exact $used-in-br-table)))))

  ;; CHECK:      (type $80 (func (param (ref (exact $used-in-return))) (result (ref (exact $used-in-return)))))

  ;; CHECK:      (type $81 (func (param (ref (exact $used-in-return-ok))) (result (ref $used-in-return-ok))))

  ;; CHECK:      (type $82 (func (param (ref (exact $used-in-call)))))

  ;; CHECK:      (type $83 (func (param (ref $used-in-call-ok))))

  ;; CHECK:      (type $84 (func (param (ref (exact $used-in-call-ok)))))

  ;; CHECK:      (type $85 (func (param (ref (exact $used-in-call-indirect)))))

  ;; CHECK:      (type $86 (func (param (ref (exact $used-in-call-indirect-ok)))))

  ;; CHECK:      (type $87 (func (param (ref $used-in-call-indirect-ok))))

  ;; CHECK:      (type $88 (func (param (ref (exact $used-in-call-ref)) (ref $call-ref-exact))))

  ;; CHECK:      (type $89 (func (param (ref (exact $used-in-call-ref-ok)) (ref $call-ref-inexact))))

  ;; CHECK:      (type $90 (func (param (ref (exact $used-in-ret-call)))))

  ;; CHECK:      (type $91 (func (param (ref $used-in-ret-call-ok))))

  ;; CHECK:      (type $92 (func (param (ref (exact $used-in-ret-call-ok)))))

  ;; CHECK:      (type $93 (func (param (ref (exact $used-in-ret-call-unreachable)) i32)))

  ;; CHECK:      (type $94 (func (param (ref (exact $used-in-throw-ok)))))

  ;; CHECK:      (type $95 (func (param (ref (exact $used-in-local-set)))))

  ;; CHECK:      (type $96 (func (param (ref (exact $used-in-local-set-ok)))))

  ;; CHECK:      (type $97 (func (param (ref (exact $used-in-local-set-tuple)))))

  ;; CHECK:      (type $98 (func (param (ref (exact $used-in-local-set-tuple-ok)))))

  ;; CHECK:      (type $99 (func (param (ref (exact $used-in-global-set)))))

  ;; CHECK:      (type $100 (func (param (ref (exact $used-in-global-set-ok)))))

  ;; CHECK:      (type $101 (func (param (ref (exact $used-in-table-set)))))

  ;; CHECK:      (type $102 (func (param (ref (exact $used-in-table-set-ok)))))

  ;; CHECK:      (type $103 (func (param (ref (exact $used-in-struct-new)))))

  ;; CHECK:      (type $104 (func (param (ref (exact $used-in-struct-new-ok)))))

  ;; CHECK:      (type $105 (func (param (ref (exact $used-in-struct-set)) (ref $struct-set-exact))))

  ;; CHECK:      (type $106 (func (param (ref (exact $used-in-struct-set-ok)) (ref $struct-set-inexact))))

  ;; CHECK:      (type $107 (func (param (ref null (exact $used-in-array-new)))))

  ;; CHECK:      (type $108 (func (param (ref null (exact $used-in-array-new-ok)))))

  ;; CHECK:      (type $109 (func (param (ref null (exact $used-in-array-new-fixed)))))

  ;; CHECK:      (type $110 (func (param (ref null (exact $used-in-array-new-fixed-ok)))))

  ;; CHECK:      (type $111 (func (param (ref (exact $used-in-array-set)) (ref $array-set-exact))))

  ;; CHECK:      (type $112 (func (param (ref (exact $used-in-array-set-ok)) (ref $array-set-inexact))))

  ;; CHECK:      (type $113 (func (param (ref (exact $used-in-array-fill)) (ref $array-fill-exact))))

  ;; CHECK:      (type $114 (func (param (ref (exact $used-in-array-fill-ok)) (ref $array-fill-inexact))))

  ;; CHECK:      (type $115 (func (param (ref (exact $used-in-array-copy-ok)) (ref $array-copy-exact))))

  ;; CHECK:      (type $116 (func (param (ref (exact $used-in-func))) (result (ref (exact $used-in-func)))))

  ;; CHECK:      (type $117 (func))

  ;; CHECK:      (rec
  ;; CHECK-NEXT:  (type $used-in-block_1 (sub $used-in-block (struct (field anyref))))

  ;; CHECK:       (type $used-in-loop_2 (sub $used-in-loop (struct (field anyref))))

  ;; CHECK:       (type $used-in-if_3 (sub $used-in-if (struct (field anyref))))

  ;; CHECK:       (type $used-in-try_4 (sub $used-in-try (struct (field anyref))))

  ;; CHECK:       (type $used-in-try-table_5 (sub $used-in-try-table (struct (field anyref))))

  ;; CHECK:       (type $used-in-branch_6 (sub $used-in-branch (struct (field anyref))))

  ;; CHECK:       (type $used-in-br-table_7 (sub $used-in-br-table (struct (field anyref))))

  ;; CHECK:       (type $used-in-return-ok_8 (sub $used-in-return-ok (struct (field anyref))))

  ;; CHECK:       (type $used-in-call-ok_9 (sub $used-in-call-ok (struct (field anyref))))

  ;; CHECK:       (type $used-in-call-indirect-ok_10 (sub $used-in-call-indirect-ok (struct (field anyref))))

  ;; CHECK:       (type $used-in-call-ref-ok_11 (sub $used-in-call-ref-ok (struct (field anyref))))

  ;; CHECK:       (type $used-in-call-ref-unreachable_12 (sub $used-in-call-ref-unreachable (struct (field anyref))))

  ;; CHECK:       (type $used-in-call-ref-bot_13 (sub $used-in-call-ref-bot (struct (field anyref))))

  ;; CHECK:       (type $used-in-ret-call-ok_14 (sub $used-in-ret-call-ok (struct (field anyref))))

  ;; CHECK:       (type $used-in-throw-ok_15 (sub $used-in-throw-ok (struct (field anyref))))

  ;; CHECK:       (type $used-in-local-set-ok_16 (sub $used-in-local-set-ok (struct (field anyref))))

  ;; CHECK:       (type $used-in-local-set-tuple-ok_17 (sub $used-in-local-set-tuple-ok (struct (field anyref))))

  ;; CHECK:       (type $used-in-global-set-ok_18 (sub $used-in-global-set-ok (struct (field anyref))))

  ;; CHECK:       (type $used-in-table-set-ok_19 (sub $used-in-table-set-ok (struct (field anyref))))

  ;; CHECK:       (type $used-in-struct-new-ok_20 (sub $used-in-struct-new-ok (struct (field anyref))))

  ;; CHECK:       (type $used-in-struct-set-ok_21 (sub $used-in-struct-set-ok (struct (field anyref))))

  ;; CHECK:       (type $array-new-exact_22 (sub $array-new-exact (array (ref null (exact $used-in-array-new)))))

  ;; CHECK:       (type $array-new-inexact_23 (sub $array-new-inexact (array (ref null $used-in-array-new-ok))))

  ;; CHECK:       (type $array-new-inexact_24 (sub $array-new-inexact (array (ref null $used-in-array-new-ok))))

  ;; CHECK:       (type $used-in-array-new-ok_25 (sub $used-in-array-new-ok (struct (field anyref))))

  ;; CHECK:       (type $array-new-fixed-exact_26 (sub $array-new-fixed-exact (array (ref null (exact $used-in-array-new-fixed)))))

  ;; CHECK:       (type $array-new-fixed-inexact_27 (sub $array-new-fixed-inexact (array (ref null $used-in-array-new-fixed-ok))))

  ;; CHECK:       (type $array-new-fixed-inexact_28 (sub $array-new-fixed-inexact (array (ref null $used-in-array-new-fixed-ok))))

  ;; CHECK:       (type $used-in-array-new-fixed-ok_29 (sub $used-in-array-new-fixed-ok (struct (field anyref))))

  ;; CHECK:       (type $used-in-array-set-ok_30 (sub $used-in-array-set-ok (struct (field anyref))))

  ;; CHECK:       (type $used-in-array-fill-ok_31 (sub $used-in-array-fill-ok (struct (field anyref))))

  ;; CHECK:       (type $used-in-array-copy-ok_32 (sub $used-in-array-copy-ok (struct (field anyref))))

  ;; CHECK:      (global $global-exact (mut (ref null (exact $used-in-global-set))) (ref.null none))
  (global $global-exact (mut (ref null (exact $used-in-global-set))) (ref.null none))
  ;; CHECK:      (global $global-inexact (mut (ref null $used-in-global-set-ok)) (ref.null none))
  (global $global-inexact (mut (ref null $used-in-global-set-ok)) (ref.null none))

  ;; CHECK:      (global $global-exact-unused (ref null (exact $used-in-global)) (ref.null none))
  (global $global-exact-unused (ref null (exact $used-in-global)) (ref.null none))

  ;; CHECK:      (table $indirect-call-table 1 1 funcref)
  (table $indirect-call-table 1 1 funcref)

  ;; CHECK:      (table $table-exact 1 1 (ref null (exact $used-in-table-set)))
  (table $table-exact 1 1 (ref null (exact $used-in-table-set)))
  ;; CHECK:      (table $table-inexact 1 1 (ref null $used-in-table-set-ok))
  (table $table-inexact 1 1 (ref null $used-in-table-set-ok))

  ;; CHECK:      (elem $segment-exact-unused (ref null (exact $used-in-segment)) (item (ref.null none)))
  (elem $segment-exact-unused (ref null (exact $used-in-segment)) (item (ref.null none)))

  ;; CHECK:      (tag $throw-exact (type $67) (param (ref (exact $used-in-throw))))
  (tag $throw-exact (param (ref (exact $used-in-throw))))
  ;; CHECK:      (tag $throw-inexact (type $68) (param (ref $used-in-throw-ok)))
  (tag $throw-inexact (param (ref $used-in-throw-ok)))

  ;; CHECK:      (func $ref-test (type $69) (param $used (ref (exact $used-in-ref-test)))
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (ref.test (ref (exact $used-in-ref-test))
  ;; CHECK-NEXT:    (local.get $used)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (struct.new $used-in-ref-test
  ;; CHECK-NEXT:    (ref.null none)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $ref-test (param $used (ref (exact $used-in-ref-test)))
    (drop
      ;; This cast will observe the exactness of the $used-in-ref-test.
      (ref.test (ref (exact $used-in-ref-test))
        (local.get $used)
      )
    )
    (drop
      ;; So this cannot be optimized since we don't do a flow analysis and don't
      ;; know that this particular allocation is never observed to be exact.
      (struct.new $used-in-ref-test
        (ref.null none)
      )
    )
  )

  ;; CHECK:      (func $ref-cast (type $70) (param $used (ref (exact $used-in-ref-cast)))
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (ref.cast (ref (exact $used-in-ref-cast))
  ;; CHECK-NEXT:    (local.get $used)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (struct.new $used-in-ref-cast
  ;; CHECK-NEXT:    (ref.null none)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $ref-cast (param $used (ref (exact $used-in-ref-cast)))
    (drop
      (ref.cast (ref (exact $used-in-ref-cast))
        (local.get $used)
      )
    )
    (drop
      (struct.new $used-in-ref-cast
        (ref.null none)
      )
    )
  )

  ;; CHECK:      (func $br_on_cast (type $71) (param $used (ref (exact $used-in-br-on-cast)))
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (block $l (result (ref (exact $used-in-br-on-cast)))
  ;; CHECK-NEXT:    (br_on_cast $l (ref (exact $used-in-br-on-cast)) (ref (exact $used-in-br-on-cast))
  ;; CHECK-NEXT:     (local.get $used)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (unreachable)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (struct.new $used-in-br-on-cast
  ;; CHECK-NEXT:    (ref.null none)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $br_on_cast (param $used (ref (exact $used-in-br-on-cast)))
    (drop
      (block $l (result anyref)
        (br_on_cast $l anyref (ref (exact $used-in-br-on-cast))
          (local.get $used)
        )
      )
      (unreachable)
    )
    (drop
      (struct.new $used-in-br-on-cast
        (ref.null none)
      )
    )
  )

  ;; CHECK:      (func $br_on_cast_fail (type $72) (param $used (ref (exact $used-in-br-on-cast-fail)))
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (block $l (result (ref (exact $used-in-br-on-cast-fail)))
  ;; CHECK-NEXT:    (drop
  ;; CHECK-NEXT:     (br_on_cast_fail $l (ref (exact $used-in-br-on-cast-fail)) (ref (exact $used-in-br-on-cast-fail))
  ;; CHECK-NEXT:      (local.get $used)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (unreachable)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (struct.new $used-in-br-on-cast-fail
  ;; CHECK-NEXT:    (ref.null none)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $br_on_cast_fail (param $used (ref (exact $used-in-br-on-cast-fail)))
    (drop
      (block $l (result anyref)
        (br_on_cast_fail 0 (ref $used-in-br-on-cast-fail) (ref (exact $used-in-br-on-cast-fail))
          (local.get $used)
        )
        (unreachable)
      )
    )
    (drop
      (struct.new $used-in-br-on-cast-fail
        (ref.null none)
      )
    )
  )

  ;; CHECK:      (func $block (type $73) (param $used (ref (exact $used-in-block)))
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (block $l (result (ref (exact $used-in-block)))
  ;; CHECK-NEXT:    (local.get $used)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (struct.new $used-in-block_1
  ;; CHECK-NEXT:    (ref.null none)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $block (param $used (ref (exact $used-in-block)))
    (drop
      ;; Blocks do not inhibit optimization, even though they observe exactness.
      (block $l (result (ref (exact $used-in-block)))
        (local.get $used)
      )
    )
    ;; TODO: Move this allocation into the block once it is typed as exact to
    ;; show that refinalization works correctly.
    (drop
      (struct.new $used-in-block
        (ref.null none)
      )
    )
  )

  ;; CHECK:      (func $loop (type $74) (param $used (ref (exact $used-in-loop)))
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (loop (result (ref (exact $used-in-loop)))
  ;; CHECK-NEXT:    (local.get $used)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (struct.new $used-in-loop_2
  ;; CHECK-NEXT:    (ref.null none)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $loop (param $used (ref (exact $used-in-loop)))
    (drop
      ;; Same with loops and other control flow.
      (loop (result (ref (exact $used-in-loop)))
        (local.get $used)
      )
    )
    (drop
      (struct.new $used-in-loop
        (ref.null none)
      )
    )
  )

  ;; CHECK:      (func $if (type $75) (param $used (ref (exact $used-in-if)))
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (if (result (ref (exact $used-in-if)))
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:    (then
  ;; CHECK-NEXT:     (local.get $used)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (else
  ;; CHECK-NEXT:     (local.get $used)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (struct.new $used-in-if_3
  ;; CHECK-NEXT:    (ref.null none)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $if (param $used (ref (exact $used-in-if)))
    (drop
      (if (result (ref (exact $used-in-if)))
        (i32.const 0)
        (then
          (local.get $used)
        )
        (else
          (local.get $used)
        )
      )
    )
    (drop
      (struct.new $used-in-if
        (ref.null none)
      )
    )
  )

  ;; CHECK:      (func $try (type $76) (param $used (ref (exact $used-in-try)))
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (try (result (ref (exact $used-in-try)))
  ;; CHECK-NEXT:    (do
  ;; CHECK-NEXT:     (local.get $used)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (struct.new $used-in-try_4
  ;; CHECK-NEXT:    (ref.null none)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $try (param $used (ref (exact $used-in-try)))
    (drop
      (try (result (ref (exact $used-in-try)))
        (do
          (local.get $used)
        )
      )
    )
    (drop
      (struct.new $used-in-try
        (ref.null none)
      )
    )
  )

  ;; CHECK:      (func $try-table (type $77) (param $used (ref (exact $used-in-try-table)))
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (try_table (result (ref (exact $used-in-try-table)))
  ;; CHECK-NEXT:    (local.get $used)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (struct.new $used-in-try-table_5
  ;; CHECK-NEXT:    (ref.null none)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $try-table (param $used (ref (exact $used-in-try-table)))
    (drop
      (try_table (result (ref (exact $used-in-try-table)))
        (local.get $used)
      )
    )
    (drop
      (struct.new $used-in-try-table
        (ref.null none)
      )
    )
  )

  ;; CHECK:      (func $branch (type $78) (param $used (ref (exact $used-in-branch)))
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (block $l (result (ref (exact $used-in-branch)))
  ;; CHECK-NEXT:    (br $l
  ;; CHECK-NEXT:     (local.get $used)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (unreachable)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (struct.new $used-in-branch_6
  ;; CHECK-NEXT:    (ref.null none)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $branch (param $used (ref (exact $used-in-branch)))
    (drop
      (block $l (result (ref (exact $used-in-branch)))
        ;; Branches don't inhibit optimizations, either.
        (br $l
          (local.get $used)
        )
        (unreachable)
      )
    )
    (drop
      ;; TODO: Use this allocation in the branch once it is typed as exact.
      (struct.new $used-in-branch
        (ref.null none)
      )
    )
  )

  ;; CHECK:      (func $br-table (type $79) (param $used (ref (exact $used-in-br-table)))
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (block $l (result (ref (exact $used-in-br-table)))
  ;; CHECK-NEXT:    (br_table $l
  ;; CHECK-NEXT:     (local.get $used)
  ;; CHECK-NEXT:     (i32.const 0)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (unreachable)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (struct.new $used-in-br-table_7
  ;; CHECK-NEXT:    (ref.null none)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $br-table (param $used (ref (exact $used-in-br-table)))
    (drop
      (block $l (result (ref (exact $used-in-br-table)))
        (br_table $l
          (local.get $used)
          (i32.const 0)
        )
        (unreachable)
      )
    )
    (drop
      ;; TODO: Use this allocation in the branch once it is typed as exact.
      (struct.new $used-in-br-table
        (ref.null none)
      )
    )
  )


  ;; CHECK:      (func $return (type $80) (param $used (ref (exact $used-in-return))) (result (ref (exact $used-in-return)))
  ;; CHECK-NEXT:  (return
  ;; CHECK-NEXT:   (local.get $used)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (struct.new $used-in-return
  ;; CHECK-NEXT:    (ref.null none)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (unreachable)
  ;; CHECK-NEXT: )
  (func $return (param $used (ref (exact $used-in-return))) (result (ref (exact $used-in-return)))
    ;; This return will inhibit optimization because it requires its operand to be exact.
    (return
      (local.get $used)
    )
    (drop
      (struct.new $used-in-return
        (ref.null none)
      )
    )
  )

  ;; CHECK:      (func $return-ok (type $81) (param $used (ref (exact $used-in-return-ok))) (result (ref $used-in-return-ok))
  ;; CHECK-NEXT:  (return
  ;; CHECK-NEXT:   (local.get $used)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (struct.new $used-in-return-ok_8
  ;; CHECK-NEXT:    (ref.null none)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (unreachable)
  ;; CHECK-NEXT: )
  (func $return-ok (param $used (ref (exact $used-in-return-ok))) (result (ref $used-in-return-ok))
    ;; The result is not exact, so the return doesn't need to be, either.
    (return
      (local.get $used)
    )
    (drop
      (struct.new $used-in-return-ok
        (ref.null none)
      )
    )
  )

  ;; CHECK:      (func $call (type $82) (param $used (ref (exact $used-in-call)))
  ;; CHECK-NEXT:  (call $call
  ;; CHECK-NEXT:   (local.get $used)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (struct.new $used-in-call
  ;; CHECK-NEXT:    (ref.null none)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $call (param $used (ref (exact $used-in-call)))
    (call $call
      (local.get $used)
    )
    (drop
      (struct.new $used-in-call
        (ref.null none)
      )
    )
  )

  ;; CHECK:      (func $inexact-callee (type $83) (param $0 (ref $used-in-call-ok))
  ;; CHECK-NEXT:  (unreachable)
  ;; CHECK-NEXT: )
  (func $inexact-callee (param (ref $used-in-call-ok))
    ;; Helper for call-ok.
    (unreachable)
  )

  ;; CHECK:      (func $call-ok (type $84) (param $used (ref (exact $used-in-call-ok)))
  ;; CHECK-NEXT:  (call $inexact-callee
  ;; CHECK-NEXT:   (local.get $used)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (struct.new $used-in-call-ok_9
  ;; CHECK-NEXT:    (ref.null none)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $call-ok (param $used (ref (exact $used-in-call-ok)))
    ;; The callee parameter is not exact, so this argument does not need to be, either.
    (call $inexact-callee
      (local.get $used)
    )
    (drop
      (struct.new $used-in-call-ok
        (ref.null none)
      )
    )
  )

  ;; CHECK:      (func $call-indirect (type $85) (param $used (ref (exact $used-in-call-indirect)))
  ;; CHECK-NEXT:  (call_indirect $indirect-call-table (type $85)
  ;; CHECK-NEXT:   (local.get $used)
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (struct.new $used-in-call-indirect
  ;; CHECK-NEXT:    (ref.null none)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $call-indirect (param $used (ref (exact $used-in-call-indirect)))
    (call_indirect $indirect-call-table (param (ref (exact $used-in-call-indirect)))
      (local.get $used)
      (i32.const 0)
    )
    (drop
      (struct.new $used-in-call-indirect
        (ref.null none)
      )
    )
  )

  ;; CHECK:      (func $call-indirect-ok (type $86) (param $used (ref (exact $used-in-call-indirect-ok)))
  ;; CHECK-NEXT:  (call_indirect $indirect-call-table (type $87)
  ;; CHECK-NEXT:   (local.get $used)
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (struct.new $used-in-call-indirect-ok_10
  ;; CHECK-NEXT:    (ref.null none)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $call-indirect-ok (param $used (ref (exact $used-in-call-indirect-ok)))
    ;; The callee parameter is not exact, so this argument does not need to be, either.
    (call_indirect $indirect-call-table (param (ref $used-in-call-indirect-ok))
      (local.get $used)
      (i32.const 0)
    )
    (drop
      (struct.new $used-in-call-indirect-ok
        (ref.null none)
      )
    )
  )

  ;; CHECK:      (func $call-ref (type $88) (param $used (ref (exact $used-in-call-ref))) (param $ref (ref $call-ref-exact))
  ;; CHECK-NEXT:  (call_ref $call-ref-exact
  ;; CHECK-NEXT:   (local.get $used)
  ;; CHECK-NEXT:   (local.get $ref)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (struct.new $used-in-call-ref
  ;; CHECK-NEXT:    (ref.null none)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $call-ref (param $used (ref (exact $used-in-call-ref))) (param $ref (ref $call-ref-exact))
    (call_ref $call-ref-exact
      (local.get $used)
      (local.get $ref)
    )
    (drop
      (struct.new $used-in-call-ref
        (ref.null none)
      )
    )
  )

  ;; CHECK:      (func $call-ref-ok (type $89) (param $used (ref (exact $used-in-call-ref-ok))) (param $ref (ref $call-ref-inexact))
  ;; CHECK-NEXT:  (call_ref $call-ref-inexact
  ;; CHECK-NEXT:   (local.get $used)
  ;; CHECK-NEXT:   (local.get $ref)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (struct.new $used-in-call-ref-ok_11
  ;; CHECK-NEXT:    (ref.null none)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $call-ref-ok (param $used (ref (exact $used-in-call-ref-ok))) (param $ref (ref $call-ref-inexact))
    ;; The callee parameter is not exact, so this argument does not need to be, either.
    (call_ref $call-ref-inexact
      (local.get $used)
      (local.get $ref)
    )
    (drop
      (struct.new $used-in-call-ref-ok
        (ref.null none)
      )
    )
  )

  ;; CHECK:      (func $call-ref-unreachable (type $call-ref-unreachable) (param $used (ref (exact $used-in-call-ref-unreachable)))
  ;; CHECK-NEXT:  (block ;; (replaces unreachable CallRef we can't emit)
  ;; CHECK-NEXT:   (drop
  ;; CHECK-NEXT:    (local.get $used)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (drop
  ;; CHECK-NEXT:    (unreachable)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (unreachable)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (struct.new $used-in-call-ref-unreachable_12
  ;; CHECK-NEXT:    (ref.null none)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $call-ref-unreachable (param $used (ref (exact $used-in-call-ref-unreachable)))
    ;; The callee parameter is not exact, so this argument does not need to be, either.
    (call_ref $call-ref-unreachable
      (local.get $used)
      (unreachable)
    )
    (drop
      ;; This is still optimizable.
      (struct.new $used-in-call-ref-unreachable
        (ref.null none)
      )
    )
  )

  ;; CHECK:      (func $call-ref-bot (type $call-ref-bot) (param $used (ref (exact $used-in-call-ref-bot)))
  ;; CHECK-NEXT:  (block ;; (replaces unreachable CallRef we can't emit)
  ;; CHECK-NEXT:   (drop
  ;; CHECK-NEXT:    (local.get $used)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (drop
  ;; CHECK-NEXT:    (ref.null nofunc)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (unreachable)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (struct.new $used-in-call-ref-bot_13
  ;; CHECK-NEXT:    (ref.null none)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $call-ref-bot (param $used (ref (exact $used-in-call-ref-bot)))
    ;; This call_ref will not be emitted, so it does not inhibit optimization.
    (call_ref $call-ref-bot
      (local.get $used)
      (ref.null nofunc)
    )
    (drop
      ;; This is still optimizable.
      (struct.new $used-in-call-ref-bot
        (ref.null none)
      )
    )
  )

  ;; CHECK:      (func $ret-call (type $90) (param $used (ref (exact $used-in-ret-call)))
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (struct.new $used-in-ret-call
  ;; CHECK-NEXT:    (ref.null none)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (return_call $ret-call
  ;; CHECK-NEXT:   (local.get $used)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $ret-call (param $used (ref (exact $used-in-ret-call)))
    (drop
      (struct.new $used-in-ret-call
        (ref.null none)
      )
    )
    (return_call $ret-call
      (local.get $used)
    )
  )

  ;; CHECK:      (func $inexact-ret-callee (type $91) (param $0 (ref $used-in-ret-call-ok))
  ;; CHECK-NEXT:  (unreachable)
  ;; CHECK-NEXT: )
  (func $inexact-ret-callee (param (ref $used-in-ret-call-ok))
    ;; Helper for ret-call-ok.
    (unreachable)
  )

  ;; CHECK:      (func $ret-call-ok (type $92) (param $used (ref (exact $used-in-ret-call-ok)))
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (struct.new $used-in-ret-call-ok_14
  ;; CHECK-NEXT:    (ref.null none)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (return_call $inexact-ret-callee
  ;; CHECK-NEXT:   (local.get $used)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $ret-call-ok (param $used (ref (exact $used-in-ret-call-ok)))
    (drop
      (struct.new $used-in-ret-call-ok
        (ref.null none)
      )
    )
    ;; The callee parameter is not exact, so this argument does not need to be, either.
    (return_call $inexact-ret-callee
      (local.get $used)
    )
  )


  ;; CHECK:      (func $ret-call-unreachable (type $93) (param $used (ref (exact $used-in-ret-call-unreachable))) (param $1 i32)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (struct.new $used-in-ret-call-unreachable
  ;; CHECK-NEXT:    (ref.null none)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (return_call $ret-call-unreachable
  ;; CHECK-NEXT:   (local.get $used)
  ;; CHECK-NEXT:   (unreachable)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $ret-call-unreachable (param $used (ref (exact $used-in-ret-call-unreachable))) (param i32)
    (drop
      (struct.new $used-in-ret-call-unreachable
        (ref.null none)
      )
    )
    ;; The callee parameter is exact, but since the call is unreachable (with an
    ;; unreachable child), we do not optimize.
    (return_call $ret-call-unreachable
      (local.get $used)
      (unreachable)
    )
  )

  ;; CHECK:      (func $throw (type $67) (param $used (ref (exact $used-in-throw)))
  ;; CHECK-NEXT:  (throw $throw-exact
  ;; CHECK-NEXT:   (local.get $used)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (struct.new $used-in-throw
  ;; CHECK-NEXT:    (ref.null none)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $throw (param $used (ref (exact $used-in-throw)))
    (throw $throw-exact
      (local.get $used)
    )
    (drop
      (struct.new $used-in-throw
        (ref.null none)
      )
    )
  )

  ;; CHECK:      (func $throw-ok (type $94) (param $used (ref (exact $used-in-throw-ok)))
  ;; CHECK-NEXT:  (throw $throw-inexact
  ;; CHECK-NEXT:   (local.get $used)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (struct.new $used-in-throw-ok_15
  ;; CHECK-NEXT:    (ref.null none)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $throw-ok (param $used (ref (exact $used-in-throw-ok)))
    (throw $throw-inexact
      (local.get $used)
    )
    (drop
      (struct.new $used-in-throw-ok
        (ref.null none)
      )
    )
  )

  ;; CHECK:      (func $local-set (type $95) (param $used (ref (exact $used-in-local-set)))
  ;; CHECK-NEXT:  (local $exact (ref (exact $used-in-local-set)))
  ;; CHECK-NEXT:  (local.set $exact
  ;; CHECK-NEXT:   (local.get $used)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (struct.new $used-in-local-set
  ;; CHECK-NEXT:    (ref.null none)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $local-set (param $used (ref (exact $used-in-local-set)))
    (local $exact (ref (exact $used-in-local-set)))
    (local.set $exact
      (local.get $used)
    )
    (drop
      (struct.new $used-in-local-set
        (ref.null none)
      )
    )
  )

  ;; CHECK:      (func $local-set-ok (type $96) (param $used (ref (exact $used-in-local-set-ok)))
  ;; CHECK-NEXT:  (local $inexact (ref $used-in-local-set-ok))
  ;; CHECK-NEXT:  (local.set $inexact
  ;; CHECK-NEXT:   (local.get $used)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (struct.new $used-in-local-set-ok_16
  ;; CHECK-NEXT:    (ref.null none)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $local-set-ok (param $used (ref (exact $used-in-local-set-ok)))
    (local $inexact (ref $used-in-local-set-ok))
    (local.set $inexact
      (local.get $used)
    )
    (drop
      (struct.new $used-in-local-set-ok
        (ref.null none)
      )
    )
  )

  ;; CHECK:      (func $local-set-tuple (type $97) (param $used (ref (exact $used-in-local-set-tuple)))
  ;; CHECK-NEXT:  (local $tuple-exact (tuple i32 (ref (exact $used-in-local-set-tuple))))
  ;; CHECK-NEXT:  (local.set $tuple-exact
  ;; CHECK-NEXT:   (tuple.make 2
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:    (local.get $used)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (struct.new $used-in-local-set-tuple
  ;; CHECK-NEXT:    (ref.null none)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $local-set-tuple (param $used (ref (exact $used-in-local-set-tuple)))
    (local $tuple-exact (tuple i32 (ref (exact $used-in-local-set-tuple))))
    (local.set $tuple-exact
      (tuple.make 2
        (i32.const 0)
        (local.get $used)
      )
    )
    (drop
      (struct.new $used-in-local-set-tuple
        (ref.null none)
      )
    )
  )

  ;; CHECK:      (func $local-set-tuple-ok (type $98) (param $used (ref (exact $used-in-local-set-tuple-ok)))
  ;; CHECK-NEXT:  (local $tuple-inexact (tuple i32 (ref $used-in-local-set-tuple-ok)))
  ;; CHECK-NEXT:  (local.set $tuple-inexact
  ;; CHECK-NEXT:   (tuple.make 2
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:    (local.get $used)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (struct.new $used-in-local-set-tuple-ok_17
  ;; CHECK-NEXT:    (ref.null none)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $local-set-tuple-ok (param $used (ref (exact $used-in-local-set-tuple-ok)))
    (local $tuple-inexact (tuple i32 (ref $used-in-local-set-tuple-ok)))
    (local.set $tuple-inexact
      (tuple.make 2
        (i32.const 0)
        (local.get $used)
      )
    )
    (drop
      (struct.new $used-in-local-set-tuple-ok
        (ref.null none)
      )
    )
  )

  ;; CHECK:      (func $global-set (type $99) (param $used (ref (exact $used-in-global-set)))
  ;; CHECK-NEXT:  (global.set $global-exact
  ;; CHECK-NEXT:   (local.get $used)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (struct.new $used-in-global-set
  ;; CHECK-NEXT:    (ref.null none)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $global-set (param $used (ref (exact $used-in-global-set)))
    (global.set $global-exact
      (local.get $used)
    )
    (drop
      (struct.new $used-in-global-set
        (ref.null none)
      )
    )
  )

  ;; CHECK:      (func $global-set-ok (type $100) (param $used (ref (exact $used-in-global-set-ok)))
  ;; CHECK-NEXT:  (global.set $global-inexact
  ;; CHECK-NEXT:   (local.get $used)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (struct.new $used-in-global-set-ok_18
  ;; CHECK-NEXT:    (ref.null none)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $global-set-ok (param $used (ref (exact $used-in-global-set-ok)))
    (global.set $global-inexact
      (local.get $used)
    )
    (drop
      (struct.new $used-in-global-set-ok
        (ref.null none)
      )
    )
  )

  ;; CHECK:      (func $table-set (type $101) (param $used (ref (exact $used-in-table-set)))
  ;; CHECK-NEXT:  (table.set $table-exact
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:   (local.get $used)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (struct.new $used-in-table-set
  ;; CHECK-NEXT:    (ref.null none)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $table-set (param $used (ref (exact $used-in-table-set)))
    (table.set $table-exact
      (i32.const 0)
      (local.get $used)
    )
    (drop
      (struct.new $used-in-table-set
        (ref.null none)
      )
    )
  )

  ;; CHECK:      (func $table-set-ok (type $102) (param $used (ref (exact $used-in-table-set-ok)))
  ;; CHECK-NEXT:  (table.set $table-inexact
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:   (local.get $used)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (struct.new $used-in-table-set-ok_19
  ;; CHECK-NEXT:    (ref.null none)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $table-set-ok (param $used (ref (exact $used-in-table-set-ok)))
    (table.set $table-inexact
      (i32.const 0)
      (local.get $used)
    )
    (drop
      (struct.new $used-in-table-set-ok
        (ref.null none)
      )
    )
  )

  ;; CHECK:      (func $struct-new (type $103) (param $used (ref (exact $used-in-struct-new)))
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (struct.new $struct-new-exact
  ;; CHECK-NEXT:    (local.get $used)
  ;; CHECK-NEXT:    (ref.null none)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (struct.new $used-in-struct-new
  ;; CHECK-NEXT:    (ref.null none)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $struct-new (param $used (ref (exact $used-in-struct-new)))
    (drop
      ;; The outer new can still be optimized.
      (struct.new $struct-new-exact
        (local.get $used)
        (ref.null none)
      )
    )
    (drop
      (struct.new $used-in-struct-new
        (ref.null none)
      )
    )
  )

  ;; CHECK:      (func $struct-new-ok (type $104) (param $used (ref (exact $used-in-struct-new-ok)))
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (struct.new $struct-new-inexact
  ;; CHECK-NEXT:    (local.get $used)
  ;; CHECK-NEXT:    (ref.null none)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (struct.new $used-in-struct-new-ok_20
  ;; CHECK-NEXT:    (ref.null none)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $struct-new-ok (param $used (ref (exact $used-in-struct-new-ok)))
    (drop
      (struct.new $struct-new-inexact
        (local.get $used)
        (ref.null none)
      )
    )
    (drop
      (struct.new $used-in-struct-new-ok
        (ref.null none)
      )
    )
  )

  ;; CHECK:      (func $struct-set (type $105) (param $used (ref (exact $used-in-struct-set))) (param $ref (ref $struct-set-exact))
  ;; CHECK-NEXT:  (struct.set $struct-set-exact 0
  ;; CHECK-NEXT:   (local.get $ref)
  ;; CHECK-NEXT:   (local.get $used)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (struct.new $used-in-struct-set
  ;; CHECK-NEXT:    (ref.null none)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $struct-set (param $used (ref (exact $used-in-struct-set))) (param $ref (ref $struct-set-exact))
    (struct.set $struct-set-exact 0
      (local.get $ref)
      (local.get $used)
    )
    (drop
      (struct.new $used-in-struct-set
        (ref.null none)
      )
    )
  )

  ;; CHECK:      (func $struct-set-ok (type $106) (param $used (ref (exact $used-in-struct-set-ok))) (param $ref (ref $struct-set-inexact))
  ;; CHECK-NEXT:  (struct.set $struct-set-inexact 0
  ;; CHECK-NEXT:   (local.get $ref)
  ;; CHECK-NEXT:   (local.get $used)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (struct.new $used-in-struct-set-ok_21
  ;; CHECK-NEXT:    (ref.null none)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $struct-set-ok (param $used (ref (exact $used-in-struct-set-ok))) (param $ref (ref $struct-set-inexact))
    (struct.set $struct-set-inexact 0
      (local.get $ref)
      (local.get $used)
    )
    (drop
      (struct.new $used-in-struct-set-ok
        (ref.null none)
      )
    )
  )

  ;; CHECK:      (func $array-new (type $107) (param $used (ref null (exact $used-in-array-new)))
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (array.new $array-new-exact
  ;; CHECK-NEXT:    (local.get $used)
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (array.new $array-new-exact_22
  ;; CHECK-NEXT:    (ref.null none)
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (struct.new $used-in-array-new
  ;; CHECK-NEXT:    (ref.null none)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $array-new (param $used (ref null (exact $used-in-array-new)))
    (drop
      (array.new $array-new-exact
        (local.get $used)
        (i32.const 0)
      )
    )
    ;; The outer type can still be optimized
    (drop
      (array.new $array-new-exact
        (ref.null none)
        (i32.const 0)
      )
    )
    (drop
      (struct.new $used-in-array-new
        (ref.null none)
      )
    )
  )

  ;; CHECK:      (func $array-new-ok (type $108) (param $used (ref null (exact $used-in-array-new-ok)))
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (array.new $array-new-inexact_23
  ;; CHECK-NEXT:    (local.get $used)
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (array.new $array-new-inexact_24
  ;; CHECK-NEXT:    (ref.null none)
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (struct.new $used-in-array-new-ok_25
  ;; CHECK-NEXT:    (ref.null none)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $array-new-ok (param $used (ref null (exact $used-in-array-new-ok)))
    (drop
      (array.new $array-new-inexact
        (local.get $used)
        (i32.const 0)
      )
    )
    ;; The outer type can also be optimized
    (drop
      (array.new $array-new-inexact
        (ref.null none)
        (i32.const 0)
      )
    )
    (drop
      (struct.new $used-in-array-new-ok
        (ref.null none)
      )
    )
  )

  ;; CHECK:      (func $array-new-fixed (type $109) (param $used (ref null (exact $used-in-array-new-fixed)))
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (array.new_fixed $array-new-fixed-exact 1
  ;; CHECK-NEXT:    (local.get $used)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (array.new $array-new-fixed-exact_26
  ;; CHECK-NEXT:    (ref.null none)
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (struct.new $used-in-array-new-fixed
  ;; CHECK-NEXT:    (ref.null none)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $array-new-fixed (param $used (ref null (exact $used-in-array-new-fixed)))
    (drop
      (array.new_fixed $array-new-fixed-exact 1
        (local.get $used)
      )
    )
    ;; The outer type can still be optimized
    (drop
      (array.new $array-new-fixed-exact
        (ref.null none)
        (i32.const 0)
      )
    )
    (drop
      (struct.new $used-in-array-new-fixed
        (ref.null none)
      )
    )
  )

  ;; CHECK:      (func $array-new-fixed-ok (type $110) (param $used (ref null (exact $used-in-array-new-fixed-ok)))
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (array.new_fixed $array-new-fixed-inexact_27 1
  ;; CHECK-NEXT:    (local.get $used)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (array.new $array-new-fixed-inexact_28
  ;; CHECK-NEXT:    (ref.null none)
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (struct.new $used-in-array-new-fixed-ok_29
  ;; CHECK-NEXT:    (ref.null none)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $array-new-fixed-ok (param $used (ref null (exact $used-in-array-new-fixed-ok)))
    (drop
      (array.new_fixed $array-new-fixed-inexact 1
        (local.get $used)
      )
    )
    ;; The outer type can also be optimized
    (drop
      (array.new $array-new-fixed-inexact
        (ref.null none)
        (i32.const 0)
      )
    )
    (drop
      (struct.new $used-in-array-new-fixed-ok
        (ref.null none)
      )
    )
  )

  ;; CHECK:      (func $array-set (type $111) (param $used (ref (exact $used-in-array-set))) (param $ref (ref $array-set-exact))
  ;; CHECK-NEXT:  (array.set $array-set-exact
  ;; CHECK-NEXT:   (local.get $ref)
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:   (local.get $used)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (struct.new $used-in-array-set
  ;; CHECK-NEXT:    (ref.null none)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $array-set (param $used (ref (exact $used-in-array-set))) (param $ref (ref $array-set-exact))
    (array.set $array-set-exact
      (local.get $ref)
      (i32.const 0)
      (local.get $used)
    )
    (drop
      (struct.new $used-in-array-set
        (ref.null none)
      )
    )
  )

  ;; CHECK:      (func $array-set-ok (type $112) (param $used (ref (exact $used-in-array-set-ok))) (param $ref (ref $array-set-inexact))
  ;; CHECK-NEXT:  (array.set $array-set-inexact
  ;; CHECK-NEXT:   (local.get $ref)
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:   (local.get $used)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (struct.new $used-in-array-set-ok_30
  ;; CHECK-NEXT:    (ref.null none)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $array-set-ok (param $used (ref (exact $used-in-array-set-ok))) (param $ref (ref $array-set-inexact))
    (array.set $array-set-inexact
      (local.get $ref)
      (i32.const 0)
      (local.get $used)
    )
    (drop
      (struct.new $used-in-array-set-ok
        (ref.null none)
      )
    )
  )

  ;; CHECK:      (func $array-fill (type $113) (param $used (ref (exact $used-in-array-fill))) (param $ref (ref $array-fill-exact))
  ;; CHECK-NEXT:  (array.fill $array-fill-exact
  ;; CHECK-NEXT:   (local.get $ref)
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:   (local.get $used)
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (struct.new $used-in-array-fill
  ;; CHECK-NEXT:    (ref.null none)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $array-fill (param $used (ref (exact $used-in-array-fill))) (param $ref (ref $array-fill-exact))
    (array.fill $array-fill-exact
      (local.get $ref)
      (i32.const 0)
      (local.get $used)
      (i32.const 0)
    )
    (drop
      (struct.new $used-in-array-fill
        (ref.null none)
      )
    )
  )

  ;; CHECK:      (func $array-fill-ok (type $114) (param $used (ref (exact $used-in-array-fill-ok))) (param $ref (ref $array-fill-inexact))
  ;; CHECK-NEXT:  (array.fill $array-fill-inexact
  ;; CHECK-NEXT:   (local.get $ref)
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:   (local.get $used)
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (struct.new $used-in-array-fill-ok_31
  ;; CHECK-NEXT:    (ref.null none)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $array-fill-ok (param $used (ref (exact $used-in-array-fill-ok))) (param $ref (ref $array-fill-inexact))
    (array.fill $array-fill-inexact
      (local.get $ref)
      (i32.const 0)
      (local.get $used)
      (i32.const 0)
    )
    (drop
      (struct.new $used-in-array-fill-ok
        (ref.null none)
      )
    )
  )

  ;; CHECK:      (func $array-copy-ok (type $115) (param $used (ref (exact $used-in-array-copy-ok))) (param $ref (ref $array-copy-exact))
  ;; CHECK-NEXT:  (array.copy $array-copy-exact $array-copy-exact
  ;; CHECK-NEXT:   (local.get $ref)
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:   (local.get $ref)
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:   (i32.const 0)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (struct.new $used-in-array-copy-ok_32
  ;; CHECK-NEXT:    (ref.null none)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $array-copy-ok (param $used (ref (exact $used-in-array-copy-ok))) (param $ref (ref $array-copy-exact))
    ;; Even though the destination array contains exact references, the copy
    ;; instruction itself does not require any exact operands. We can still
    ;; optimize, but in practice there would be other instructions creating the
    ;; array in the first place that would inhibit optimization.
    (array.copy $array-copy-exact $array-copy-exact
      (local.get $ref)
      (i32.const 0)
      (local.get $ref)
      (i32.const 0)
      (i32.const 0)
    )
    (drop
      (struct.new $used-in-array-copy-ok
        (ref.null none)
      )
    )
  )

  ;; CHECK:      (func $func (type $116) (param $used (ref (exact $used-in-func))) (result (ref (exact $used-in-func)))
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (struct.new $used-in-func
  ;; CHECK-NEXT:    (ref.null none)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT:  (local.get $used)
  ;; CHECK-NEXT: )
  (func $func (param $used (ref (exact $used-in-func))) (result (ref (exact $used-in-func)))
    (drop
      ;; TODO: Return this directly once it is typed as exact.
      (struct.new $used-in-func
        (ref.null none)
      )
    )
    (local.get $used)
  )

  ;; CHECK:      (func $global (type $117)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (struct.new $used-in-global
  ;; CHECK-NEXT:    (ref.null none)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $global
    (drop
      ;; This optimization is inhibited even though no instruction accesses the
      ;; global. TODO: we could be more precise here.
      (struct.new $used-in-global
        (ref.null none)
      )
    )
  )

  ;; CHECK:      (func $segment (type $117)
  ;; CHECK-NEXT:  (drop
  ;; CHECK-NEXT:   (struct.new $used-in-segment
  ;; CHECK-NEXT:    (ref.null none)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $segment
    (drop
      ;; This optimization is inhibited even though no instruction accesses the
      ;; segment. TODO: we could be more precise here.
      (struct.new $used-in-segment
        (ref.null none)
      )
    )
  )
)

(module
  (rec
    ;; CHECK:      (rec
    ;; CHECK-NEXT:  (type $func (func (param (ref (exact $array)) i32)))
    (type $func (func (param (ref (exact $array)) i32)))
    ;; CHECK:       (type $array (sub (array v128)))
    (type $array (sub (array v128)))
  )
  ;; CHECK:      (type $2 (func))

  ;; CHECK:      (func $caller (type $2)
  ;; CHECK-NEXT:  (call $called
  ;; CHECK-NEXT:   (array.new_default $array
  ;; CHECK-NEXT:    (i32.const 0)
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:   (unreachable)
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $caller
    ;; This call is unreachable, but we cannot optimize here, as it would break
    ;; validation: the called function expects an exact ref to $array.
    (call $called
      (array.new_default $array
        (i32.const 0)
      )
      (unreachable)
    )
  )
  ;; CHECK:      (func $called (type $func) (param $0 (ref (exact $array))) (param $1 i32)
  ;; CHECK-NEXT:  (nop)
  ;; CHECK-NEXT: )
  (func $called (type $func) (param $0 (ref (exact $array))) (param $1 i32)
    (nop)
  )
)

