blob: b4823e82295aff5b9b3cc8c8ccf75978f0277a07 [file] [edit]
;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited.
;; RUN: foreach %s %t wasm-opt --all-features --closed-world --generate-global-effects --vacuum --type-merging --remove-unused-types -S -o - | filecheck %s --check-prefix VACUUM_FIRST
;; RUN: foreach %s %t wasm-opt --all-features --closed-world --generate-global-effects --type-merging --remove-unused-types --vacuum -S -o - | filecheck %s --check-prefix MERGE_FIRST
;; Test that indirect call effects are preserved when types are rewritten
;; globally. When we rewrite $effectful and $not-effectful into the same type,
;; the resulting type has the same effects as the union of the two. This is
;; pessimistic since indirect calls that targeted $not-effectful now look like
;; they may target $effectful as well which is not true in practice. This is the
;; best we can do without preserving extra information before rewriting.
(module
(rec
;; VACUUM_FIRST: (type $effectful (func (result i32)))
;; MERGE_FIRST: (type $effectful (func (result i32)))
(type $effectful (func (result i32)))
(type $not-effectful (func (result i32)))
)
;; VACUUM_FIRST: (func $unreachable (type $effectful) (result i32)
;; VACUUM_FIRST-NEXT: (unreachable)
;; VACUUM_FIRST-NEXT: )
;; MERGE_FIRST: (func $unreachable (type $effectful) (result i32)
;; MERGE_FIRST-NEXT: (unreachable)
;; MERGE_FIRST-NEXT: )
(func $unreachable (type $effectful)
(unreachable)
)
;; VACUUM_FIRST: (func $const (type $effectful) (result i32)
;; VACUUM_FIRST-NEXT: (i32.const 0)
;; VACUUM_FIRST-NEXT: )
;; MERGE_FIRST: (func $const (type $effectful) (result i32)
;; MERGE_FIRST-NEXT: (i32.const 0)
;; MERGE_FIRST-NEXT: )
(func $const (type $not-effectful)
(i32.const 0)
)
(func
;; Reference the functions in a ref.func so that it's possible that they're
;; the target of indirect calls.
(drop (ref.func $unreachable))
(drop (ref.func $const))
)
;; VACUUM_FIRST: (func $test (type $0) (param $effectful-ref (ref $effectful)) (param $not-effectful-ref (ref $effectful))
;; VACUUM_FIRST-NEXT: (drop
;; VACUUM_FIRST-NEXT: (call_ref $effectful
;; VACUUM_FIRST-NEXT: (local.get $effectful-ref)
;; VACUUM_FIRST-NEXT: )
;; VACUUM_FIRST-NEXT: )
;; VACUUM_FIRST-NEXT: )
;; MERGE_FIRST: (func $test (type $0) (param $effectful-ref (ref $effectful)) (param $not-effectful-ref (ref $effectful))
;; MERGE_FIRST-NEXT: (drop
;; MERGE_FIRST-NEXT: (call_ref $effectful
;; MERGE_FIRST-NEXT: (local.get $not-effectful-ref)
;; MERGE_FIRST-NEXT: )
;; MERGE_FIRST-NEXT: )
;; MERGE_FIRST-NEXT: (drop
;; MERGE_FIRST-NEXT: (call_ref $effectful
;; MERGE_FIRST-NEXT: (local.get $effectful-ref)
;; MERGE_FIRST-NEXT: )
;; MERGE_FIRST-NEXT: )
;; MERGE_FIRST-NEXT: )
(func $test (param $effectful-ref (ref $effectful)) (param $not-effectful-ref (ref $not-effectful))
;; If we run global effects followed by vacuum, we can tell that this call
;; can't possibly have any effects and remove it. But if we run global
;; effects, then merge types, we can no longer distinguish this from
;; $effectful, so we have to conservatively not optimize this out.
(drop
(call_ref $not-effectful (local.get $not-effectful-ref))
)
(drop
(call_ref $effectful (local.get $effectful-ref))
)
)
)
(module
(rec
;; VACUUM_FIRST: (type $nop-type (func))
;; MERGE_FIRST: (type $nop-type (func))
(type $nop-type (func))
(type $effectful-type (func))
)
;; VACUUM_FIRST: (type $import-type (func))
;; MERGE_FIRST: (type $import-type (func))
(type $import-type (func))
;; VACUUM_FIRST: (import "" "" (func $import (type $import-type)))
;; MERGE_FIRST: (import "" "" (func $import (type $import-type)))
(import "" "" (func $import (type $import-type)))
;; VACUUM_FIRST: (func $nop (type $nop-type)
;; VACUUM_FIRST-NEXT: (nop)
;; VACUUM_FIRST-NEXT: )
;; MERGE_FIRST: (func $nop (type $nop-type)
;; MERGE_FIRST-NEXT: (nop)
;; MERGE_FIRST-NEXT: )
(func $nop (type $nop-type)
(nop)
)
;; VACUUM_FIRST: (func $effectful (type $nop-type)
;; VACUUM_FIRST-NEXT: (call $import)
;; VACUUM_FIRST-NEXT: )
;; MERGE_FIRST: (func $effectful (type $nop-type)
;; MERGE_FIRST-NEXT: (call $import)
;; MERGE_FIRST-NEXT: )
(func $effectful (type $effectful-type)
;; We need an extra indirection here for the test.
;; If we give $import the type $effectful-type directly, the type will be
;; public and --type-merging won't optimize it.
(call $import)
)
(func
(drop (ref.func $nop))
(drop (ref.func $effectful))
)
;; VACUUM_FIRST: (func $calls-effectful-type (type $0) (param $ref (ref $nop-type))
;; VACUUM_FIRST-NEXT: (call_ref $nop-type
;; VACUUM_FIRST-NEXT: (local.get $ref)
;; VACUUM_FIRST-NEXT: )
;; VACUUM_FIRST-NEXT: )
;; MERGE_FIRST: (func $calls-effectful-type (type $0) (param $ref (ref $nop-type))
;; MERGE_FIRST-NEXT: (call_ref $nop-type
;; MERGE_FIRST-NEXT: (local.get $ref)
;; MERGE_FIRST-NEXT: )
;; MERGE_FIRST-NEXT: )
(func $calls-effectful-type (param $ref (ref $effectful-type))
;; See #8831. Test that effects are preserved after type merging even for
;; 'unknown' effects that are represented with a missing entry in the
;; `indirectCallEffects` map.
(call_ref $effectful-type
(local.get $ref)
)
)
)