| ;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. |
| ;; NOTE: This test was ported using port_passes_tests_to_lit.py and could be cleaned up. |
| |
| ;; 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=T_N_H |
| |
| ;; The segments here will trap during startup as they are out of bounds. We |
| ;; can only remove such segments if we assume TrapsNeverHappen. |
| ;; |
| ;; The passive segments, however, can be removed: they do nothing during |
| ;; startup, and have no uses. |
| (module |
| ;; CHECK: (memory $0 16 17 shared) |
| (memory $0 16 17 shared) |
| |
| ;; CHECK: (data $0 (i32.const -1) "") |
| (data $0 (i32.const -1) "") |
| |
| (data $1 "") |
| |
| ;; CHECK: (table $0 1 1 funcref) |
| (table $0 1 1 funcref) |
| |
| ;; CHECK: (elem $0 (i32.const -1)) |
| (elem $0 (i32.const -1)) |
| |
| (elem $1 func) |
| ) |
| |
| ;; Some segments can be removed: any segment that writes to address 131072 or |
| ;; higher will trap, and must be kept (unless TNH). Only the $bad segment |
| ;; should remain for that reason, however, it keeps the memory alive which |
| ;; keeps the $ok* segments alive too. |
| (module |
| ;; CHECK: (memory $0 2 2) |
| (memory $0 2 2) |
| |
| ;; CHECK: (data $ok1 (i32.const 0) "a") |
| (data $ok1 (i32.const 0) "a") |
| ;; CHECK: (data $ok2 (i32.const 1000) "a") |
| (data $ok2 (i32.const 1000) "a") |
| ;; CHECK: (data $ok3 (i32.const 131071) "a") |
| (data $ok3 (i32.const 131071) "a") |
| ;; CHECK: (data $bad (i32.const 131071) "ab") |
| (data $bad (i32.const 131071) "ab") |
| ) |
| |
| ;; The following modules have variations on the bad segment. |
| (module |
| ;; CHECK: (memory $0 2 2) |
| (memory $0 2 2) |
| |
| ;; CHECK: (data $ok1 (i32.const 0) "a") |
| (data $ok1 (i32.const 0) "a") |
| ;; CHECK: (data $ok2 (i32.const 1000) "a") |
| (data $ok2 (i32.const 1000) "a") |
| ;; CHECK: (data $ok3 (i32.const 131071) "a") |
| (data $ok3 (i32.const 131071) "a") |
| ;; CHECK: (data $bad (i32.const 131072) "a") |
| (data $bad (i32.const 131072) "a") |
| ) |
| |
| (module |
| ;; CHECK: (memory $0 2 2) |
| (memory $0 2 2) |
| |
| ;; CHECK: (data $ok1 (i32.const 0) "a") |
| (data $ok1 (i32.const 0) "a") |
| ;; CHECK: (data $ok2 (i32.const 1000) "a") |
| (data $ok2 (i32.const 1000) "a") |
| ;; CHECK: (data $ok3 (i32.const 131071) "a") |
| (data $ok3 (i32.const 131071) "a") |
| ;; CHECK: (data $bad (i32.const 9999999) "a") |
| (data $bad (i32.const 9999999) "a") |
| ) |
| |
| (module |
| ;; CHECK: (memory $0 2 2) |
| (memory $0 2 2) |
| |
| ;; CHECK: (data $ok1 (i32.const 0) "a") |
| (data $ok1 (i32.const 0) "a") |
| ;; CHECK: (data $ok2 (i32.const 1000) "a") |
| (data $ok2 (i32.const 1000) "a") |
| ;; CHECK: (data $ok3 (i32.const 131071) "a") |
| (data $ok3 (i32.const 131071) "a") |
| ;; CHECK: (data $bad (i32.const -2) "a") |
| (data $bad (i32.const 4294967294) "a") |
| ) |
| |
| (module |
| ;; CHECK: (memory $0 2 2) |
| (memory $0 2 2) |
| |
| ;; CHECK: (data $ok1 (i32.const 0) "a") |
| (data $ok1 (i32.const 0) "a") |
| ;; CHECK: (data $ok2 (i32.const 1000) "a") |
| (data $ok2 (i32.const 1000) "a") |
| ;; CHECK: (data $ok3 (i32.const 131071) "a") |
| (data $ok3 (i32.const 131071) "a") |
| ;; CHECK: (data $bad (i32.const -6) "abcdefghijklmnop_overflow") |
| (data $bad (i32.const 4294967290) "abcdefghijklmnop_overflow") |
| ) |
| |
| (module |
| ;; CHECK: (memory $0 2 2) |
| (memory $0 2 2) |
| |
| ;; CHECK: (data $ok1 (i32.const 0) "a") |
| (data $ok1 (i32.const 0) "a") |
| ;; CHECK: (data $ok2 (i32.const 1000) "a") |
| (data $ok2 (i32.const 1000) "a") |
| ;; CHECK: (data $ok3 (i32.const 131071) "a") |
| (data $ok3 (i32.const 131071) "a") |
| ;; CHECK: (data $bad (i32.const -2) "a") |
| (data $bad (i32.const -2) "a") |
| ) |
| |
| ;; An imported global is an unknown offset, so it might trap. |
| (module |
| ;; CHECK: (import "a" "b" (global $imported i32)) |
| (import "a" "b" (global $imported i32)) |
| |
| ;; CHECK: (memory $0 2 2) |
| (memory $0 2 2) |
| |
| ;; CHECK: (data $ok1 (i32.const 0) "a") |
| (data $ok1 (i32.const 0) "a") |
| ;; CHECK: (data $ok2 (i32.const 1000) "a") |
| (data $ok2 (i32.const 1000) "a") |
| ;; CHECK: (data $ok3 (i32.const 131071) "a") |
| (data $ok3 (i32.const 131071) "a") |
| ;; CHECK: (data $bad (global.get $imported) "a") |
| (data $bad (global.get $imported) "a") |
| ) |
| |
| ;; Finally, a module with no bad segments. We can remove all the contents. |
| (module |
| (memory $0 2 2) |
| |
| (data $ok1 (i32.const 0) "a") |
| (data $ok2 (i32.const 1000) "a") |
| (data $ok3 (i32.const 131071) "a") |
| ) |
| |
| ;; Similar testing for element segments. One bad segment keeps it all alive |
| ;; here. |
| (module |
| (table 10 10 funcref) |
| |
| ;; CHECK: (type $0 (func)) |
| |
| ;; CHECK: (table $0 10 10 funcref) |
| |
| ;; CHECK: (elem $ok1 (i32.const 0) $func) |
| (elem $ok1 (i32.const 0) $func) |
| ;; CHECK: (elem $ok2 (i32.const 8) $func $func) |
| (elem $ok2 (i32.const 8) $func $func) |
| ;; CHECK: (elem $ok3 (i32.const 9) $func) |
| (elem $ok3 (i32.const 9) $func) |
| ;; CHECK: (elem $bad (i32.const 10) $func) |
| (elem $bad (i32.const 10) $func) |
| |
| ;; CHECK: (func $func (type $0) |
| ;; CHECK-NEXT: ) |
| ;; T_N_H: (type $0 (func)) |
| |
| ;; T_N_H: (func $func (type $0) |
| ;; T_N_H-NEXT: ) |
| (func $func) |
| ) |
| |
| ;; A different bad segment. |
| (module |
| (table 10 10 funcref) |
| |
| ;; CHECK: (type $0 (func)) |
| |
| ;; CHECK: (table $0 10 10 funcref) |
| |
| ;; CHECK: (elem $ok1 (i32.const 0) $func) |
| (elem $ok1 (i32.const 0) $func) |
| ;; CHECK: (elem $ok2 (i32.const 8) $func $func) |
| (elem $ok2 (i32.const 8) $func $func) |
| ;; CHECK: (elem $ok3 (i32.const 9) $func) |
| (elem $ok3 (i32.const 9) $func) |
| ;; CHECK: (elem $bad (i32.const 9) $func $func) |
| (elem $bad (i32.const 9) $func $func) |
| |
| ;; CHECK: (func $func (type $0) |
| ;; CHECK-NEXT: ) |
| ;; T_N_H: (type $0 (func)) |
| |
| ;; T_N_H: (func $func (type $0) |
| ;; T_N_H-NEXT: ) |
| (func $func) |
| ) |
| |
| ;; No bad segments: all element segments vanish. TODO: the function could too |
| (module |
| (table 10 10 funcref) |
| |
| (elem $ok1 (i32.const 0) $func) |
| (elem $ok2 (i32.const 8) $func $func) |
| (elem $ok3 (i32.const 9) $func) |
| |
| ;; CHECK: (type $0 (func)) |
| |
| ;; CHECK: (func $func (type $0) |
| ;; CHECK-NEXT: ) |
| ;; T_N_H: (type $0 (func)) |
| |
| ;; T_N_H: (func $func (type $0) |
| ;; T_N_H-NEXT: ) |
| (func $func) |
| ) |
| |
| ;; Multiple memories. One can be removed, the other remains due to a trapping |
| ;; segment. |
| (module |
| ;; CHECK: (memory $small 1 1) |
| (memory $small 1 1) |
| |
| (memory $big 2 2) |
| |
| ;; CHECK: (data $a (i32.const 100000) "ab") |
| (data $a (memory $small) (i32.const 100000) "ab") ;; fits in $big; not $small |
| |
| (data $b (memory $big) (i32.const 100000) "cd") |
| ) |
| |
| ;; Reverse order of memories. |
| (module |
| (memory $big 2 2) |
| |
| ;; CHECK: (memory $small 1 1) |
| (memory $small 1 1) |
| |
| ;; CHECK: (data $a (i32.const 100000) "ab") |
| (data $a (memory $small) (i32.const 100000) "ab") ;; fits in $big; not $small |
| |
| (data $b (memory $big) (i32.const 100000) "cd") |
| ) |