;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited.

;; Compare the normal type refining pass to the GUFA variant. Also compare to
;; -O3 -O3, that is, all the refining passes run twice, showing that GUFA can
;; outdo them all.

;; RUN: foreach %s %t wasm-opt -all --closed-world --preserve-type-order \
;; RUN:     --type-refining      -S -o - | filecheck %s --check-prefix=NRML
;; RUN: foreach %s %t wasm-opt -all --closed-world --preserve-type-order \
;; RUN:     --type-refining-gufa -S -o - | filecheck %s --check-prefix=GUFA
;; RUN: foreach %s %t wasm-opt -all --closed-world --preserve-type-order \
;; RUN:     -O3 -O3              -S -o - | filecheck %s --check-prefix=O3O3

;; A module that requires GUFA to fully optimize, as we must track type
;; information through locals etc.
;;
;; In NRML mode (normal type-refining), we can improve $A's field to nullref,
;; but can do nothing for $B.
;;
;; In GUFA mode we can also turn $B's field to (ref null $A).
;;
;; -O3 -O3 can remove the field from $A, and we can make $B's field immutable,
;; but because of the cyclic nature of the dataflow graph, iteratively running
;; separate refinement passes for globals, types, locals, etc. is not able to
;; refine the type of $B's field.
(module
  (rec
    ;; NRML:      (rec
    ;; NRML-NEXT:  (type $A (sub (struct (field (mut nullref)))))
    ;; GUFA:      (rec
    ;; GUFA-NEXT:  (type $A (sub (struct (field (mut nullref)))))
    ;; O3O3:      (rec
    ;; O3O3-NEXT:  (type $A (sub (struct)))
    (type $A (sub (struct (field (mut anyref)))))
    ;; NRML:       (type $B (sub (struct (field (mut anyref)))))
    ;; GUFA:       (type $B (sub (struct (field (mut (ref null (exact $A)))))))
    ;; O3O3:       (type $B (sub (struct (field anyref))))
    (type $B (sub (struct (field (mut anyref)))))
  )

  ;; NRML:      (type $2 (func (param i32) (result anyref)))

  ;; NRML:      (type $3 (func (param i32)))

  ;; NRML:      (global $any (mut anyref) (ref.null none))
  ;; GUFA:      (type $2 (func (param i32) (result anyref)))

  ;; GUFA:      (type $3 (func (param i32)))

  ;; GUFA:      (global $any (mut anyref) (ref.null none))
  ;; O3O3:      (type $2 (func (param i32) (result anyref)))

  ;; O3O3:      (type $3 (func (param i32)))

  ;; O3O3:      (global $any (mut structref) (ref.null none))
  (global $any (mut anyref) (ref.null any))

  ;; NRML:      (export "get_from_global" (func $get_from_global))

  ;; NRML:      (export "work" (func $work))

  ;; NRML:      (func $get_from_global (type $2) (param $x i32) (result anyref)
  ;; NRML-NEXT:  (if (result anyref)
  ;; NRML-NEXT:   (local.get $x)
  ;; NRML-NEXT:   (then
  ;; NRML-NEXT:    (struct.get $A 0
  ;; NRML-NEXT:     (ref.cast (ref $A)
  ;; NRML-NEXT:      (global.get $any)
  ;; NRML-NEXT:     )
  ;; NRML-NEXT:    )
  ;; NRML-NEXT:   )
  ;; NRML-NEXT:   (else
  ;; NRML-NEXT:    (struct.get $B 0
  ;; NRML-NEXT:     (ref.cast (ref $B)
  ;; NRML-NEXT:      (global.get $any)
  ;; NRML-NEXT:     )
  ;; NRML-NEXT:    )
  ;; NRML-NEXT:   )
  ;; NRML-NEXT:  )
  ;; NRML-NEXT: )
  ;; GUFA:      (export "get_from_global" (func $get_from_global))

  ;; GUFA:      (export "work" (func $work))

  ;; GUFA:      (func $get_from_global (type $2) (param $x i32) (result anyref)
  ;; GUFA-NEXT:  (if (result (ref null (exact $A)))
  ;; GUFA-NEXT:   (local.get $x)
  ;; GUFA-NEXT:   (then
  ;; GUFA-NEXT:    (struct.get $A 0
  ;; GUFA-NEXT:     (ref.cast (ref $A)
  ;; GUFA-NEXT:      (global.get $any)
  ;; GUFA-NEXT:     )
  ;; GUFA-NEXT:    )
  ;; GUFA-NEXT:   )
  ;; GUFA-NEXT:   (else
  ;; GUFA-NEXT:    (struct.get $B 0
  ;; GUFA-NEXT:     (ref.cast (ref $B)
  ;; GUFA-NEXT:      (global.get $any)
  ;; GUFA-NEXT:     )
  ;; GUFA-NEXT:    )
  ;; GUFA-NEXT:   )
  ;; GUFA-NEXT:  )
  ;; GUFA-NEXT: )
  ;; O3O3:      (export "get_from_global" (func $get_from_global))

  ;; O3O3:      (export "work" (func $work))

  ;; O3O3:      (func $get_from_global (type $2) (param $0 i32) (result anyref)
  ;; O3O3-NEXT:  (if (result anyref)
  ;; O3O3-NEXT:   (local.get $0)
  ;; O3O3-NEXT:   (then
  ;; O3O3-NEXT:    (drop
  ;; O3O3-NEXT:     (ref.cast (ref $A)
  ;; O3O3-NEXT:      (global.get $any)
  ;; O3O3-NEXT:     )
  ;; O3O3-NEXT:    )
  ;; O3O3-NEXT:    (ref.null none)
  ;; O3O3-NEXT:   )
  ;; O3O3-NEXT:   (else
  ;; O3O3-NEXT:    (struct.get $B 0
  ;; O3O3-NEXT:     (ref.cast (ref $B)
  ;; O3O3-NEXT:      (global.get $any)
  ;; O3O3-NEXT:     )
  ;; O3O3-NEXT:    )
  ;; O3O3-NEXT:   )
  ;; O3O3-NEXT:  )
  ;; O3O3-NEXT: )
  (func $get_from_global (export "get_from_global") (param $x i32) (result anyref)
    ;; Read from the global, casting in a way that depends on the parameter.
    ;; By storing objects in the global + having this function, we prevent -O3
    ;; from being able to trivially clear out the entire module.
    (if (result anyref)
      (local.get $x)
      (then
        (struct.get $A 0
          (ref.cast (ref $A)
            (global.get $any)
          )
        )
      )
      (else
        (struct.get $B 0
          (ref.cast (ref $B)
            (global.get $any)
          )
        )
      )
    )
  )

  ;; NRML:      (func $work (type $3) (param $x i32)
  ;; NRML-NEXT:  (local $a anyref)
  ;; NRML-NEXT:  (local $b (ref null $B))
  ;; NRML-NEXT:  (local.set $a
  ;; NRML-NEXT:   (struct.new_default $A)
  ;; NRML-NEXT:  )
  ;; NRML-NEXT:  (local.set $b
  ;; NRML-NEXT:   (struct.new $B
  ;; NRML-NEXT:    (local.get $a)
  ;; NRML-NEXT:   )
  ;; NRML-NEXT:  )
  ;; NRML-NEXT:  (local.set $b
  ;; NRML-NEXT:   (struct.new $B
  ;; NRML-NEXT:    (call $get_from_global
  ;; NRML-NEXT:     (local.get $x)
  ;; NRML-NEXT:    )
  ;; NRML-NEXT:   )
  ;; NRML-NEXT:  )
  ;; NRML-NEXT:  (if
  ;; NRML-NEXT:   (local.get $x)
  ;; NRML-NEXT:   (then
  ;; NRML-NEXT:    (global.set $any
  ;; NRML-NEXT:     (local.get $a)
  ;; NRML-NEXT:    )
  ;; NRML-NEXT:   )
  ;; NRML-NEXT:   (else
  ;; NRML-NEXT:    (global.set $any
  ;; NRML-NEXT:     (local.get $b)
  ;; NRML-NEXT:    )
  ;; NRML-NEXT:   )
  ;; NRML-NEXT:  )
  ;; NRML-NEXT: )
  ;; GUFA:      (func $work (type $3) (param $x i32)
  ;; GUFA-NEXT:  (local $a anyref)
  ;; GUFA-NEXT:  (local $b (ref null $B))
  ;; GUFA-NEXT:  (local.set $a
  ;; GUFA-NEXT:   (struct.new_default $A)
  ;; GUFA-NEXT:  )
  ;; GUFA-NEXT:  (local.set $b
  ;; GUFA-NEXT:   (struct.new $B
  ;; GUFA-NEXT:    (ref.cast (ref null (exact $A))
  ;; GUFA-NEXT:     (local.get $a)
  ;; GUFA-NEXT:    )
  ;; GUFA-NEXT:   )
  ;; GUFA-NEXT:  )
  ;; GUFA-NEXT:  (local.set $b
  ;; GUFA-NEXT:   (struct.new $B
  ;; GUFA-NEXT:    (ref.cast (ref null (exact $A))
  ;; GUFA-NEXT:     (call $get_from_global
  ;; GUFA-NEXT:      (local.get $x)
  ;; GUFA-NEXT:     )
  ;; GUFA-NEXT:    )
  ;; GUFA-NEXT:   )
  ;; GUFA-NEXT:  )
  ;; GUFA-NEXT:  (if
  ;; GUFA-NEXT:   (local.get $x)
  ;; GUFA-NEXT:   (then
  ;; GUFA-NEXT:    (global.set $any
  ;; GUFA-NEXT:     (local.get $a)
  ;; GUFA-NEXT:    )
  ;; GUFA-NEXT:   )
  ;; GUFA-NEXT:   (else
  ;; GUFA-NEXT:    (global.set $any
  ;; GUFA-NEXT:     (local.get $b)
  ;; GUFA-NEXT:    )
  ;; GUFA-NEXT:   )
  ;; GUFA-NEXT:  )
  ;; GUFA-NEXT: )
  ;; O3O3:      (func $work (type $3) (param $0 i32)
  ;; O3O3-NEXT:  (local $1 (ref (exact $B)))
  ;; O3O3-NEXT:  (local.set $1
  ;; O3O3-NEXT:   (struct.new $B
  ;; O3O3-NEXT:    (if (result anyref)
  ;; O3O3-NEXT:     (local.get $0)
  ;; O3O3-NEXT:     (then
  ;; O3O3-NEXT:      (drop
  ;; O3O3-NEXT:       (ref.cast (ref $A)
  ;; O3O3-NEXT:        (global.get $any)
  ;; O3O3-NEXT:       )
  ;; O3O3-NEXT:      )
  ;; O3O3-NEXT:      (ref.null none)
  ;; O3O3-NEXT:     )
  ;; O3O3-NEXT:     (else
  ;; O3O3-NEXT:      (struct.get $B 0
  ;; O3O3-NEXT:       (ref.cast (ref $B)
  ;; O3O3-NEXT:        (global.get $any)
  ;; O3O3-NEXT:       )
  ;; O3O3-NEXT:      )
  ;; O3O3-NEXT:     )
  ;; O3O3-NEXT:    )
  ;; O3O3-NEXT:   )
  ;; O3O3-NEXT:  )
  ;; O3O3-NEXT:  (if
  ;; O3O3-NEXT:   (local.get $0)
  ;; O3O3-NEXT:   (then
  ;; O3O3-NEXT:    (global.set $any
  ;; O3O3-NEXT:     (struct.new_default $A)
  ;; O3O3-NEXT:    )
  ;; O3O3-NEXT:   )
  ;; O3O3-NEXT:   (else
  ;; O3O3-NEXT:    (global.set $any
  ;; O3O3-NEXT:     (local.get $1)
  ;; O3O3-NEXT:    )
  ;; O3O3-NEXT:   )
  ;; O3O3-NEXT:  )
  ;; O3O3-NEXT: )
  (func $work (export "work") (param $x i32)
    (local $a anyref)
    (local $b (ref null $B))
    ;; $A's field contains null.
    (local.set $a
      (struct.new_default $A)
    )
    ;; $B's field contains a reference to $A, even though the local's type is
    ;; anyref. When we refine the field in GUFA, a cast will be added here.
    (local.set $b
      (struct.new $B
        (local.get $a)
      )
    )
    ;; Another write to $B's field, using $get_from_global, which reads from
    ;; either an $A (which always contains null) or a $B (cyclic dependency, but
    ;; in the end only an $A is written there).
    (local.set $b
      (struct.new $B
        (call $get_from_global
          (local.get $x)
        )
      )
    )
    ;; Store something in the global, so the entire program is not trivial in
    ;; the eyes of -O3.
    (if
      (local.get $x)
      (then
        (global.set $any
          (local.get $a)
        )
      )
      (else
        (global.set $any
          (local.get $b)
        )
      )
    )
  )
)

;; GUFA can infer the first global contains a $func, so the struct type's field
;; can be refined. However, doing so would require adding a cast from the
;; global's declared type (ref func) to the refined type, so that the struct.new
;; validates. (Alternatively, we would need to refine the global's type at the
;; same time we refine the struct, but this pass only refines structs.) The type
;; of the struct's field should only refine as much as is valid, which is the
;; type of the global, (ref func), and not the declared type $func. Both GUFA
;; and normal type refining succeed here (-O3 removes the entire module, and is
;; not interesting here).
(module
  ;; NRML:      (rec
  ;; NRML-NEXT:  (type $struct (struct (field (ref func))))
  ;; GUFA:      (rec
  ;; GUFA-NEXT:  (type $struct (struct (field (ref func))))
  (type $struct (struct (field funcref)))

  ;; NRML:       (type $func (func))
  ;; GUFA:       (type $func (func))
  (type $func (func))

  ;; NRML:      (global $A (ref func) (ref.func $func))
  ;; GUFA:      (global $A (ref func) (ref.func $func))
  (global $A (ref func) (ref.func $func))

  ;; NRML:      (global $B (ref $struct) (struct.new $struct
  ;; NRML-NEXT:  (global.get $A)
  ;; NRML-NEXT: ))
  ;; GUFA:      (global $B (ref $struct) (struct.new $struct
  ;; GUFA-NEXT:  (global.get $A)
  ;; GUFA-NEXT: ))
  (global $B (ref $struct) (struct.new $struct
    (global.get $A)
  ))

  ;; NRML:      (func $func (type $func)
  ;; NRML-NEXT: )
  ;; GUFA:      (func $func (type $func)
  ;; GUFA-NEXT: )
  (func $func (type $func)
  )
)

;; As above, but now the global has a refined type, so we can refine fully.
(module
  ;; NRML:      (rec
  ;; NRML-NEXT:  (type $struct (struct (field (ref $func))))
  ;; GUFA:      (rec
  ;; GUFA-NEXT:  (type $struct (struct (field (ref $func))))
  (type $struct (struct (field funcref)))

  ;; NRML:       (type $func (func))
  ;; GUFA:       (type $func (func))
  (type $func (func))

  ;; NRML:      (global $A (ref $func) (ref.func $func))
  ;; GUFA:      (global $A (ref $func) (ref.func $func))
  (global $A (ref $func) (ref.func $func))  ;; the type here changed

  ;; NRML:      (global $B (ref $struct) (struct.new $struct
  ;; NRML-NEXT:  (global.get $A)
  ;; NRML-NEXT: ))
  ;; GUFA:      (global $B (ref $struct) (struct.new $struct
  ;; GUFA-NEXT:  (global.get $A)
  ;; GUFA-NEXT: ))
  (global $B (ref $struct) (struct.new $struct
    (global.get $A)
  ))

  ;; NRML:      (func $func (type $func)
  ;; NRML-NEXT: )
  ;; GUFA:      (func $func (type $func)
  ;; GUFA-NEXT: )
  (func $func (type $func)
  )
)

;; Check we do not error on struct.new_default in a global. Here we can refine
;; the field to nullref.
(module
  ;; NRML:      (type $struct (struct (field nullfuncref)))
  ;; GUFA:      (type $struct (struct (field nullfuncref)))
  (type $struct (struct (field funcref)))

  ;; NRML:      (global $C (ref $struct) (struct.new_default $struct))
  ;; GUFA:      (global $C (ref $struct) (struct.new_default $struct))
  (global $C (ref $struct) (struct.new_default $struct))
)

;; As above, but $struct has a supertype. We must propagate restrictions on it
;; to its supertype. After doing so, we can refine the field to (ref func) in
;; both, but no further, because of the restriction of global.get $A, which has
;; that type.
(module
  (rec
    ;; NRML:      (rec
    ;; NRML-NEXT:  (type $super (sub (struct (field (ref func)))))
    ;; GUFA:      (rec
    ;; GUFA-NEXT:  (type $super (sub (struct (field (ref func)))))
    (type $super (sub (struct (field funcref))))
    ;; NRML:       (type $struct (sub $super (struct (field (ref func)))))
    ;; GUFA:       (type $struct (sub $super (struct (field (ref func)))))
    (type $struct (sub $super (struct (field funcref))))
  )

  ;; NRML:       (type $func (func))
  ;; GUFA:       (type $func (func))
  (type $func (func))

  ;; NRML:      (global $A (ref func) (ref.func $func))
  ;; GUFA:      (global $A (ref func) (ref.func $func))
  (global $A (ref func) (ref.func $func))

  ;; NRML:      (global $B (ref $struct) (struct.new $struct
  ;; NRML-NEXT:  (global.get $A)
  ;; NRML-NEXT: ))
  ;; GUFA:      (global $B (ref $struct) (struct.new $struct
  ;; GUFA-NEXT:  (global.get $A)
  ;; GUFA-NEXT: ))
  (global $B (ref $struct) (struct.new $struct
    (global.get $A)
  ))

  ;; NRML:      (func $func (type $func)
  ;; NRML-NEXT: )
  ;; GUFA:      (func $func (type $func)
  ;; GUFA-NEXT: )
  (func $func (type $func)
  )
)

;; Regression test for an assertion failure on packed data reads from null
;; references.
(module
 (type $i8 (struct (field i8)))

 ;; NRML:      (type $0 (func (param (ref none)) (result i32)))

 ;; NRML:      (table $0 1 funcref)
 ;; GUFA:      (type $0 (func (param (ref none)) (result i32)))

 ;; GUFA:      (table $0 1 funcref)
 ;; O3O3:      (type $0 (func (param (ref none)) (result i32)))

 ;; O3O3:      (table $0 1 funcref)
 (table $0 1 funcref)
 ;; NRML:      (elem $0 (i32.const 0) $test)
 ;; GUFA:      (elem $0 (i32.const 0) $test)
 ;; O3O3:      (elem $0 (i32.const 0) $test)
 (elem $0 (i32.const 0) $test)

 ;; NRML:      (export "table" (table $0))
 ;; GUFA:      (export "table" (table $0))
 ;; O3O3:      (export "table" (table $0))
 (export "table" (table $0))

 ;; NRML:      (func $test (type $0) (param $i8 (ref none)) (result i32)
 ;; NRML-NEXT:  (block ;; (replaces unreachable StructGet we can't emit)
 ;; NRML-NEXT:   (drop
 ;; NRML-NEXT:    (local.get $i8)
 ;; NRML-NEXT:   )
 ;; NRML-NEXT:   (unreachable)
 ;; NRML-NEXT:  )
 ;; NRML-NEXT: )
 ;; GUFA:      (func $test (type $0) (param $i8 (ref none)) (result i32)
 ;; GUFA-NEXT:  (block ;; (replaces unreachable StructGet we can't emit)
 ;; GUFA-NEXT:   (drop
 ;; GUFA-NEXT:    (local.get $i8)
 ;; GUFA-NEXT:   )
 ;; GUFA-NEXT:   (unreachable)
 ;; GUFA-NEXT:  )
 ;; GUFA-NEXT: )
 ;; O3O3:      (func $test (type $0) (param $0 (ref none)) (result i32)
 ;; O3O3-NEXT:  (unreachable)
 ;; O3O3-NEXT: )
 (func $test (param $i8 (ref none)) (result i32)
  (struct.get_s $i8 0
   (local.get $i8)
  )
 )
)

;; $wrap-cont has a continuation field, a type which we must not modify. There
;; are other optimization opportunities in the module ($wrap-array's field can
;; become exact), so we end up optimizing here. While doing so, we must not
;; change the continuation type (due to cast limitations), and we must not get
;; confused and think there is no value in that field because of that
;; restriction (if we did, the outer struct.get in $a would trap, as it would be
;; reading from a place nothing was written to, so it would need to be
;; unreachable).
(module
 ;; NRML:      (type $func (func))
 ;; GUFA:      (type $func (func))
 ;; O3O3:      (type $func (func))
 (type $func (func))
 (rec
  ;; NRML:      (rec
  ;; NRML-NEXT:  (type $cont (cont $func))
  ;; GUFA:      (rec
  ;; GUFA-NEXT:  (type $cont (cont $func))
  ;; O3O3:      (rec
  ;; O3O3-NEXT:  (type $cont (cont $func))
  (type $cont (cont $func))
  ;; NRML:       (type $wrap-cont (struct (field (ref $cont))))
  ;; GUFA:       (type $wrap-cont (struct (field (ref $cont))))
  ;; O3O3:       (type $wrap-cont (struct (field (ref $cont))))
  (type $wrap-cont (struct (field (ref $cont))))
 )
 ;; NRML:      (rec
 ;; NRML-NEXT:  (type $array (array i32))
 ;; GUFA:      (rec
 ;; GUFA-NEXT:  (type $array (array i32))
 (type $array (array i32))
 ;; NRML:       (type $wrap-array (sub (struct (field (ref (exact $array))))))
 ;; GUFA:       (type $wrap-array (sub (struct (field (ref (exact $array))))))
 (type $wrap-array (sub (struct (field (ref $array)))))

 ;; NRML:      (type $5 (func (result (ref $cont))))

 ;; NRML:      (elem declare func $ref)

 ;; NRML:      (export "a" (func $a))
 ;; GUFA:      (type $5 (func (result (ref $cont))))

 ;; GUFA:      (elem declare func $ref)

 ;; GUFA:      (export "a" (func $a))
 ;; O3O3:      (type $3 (func (result (ref $cont))))

 ;; O3O3:      (export "a" (func $a))
 (export "a" (func $a))
 ;; NRML:      (export "b" (func $b))
 ;; GUFA:      (export "b" (func $b))
 ;; O3O3:      (export "b" (func $b))
 (export "b" (func $b))

 ;; NRML:      (func $a (type $func)
 ;; NRML-NEXT:  (drop
 ;; NRML-NEXT:   (struct.get $wrap-cont 0
 ;; NRML-NEXT:    (struct.new $wrap-cont
 ;; NRML-NEXT:     (cont.new $cont
 ;; NRML-NEXT:      (ref.func $ref)
 ;; NRML-NEXT:     )
 ;; NRML-NEXT:    )
 ;; NRML-NEXT:   )
 ;; NRML-NEXT:  )
 ;; NRML-NEXT: )
 ;; GUFA:      (func $a (type $func)
 ;; GUFA-NEXT:  (drop
 ;; GUFA-NEXT:   (struct.get $wrap-cont 0
 ;; GUFA-NEXT:    (struct.new $wrap-cont
 ;; GUFA-NEXT:     (cont.new $cont
 ;; GUFA-NEXT:      (ref.func $ref)
 ;; GUFA-NEXT:     )
 ;; GUFA-NEXT:    )
 ;; GUFA-NEXT:   )
 ;; GUFA-NEXT:  )
 ;; GUFA-NEXT: )
 ;; O3O3:      (func $a (type $func)
 ;; O3O3-NEXT:  (nop)
 ;; O3O3-NEXT: )
 (func $a
  ;; GUFA cannot improve things here (-O3 can remove everything, though).
  (drop
   (struct.get $wrap-cont 0
    (struct.new $wrap-cont
     (cont.new $cont
      (ref.func $ref)
     )
    )
   )
  )
 )

 ;; NRML:      (func $b (type $5) (result (ref $cont))
 ;; NRML-NEXT:  (unreachable)
 ;; NRML-NEXT: )
 ;; GUFA:      (func $b (type $5) (result (ref $cont))
 ;; GUFA-NEXT:  (unreachable)
 ;; GUFA-NEXT: )
 ;; O3O3:      (func $b (type $3) (result (ref $cont))
 ;; O3O3-NEXT:  (unreachable)
 ;; O3O3-NEXT: )
 (func $b (result (ref $cont))
  (unreachable)
 )

 ;; NRML:      (func $ref (type $func)
 ;; NRML-NEXT:  (drop
 ;; NRML-NEXT:   (struct.new $wrap-array
 ;; NRML-NEXT:    (array.new_default $array
 ;; NRML-NEXT:     (i32.const 0)
 ;; NRML-NEXT:    )
 ;; NRML-NEXT:   )
 ;; NRML-NEXT:  )
 ;; NRML-NEXT: )
 ;; GUFA:      (func $ref (type $func)
 ;; GUFA-NEXT:  (drop
 ;; GUFA-NEXT:   (struct.new $wrap-array
 ;; GUFA-NEXT:    (array.new_default $array
 ;; GUFA-NEXT:     (i32.const 0)
 ;; GUFA-NEXT:    )
 ;; GUFA-NEXT:   )
 ;; GUFA-NEXT:  )
 ;; GUFA-NEXT: )
 (func $ref (type $func)
  (drop
   (struct.new $wrap-array
    (array.new_default $array
     (i32.const 0)
    )
   )
  )
 )
)

