blob: 12e5719cdcc10797f4aecf38e41118116f1fd833 [file] [edit]
;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited.
;; Test the optimal path of closed-world and traps-never happen, compared to the
;; default of open world with trapping.
;; RUN: foreach %s %t wasm-opt --remove-unused-module-elements --closed-world -tnh -all -S -o - | filecheck %s --check-prefix CLOSED_TNH
;; RUN: foreach %s %t wasm-opt --remove-unused-module-elements -all -S -o - | filecheck %s --check-prefix OPEN_TRAPS
;; A table with a single elem with non-constant offset that we can remove.
;; Usually a non-constant segment suggests it might overlap with others, which
;; causes us to keep all elems, but here there is just one, so we can optimize.
;; We require closed world (to know about which calls can reach it - the only
;; call is to type $func, so elem $elem which contains $other is not needed).
;; We also require traps-never-happen, as an elem with non-constant offset can
;; trap, normally. When both closed world and tnh, we remove elem $elem.
(module
;; CLOSED_TNH: (type $func (func))
;; OPEN_TRAPS: (type $func (func))
(type $func (func))
;; OPEN_TRAPS: (type $other (func (result i32)))
(type $other (func (result i32)))
;; OPEN_TRAPS: (import "a" "b" (global $offset i32))
(import "a" "b" (global $offset i32))
;; CLOSED_TNH: (table $table 6 6 funcref)
;; OPEN_TRAPS: (table $table 6 6 funcref)
(table $table 6 6 funcref)
;; OPEN_TRAPS: (elem $elem (global.get $offset) $other)
(elem $elem (global.get $offset) $other)
;; OPEN_TRAPS: (export "export" (func $export))
;; OPEN_TRAPS: (func $other (type $other) (result i32)
;; OPEN_TRAPS-NEXT: (i32.const 42)
;; OPEN_TRAPS-NEXT: )
(func $other (type $other) (result i32)
(i32.const 42)
)
;; CLOSED_TNH: (export "export" (func $export))
;; CLOSED_TNH: (func $export (type $func)
;; CLOSED_TNH-NEXT: (call_indirect $table (type $func)
;; CLOSED_TNH-NEXT: (i32.const 0)
;; CLOSED_TNH-NEXT: )
;; CLOSED_TNH-NEXT: )
;; OPEN_TRAPS: (func $export (type $func)
;; OPEN_TRAPS-NEXT: (call_indirect $table (type $func)
;; OPEN_TRAPS-NEXT: (i32.const 0)
;; OPEN_TRAPS-NEXT: )
;; OPEN_TRAPS-NEXT: )
(func $export (export "export")
;; Call with type $func, but the table contains $other.
(call_indirect $table (type $func)
(i32.const 0)
)
)
)
;; As above, but now we have two segments, one constant. We don't know if they
;; overlap, so we normally assume the worst. However, with tnh, we can assume no
;; traps, and remove elem $elem. (We cannot remove elem $second in either case,
;; as it contains a function we have an indirect call for its type.)
(module
;; CLOSED_TNH: (type $func (func))
;; OPEN_TRAPS: (type $func (func))
(type $func (func))
;; OPEN_TRAPS: (type $other (func (result i32)))
(type $other (func (result i32)))
;; OPEN_TRAPS: (import "a" "b" (global $offset i32))
(import "a" "b" (global $offset i32))
;; CLOSED_TNH: (table $table 6 6 funcref)
;; OPEN_TRAPS: (table $table 6 6 funcref)
(table $table 6 6 funcref)
;; OPEN_TRAPS: (elem $elem (global.get $offset) $other)
(elem $elem (global.get $offset) $other)
;; CLOSED_TNH: (elem $second (i32.const 0) $export)
;; OPEN_TRAPS: (elem $second (i32.const 0) $export)
(elem $second (i32.const 0) $export)
;; OPEN_TRAPS: (export "export" (func $export))
;; OPEN_TRAPS: (func $other (type $other) (result i32)
;; OPEN_TRAPS-NEXT: (i32.const 42)
;; OPEN_TRAPS-NEXT: )
(func $other (type $other) (result i32)
(i32.const 42)
)
;; CLOSED_TNH: (export "export" (func $export))
;; CLOSED_TNH: (func $export (type $func)
;; CLOSED_TNH-NEXT: (call_indirect $table (type $func)
;; CLOSED_TNH-NEXT: (i32.const 0)
;; CLOSED_TNH-NEXT: )
;; CLOSED_TNH-NEXT: )
;; OPEN_TRAPS: (func $export (type $func)
;; OPEN_TRAPS-NEXT: (call_indirect $table (type $func)
;; OPEN_TRAPS-NEXT: (i32.const 0)
;; OPEN_TRAPS-NEXT: )
;; OPEN_TRAPS-NEXT: )
(func $export (export "export")
(call_indirect $table (type $func)
(i32.const 0)
)
)
)