blob: 5c3b591062f739b6ac2df4f035da4a6bb4e664f2 [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
(module
;; CHECK: (type $FUNCSIG$v (func))
(type $FUNCSIG$v (func))
;; CHECK: (type $6 (func (param i32) (result i32)))
;; CHECK: (type $5 (func (result i32)))
;; CHECK: (type $FUNCSIG$vf (func (param f32)))
(type $FUNCSIG$vf (func (param f32)))
;; CHECK: (type $4 (func (result f64)))
;; CHECK: (type $FUNCSIG$ddd (func (param f64 f64) (result f64)))
;; CHECK: (type $10 (func (param f32) (result f32)))
;; CHECK: (type $FUNCSIG$id (func (param f64) (result i32)))
(type $FUNCSIG$id (func (param f64) (result i32)))
(type $FUNCSIG$ddd (func (param f64 f64) (result f64)))
(type $4 (func (result f64)))
(type $5 (func (result i32)))
(type $6 (func (param i32) (result i32)))
;; CHECK: (type $7 (func (param f64) (result f64)))
(type $7 (func (param f64) (result f64)))
;; CHECK: (type $8 (func (result i64)))
(type $8 (func (result i64)))
;; CHECK: (type $9 (func (param i32 i64)))
(type $9 (func (param i32 i64)))
;; CHECK: (type $15 (func (param eqref) (result i32)))
;; CHECK: (type $16 (func (param eqref) (result eqref)))
;; CHECK: (import "env" "_emscripten_asm_const_vi" (func $_emscripten_asm_const_vi (type $FUNCSIG$v)))
(import "env" "_emscripten_asm_const_vi" (func $_emscripten_asm_const_vi))
;; CHECK: (import "asm2wasm" "f64-to-int" (func $f64-to-int (type $FUNCSIG$id) (param f64) (result i32)))
(import "asm2wasm" "f64-to-int" (func $f64-to-int (param f64) (result i32)))
;; CHECK: (import "asm2wasm" "f64-rem" (func $f64-rem (type $FUNCSIG$ddd) (param f64 f64) (result f64)))
(import "asm2wasm" "f64-rem" (func $f64-rem (param f64 f64) (result f64)))
;; CHECK: (memory $mem 4096 4096)
;; CHECK: (data $data (i32.const 1026) "\14\00")
;; CHECK: (table $table 10 funcref)
(table $table 10 funcref)
;; CHECK: (elem $elem (i32.const 0) $z $big_negative $z $z $w $w $importedDoubles $w $z $cneg)
(elem $elem (i32.const 0) $z $big_negative $z $z $w $w $importedDoubles $w $z $cneg)
(memory $mem 4096 4096)
(data $data (i32.const 1026) "\14\00")
;; CHECK: (export "big_negative" (func $big_negative))
(export "big_negative" (func $big_negative))
;; CHECK: (func $big_negative (type $FUNCSIG$v)
;; CHECK-NEXT: (local $temp f64)
;; CHECK-NEXT: f64.const -2147483648
;; CHECK-NEXT: local.set $temp
;; CHECK-NEXT: f64.const -2147483648
;; CHECK-NEXT: local.set $temp
;; CHECK-NEXT: f64.const -21474836480
;; CHECK-NEXT: local.set $temp
;; CHECK-NEXT: f64.const 0.039625
;; CHECK-NEXT: local.set $temp
;; CHECK-NEXT: f64.const -0.039625
;; CHECK-NEXT: local.set $temp
;; CHECK-NEXT: )
(func $big_negative (type $FUNCSIG$v)
(local $temp f64)
(block $block0
(local.set $temp
(f64.const -2147483648)
)
(local.set $temp
(f64.const -2147483648)
)
(local.set $temp
(f64.const -21474836480)
)
(local.set $temp
(f64.const 0.039625)
)
(local.set $temp
(f64.const -0.039625)
)
)
)
;; CHECK: (func $importedDoubles (type $4) (result f64)
;; CHECK-NEXT: (local $temp f64)
;; CHECK-NEXT: block $topmost (result f64)
;; CHECK-NEXT: i32.const 8
;; CHECK-NEXT: f64.load
;; CHECK-NEXT: i32.const 16
;; CHECK-NEXT: f64.load
;; CHECK-NEXT: f64.add
;; CHECK-NEXT: i32.const 16
;; CHECK-NEXT: f64.load
;; CHECK-NEXT: f64.neg
;; CHECK-NEXT: f64.add
;; CHECK-NEXT: i32.const 8
;; CHECK-NEXT: f64.load
;; CHECK-NEXT: f64.neg
;; CHECK-NEXT: f64.add
;; CHECK-NEXT: local.set $temp
;; CHECK-NEXT: i32.const 24
;; CHECK-NEXT: i32.load
;; CHECK-NEXT: i32.const 0
;; CHECK-NEXT: i32.gt_s
;; CHECK-NEXT: if
;; CHECK-NEXT: f64.const -3.4
;; CHECK-NEXT: br $topmost
;; CHECK-NEXT: end
;; CHECK-NEXT: i32.const 32
;; CHECK-NEXT: f64.load
;; CHECK-NEXT: f64.const 0
;; CHECK-NEXT: f64.gt
;; CHECK-NEXT: if
;; CHECK-NEXT: f64.const 5.6
;; CHECK-NEXT: br $topmost
;; CHECK-NEXT: end
;; CHECK-NEXT: f64.const 1.2
;; CHECK-NEXT: end
;; CHECK-NEXT: )
(func $importedDoubles (type $4) (result f64)
(local $temp f64)
(block $topmost (result f64)
(local.set $temp
(f64.add
(f64.add
(f64.add
(f64.load
(i32.const 8)
)
(f64.load
(i32.const 16)
)
)
(f64.neg
(f64.load
(i32.const 16)
)
)
)
(f64.neg
(f64.load
(i32.const 8)
)
)
)
)
(if
(i32.gt_s
(i32.load
(i32.const 24)
)
(i32.const 0)
)
(then
(br $topmost
(f64.const -3.4)
)
)
)
(if
(f64.gt
(f64.load
(i32.const 32)
)
(f64.const 0)
)
(then
(br $topmost
(f64.const 5.6)
)
)
)
(f64.const 1.2)
)
)
;; CHECK: (func $doubleCompares (type $FUNCSIG$ddd) (param $x f64) (param $y f64) (result f64)
;; CHECK-NEXT: (local $t f64)
;; CHECK-NEXT: (local $Int f64)
;; CHECK-NEXT: (local $Double i32)
;; CHECK-NEXT: block $topmost (result f64)
;; CHECK-NEXT: local.get $x
;; CHECK-NEXT: f64.const 0
;; CHECK-NEXT: f64.gt
;; CHECK-NEXT: if
;; CHECK-NEXT: f64.const 1.2
;; CHECK-NEXT: br $topmost
;; CHECK-NEXT: end
;; CHECK-NEXT: local.get $Int
;; CHECK-NEXT: f64.const 0
;; CHECK-NEXT: f64.gt
;; CHECK-NEXT: if
;; CHECK-NEXT: f64.const -3.4
;; CHECK-NEXT: br $topmost
;; CHECK-NEXT: end
;; CHECK-NEXT: local.get $Double
;; CHECK-NEXT: i32.const 0
;; CHECK-NEXT: i32.gt_s
;; CHECK-NEXT: if
;; CHECK-NEXT: f64.const 5.6
;; CHECK-NEXT: br $topmost
;; CHECK-NEXT: end
;; CHECK-NEXT: local.get $x
;; CHECK-NEXT: local.get $y
;; CHECK-NEXT: f64.lt
;; CHECK-NEXT: if
;; CHECK-NEXT: local.get $x
;; CHECK-NEXT: br $topmost
;; CHECK-NEXT: end
;; CHECK-NEXT: local.get $y
;; CHECK-NEXT: end
;; CHECK-NEXT: )
(func $doubleCompares (type $FUNCSIG$ddd) (param $x f64) (param $y f64) (result f64)
(local $t f64)
(local $Int f64)
(local $Double i32)
(block $topmost (result f64)
(if
(f64.gt
(local.get $x)
(f64.const 0)
)
(then
(br $topmost
(f64.const 1.2)
)
)
)
(if
(f64.gt
(local.get $Int)
(f64.const 0)
)
(then
(br $topmost
(f64.const -3.4)
)
)
)
(if
(i32.gt_s
(local.get $Double)
(i32.const 0)
)
(then
(br $topmost
(f64.const 5.6)
)
)
)
(if
(f64.lt
(local.get $x)
(local.get $y)
)
(then
(br $topmost
(local.get $x)
)
)
)
(local.get $y)
)
)
;; CHECK: (func $intOps (type $5) (result i32)
;; CHECK-NEXT: (local $x i32)
;; CHECK-NEXT: local.get $x
;; CHECK-NEXT: i32.const 0
;; CHECK-NEXT: i32.eq
;; CHECK-NEXT: )
(func $intOps (type $5) (result i32)
(local $x i32)
(i32.eq
(local.get $x)
(i32.const 0)
)
)
;; CHECK: (func $hexLiterals (type $FUNCSIG$v)
;; CHECK-NEXT: i32.const 0
;; CHECK-NEXT: i32.const 313249263
;; CHECK-NEXT: i32.add
;; CHECK-NEXT: i32.const -19088752
;; CHECK-NEXT: i32.add
;; CHECK-NEXT: drop
;; CHECK-NEXT: )
(func $hexLiterals (type $FUNCSIG$v)
(drop
(i32.add
(i32.add
(i32.const 0)
(i32.const 313249263)
)
(i32.const -19088752)
)
)
)
;; CHECK: (func $conversions (type $FUNCSIG$v)
;; CHECK-NEXT: (local $i i32)
;; CHECK-NEXT: (local $d f64)
;; CHECK-NEXT: local.get $d
;; CHECK-NEXT: call $f64-to-int
;; CHECK-NEXT: local.set $i
;; CHECK-NEXT: local.get $i
;; CHECK-NEXT: f64.convert_i32_s
;; CHECK-NEXT: local.set $d
;; CHECK-NEXT: local.get $i
;; CHECK-NEXT: i32.const 0
;; CHECK-NEXT: i32.shr_u
;; CHECK-NEXT: f64.convert_i32_u
;; CHECK-NEXT: local.set $d
;; CHECK-NEXT: )
(func $conversions (type $FUNCSIG$v)
(local $i i32)
(local $d f64)
(block $block0
(local.set $i
(call $f64-to-int
(local.get $d)
)
)
(local.set $d
(f64.convert_i32_s
(local.get $i)
)
)
(local.set $d
(f64.convert_i32_u
(i32.shr_u
(local.get $i)
(i32.const 0)
)
)
)
)
)
;; CHECK: (func $seq (type $FUNCSIG$v)
;; CHECK-NEXT: (local $J f64)
;; CHECK-NEXT: f64.const 0.1
;; CHECK-NEXT: drop
;; CHECK-NEXT: f64.const 5.1
;; CHECK-NEXT: f64.const 3.2
;; CHECK-NEXT: drop
;; CHECK-NEXT: f64.const 4.2
;; CHECK-NEXT: f64.sub
;; CHECK-NEXT: local.set $J
;; CHECK-NEXT: )
(func $seq (type $FUNCSIG$v)
(local $J f64)
(local.set $J
(f64.sub
(block $block0 (result f64)
(drop
(f64.const 0.1)
)
(f64.const 5.1)
)
(block $block1 (result f64)
(drop
(f64.const 3.2)
)
(f64.const 4.2)
)
)
)
)
;; CHECK: (func $switcher (type $6) (param $x i32) (result i32)
;; CHECK-NEXT: block $topmost (result i32)
;; CHECK-NEXT: block $switch-default$3
;; CHECK-NEXT: block $switch-case$2
;; CHECK-NEXT: block $switch-case$1
;; CHECK-NEXT: local.get $x
;; CHECK-NEXT: i32.const 1
;; CHECK-NEXT: i32.sub
;; CHECK-NEXT: br_table $switch-case$1 $switch-case$2 $switch-default$3
;; CHECK-NEXT: end
;; CHECK-NEXT: i32.const 1
;; CHECK-NEXT: br $topmost
;; CHECK-NEXT: end
;; CHECK-NEXT: i32.const 2
;; CHECK-NEXT: br $topmost
;; CHECK-NEXT: end
;; CHECK-NEXT: block $switch-default$7
;; CHECK-NEXT: block $switch-case$6
;; CHECK-NEXT: block $switch-case$5
;; CHECK-NEXT: local.get $x
;; CHECK-NEXT: i32.const 5
;; CHECK-NEXT: i32.sub
;; CHECK-NEXT: br_table $switch-case$6 $switch-default$7 $switch-default$7 $switch-default$7 $switch-default$7 $switch-default$7 $switch-default$7 $switch-case$5 $switch-default$7
;; CHECK-NEXT: end
;; CHECK-NEXT: i32.const 121
;; CHECK-NEXT: br $topmost
;; CHECK-NEXT: end
;; CHECK-NEXT: i32.const 51
;; CHECK-NEXT: br $topmost
;; CHECK-NEXT: end
;; CHECK-NEXT: block $label$break$Lout
;; CHECK-NEXT: block $switch-default$16
;; CHECK-NEXT: block $switch-case$15
;; CHECK-NEXT: block $switch-case$12
;; CHECK-NEXT: block $switch-case$9
;; CHECK-NEXT: block $switch-case$8
;; CHECK-NEXT: local.get $x
;; CHECK-NEXT: i32.const 2
;; CHECK-NEXT: i32.sub
;; CHECK-NEXT: br_table $switch-case$15 $switch-default$16 $switch-default$16 $switch-case$12 $switch-default$16 $switch-default$16 $switch-default$16 $switch-default$16 $switch-case$9 $switch-default$16 $switch-case$8 $switch-default$16
;; CHECK-NEXT: end
;; CHECK-NEXT: br $label$break$Lout
;; CHECK-NEXT: end
;; CHECK-NEXT: br $label$break$Lout
;; CHECK-NEXT: end
;; CHECK-NEXT: block $while-out$10
;; CHECK-NEXT: loop $while-in$11
;; CHECK-NEXT: br $while-out$10
;; CHECK-NEXT: end
;; CHECK-NEXT: unreachable
;; CHECK-NEXT: end
;; CHECK-NEXT: end
;; CHECK-NEXT: loop $while-in$14
;; CHECK-NEXT: br $label$break$Lout
;; CHECK-NEXT: end
;; CHECK-NEXT: unreachable
;; CHECK-NEXT: end
;; CHECK-NEXT: end
;; CHECK-NEXT: i32.const 0
;; CHECK-NEXT: end
;; CHECK-NEXT: )
(func $switcher (type $6) (param $x i32) (result i32)
(block $topmost (result i32)
(block $switch$0
(block $switch-default$3
(block $switch-case$2
(block $switch-case$1
(br_table $switch-case$1 $switch-case$2 $switch-default$3
(i32.sub
(local.get $x)
(i32.const 1)
)
)
)
(br $topmost
(i32.const 1)
)
)
(br $topmost
(i32.const 2)
)
)
(nop)
)
(block $switch$4
(block $switch-default$7
(block $switch-case$6
(block $switch-case$5
(br_table $switch-case$6 $switch-default$7 $switch-default$7 $switch-default$7 $switch-default$7 $switch-default$7 $switch-default$7 $switch-case$5 $switch-default$7
(i32.sub
(local.get $x)
(i32.const 5)
)
)
)
(br $topmost
(i32.const 121)
)
)
(br $topmost
(i32.const 51)
)
)
(nop)
)
(block $label$break$Lout
(block $switch-default$16
(block $switch-case$15
(block $switch-case$12
(block $switch-case$9
(block $switch-case$8
(br_table $switch-case$15 $switch-default$16 $switch-default$16 $switch-case$12 $switch-default$16 $switch-default$16 $switch-default$16 $switch-default$16 $switch-case$9 $switch-default$16 $switch-case$8 $switch-default$16
(i32.sub
(local.get $x)
(i32.const 2)
)
)
)
(br $label$break$Lout)
)
(br $label$break$Lout)
)
(block $while-out$10
(loop $while-in$11
(block $block1
(br $while-out$10)
(br $while-in$11)
)
)
(br $label$break$Lout)
)
)
(block $while-out$13
(loop $while-in$14
(block $block3
(br $label$break$Lout)
(br $while-in$14)
)
)
(br $label$break$Lout)
)
)
(nop)
)
(i32.const 0)
)
)
;; CHECK: (func $blocker (type $FUNCSIG$v)
;; CHECK-NEXT: block $label$break$L
;; CHECK-NEXT: br $label$break$L
;; CHECK-NEXT: end
;; CHECK-NEXT: )
(func $blocker (type $FUNCSIG$v)
(block $label$break$L
(br $label$break$L)
)
)
;; CHECK: (func $frem (type $4) (result f64)
;; CHECK-NEXT: f64.const 5.5
;; CHECK-NEXT: f64.const 1.2
;; CHECK-NEXT: call $f64-rem
;; CHECK-NEXT: )
(func $frem (type $4) (result f64)
(call $f64-rem
(f64.const 5.5)
(f64.const 1.2)
)
)
;; CHECK: (func $big_uint_div_u (type $5) (result i32)
;; CHECK-NEXT: (local $x i32)
;; CHECK-NEXT: i32.const -1
;; CHECK-NEXT: i32.const 2
;; CHECK-NEXT: i32.div_u
;; CHECK-NEXT: i32.const -1
;; CHECK-NEXT: i32.and
;; CHECK-NEXT: )
(func $big_uint_div_u (type $5) (result i32)
(local $x i32)
(block $topmost (result i32)
(local.set $x
(i32.and
(i32.div_u
(i32.const -1)
(i32.const 2)
)
(i32.const -1)
)
)
(local.get $x)
)
)
;; CHECK: (func $fr (type $FUNCSIG$vf) (param $x f32)
;; CHECK-NEXT: (local $y f32)
;; CHECK-NEXT: (local $z f64)
;; CHECK-NEXT: local.get $z
;; CHECK-NEXT: f32.demote_f64
;; CHECK-NEXT: drop
;; CHECK-NEXT: local.get $y
;; CHECK-NEXT: drop
;; CHECK-NEXT: f32.const 5
;; CHECK-NEXT: drop
;; CHECK-NEXT: f32.const 0
;; CHECK-NEXT: drop
;; CHECK-NEXT: f32.const 5
;; CHECK-NEXT: drop
;; CHECK-NEXT: f32.const 0
;; CHECK-NEXT: drop
;; CHECK-NEXT: )
(func $fr (type $FUNCSIG$vf) (param $x f32)
(local $y f32)
(local $z f64)
(block $block0
(drop
(f32.demote_f64
(local.get $z)
)
)
(drop
(local.get $y)
)
(drop
(f32.const 5)
)
(drop
(f32.const 0)
)
(drop
(f32.const 5)
)
(drop
(f32.const 0)
)
)
)
;; CHECK: (func $negZero (type $4) (result f64)
;; CHECK-NEXT: f64.const -0
;; CHECK-NEXT: )
(func $negZero (type $4) (result f64)
(f64.const -0)
)
;; CHECK: (func $abs (type $FUNCSIG$v)
;; CHECK-NEXT: (local $x i32)
;; CHECK-NEXT: (local $y f64)
;; CHECK-NEXT: (local $z f32)
;; CHECK-NEXT: (local $asm2wasm_i32_temp i32)
;; CHECK-NEXT: i32.const 0
;; CHECK-NEXT: local.set $asm2wasm_i32_temp
;; CHECK-NEXT: i32.const 0
;; CHECK-NEXT: local.get $asm2wasm_i32_temp
;; CHECK-NEXT: i32.sub
;; CHECK-NEXT: local.get $asm2wasm_i32_temp
;; CHECK-NEXT: local.get $asm2wasm_i32_temp
;; CHECK-NEXT: i32.const 0
;; CHECK-NEXT: i32.lt_s
;; CHECK-NEXT: select
;; CHECK-NEXT: local.set $x
;; CHECK-NEXT: f64.const 0
;; CHECK-NEXT: f64.abs
;; CHECK-NEXT: local.set $y
;; CHECK-NEXT: f32.const 0
;; CHECK-NEXT: f32.abs
;; CHECK-NEXT: local.set $z
;; CHECK-NEXT: )
(func $abs (type $FUNCSIG$v)
(local $x i32)
(local $y f64)
(local $z f32)
(local $asm2wasm_i32_temp i32)
(block $block0
(local.set $x
(block $block1 (result i32)
(local.set $asm2wasm_i32_temp
(i32.const 0)
)
(select
(i32.sub
(i32.const 0)
(local.get $asm2wasm_i32_temp)
)
(local.get $asm2wasm_i32_temp)
(i32.lt_s
(local.get $asm2wasm_i32_temp)
(i32.const 0)
)
)
)
)
(local.set $y
(f64.abs
(f64.const 0)
)
)
(local.set $z
(f32.abs
(f32.const 0)
)
)
)
)
;; CHECK: (func $neg (type $FUNCSIG$v)
;; CHECK-NEXT: (local $x f32)
;; CHECK-NEXT: local.get $x
;; CHECK-NEXT: f32.neg
;; CHECK-NEXT: i32.const 1
;; CHECK-NEXT: i32.const 7
;; CHECK-NEXT: i32.and
;; CHECK-NEXT: i32.const 8
;; CHECK-NEXT: i32.add
;; CHECK-NEXT: call_indirect $table (type $FUNCSIG$vf)
;; CHECK-NEXT: )
(func $neg (type $FUNCSIG$v)
(local $x f32)
(block $block0
(local.set $x
(f32.neg
(local.get $x)
)
)
(call_indirect (type $FUNCSIG$vf)
(local.get $x)
(i32.add
(i32.and
(i32.const 1)
(i32.const 7)
)
(i32.const 8)
)
)
)
)
;; CHECK: (func $cneg (type $FUNCSIG$vf) (param $x f32)
;; CHECK-NEXT: local.get $x
;; CHECK-NEXT: i32.const 1
;; CHECK-NEXT: i32.const 7
;; CHECK-NEXT: i32.and
;; CHECK-NEXT: i32.const 8
;; CHECK-NEXT: i32.add
;; CHECK-NEXT: call_indirect $table (type $FUNCSIG$vf)
;; CHECK-NEXT: )
(func $cneg (type $FUNCSIG$vf) (param $x f32)
(call_indirect (type $FUNCSIG$vf)
(local.get $x)
(i32.add
(i32.and
(i32.const 1)
(i32.const 7)
)
(i32.const 8)
)
)
)
;; CHECK: (func $___syscall_ret (type $FUNCSIG$v)
;; CHECK-NEXT: (local $$0 i32)
;; CHECK-NEXT: local.get $$0
;; CHECK-NEXT: i32.const 0
;; CHECK-NEXT: i32.shr_u
;; CHECK-NEXT: i32.const -4096
;; CHECK-NEXT: i32.gt_u
;; CHECK-NEXT: drop
;; CHECK-NEXT: )
(func $___syscall_ret (type $FUNCSIG$v)
(local $$0 i32)
(drop
(i32.gt_u
(i32.shr_u
(local.get $$0)
(i32.const 0)
)
(i32.const -4096)
)
)
)
;; CHECK: (func $z (type $FUNCSIG$v)
;; CHECK-NEXT: )
(func $z (type $FUNCSIG$v)
(nop)
)
;; CHECK: (func $w (type $FUNCSIG$v)
;; CHECK-NEXT: )
(func $w (type $FUNCSIG$v)
(nop)
)
;; CHECK: (func $block_and_after (type $5) (result i32)
;; CHECK-NEXT: block $waka
;; CHECK-NEXT: i32.const 1
;; CHECK-NEXT: drop
;; CHECK-NEXT: br $waka
;; CHECK-NEXT: end
;; CHECK-NEXT: i32.const 0
;; CHECK-NEXT: )
(func $block_and_after (type $5) (result i32)
(block $waka
(drop
(i32.const 1)
)
(br $waka)
)
(i32.const 0)
)
;; CHECK: (func $loop-roundtrip (type $7) (param $0 f64) (result f64)
;; CHECK-NEXT: loop $loop-in1 (result f64)
;; CHECK-NEXT: local.get $0
;; CHECK-NEXT: drop
;; CHECK-NEXT: local.get $0
;; CHECK-NEXT: end
;; CHECK-NEXT: )
(func $loop-roundtrip (type $7) (param $0 f64) (result f64)
(loop $loop-in1 (result f64)
(drop
(local.get $0)
)
(local.get $0)
)
)
;; CHECK: (func $big-i64 (type $8) (result i64)
;; CHECK-NEXT: i64.const -9218868437227405313
;; CHECK-NEXT: )
(func $big-i64 (type $8) (result i64)
(i64.const -9218868437227405313)
)
;; CHECK: (func $i64-store32 (type $9) (param $0 i32) (param $1 i64)
;; CHECK-NEXT: local.get $0
;; CHECK-NEXT: local.get $1
;; CHECK-NEXT: i64.store32
;; CHECK-NEXT: )
(func $i64-store32 (type $9) (param $0 i32) (param $1 i64)
(i64.store32
(local.get $0)
(local.get $1)
)
)
;; CHECK: (func $return-unreachable (type $5) (result i32)
;; CHECK-NEXT: i32.const 1
;; CHECK-NEXT: return
;; CHECK-NEXT: )
(func $return-unreachable (result i32)
(return (i32.const 1))
)
;; CHECK: (func $unreachable-block (type $5) (result i32)
;; CHECK-NEXT: i32.const 1
;; CHECK-NEXT: drop
;; CHECK-NEXT: i32.const 2
;; CHECK-NEXT: return
;; CHECK-NEXT: )
(func $unreachable-block (result i32)
(f64.abs
(block ;; note no type - valid in binaryen IR, in wasm must be i32
(drop (i32.const 1))
(return (i32.const 2))
)
)
)
;; CHECK: (func $unreachable-block-toplevel (type $5) (result i32)
;; CHECK-NEXT: i32.const 1
;; CHECK-NEXT: drop
;; CHECK-NEXT: i32.const 2
;; CHECK-NEXT: return
;; CHECK-NEXT: )
(func $unreachable-block-toplevel (result i32)
(block ;; note no type - valid in binaryen IR, in wasm must be i32
(drop (i32.const 1))
(return (i32.const 2))
)
)
;; CHECK: (func $unreachable-block0 (type $5) (result i32)
;; CHECK-NEXT: i32.const 2
;; CHECK-NEXT: return
;; CHECK-NEXT: )
(func $unreachable-block0 (result i32)
(f64.abs
(block ;; note no type - valid in binaryen IR, in wasm must be i32
(return (i32.const 2))
)
)
)
;; CHECK: (func $unreachable-block0-toplevel (type $5) (result i32)
;; CHECK-NEXT: i32.const 2
;; CHECK-NEXT: return
;; CHECK-NEXT: )
(func $unreachable-block0-toplevel (result i32)
(block ;; note no type - valid in binaryen IR, in wasm must be i32
(return (i32.const 2))
)
)
;; CHECK: (func $unreachable-block-with-br (type $5) (result i32)
;; CHECK-NEXT: block $block
;; CHECK-NEXT: i32.const 1
;; CHECK-NEXT: drop
;; CHECK-NEXT: br $block
;; CHECK-NEXT: end
;; CHECK-NEXT: i32.const 1
;; CHECK-NEXT: )
(func $unreachable-block-with-br (result i32)
(block $block ;; unreachable type due to last element having that type, but the block is exitable
(drop (i32.const 1))
(br $block)
)
(i32.const 1)
)
;; CHECK: (func $unreachable-if (type $5) (result i32)
;; CHECK-NEXT: i32.const 3
;; CHECK-NEXT: if
;; CHECK-NEXT: i32.const 2
;; CHECK-NEXT: return
;; CHECK-NEXT: else
;; CHECK-NEXT: i32.const 1
;; CHECK-NEXT: return
;; CHECK-NEXT: end
;; CHECK-NEXT: unreachable
;; CHECK-NEXT: )
(func $unreachable-if (result i32)
(f64.abs
(if ;; note no type - valid in binaryen IR, in wasm must be i32
(i32.const 3)
(then
(return (i32.const 2))
)
(else
(return (i32.const 1))
)
)
)
)
;; CHECK: (func $unreachable-if-toplevel (type $5) (result i32)
;; CHECK-NEXT: i32.const 3
;; CHECK-NEXT: if
;; CHECK-NEXT: i32.const 2
;; CHECK-NEXT: return
;; CHECK-NEXT: else
;; CHECK-NEXT: i32.const 1
;; CHECK-NEXT: return
;; CHECK-NEXT: end
;; CHECK-NEXT: unreachable
;; CHECK-NEXT: )
(func $unreachable-if-toplevel (result i32)
(if ;; note no type - valid in binaryen IR, in wasm must be i32
(i32.const 3)
(then
(return (i32.const 2))
)
(else
(return (i32.const 1))
)
)
)
;; CHECK: (func $unreachable-loop (type $5) (result i32)
;; CHECK-NEXT: loop
;; CHECK-NEXT: i32.const 1
;; CHECK-NEXT: return
;; CHECK-NEXT: end
;; CHECK-NEXT: unreachable
;; CHECK-NEXT: )
(func $unreachable-loop (result i32)
(f64.abs
(loop ;; note no type - valid in binaryen IR, in wasm must be i32
(nop)
(return (i32.const 1))
)
)
)
;; CHECK: (func $unreachable-loop0 (type $5) (result i32)
;; CHECK-NEXT: loop
;; CHECK-NEXT: i32.const 1
;; CHECK-NEXT: return
;; CHECK-NEXT: end
;; CHECK-NEXT: unreachable
;; CHECK-NEXT: )
(func $unreachable-loop0 (result i32)
(f64.abs
(loop ;; note no type - valid in binaryen IR, in wasm must be i32
(return (i32.const 1))
)
)
)
;; CHECK: (func $unreachable-loop-toplevel (type $5) (result i32)
;; CHECK-NEXT: loop
;; CHECK-NEXT: i32.const 1
;; CHECK-NEXT: return
;; CHECK-NEXT: end
;; CHECK-NEXT: unreachable
;; CHECK-NEXT: )
(func $unreachable-loop-toplevel (result i32)
(loop ;; note no type - valid in binaryen IR, in wasm must be i32
(nop)
(return (i32.const 1))
)
)
;; CHECK: (func $unreachable-loop0-toplevel (type $5) (result i32)
;; CHECK-NEXT: loop
;; CHECK-NEXT: i32.const 1
;; CHECK-NEXT: return
;; CHECK-NEXT: end
;; CHECK-NEXT: unreachable
;; CHECK-NEXT: )
(func $unreachable-loop0-toplevel (result i32)
(loop ;; note no type - valid in binaryen IR, in wasm must be i32
(return (i32.const 1))
)
)
;; CHECK: (func $unreachable-ifs (type $FUNCSIG$v)
;; CHECK-NEXT: unreachable
;; CHECK-NEXT: )
(func $unreachable-ifs
(if (unreachable) (then (nop)))
(if (unreachable) (then (unreachable)))
(if (unreachable) (then (nop) )(else (nop)))
(if (unreachable) (then (unreachable) )(else (nop)))
(if (unreachable) (then (nop) )(else (unreachable)))
(if (unreachable) (then (unreachable) )(else (unreachable)))
;;
(if (i32.const 1) (then (unreachable) )(else (nop)))
(if (i32.const 1) (then (nop) )(else (unreachable)))
(if (i32.const 1) (then (unreachable) )(else (unreachable)))
)
;; CHECK: (func $unreachable-if-arm (type $FUNCSIG$v)
;; CHECK-NEXT: i32.const 1
;; CHECK-NEXT: if
;; CHECK-NEXT: else
;; CHECK-NEXT: unreachable
;; CHECK-NEXT: end
;; CHECK-NEXT: )
(func $unreachable-if-arm
(if
(i32.const 1)
(then
(block
(nop)
)
)
(else
(block
(unreachable)
(drop
(i32.const 1)
)
)
)
)
)
;; CHECK: (func $local-to-stack (type $6) (param $x i32) (result i32)
;; CHECK-NEXT: (local $temp i32)
;; CHECK-NEXT: i32.const 1
;; CHECK-NEXT: call $local-to-stack
;; CHECK-NEXT: i32.const 2
;; CHECK-NEXT: call $local-to-stack
;; CHECK-NEXT: drop
;; CHECK-NEXT: )
(func $local-to-stack (param $x i32) (result i32)
(local $temp i32)
(local.set $temp (call $local-to-stack (i32.const 1))) ;; this set could just be on the stack
(drop (call $local-to-stack (i32.const 2)))
(local.get $temp)
)
;; CHECK: (func $local-to-stack-1 (type $6) (param $x i32) (result i32)
;; CHECK-NEXT: (local $temp i32)
;; CHECK-NEXT: i32.const 1
;; CHECK-NEXT: call $local-to-stack
;; CHECK-NEXT: i32.const 2
;; CHECK-NEXT: call $local-to-stack
;; CHECK-NEXT: drop
;; CHECK-NEXT: i32.eqz
;; CHECK-NEXT: )
(func $local-to-stack-1 (param $x i32) (result i32)
(local $temp i32)
(local.set $temp (call $local-to-stack (i32.const 1)))
(drop (call $local-to-stack (i32.const 2)))
(i32.eqz
(local.get $temp)
)
)
;; CHECK: (func $local-to-stack-1b (type $6) (param $x i32) (result i32)
;; CHECK-NEXT: (local $temp i32)
;; CHECK-NEXT: i32.const 1
;; CHECK-NEXT: call $local-to-stack
;; CHECK-NEXT: i32.const 2
;; CHECK-NEXT: call $local-to-stack
;; CHECK-NEXT: drop
;; CHECK-NEXT: i32.const 3
;; CHECK-NEXT: i32.add
;; CHECK-NEXT: )
(func $local-to-stack-1b (param $x i32) (result i32)
(local $temp i32)
(local.set $temp (call $local-to-stack (i32.const 1)))
(drop (call $local-to-stack (i32.const 2)))
(i32.add
(local.get $temp)
(i32.const 3)
)
)
;; CHECK: (func $local-to-stack-1c (type $6) (param $x i32) (result i32)
;; CHECK-NEXT: (local $temp i32)
;; CHECK-NEXT: i32.const 1
;; CHECK-NEXT: call $local-to-stack
;; CHECK-NEXT: i32.const 2
;; CHECK-NEXT: call $local-to-stack
;; CHECK-NEXT: drop
;; CHECK-NEXT: i32.const 3
;; CHECK-NEXT: i32.add
;; CHECK-NEXT: )
(func $local-to-stack-1c (param $x i32) (result i32)
(local $temp i32)
(local.set $temp (call $local-to-stack (i32.const 1)))
(drop (call $local-to-stack (i32.const 2)))
(i32.add
(i32.const 3) ;; in the way, but the add is commutative so we can
(local.get $temp) ;; still use the value on the stack
)
)
;; CHECK: (func $local-to-stack-1d-sub-no (type $6) (param $x i32) (result i32)
;; CHECK-NEXT: (local $temp i32)
;; CHECK-NEXT: i32.const 1
;; CHECK-NEXT: call $local-to-stack
;; CHECK-NEXT: local.set $temp
;; CHECK-NEXT: i32.const 2
;; CHECK-NEXT: call $local-to-stack
;; CHECK-NEXT: drop
;; CHECK-NEXT: i32.const 3
;; CHECK-NEXT: local.get $temp
;; CHECK-NEXT: i32.sub
;; CHECK-NEXT: )
(func $local-to-stack-1d-sub-no (param $x i32) (result i32)
(local $temp i32)
(local.set $temp (call $local-to-stack (i32.const 1)))
(drop (call $local-to-stack (i32.const 2)))
(i32.sub
(i32.const 3) ;; not commutative: the set/get pair must stay
(local.get $temp)
)
)
;; CHECK: (func $local-to-stack-2-no (type $6) (param $x i32) (result i32)
;; CHECK-NEXT: (local $temp i32)
;; CHECK-NEXT: i32.const 1
;; CHECK-NEXT: call $local-to-stack
;; CHECK-NEXT: local.set $temp
;; CHECK-NEXT: i32.const 2
;; CHECK-NEXT: call $local-to-stack
;; CHECK-NEXT: drop
;; CHECK-NEXT: local.get $temp
;; CHECK-NEXT: local.get $temp
;; CHECK-NEXT: i32.add
;; CHECK-NEXT: )
(func $local-to-stack-2-no (param $x i32) (result i32)
(local $temp i32)
(local.set $temp (call $local-to-stack (i32.const 1)))
(drop (call $local-to-stack (i32.const 2)))
(i32.add
(local.get $temp)
(local.get $temp) ;; a second use - so cannot stack it
)
)
;; CHECK: (func $local-to-stack-3-no (type $6) (param $x i32) (result i32)
;; CHECK-NEXT: (local $temp i32)
;; CHECK-NEXT: i32.const 1
;; CHECK-NEXT: if
;; CHECK-NEXT: i32.const 1
;; CHECK-NEXT: call $local-to-stack
;; CHECK-NEXT: local.set $temp
;; CHECK-NEXT: else
;; CHECK-NEXT: i32.const 2
;; CHECK-NEXT: call $local-to-stack
;; CHECK-NEXT: local.set $temp
;; CHECK-NEXT: end
;; CHECK-NEXT: i32.const 3
;; CHECK-NEXT: call $local-to-stack
;; CHECK-NEXT: drop
;; CHECK-NEXT: local.get $temp
;; CHECK-NEXT: )
(func $local-to-stack-3-no (param $x i32) (result i32)
(local $temp i32)
(if (i32.const 1)
(then
(local.set $temp (call $local-to-stack (i32.const 1)))
)
(else
(local.set $temp (call $local-to-stack (i32.const 2))) ;; two sets for that get
)
)
(drop (call $local-to-stack (i32.const 3)))
(local.get $temp)
)
;; CHECK: (func $local-to-stack-multi-4 (type $6) (param $x i32) (result i32)
;; CHECK-NEXT: (local $temp1 i32)
;; CHECK-NEXT: (local $temp2 i32)
;; CHECK-NEXT: i32.const 1
;; CHECK-NEXT: call $local-to-stack-multi-4
;; CHECK-NEXT: i32.const 2
;; CHECK-NEXT: call $local-to-stack-multi-4
;; CHECK-NEXT: drop
;; CHECK-NEXT: drop
;; CHECK-NEXT: i32.const 3
;; CHECK-NEXT: call $local-to-stack-multi-4
;; CHECK-NEXT: i32.const 4
;; CHECK-NEXT: call $local-to-stack-multi-4
;; CHECK-NEXT: drop
;; CHECK-NEXT: )
(func $local-to-stack-multi-4 (param $x i32) (result i32)
(local $temp1 i32)
(local $temp2 i32)
(local.set $temp1 (call $local-to-stack-multi-4 (i32.const 1)))
(drop (call $local-to-stack-multi-4 (i32.const 2)))
(drop (local.get $temp1))
(local.set $temp1 (call $local-to-stack-multi-4 (i32.const 3))) ;; same local, used later
(drop (call $local-to-stack-multi-4 (i32.const 4)))
(local.get $temp1)
)
;; CHECK: (func $local-to-stack-multi-5 (type $6) (param $x i32) (result i32)
;; CHECK-NEXT: (local $temp1 i32)
;; CHECK-NEXT: (local $temp2 i32)
;; CHECK-NEXT: i32.const 1
;; CHECK-NEXT: call $local-to-stack-multi-4
;; CHECK-NEXT: i32.const 2
;; CHECK-NEXT: call $local-to-stack-multi-4
;; CHECK-NEXT: drop
;; CHECK-NEXT: drop
;; CHECK-NEXT: i32.const 3
;; CHECK-NEXT: call $local-to-stack-multi-4
;; CHECK-NEXT: i32.const 4
;; CHECK-NEXT: call $local-to-stack-multi-4
;; CHECK-NEXT: drop
;; CHECK-NEXT: )
(func $local-to-stack-multi-5 (param $x i32) (result i32)
(local $temp1 i32)
(local $temp2 i32)
(local.set $temp1 (call $local-to-stack-multi-4 (i32.const 1)))
(drop (call $local-to-stack-multi-4 (i32.const 2)))
(drop (local.get $temp1))
(local.set $temp2 (call $local-to-stack-multi-4 (i32.const 3))) ;; different local, used later
(drop (call $local-to-stack-multi-4 (i32.const 4)))
(local.get $temp2)
)
;; CHECK: (func $local-to-stack-multi-6-justone (type $6) (param $x i32) (result i32)
;; CHECK-NEXT: (local $temp1 i32)
;; CHECK-NEXT: (local $temp2 i32)
;; CHECK-NEXT: i32.const 1
;; CHECK-NEXT: call $local-to-stack-multi-4
;; CHECK-NEXT: i32.const 2
;; CHECK-NEXT: call $local-to-stack-multi-4
;; CHECK-NEXT: drop
;; CHECK-NEXT: drop
;; CHECK-NEXT: i32.const 3
;; CHECK-NEXT: call $local-to-stack-multi-4
;; CHECK-NEXT: local.set $temp2
;; CHECK-NEXT: i32.const 4
;; CHECK-NEXT: call $local-to-stack-multi-4
;; CHECK-NEXT: drop
;; CHECK-NEXT: local.get $temp2
;; CHECK-NEXT: local.get $temp2
;; CHECK-NEXT: i32.add
;; CHECK-NEXT: )
(func $local-to-stack-multi-6-justone (param $x i32) (result i32)
(local $temp1 i32)
(local $temp2 i32)
(local.set $temp1 (call $local-to-stack-multi-4 (i32.const 1)))
(drop (call $local-to-stack-multi-4 (i32.const 2)))
(drop (local.get $temp1))
(local.set $temp2 (call $local-to-stack-multi-4 (i32.const 3))) ;; different local, used later
(drop (call $local-to-stack-multi-4 (i32.const 4)))
(i32.add
(local.get $temp2)
(local.get $temp2)
)
)
;; CHECK: (func $local-to-stack-multi-7-justone (type $6) (param $x i32) (result i32)
;; CHECK-NEXT: (local $temp1 i32)
;; CHECK-NEXT: (local $temp2 i32)
;; CHECK-NEXT: i32.const 1
;; CHECK-NEXT: call $local-to-stack-multi-4
;; CHECK-NEXT: local.set $temp1
;; CHECK-NEXT: i32.const 2
;; CHECK-NEXT: call $local-to-stack-multi-4
;; CHECK-NEXT: drop
;; CHECK-NEXT: local.get $temp1
;; CHECK-NEXT: local.get $temp1
;; CHECK-NEXT: i32.add
;; CHECK-NEXT: drop
;; CHECK-NEXT: i32.const 3
;; CHECK-NEXT: call $local-to-stack-multi-4
;; CHECK-NEXT: i32.const 4
;; CHECK-NEXT: call $local-to-stack-multi-4
;; CHECK-NEXT: drop
;; CHECK-NEXT: )
(func $local-to-stack-multi-7-justone (param $x i32) (result i32)
(local $temp1 i32)
(local $temp2 i32)
(local.set $temp1 (call $local-to-stack-multi-4 (i32.const 1)))
(drop (call $local-to-stack-multi-4 (i32.const 2)))
(drop
(i32.add
(local.get $temp1)
(local.get $temp1)
)
)
(local.set $temp2 (call $local-to-stack-multi-4 (i32.const 3))) ;; different local, used later
(drop (call $local-to-stack-multi-4 (i32.const 4)))
(local.get $temp2)
)
;; CHECK: (func $local-to-stack-overlapping-multi-8 (type $6) (param $x i32) (result i32)
;; CHECK-NEXT: (local $temp1 i32)
;; CHECK-NEXT: (local $temp2 i32)
;; CHECK-NEXT: i32.const 1
;; CHECK-NEXT: call $local-to-stack-multi-4
;; CHECK-NEXT: i32.const 1
;; CHECK-NEXT: call $local-to-stack-multi-4
;; CHECK-NEXT: i32.const 3
;; CHECK-NEXT: call $local-to-stack-multi-4
;; CHECK-NEXT: drop
;; CHECK-NEXT: i32.add
;; CHECK-NEXT: )
(func $local-to-stack-overlapping-multi-8 (param $x i32) (result i32)
(local $temp1 i32)
(local $temp2 i32)
(local.set $temp1 (call $local-to-stack-multi-4 (i32.const 1)))
(local.set $temp2 (call $local-to-stack-multi-4 (i32.const 1)))
(drop (call $local-to-stack-multi-4 (i32.const 3)))
(i32.add ;; the operands are flipped, but the add is commutative
(local.get $temp2)
(local.get $temp1)
)
)
;; CHECK: (func $local-to-stack-overlapping-multi-9-yes (type $6) (param $x i32) (result i32)
;; CHECK-NEXT: (local $temp1 i32)
;; CHECK-NEXT: (local $temp2 i32)
;; CHECK-NEXT: i32.const 1
;; CHECK-NEXT: call $local-to-stack-multi-4
;; CHECK-NEXT: i32.const 1
;; CHECK-NEXT: call $local-to-stack-multi-4
;; CHECK-NEXT: i32.const 3
;; CHECK-NEXT: call $local-to-stack-multi-4
;; CHECK-NEXT: drop
;; CHECK-NEXT: i32.add
;; CHECK-NEXT: )
(func $local-to-stack-overlapping-multi-9-yes (param $x i32) (result i32)
(local $temp1 i32)
(local $temp2 i32)
(local.set $temp1 (call $local-to-stack-multi-4 (i32.const 1)))
(local.set $temp2 (call $local-to-stack-multi-4 (i32.const 1)))
(drop (call $local-to-stack-multi-4 (i32.const 3)))
(i32.add
(local.get $temp1) ;; the stars align
(local.get $temp2) ;; and a time presents itself
)
)
;; CHECK: (func $local-to-stack-through-control-flow (type $FUNCSIG$v)
;; CHECK-NEXT: (local $temp1 i32)
;; CHECK-NEXT: (local $temp2 i32)
;; CHECK-NEXT: i32.const 0
;; CHECK-NEXT: call $local-to-stack-multi-4
;; CHECK-NEXT: i32.const 1
;; CHECK-NEXT: call $local-to-stack-multi-4
;; CHECK-NEXT: i32.const 0
;; CHECK-NEXT: if
;; CHECK-NEXT: end
;; CHECK-NEXT: drop
;; CHECK-NEXT: i32.const 2
;; CHECK-NEXT: call $local-to-stack-multi-4
;; CHECK-NEXT: block $block
;; CHECK-NEXT: br $block
;; CHECK-NEXT: end
;; CHECK-NEXT: drop
;; CHECK-NEXT: drop
;; CHECK-NEXT: )
(func $local-to-stack-through-control-flow
(local $temp1 i32)
(local $temp2 i32)
(local.set $temp2 (call $local-to-stack-multi-4 (i32.const 0)))
(local.set $temp1 (call $local-to-stack-multi-4 (i32.const 1)))
(if (i32.const 0) (then (nop)))
(drop (local.get $temp1))
(local.set $temp1 (call $local-to-stack-multi-4 (i32.const 2)))
(block $block (br $block))
(drop (local.get $temp1))
(drop (local.get $temp2))
)
;; CHECK: (func $local-to-stack-in-control-flow (type $FUNCSIG$v)
;; CHECK-NEXT: (local $temp1 i32)
;; CHECK-NEXT: i32.const 0
;; CHECK-NEXT: if
;; CHECK-NEXT: i32.const 0
;; CHECK-NEXT: call $local-to-stack-multi-4
;; CHECK-NEXT: drop
;; CHECK-NEXT: else
;; CHECK-NEXT: i32.const 1
;; CHECK-NEXT: call $local-to-stack-multi-4
;; CHECK-NEXT: drop
;; CHECK-NEXT: end
;; CHECK-NEXT: )
(func $local-to-stack-in-control-flow
(local $temp1 i32)
(if (i32.const 0)
(then
(block
(local.set $temp1 (call $local-to-stack-multi-4 (i32.const 0)))
(drop (local.get $temp1))
)
)
(else
(block
(local.set $temp1 (call $local-to-stack-multi-4 (i32.const 1)))
(drop (local.get $temp1))
)
)
)
)
;; CHECK: (func $remove-block (type $6) (param $x i32) (result i32)
;; CHECK-NEXT: (local $temp i32)
;; CHECK-NEXT: i32.const 0
;; CHECK-NEXT: call $remove-block
;; CHECK-NEXT: i32.const 1
;; CHECK-NEXT: call $remove-block
;; CHECK-NEXT: i32.const 2
;; CHECK-NEXT: call $remove-block
;; CHECK-NEXT: drop
;; CHECK-NEXT: i32.eqz
;; CHECK-NEXT: i32.add
;; CHECK-NEXT: )
(func $remove-block (param $x i32) (result i32)
(local $temp i32)
(i32.add
(call $remove-block (i32.const 0))
(i32.eqz
(block (result i32) ;; after we use the stack instead of the local, we can remove this block
(local.set $temp (call $remove-block (i32.const 1)))
(drop (call $remove-block (i32.const 2)))
(local.get $temp)
)
)
)
)
;; CHECK: (func $tuple-local2stack (type $FUNCSIG$v)
;; CHECK-NEXT: (local $pair (tuple f32 i32))
;; CHECK-NEXT: (local $f32 f32)
;; CHECK-NEXT: f32.const 0
;; CHECK-NEXT: i32.const 0
;; CHECK-NEXT: tuple.make 2
;; CHECK-NEXT: local.set $pair
;; CHECK-NEXT: local.get $pair
;; CHECK-NEXT: tuple.extract 2 0
;; CHECK-NEXT: local.set $f32
;; CHECK-NEXT: )
(func $tuple-local2stack
(local $pair (tuple f32 i32))
(local $f32 f32)
;; We should not optimize out this get-set pair in Stack IR since we can do
;; better in the binary writer.
(local.set $pair
(tuple.make 2
(f32.const 0)
(i32.const 0)
)
)
(local.set $f32
(tuple.extract 2 0
(local.get $pair)
)
)
)
;; A ref.eq with an intervening value: its operands can be swapped.
;; CHECK: (func $local-to-stack-ref-eq (type $15) (param $x eqref) (result i32)
;; CHECK-NEXT: (local $temp eqref)
;; CHECK-NEXT: local.get $x
;; CHECK-NEXT: call $eqref-value
;; CHECK-NEXT: local.get $x
;; CHECK-NEXT: call $eqref-value
;; CHECK-NEXT: drop
;; CHECK-NEXT: local.get $x
;; CHECK-NEXT: ref.eq
;; CHECK-NEXT: )
(func $local-to-stack-ref-eq (param $x eqref) (result i32)
(local $temp eqref)
(local.set $temp (call $eqref-value (local.get $x)))
(drop (call $eqref-value (local.get $x)))
(ref.eq
(local.get $x)
(local.get $temp)
)
)
;; CHECK: (func $eqref-value (type $16) (param $x eqref) (result eqref)
;; CHECK-NEXT: local.get $x
;; CHECK-NEXT: call $eqref-value
;; CHECK-NEXT: )
(func $eqref-value (param $x eqref) (result eqref)
(call $eqref-value (local.get $x))
)
;; f32.min has swappable operands, so the set/get pair can be removed.
;; CHECK: (func $local-to-stack-f32-min (type $10) (param $x f32) (result f32)
;; CHECK-NEXT: (local $temp f32)
;; CHECK-NEXT: local.get $x
;; CHECK-NEXT: call $float-value
;; CHECK-NEXT: local.get $x
;; CHECK-NEXT: call $float-value
;; CHECK-NEXT: drop
;; CHECK-NEXT: local.get $x
;; CHECK-NEXT: f32.min
;; CHECK-NEXT: )
(func $local-to-stack-f32-min (param $x f32) (result f32)
(local $temp f32)
(local.set $temp (call $float-value (local.get $x)))
(drop (call $float-value (local.get $x)))
(f32.min
(local.get $x)
(local.get $temp)
)
)
;; CHECK: (func $float-value (type $10) (param $x f32) (result f32)
;; CHECK-NEXT: local.get $x
;; CHECK-NEXT: call $float-value
;; CHECK-NEXT: )
(func $float-value (param $x f32) (result f32)
(call $float-value (local.get $x))
)
;; Two values are in the way, so the set/get pair must stay.
;; CHECK: (func $local-to-stack-two-in-the-way (type $6) (param $x i32) (result i32)
;; CHECK-NEXT: (local $temp i32)
;; CHECK-NEXT: i32.const 1
;; CHECK-NEXT: call $local-to-stack
;; CHECK-NEXT: local.set $temp
;; CHECK-NEXT: i32.const 2
;; CHECK-NEXT: call $local-to-stack
;; CHECK-NEXT: drop
;; CHECK-NEXT: i32.const 3
;; CHECK-NEXT: call $local-to-stack
;; CHECK-NEXT: i32.const 4
;; CHECK-NEXT: call $local-to-stack
;; CHECK-NEXT: local.get $temp
;; CHECK-NEXT: i32.add
;; CHECK-NEXT: i32.add
;; CHECK-NEXT: )
(func $local-to-stack-two-in-the-way (param $x i32) (result i32)
(local $temp i32)
(local.set $temp (call $local-to-stack (i32.const 1)))
(drop (call $local-to-stack (i32.const 2)))
(i32.add
(call $local-to-stack (i32.const 3))
(i32.add
(call $local-to-stack (i32.const 4))
(local.get $temp)
)
)
)
)