;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. ;; RUN: wasm-opt %s --dce -all -S -o - | filecheck %s ;; If either try body or catch body is reachable, the whole try construct is ;; reachable (module ;; CHECK: (type $0 (func)) ;; CHECK: (type $1 (func (param i32))) ;; CHECK: (type $2 (func (param eqref))) ;; CHECK: (type $3 (func (param i32 i32))) ;; CHECK: (type $4 (func (result i32))) ;; CHECK: (type $struct (struct (field (mut eqref)))) (type $struct (struct (field (mut (ref null eq))))) ;; CHECK: (tag $e) (tag $e) ;; CHECK: (tag $e-i32 (param i32)) (tag $e-i32 (param i32)) ;; CHECK: (tag $e-eqref (param eqref)) (tag $e-eqref (param (ref null eq))) ;; CHECK: (func $foo (type $0) ;; CHECK-NEXT: ) (func $foo) ;; CHECK: (func $try_unreachable (type $0) ;; CHECK-NEXT: (try ;; CHECK-NEXT: (do ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (catch_all ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (call $foo) ;; CHECK-NEXT: ) (func $try_unreachable (try (do (unreachable) ) (catch_all) ) (call $foo) ;; shouldn't be dce'd ) ;; CHECK: (func $catch_unreachable (type $0) ;; CHECK-NEXT: (try ;; CHECK-NEXT: (do ;; CHECK-NEXT: ) ;; CHECK-NEXT: (catch_all ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (call $foo) ;; CHECK-NEXT: ) (func $catch_unreachable (try (do) (catch_all (unreachable) ) ) (call $foo) ;; shouldn't be dce'd ) ;; CHECK: (func $both_unreachable (type $0) ;; CHECK-NEXT: (try ;; CHECK-NEXT: (do ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (catch_all ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $both_unreachable (try (do (unreachable) ) (catch_all (unreachable) ) ) (call $foo) ;; should be dce'd ) ;; CHECK: (func $rethrow (type $0) ;; CHECK-NEXT: (try $l0 ;; CHECK-NEXT: (do ;; CHECK-NEXT: ) ;; CHECK-NEXT: (catch $e ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (rethrow $l0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $rethrow (try $l0 (do) (catch $e (drop ;; This i32.add will be dce'd (i32.add (i32.const 0) (rethrow $l0) ) ) ) ) ) ;; CHECK: (func $call-pop-catch (type $0) ;; CHECK-NEXT: (local $0 i32) ;; CHECK-NEXT: (block $label ;; CHECK-NEXT: (try ;; CHECK-NEXT: (do ;; CHECK-NEXT: (nop) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (catch $e-i32 ;; CHECK-NEXT: (local.set $0 ;; CHECK-NEXT: (pop i32) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (block ;; CHECK-NEXT: (block ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (br $label) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $call-pop-catch (block $label (try (do (nop) ) (catch $e-i32 ;; This call is unreachable and can be removed. The pop, however, must ;; be carefully handled while we do so, to not break validation. (call $helper-i32-i32 (pop i32) (br $label) ) (nop) ) ) ) ) ;; CHECK: (func $helper-i32-i32 (type $3) (param $0 i32) (param $1 i32) ;; CHECK-NEXT: (nop) ;; CHECK-NEXT: ) (func $helper-i32-i32 (param $0 i32) (param $1 i32) (nop) ) ;; CHECK: (func $pop-within-block (type $4) (result i32) ;; CHECK-NEXT: (local $0 eqref) ;; CHECK-NEXT: (try (result i32) ;; CHECK-NEXT: (do ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (catch $e-eqref ;; CHECK-NEXT: (local.set $0 ;; CHECK-NEXT: (pop eqref) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (block ;; CHECK-NEXT: (block ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (struct.new $struct ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $pop-within-block (result i32) (try (result i32) (do (i32.const 0) ) (catch $e-eqref (drop ;; Optimization moves the 'pop' inside a block, which needs to be ;; extracted out of the block at the end. ;; (block ;; (drop ;; (struct.new $struct.0 ;; (pop eqref) ;; ) ;; ) ;; (unreachable) ;; ) (ref.eq (struct.new $struct (pop (ref null eq)) ) (unreachable) ) ) (i32.const 0) ) ) ) )