| ;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. |
| |
| ;; RUN: foreach %s %t wasm-opt --remove-unused-module-elements -all -S -o - | filecheck %s |
| ;; RUN: foreach %s %t wasm-opt --remove-unused-module-elements -tnh -all -S -o - | filecheck %s --check-prefix TNH__ |
| |
| (module |
| ;; CHECK: (type $i32 (func (result i32))) |
| ;; TNH__: (type $i32 (func (result i32))) |
| (type $i32 (func (result i32))) |
| |
| ;; CHECK: (type $1 (func)) |
| |
| ;; CHECK: (type $2 (func (result i64))) |
| |
| ;; CHECK: (table $table 1 funcref (ref.func $i32)) |
| ;; TNH__: (type $1 (func)) |
| |
| ;; TNH__: (table $table 1 funcref (ref.func $i32)) |
| (table $table 1 funcref (ref.func $i32)) |
| |
| ;; CHECK: (elem $elem (i32.const 0) $i64) |
| (elem $elem (i32.const 0) func $i64) |
| |
| ;; CHECK: (export "caller" (func $caller)) |
| ;; TNH__: (export "caller" (func $caller)) |
| (export "caller" (func $caller)) |
| |
| ;; CHECK: (func $caller (type $1) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (call_indirect $table (type $i32) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; TNH__: (func $caller (type $1) |
| ;; TNH__-NEXT: (drop |
| ;; TNH__-NEXT: (call_indirect $table (type $i32) |
| ;; TNH__-NEXT: (i32.const 0) |
| ;; TNH__-NEXT: ) |
| ;; TNH__-NEXT: ) |
| ;; TNH__-NEXT: ) |
| (func $caller |
| ;; This call traps on the wrong type: we call $i32, but the elem puts an $i64 |
| ;; there. When optimizing, we should not remove the elem, as then we would |
| ;; end up calling the default value of $i32, which would not trap. |
| ;; |
| ;; However, when we assume traps never happen, we can still optimize here |
| ;; and remove the elem. |
| (drop |
| (call_indirect $table (type $i32) |
| (i32.const 0) |
| ) |
| ) |
| ) |
| |
| ;; CHECK: (func $i32 (type $i32) (result i32) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; TNH__: (func $i32 (type $i32) (result i32) |
| ;; TNH__-NEXT: (i32.const 0) |
| ;; TNH__-NEXT: ) |
| (func $i32 (type $i32) (result i32) |
| (i32.const 0) |
| ) |
| |
| ;; CHECK: (func $i64 (type $2) (result i64) |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: ) |
| (func $i64 (result i64) |
| (unreachable) |
| ) |
| ) |
| |
| ;; As above, but without an initial value in the table. |
| (module |
| ;; CHECK: (type $0 (func)) |
| |
| ;; CHECK: (type $i32 (func (result i32))) |
| ;; TNH__: (type $0 (func)) |
| |
| ;; TNH__: (type $i32 (func (result i32))) |
| (type $i32 (func (result i32))) |
| |
| ;; CHECK: (table $table 1 funcref) |
| ;; TNH__: (table $table 1 funcref) |
| (table $table 1 funcref) |
| |
| (elem $elem (i32.const 0) func $i64) |
| |
| ;; CHECK: (export "caller" (func $caller)) |
| ;; TNH__: (export "caller" (func $caller)) |
| (export "caller" (func $caller)) |
| |
| ;; CHECK: (func $caller (type $0) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (call_indirect $table (type $i32) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; TNH__: (func $caller (type $0) |
| ;; TNH__-NEXT: (drop |
| ;; TNH__-NEXT: (call_indirect $table (type $i32) |
| ;; TNH__-NEXT: (i32.const 0) |
| ;; TNH__-NEXT: ) |
| ;; TNH__-NEXT: ) |
| ;; TNH__-NEXT: ) |
| (func $caller |
| ;; Without an initial value in the table, we can optimize (removing the |
| ;; elem) even without TNH: we still trap, just on a null rather than the |
| ;; wrong type. |
| (drop |
| (call_indirect $table (type $i32) |
| (i32.const 0) |
| ) |
| ) |
| ) |
| |
| (func $i32 (type $i32) (result i32) |
| (i32.const 0) |
| ) |
| |
| (func $i64 (result i64) |
| (unreachable) |
| ) |
| ) |
| |