;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. ;; RUN: wasm-opt %s --vacuum -all -S -o - | filecheck %s (module ;; CHECK: (import "binaryen-intrinsics" "call.without.effects" (func $call.without.effects (type $2) (param funcref) (result i32))) (import "binaryen-intrinsics" "call.without.effects" (func $call.without.effects (param funcref) (result i32))) ;; CHECK: (import "binaryen-intrinsics" "call.without.effects" (func $call.without.effects-fj (type $3) (param f32 funcref) (result i64))) (import "binaryen-intrinsics" "call.without.effects" (func $call.without.effects-fj (param f32) (param funcref) (result i64))) ;; CHECK: (import "binaryen-intrinsics" "call.without.effects" (func $call.without.effects-ref (type $4) (param funcref) (result (ref any)))) (import "binaryen-intrinsics" "call.without.effects" (func $call.without.effects-ref (param funcref) (result (ref any)))) ;; CHECK: (func $used (type $1) (result i32) ;; CHECK-NEXT: (local $i32 i32) ;; CHECK-NEXT: (local.set $i32 ;; CHECK-NEXT: (call $call.without.effects ;; CHECK-NEXT: (ref.func $i) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.get $i32) ;; CHECK-NEXT: ) (func $used (result i32) (local $i32 i32) ;; The result is used (by the local.set), so we cannot do anything here. (local.set $i32 (call $call.without.effects (ref.func $i)) ) (local.get $i32) ) ;; CHECK: (func $unused (type $0) ;; CHECK-NEXT: (nop) ;; CHECK-NEXT: ) (func $unused ;; The result is unused, so we can remove the call. (drop (call $call.without.effects (ref.func $i)) ) ) ;; CHECK: (func $unused-fj (type $0) ;; CHECK-NEXT: (nop) ;; CHECK-NEXT: ) (func $unused-fj ;; As above, but with an extra float param and a different result type. (drop (call $call.without.effects-fj (f32.const 2.71828) (ref.func $fj)) ) ) ;; CHECK: (func $unused-fj-side-effects (type $5) (result f32) ;; CHECK-NEXT: (local $f32 f32) ;; CHECK-NEXT: (local.set $f32 ;; CHECK-NEXT: (f32.const 2.718280076980591) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.get $f32) ;; CHECK-NEXT: ) (func $unused-fj-side-effects (result f32) (local $f32 f32) ;; As above, but side effects in the param. We must keep the params around ;; and drop them. (drop (call $call.without.effects-fj (local.tee $f32 (f32.const 2.71828) ) (ref.func $fj) ) ) (local.get $f32) ) ;; CHECK: (func $unused-unreachable (type $0) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (call $call.without.effects-fj ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: (ref.func $fj) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $unused-unreachable ;; An unused result, but the call is unreachable and so we ignore it (and ;; leave it for DCE). (drop (call $call.without.effects-fj (unreachable) (ref.func $fj)) ) ) ;; CHECK: (func $used-fallthrough (type $0) ;; CHECK-NEXT: (local $i32 i32) ;; CHECK-NEXT: (local.set $i32 ;; CHECK-NEXT: (if (result i32) ;; CHECK-NEXT: (block $condition (result i32) ;; CHECK-NEXT: (call $nop) ;; CHECK-NEXT: (call $call.without.effects ;; CHECK-NEXT: (ref.func $i) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (then ;; CHECK-NEXT: (block $ifTrue (result i32) ;; CHECK-NEXT: (call $nop) ;; CHECK-NEXT: (call $call.without.effects ;; CHECK-NEXT: (ref.func $i) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (else ;; CHECK-NEXT: (block $ifFalse (result i32) ;; CHECK-NEXT: (call $nop) ;; CHECK-NEXT: (call $call.without.effects ;; CHECK-NEXT: (ref.func $i) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $used-fallthrough (local $i32 i32) (local.set $i32 (if (result i32) ;; The block falls through a value that is used as the if condition. (block $condition (result i32) ;; Add a call to $nop so that the blocks are not optimized away. (call $nop) (call $call.without.effects (ref.func $i)) ) ;; The arms fall through their blocks and also through the if, and end ;; up used by the set. (then (block $ifTrue (result i32) (call $nop) (call $call.without.effects (ref.func $i)) ) ) (else (block $ifFalse (result i32) (call $nop) (call $call.without.effects (ref.func $i)) ) ) ) ) ) ;; CHECK: (func $unused-fallthrough (type $0) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (if (result i32) ;; CHECK-NEXT: (block $condition (result i32) ;; CHECK-NEXT: (call $nop) ;; CHECK-NEXT: (call $call.without.effects ;; CHECK-NEXT: (ref.func $i) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (then ;; CHECK-NEXT: (block $ifTrue (result i32) ;; CHECK-NEXT: (call $nop) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (else ;; CHECK-NEXT: (block $ifFalse (result i32) ;; CHECK-NEXT: (call $nop) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $unused-fallthrough (drop (if (result i32) (block $condition (result i32) (call $nop) (call $call.without.effects (ref.func $i)) ) ;; As above, but now there is a drop outside the if, so the arms are ;; unused and we can optimize them. (then (block $ifTrue (result i32) (call $nop) (call $call.without.effects (ref.func $i)) ) ) (else (block $ifFalse (result i32) (call $nop) (call $call.without.effects (ref.func $i)) ) ) ) ) ) ;; CHECK: (func $unused-fallthrough-bad-type (type $0) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (if (result (ref any)) ;; CHECK-NEXT: (call $i) ;; CHECK-NEXT: (then ;; CHECK-NEXT: (call $call.without.effects-ref ;; CHECK-NEXT: (ref.func $ref) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (else ;; CHECK-NEXT: (call $call.without.effects-ref ;; CHECK-NEXT: (ref.func $ref) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $unused-fallthrough-bad-type (drop (if (result (ref any)) (call $i) ;; As above, but the type of these unused values prevents us from ;; optimizing as we cannot create a "zero" for them. (then (call $call.without.effects-ref (ref.func $ref)) ) (else (call $call.without.effects-ref (ref.func $ref)) ) ) ) ) ;; CHECK: (func $i (type $1) (result i32) ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) (func $i (result i32) ;; Helper function for the above. (unreachable) ) ;; CHECK: (func $fj (type $6) (param $0 f32) (result i64) ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) (func $fj (param f32) (result i64) ;; Helper function for the above. (unreachable) ) ;; CHECK: (func $ref (type $7) (result (ref any)) ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) (func $ref (result (ref any)) ;; Helper function for the above. (unreachable) ) ;; CHECK: (func $nop (type $0) ;; CHECK-NEXT: (nop) ;; CHECK-NEXT: ) (func $nop ;; Helper function for the above. (nop) ) )