blob: 0eeb4dee870f4860cfa008838fab8219587d916d [file] [edit]
;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited.
;; RUN: wasm-opt %s -all --optimize-level=3 --generate-stack-ir --optimize-stack-ir --print-stack-ir | filecheck %s
;; Also test with roundtrip to verify that parsing does not undo this
;; optimization.
;; RUN: wasm-opt %s -all --optimize-level=3 --generate-stack-ir --optimize-stack-ir --roundtrip --print-stack-ir | filecheck %s --check-prefix=ROUNDTRIP
(module
;; CHECK: (type $0 (func (result i32 f64 anyref)))
;; CHECK: (type $1 (func (param f64) (result i32 f64 anyref)))
;; CHECK: (type $2 (func (param i32 f64 anyref)))
;; CHECK: (type $3 (func (result i32 f64)))
;; CHECK: (type $4 (func (result i32 f64 anyref eqref)))
;; CHECK: (type $5 (func (result i32 f64 anyref anyref)))
;; CHECK: (type $6 (func (param f64) (result i32 anyref anyref)))
;; CHECK: (func $multivalue-return (type $0) (result i32 f64 anyref)
;; CHECK-NEXT: (local $temp (tuple i32 f64 anyref))
;; CHECK-NEXT: call $multivalue-return
;; CHECK-NEXT: tuple.make 3
;; CHECK-NEXT: )
;; ROUNDTRIP: (type $0 (func (result i32 f64 anyref)))
;; ROUNDTRIP: (type $1 (func (param f64) (result i32 f64 anyref)))
;; ROUNDTRIP: (type $2 (func (param i32 f64 anyref)))
;; ROUNDTRIP: (type $3 (func (result i32 f64)))
;; ROUNDTRIP: (type $4 (func (result i32 f64 anyref eqref)))
;; ROUNDTRIP: (type $5 (func (result i32 f64 anyref anyref)))
;; ROUNDTRIP: (type $6 (func (param f64) (result i32 anyref anyref)))
;; ROUNDTRIP: (func $multivalue-return (type $0) (result i32 f64 anyref)
;; ROUNDTRIP-NEXT: (local $temp i32)
;; ROUNDTRIP-NEXT: (local $1 f64)
;; ROUNDTRIP-NEXT: (local $2 anyref)
;; ROUNDTRIP-NEXT: call $multivalue-return
;; ROUNDTRIP-NEXT: )
(func $multivalue-return (result i32 f64 anyref)
(local $temp (tuple i32 f64 anyref))
;; We can remove all these tuple operations after optiming and
;; roundtripping (though a few locals will be added in roundtripping FIXME).
(tuple.make 3
(tuple.extract 3 0
(local.tee $temp
(call $multivalue-return)
)
)
(tuple.extract 3 1
(local.get $temp)
)
(tuple.extract 3 2
(local.get $temp)
)
)
)
;; CHECK: (func $multivalue-return-too-short (type $3) (result i32 f64)
;; CHECK-NEXT: (local $temp (tuple i32 f64 anyref))
;; CHECK-NEXT: call $multivalue-return
;; CHECK-NEXT: local.tee $temp
;; CHECK-NEXT: tuple.extract 3 0
;; CHECK-NEXT: local.get $temp
;; CHECK-NEXT: tuple.extract 3 1
;; CHECK-NEXT: tuple.make 2
;; CHECK-NEXT: )
;; ROUNDTRIP: (func $multivalue-return-too-short (type $3) (result i32 f64)
;; ROUNDTRIP-NEXT: (local $temp i32)
;; ROUNDTRIP-NEXT: (local $1 f64)
;; ROUNDTRIP-NEXT: (local $2 anyref)
;; ROUNDTRIP-NEXT: (local $scratch (tuple i32 f64 anyref))
;; ROUNDTRIP-NEXT: (local $scratch_4 f64)
;; ROUNDTRIP-NEXT: (local $scratch_5 i32)
;; ROUNDTRIP-NEXT: call $multivalue-return
;; ROUNDTRIP-NEXT: local.tee $scratch
;; ROUNDTRIP-NEXT: tuple.extract 3 0
;; ROUNDTRIP-NEXT: local.get $scratch
;; ROUNDTRIP-NEXT: tuple.extract 3 1
;; ROUNDTRIP-NEXT: local.get $scratch
;; ROUNDTRIP-NEXT: tuple.extract 3 2
;; ROUNDTRIP-NEXT: local.set $2
;; ROUNDTRIP-NEXT: local.set $1
;; ROUNDTRIP-NEXT: local.tee $temp
;; ROUNDTRIP-NEXT: local.get $1
;; ROUNDTRIP-NEXT: tuple.make 2
;; ROUNDTRIP-NEXT: )
(func $multivalue-return-too-short (result i32 f64)
(local $temp (tuple i32 f64 anyref))
;; As above, but we only return 2 of the tuple's 3 items (i.e., we are too
;; short to fit the pattern), so we do not optimize here.
(tuple.make 2
(tuple.extract 3 0
(local.tee $temp
(call $multivalue-return)
)
)
(tuple.extract 3 1
(local.get $temp)
)
)
)
;; CHECK: (func $multivalue-return-extra (type $4) (result i32 f64 anyref eqref)
;; CHECK-NEXT: (local $temp (tuple i32 f64 anyref))
;; CHECK-NEXT: call $multivalue-return
;; CHECK-NEXT: ref.null none
;; CHECK-NEXT: tuple.make 4
;; CHECK-NEXT: )
;; ROUNDTRIP: (func $multivalue-return-extra (type $4) (result i32 f64 anyref eqref)
;; ROUNDTRIP-NEXT: (local $temp i32)
;; ROUNDTRIP-NEXT: (local $1 f64)
;; ROUNDTRIP-NEXT: (local $2 anyref)
;; ROUNDTRIP-NEXT: (local $scratch (tuple i32 f64 anyref))
;; ROUNDTRIP-NEXT: call $multivalue-return
;; ROUNDTRIP-NEXT: ref.null none
;; ROUNDTRIP-NEXT: tuple.make 4
;; ROUNDTRIP-NEXT: )
(func $multivalue-return-extra (result i32 f64 anyref eqref)
(local $temp (tuple i32 f64 anyref))
;; As above, but we add an item to the tuple. We can optimize here.
(tuple.make 4
(tuple.extract 3 0
(local.tee $temp
(call $multivalue-return)
)
)
(tuple.extract 3 1
(local.get $temp)
)
(tuple.extract 3 2
(local.get $temp)
)
(ref.null eq)
)
)
;; CHECK: (func $multivalue-return-extra-middle (type $5) (result i32 f64 anyref anyref)
;; CHECK-NEXT: (local $temp (tuple i32 f64 anyref))
;; CHECK-NEXT: call $multivalue-return
;; CHECK-NEXT: local.tee $temp
;; CHECK-NEXT: tuple.extract 3 0
;; CHECK-NEXT: local.get $temp
;; CHECK-NEXT: tuple.extract 3 1
;; CHECK-NEXT: ref.null none
;; CHECK-NEXT: local.get $temp
;; CHECK-NEXT: tuple.extract 3 2
;; CHECK-NEXT: tuple.make 4
;; CHECK-NEXT: )
;; ROUNDTRIP: (func $multivalue-return-extra-middle (type $5) (result i32 f64 anyref anyref)
;; ROUNDTRIP-NEXT: (local $temp i32)
;; ROUNDTRIP-NEXT: (local $1 f64)
;; ROUNDTRIP-NEXT: (local $2 anyref)
;; ROUNDTRIP-NEXT: (local $scratch (tuple i32 f64 anyref))
;; ROUNDTRIP-NEXT: (local $scratch_4 f64)
;; ROUNDTRIP-NEXT: (local $scratch_5 i32)
;; ROUNDTRIP-NEXT: call $multivalue-return
;; ROUNDTRIP-NEXT: local.tee $scratch
;; ROUNDTRIP-NEXT: tuple.extract 3 0
;; ROUNDTRIP-NEXT: local.get $scratch
;; ROUNDTRIP-NEXT: tuple.extract 3 1
;; ROUNDTRIP-NEXT: local.get $scratch
;; ROUNDTRIP-NEXT: tuple.extract 3 2
;; ROUNDTRIP-NEXT: local.set $2
;; ROUNDTRIP-NEXT: local.set $1
;; ROUNDTRIP-NEXT: local.tee $temp
;; ROUNDTRIP-NEXT: local.get $1
;; ROUNDTRIP-NEXT: ref.null none
;; ROUNDTRIP-NEXT: local.get $2
;; ROUNDTRIP-NEXT: tuple.make 4
;; ROUNDTRIP-NEXT: )
(func $multivalue-return-extra-middle (result i32 f64 anyref anyref)
(local $temp (tuple i32 f64 anyref))
;; As the last case, but the extra item is in the middle. We cannot
;; optimize.
(tuple.make 4
(tuple.extract 3 0
(local.tee $temp
(call $multivalue-return)
)
)
(tuple.extract 3 1
(local.get $temp)
)
(ref.null eq)
(tuple.extract 3 2
(local.get $temp)
)
)
)
;; CHECK: (func $multivalue-return-bad-get (type $1) (param $other f64) (result i32 f64 anyref)
;; CHECK-NEXT: (local $temp (tuple i32 f64 anyref))
;; CHECK-NEXT: call $multivalue-return
;; CHECK-NEXT: local.tee $temp
;; CHECK-NEXT: tuple.extract 3 0
;; CHECK-NEXT: local.get $other
;; CHECK-NEXT: local.get $temp
;; CHECK-NEXT: tuple.extract 3 2
;; CHECK-NEXT: tuple.make 3
;; CHECK-NEXT: )
;; ROUNDTRIP: (func $multivalue-return-bad-get (type $1) (param $other f64) (result i32 f64 anyref)
;; ROUNDTRIP-NEXT: (local $temp i32)
;; ROUNDTRIP-NEXT: (local $2 f64)
;; ROUNDTRIP-NEXT: (local $3 anyref)
;; ROUNDTRIP-NEXT: (local $scratch (tuple i32 f64 anyref))
;; ROUNDTRIP-NEXT: (local $scratch_5 f64)
;; ROUNDTRIP-NEXT: (local $scratch_6 i32)
;; ROUNDTRIP-NEXT: call $multivalue-return
;; ROUNDTRIP-NEXT: local.tee $scratch
;; ROUNDTRIP-NEXT: tuple.extract 3 0
;; ROUNDTRIP-NEXT: local.get $scratch
;; ROUNDTRIP-NEXT: tuple.extract 3 1
;; ROUNDTRIP-NEXT: local.get $scratch
;; ROUNDTRIP-NEXT: tuple.extract 3 2
;; ROUNDTRIP-NEXT: local.set $3
;; ROUNDTRIP-NEXT: local.set $2
;; ROUNDTRIP-NEXT: local.tee $temp
;; ROUNDTRIP-NEXT: local.get $other
;; ROUNDTRIP-NEXT: local.get $3
;; ROUNDTRIP-NEXT: tuple.make 3
;; ROUNDTRIP-NEXT: )
(func $multivalue-return-bad-get (param $other f64) (result i32 f64 anyref)
(local $temp (tuple i32 f64 anyref))
;; As the first case, but one get has the wrong index, so we do
;; not optimize.
(tuple.make 3
(tuple.extract 3 0
(local.tee $temp
(call $multivalue-return)
)
)
(local.get $other) ;; this changed
(tuple.extract 3 2
(local.get $temp)
)
)
)
;; CHECK: (func $multivalue-return-non-get (type $0) (result i32 f64 anyref)
;; CHECK-NEXT: (local $temp (tuple i32 f64 anyref))
;; CHECK-NEXT: call $multivalue-return
;; CHECK-NEXT: local.tee $temp
;; CHECK-NEXT: tuple.extract 3 0
;; CHECK-NEXT: local.get $temp
;; CHECK-NEXT: tuple.extract 3 1
;; CHECK-NEXT: local.get $temp
;; CHECK-NEXT: tuple.extract 3 2
;; CHECK-NEXT: tuple.make 3
;; CHECK-NEXT: )
;; ROUNDTRIP: (func $multivalue-return-non-get (type $0) (result i32 f64 anyref)
;; ROUNDTRIP-NEXT: (local $temp i32)
;; ROUNDTRIP-NEXT: (local $1 f64)
;; ROUNDTRIP-NEXT: (local $2 anyref)
;; ROUNDTRIP-NEXT: (local $scratch (tuple i32 f64 anyref))
;; ROUNDTRIP-NEXT: (local $scratch_4 f64)
;; ROUNDTRIP-NEXT: (local $scratch_5 i32)
;; ROUNDTRIP-NEXT: call $multivalue-return
;; ROUNDTRIP-NEXT: local.tee $scratch
;; ROUNDTRIP-NEXT: tuple.extract 3 0
;; ROUNDTRIP-NEXT: local.get $scratch
;; ROUNDTRIP-NEXT: tuple.extract 3 1
;; ROUNDTRIP-NEXT: local.get $scratch
;; ROUNDTRIP-NEXT: tuple.extract 3 2
;; ROUNDTRIP-NEXT: local.set $2
;; ROUNDTRIP-NEXT: local.set $1
;; ROUNDTRIP-NEXT: local.tee $temp
;; ROUNDTRIP-NEXT: local.get $1
;; ROUNDTRIP-NEXT: local.get $2
;; ROUNDTRIP-NEXT: tuple.make 3
;; ROUNDTRIP-NEXT: )
(func $multivalue-return-non-get (result i32 f64 anyref)
(local $temp (tuple i32 f64 anyref))
;; As the first case, but one get is replaced by a non-get, so we do
;; not optimize.
(tuple.make 3
(tuple.extract 3 0
(local.tee $temp
(call $multivalue-return)
)
)
(tuple.extract 3 1
(nop) ;; this breaks the pattern, appearing where the get
;; should be
(local.get $temp)
)
(tuple.extract 3 2
(local.get $temp)
)
)
)
;; CHECK: (func $multivalue-return-bad-extract (type $6) (param $other f64) (result i32 anyref anyref)
;; CHECK-NEXT: (local $temp (tuple i32 f64 anyref))
;; CHECK-NEXT: call $multivalue-return
;; CHECK-NEXT: local.tee $temp
;; CHECK-NEXT: tuple.extract 3 0
;; CHECK-NEXT: local.get $temp
;; CHECK-NEXT: tuple.extract 3 2
;; CHECK-NEXT: local.get $temp
;; CHECK-NEXT: tuple.extract 3 2
;; CHECK-NEXT: tuple.make 3
;; CHECK-NEXT: )
;; ROUNDTRIP: (func $multivalue-return-bad-extract (type $6) (param $other f64) (result i32 anyref anyref)
;; ROUNDTRIP-NEXT: (local $temp i32)
;; ROUNDTRIP-NEXT: (local $2 f64)
;; ROUNDTRIP-NEXT: (local $3 anyref)
;; ROUNDTRIP-NEXT: (local $scratch (tuple i32 f64 anyref))
;; ROUNDTRIP-NEXT: (local $scratch_5 f64)
;; ROUNDTRIP-NEXT: (local $scratch_6 i32)
;; ROUNDTRIP-NEXT: call $multivalue-return
;; ROUNDTRIP-NEXT: local.tee $scratch
;; ROUNDTRIP-NEXT: tuple.extract 3 0
;; ROUNDTRIP-NEXT: local.get $scratch
;; ROUNDTRIP-NEXT: tuple.extract 3 1
;; ROUNDTRIP-NEXT: local.get $scratch
;; ROUNDTRIP-NEXT: tuple.extract 3 2
;; ROUNDTRIP-NEXT: local.set $3
;; ROUNDTRIP-NEXT: local.set $2
;; ROUNDTRIP-NEXT: local.tee $temp
;; ROUNDTRIP-NEXT: local.get $3
;; ROUNDTRIP-NEXT: local.get $3
;; ROUNDTRIP-NEXT: tuple.make 3
;; ROUNDTRIP-NEXT: )
(func $multivalue-return-bad-extract (param $other f64) (result i32 anyref anyref)
(local $temp (tuple i32 f64 anyref))
;; As the first case, but one extract has the wrong index, so we
;; do not optimize.
(tuple.make 3
(tuple.extract 3 0
(local.tee $temp
(call $multivalue-return)
)
)
(tuple.extract 3 2 ;; this changed from 1 to 2
(local.get $temp)
)
(tuple.extract 3 2
(local.get $temp)
)
)
)
;; CHECK: (func $multivalue-return-non-extract (type $1) (param $other f64) (result i32 f64 anyref)
;; CHECK-NEXT: (local $temp (tuple i32 f64 anyref))
;; CHECK-NEXT: (local $scratch (tuple i32 f64 anyref))
;; CHECK-NEXT: call $multivalue-return
;; CHECK-NEXT: local.tee $temp
;; CHECK-NEXT: tuple.extract 3 0
;; CHECK-NEXT: local.get $temp
;; CHECK-NEXT: local.set $scratch
;; CHECK-NEXT: local.get $scratch
;; CHECK-NEXT: tuple.extract 3 1
;; CHECK-NEXT: local.get $temp
;; CHECK-NEXT: tuple.extract 3 2
;; CHECK-NEXT: tuple.make 3
;; CHECK-NEXT: )
;; ROUNDTRIP: (func $multivalue-return-non-extract (type $1) (param $other f64) (result i32 f64 anyref)
;; ROUNDTRIP-NEXT: (local $temp i32)
;; ROUNDTRIP-NEXT: (local $scratch i32)
;; ROUNDTRIP-NEXT: (local $3 f64)
;; ROUNDTRIP-NEXT: (local $4 f64)
;; ROUNDTRIP-NEXT: (local $5 f64)
;; ROUNDTRIP-NEXT: (local $6 anyref)
;; ROUNDTRIP-NEXT: (local $7 anyref)
;; ROUNDTRIP-NEXT: (local $scratch_8 (tuple i32 f64 anyref))
;; ROUNDTRIP-NEXT: (local $scratch_9 f64)
;; ROUNDTRIP-NEXT: (local $scratch_10 i32)
;; ROUNDTRIP-NEXT: (local $scratch_11 f64)
;; ROUNDTRIP-NEXT: (local $scratch_12 i32)
;; ROUNDTRIP-NEXT: (local $scratch_13 f64)
;; ROUNDTRIP-NEXT: (local $scratch_14 i32)
;; ROUNDTRIP-NEXT: call $multivalue-return
;; ROUNDTRIP-NEXT: local.tee $scratch_8
;; ROUNDTRIP-NEXT: tuple.extract 3 0
;; ROUNDTRIP-NEXT: local.get $scratch_8
;; ROUNDTRIP-NEXT: tuple.extract 3 1
;; ROUNDTRIP-NEXT: local.get $scratch_8
;; ROUNDTRIP-NEXT: tuple.extract 3 2
;; ROUNDTRIP-NEXT: local.set $6
;; ROUNDTRIP-NEXT: local.set $3
;; ROUNDTRIP-NEXT: local.tee $temp
;; ROUNDTRIP-NEXT: local.get $temp
;; ROUNDTRIP-NEXT: local.get $3
;; ROUNDTRIP-NEXT: local.get $6
;; ROUNDTRIP-NEXT: local.set $7
;; ROUNDTRIP-NEXT: local.set $4
;; ROUNDTRIP-NEXT: local.get $4
;; ROUNDTRIP-NEXT: local.get $7
;; ROUNDTRIP-NEXT: drop
;; ROUNDTRIP-NEXT: local.set $5
;; ROUNDTRIP-NEXT: drop
;; ROUNDTRIP-NEXT: local.get $5
;; ROUNDTRIP-NEXT: local.get $6
;; ROUNDTRIP-NEXT: tuple.make 3
;; ROUNDTRIP-NEXT: )
(func $multivalue-return-non-extract (param $other f64) (result i32 f64 anyref)
(local $temp (tuple i32 f64 anyref))
;; As the first case, but one extract is replaced with something else, so we
;; do not optimize.
(tuple.make 3
(tuple.extract 3 0
(local.tee $temp
(call $multivalue-return)
)
)
(tuple.extract 3 1
(local.get $temp)
(nop) ;; this breaks the pattern, appearing where the tuple.extract
;; should be
)
(tuple.extract 3 2
(local.get $temp)
)
)
)
;; CHECK: (func $multiple-multivalue-return (type $2) (param $0 i32) (param $1 f64) (param $2 anyref)
;; CHECK-NEXT: (local $temp3 (tuple i32 f64 anyref))
;; CHECK-NEXT: (local $temp2 (tuple i32 f64))
;; CHECK-NEXT: call $multivalue-return
;; CHECK-NEXT: call $multiple-multivalue-return
;; CHECK-NEXT: call $multivalue-return-too-short
;; CHECK-NEXT: ref.null none
;; CHECK-NEXT: call $multiple-multivalue-return
;; CHECK-NEXT: call $multivalue-return
;; CHECK-NEXT: call $multiple-multivalue-return
;; CHECK-NEXT: )
;; ROUNDTRIP: (func $multiple-multivalue-return (type $2) (param $0 i32) (param $1 f64) (param $2 anyref)
;; ROUNDTRIP-NEXT: (local $temp3 i32)
;; ROUNDTRIP-NEXT: (local $temp2 i32)
;; ROUNDTRIP-NEXT: (local $5 f64)
;; ROUNDTRIP-NEXT: (local $6 f64)
;; ROUNDTRIP-NEXT: (local $7 anyref)
;; ROUNDTRIP-NEXT: (local $scratch (tuple i32 f64 anyref))
;; ROUNDTRIP-NEXT: (local $scratch_9 (tuple i32 f64))
;; ROUNDTRIP-NEXT: (local $scratch_10 (tuple i32 f64 anyref))
;; ROUNDTRIP-NEXT: call $multivalue-return
;; ROUNDTRIP-NEXT: call $multiple-multivalue-return
;; ROUNDTRIP-NEXT: call $multivalue-return-too-short
;; ROUNDTRIP-NEXT: ref.null none
;; ROUNDTRIP-NEXT: call $multiple-multivalue-return
;; ROUNDTRIP-NEXT: call $multivalue-return
;; ROUNDTRIP-NEXT: call $multiple-multivalue-return
;; ROUNDTRIP-NEXT: )
(func $multiple-multivalue-return (param i32 f64 anyref)
(local $temp3 (tuple i32 f64 anyref))
(local $temp2 (tuple i32 f64))
;; Multiple optimizations in one function, including a case where we reuse
;; the local index.
(call $multiple-multivalue-return
(tuple.extract 3 0
(local.tee $temp3
(call $multivalue-return)
)
)
(tuple.extract 3 1
(local.get $temp3)
)
(tuple.extract 3 2
(local.get $temp3)
)
)
(call $multiple-multivalue-return
(tuple.extract 2 0
(local.tee $temp2
(call $multivalue-return-too-short)
)
)
(tuple.extract 2 1
(local.get $temp2)
)
(ref.null any)
)
(call $multiple-multivalue-return
(tuple.extract 3 0
(local.tee $temp3
(call $multivalue-return)
)
)
(tuple.extract 3 1
(local.get $temp3)
)
(tuple.extract 3 2
(local.get $temp3)
)
)
)
;; CHECK: (func $multiple-multivalue-return-local-reuse (type $2) (param $0 i32) (param $1 f64) (param $2 anyref)
;; CHECK-NEXT: (local $temp3 (tuple i32 f64 anyref))
;; CHECK-NEXT: (local $temp2 (tuple i32 f64))
;; CHECK-NEXT: call $multivalue-return
;; CHECK-NEXT: local.tee $temp3
;; CHECK-NEXT: tuple.extract 3 0
;; CHECK-NEXT: local.get $temp3
;; CHECK-NEXT: tuple.extract 3 1
;; CHECK-NEXT: local.get $temp3
;; CHECK-NEXT: tuple.extract 3 2
;; CHECK-NEXT: call $multiple-multivalue-return
;; CHECK-NEXT: local.get $temp3
;; CHECK-NEXT: tuple.extract 3 0
;; CHECK-NEXT: local.get $temp3
;; CHECK-NEXT: tuple.extract 3 1
;; CHECK-NEXT: local.get $temp3
;; CHECK-NEXT: tuple.extract 3 2
;; CHECK-NEXT: call $multiple-multivalue-return
;; CHECK-NEXT: )
;; ROUNDTRIP: (func $multiple-multivalue-return-local-reuse (type $2) (param $0 i32) (param $1 f64) (param $2 anyref)
;; ROUNDTRIP-NEXT: (local $temp3 i32)
;; ROUNDTRIP-NEXT: (local $temp2 i32)
;; ROUNDTRIP-NEXT: (local $5 f64)
;; ROUNDTRIP-NEXT: (local $6 f64)
;; ROUNDTRIP-NEXT: (local $7 anyref)
;; ROUNDTRIP-NEXT: (local $scratch (tuple i32 f64 anyref))
;; ROUNDTRIP-NEXT: (local $scratch_9 f64)
;; ROUNDTRIP-NEXT: (local $scratch_10 i32)
;; ROUNDTRIP-NEXT: call $multivalue-return
;; ROUNDTRIP-NEXT: local.tee $scratch
;; ROUNDTRIP-NEXT: tuple.extract 3 0
;; ROUNDTRIP-NEXT: local.get $scratch
;; ROUNDTRIP-NEXT: tuple.extract 3 1
;; ROUNDTRIP-NEXT: local.get $scratch
;; ROUNDTRIP-NEXT: tuple.extract 3 2
;; ROUNDTRIP-NEXT: local.set $7
;; ROUNDTRIP-NEXT: local.set $5
;; ROUNDTRIP-NEXT: local.tee $temp3
;; ROUNDTRIP-NEXT: local.get $5
;; ROUNDTRIP-NEXT: local.get $7
;; ROUNDTRIP-NEXT: call $multiple-multivalue-return
;; ROUNDTRIP-NEXT: local.get $temp3
;; ROUNDTRIP-NEXT: local.get $5
;; ROUNDTRIP-NEXT: local.get $7
;; ROUNDTRIP-NEXT: call $multiple-multivalue-return
;; ROUNDTRIP-NEXT: )
(func $multiple-multivalue-return-local-reuse (param i32 f64 anyref)
(local $temp3 (tuple i32 f64 anyref))
(local $temp2 (tuple i32 f64))
;; As the last case, we have two things to possibly optimize. Here we reuse
;; the tee'd value after the first one, which prevents any optimizations of
;; this pattern.
(call $multiple-multivalue-return
(tuple.extract 3 0
(local.tee $temp3
(call $multivalue-return)
)
)
(tuple.extract 3 1
(local.get $temp3)
)
(tuple.extract 3 2
(local.get $temp3)
)
)
(call $multiple-multivalue-return
(tuple.extract 3 0
(local.get $temp3) ;; this changed
)
(tuple.extract 3 1
(local.get $temp3)
)
(tuple.extract 3 2
(local.get $temp3)
)
)
)
)