blob: 191970ce075ab73f977a92711da3176e53cfefa7 [file]
;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited.
;; Test tail-call optimization with --traps-never-happen (-tnh).
;; RUN: wasm-opt %s --tail-call --enable-tail-call -S -o - | filecheck %s --check-prefix=DEFAULT
;; RUN: wasm-opt %s --tail-call -tnh --enable-tail-call -S -o - | filecheck %s --check-prefix=TNH
(module
(memory 1 1)
;; DEFAULT: (global $g (mut i32) (i32.const 0))
;; TNH: (global $g (mut i32) (i32.const 0))
(global $g (mut i32) (i32.const 0))
;; DEFAULT: (func $value-callee (result i32)
;; DEFAULT-NEXT: (i32.const 1)
;; DEFAULT-NEXT: )
;; TNH: (func $value-callee (result i32)
;; TNH-NEXT: (i32.const 1)
;; TNH-NEXT: )
(func $value-callee (result i32)
(i32.const 1)
)
;; DEFAULT: (func $br-if-trapping-condition (param $x i32) (result i32)
;; DEFAULT-NEXT: (block $out (result i32)
;; DEFAULT-NEXT: (br_if $out
;; DEFAULT-NEXT: (call $value-callee)
;; DEFAULT-NEXT: (i32.load
;; DEFAULT-NEXT: (local.get $x)
;; DEFAULT-NEXT: )
;; DEFAULT-NEXT: )
;; DEFAULT-NEXT: )
;; DEFAULT-NEXT: )
;; TNH: (func $br-if-trapping-condition (param $x i32) (result i32)
;; TNH-NEXT: (block $out
;; TNH-NEXT: (block
;; TNH-NEXT: (return_call $value-callee)
;; TNH-NEXT: (drop
;; TNH-NEXT: (i32.load
;; TNH-NEXT: (local.get $x)
;; TNH-NEXT: )
;; TNH-NEXT: )
;; TNH-NEXT: )
;; TNH-NEXT: )
;; TNH-NEXT: )
(func $br-if-trapping-condition (param $x i32) (result i32)
;; Without -tnh, the load in the condition might trap, so converting the
;; call to a return_call (which skips the condition) is disallowed. With
;; -tnh, the load's trap is ignored and the call becomes a return_call.
(block $out (result i32)
(br_if $out
(call $value-callee)
(i32.load
(local.get $x)
)
)
)
)
;; DEFAULT: (func $br-table-trapping-condition (param $x i32) (result i32)
;; DEFAULT-NEXT: (block $out1 (result i32)
;; DEFAULT-NEXT: (block $out2 (result i32)
;; DEFAULT-NEXT: (br_table $out1 $out2
;; DEFAULT-NEXT: (call $value-callee)
;; DEFAULT-NEXT: (i32.div_s
;; DEFAULT-NEXT: (i32.const 10)
;; DEFAULT-NEXT: (local.get $x)
;; DEFAULT-NEXT: )
;; DEFAULT-NEXT: )
;; DEFAULT-NEXT: )
;; DEFAULT-NEXT: )
;; DEFAULT-NEXT: )
;; TNH: (func $br-table-trapping-condition (param $x i32) (result i32)
;; TNH-NEXT: (block $out1
;; TNH-NEXT: (block $out2
;; TNH-NEXT: (block
;; TNH-NEXT: (return_call $value-callee)
;; TNH-NEXT: (drop
;; TNH-NEXT: (i32.div_s
;; TNH-NEXT: (i32.const 10)
;; TNH-NEXT: (local.get $x)
;; TNH-NEXT: )
;; TNH-NEXT: )
;; TNH-NEXT: )
;; TNH-NEXT: )
;; TNH-NEXT: )
;; TNH-NEXT: )
(func $br-table-trapping-condition (param $x i32) (result i32)
;; Similarly, a potentially trapping division in a br_table condition
;; prevents tail-call conversion unless -tnh is enabled.
(block $out1 (result i32)
(block $out2 (result i32)
(br_table $out1 $out2
(call $value-callee)
(i32.div_s
(i32.const 10)
(local.get $x)
)
)
)
)
)
;; DEFAULT: (func $br-if-non-trap-side-effect (result i32)
;; DEFAULT-NEXT: (block $out (result i32)
;; DEFAULT-NEXT: (br_if $out
;; DEFAULT-NEXT: (call $value-callee)
;; DEFAULT-NEXT: (block (result i32)
;; DEFAULT-NEXT: (global.set $g
;; DEFAULT-NEXT: (i32.const 1)
;; DEFAULT-NEXT: )
;; DEFAULT-NEXT: (i32.const 0)
;; DEFAULT-NEXT: )
;; DEFAULT-NEXT: )
;; DEFAULT-NEXT: )
;; DEFAULT-NEXT: )
;; TNH: (func $br-if-non-trap-side-effect (result i32)
;; TNH-NEXT: (block $out (result i32)
;; TNH-NEXT: (br_if $out
;; TNH-NEXT: (call $value-callee)
;; TNH-NEXT: (block (result i32)
;; TNH-NEXT: (global.set $g
;; TNH-NEXT: (i32.const 1)
;; TNH-NEXT: )
;; TNH-NEXT: (i32.const 0)
;; TNH-NEXT: )
;; TNH-NEXT: )
;; TNH-NEXT: )
;; TNH-NEXT: )
(func $br-if-non-trap-side-effect (result i32)
;; Non-trap side effects (like global.set) in a condition still inhibit
;; optimization even when -tnh is enabled.
(block $out (result i32)
(br_if $out
(call $value-callee)
(block (result i32)
(global.set $g
(i32.const 1)
)
(i32.const 0)
)
)
)
)
)