| ;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. |
| |
| ;; RUN: foreach %s %t wasm-opt -all --closed-world --gto --preserve-type-order -S -o - | filecheck %s |
| |
| (module |
| (rec |
| ;; CHECK: (rec |
| ;; CHECK-NEXT: (type $struct (descriptor $desc) (struct (field i32))) |
| (type $struct (descriptor $desc) (struct (field i32))) |
| ;; CHECK: (type $desc (describes $struct) (struct)) |
| (type $desc (describes $struct) (struct)) |
| ;; CHECK: (type $pair (struct)) |
| (type $pair (struct (field (ref $struct)) (field (ref $struct)))) |
| ;; CHECK: (type $used-pair (struct (field (ref $struct)) (field (ref $struct)))) |
| (type $used-pair (struct (field (ref $struct)) (field (ref $struct)))) |
| ) |
| |
| ;; CHECK: (type $4 (func (param (ref $struct) (ref $used-pair)))) |
| |
| ;; CHECK: (global $nullable-desc (ref null (exact $desc)) (struct.new_default $desc)) |
| (global $nullable-desc (ref null (exact $desc)) (struct.new $desc)) |
| |
| ;; Check that we generate fresh names for added globals. |
| ;; CHECK: (global $gto-removed-1 nullref (ref.null none)) |
| (global $gto-removed-1 nullref (ref.null none)) |
| |
| ;; CHECK: (global $second-traps (ref $pair) (struct.new_default $pair)) |
| (global $second-traps (ref $pair) |
| ;; Both fields will be removed, but only the second can trap, so only the |
| ;; second will be moved to a new global. |
| (struct.new $pair |
| (struct.new_desc $struct |
| (i32.const 0) |
| (struct.new $desc) |
| ) |
| (struct.new_desc $struct |
| (i32.const 1) |
| (ref.null none) |
| ) |
| ) |
| ) |
| |
| ;; CHECK: (global $first-traps (ref $pair) (struct.new_default $pair)) |
| (global $first-traps (ref $pair) |
| ;; Same as above, but now the first traps (or at least we assume it can |
| ;; based on its type). |
| (struct.new $pair |
| (struct.new_desc $struct |
| (i32.const 2) |
| (global.get $nullable-desc) |
| ) |
| (struct.new_desc $struct |
| (i32.const 3) |
| (struct.new $desc) |
| ) |
| ) |
| ) |
| |
| ;; CHECK: (global $used-traps (ref $used-pair) (struct.new $used-pair |
| ;; CHECK-NEXT: (struct.new_desc $struct |
| ;; CHECK-NEXT: (i32.const 4) |
| ;; CHECK-NEXT: (ref.null none) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (struct.new_desc $struct |
| ;; CHECK-NEXT: (i32.const 5) |
| ;; CHECK-NEXT: (ref.null none) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: )) |
| (global $used-traps (ref $used-pair) |
| ;; Now both trap, but they are also used, so they will not be removed and no |
| ;; globals will be created. |
| (struct.new $used-pair |
| (struct.new_desc $struct |
| (i32.const 4) |
| (ref.null none) |
| ) |
| (struct.new_desc $struct |
| (i32.const 5) |
| (ref.null none) |
| ) |
| ) |
| ) |
| |
| ;; CHECK: (global $gto-removed-0 (ref (exact $struct)) (struct.new_desc $struct |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: (ref.null none) |
| ;; CHECK-NEXT: )) |
| |
| ;; CHECK: (global $gto-removed-1_6 (ref (exact $struct)) (struct.new_desc $struct |
| ;; CHECK-NEXT: (i32.const 2) |
| ;; CHECK-NEXT: (global.get $nullable-desc) |
| ;; CHECK-NEXT: )) |
| |
| ;; CHECK: (func $use-struct-fields (type $4) (param $0 (ref $struct)) (param $1 (ref $used-pair)) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (struct.get $struct 0 |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (struct.get $used-pair 0 |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (struct.get $used-pair 1 |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $use-struct-fields (param (ref $struct)) (param (ref $used-pair)) |
| ;; Prevent the i32s in the initializers from being removed. |
| (drop |
| (struct.get $struct 0 |
| (local.get 0) |
| ) |
| ) |
| ;; Prevent the fields in used-pair from being removed. |
| (drop |
| (struct.get $used-pair 0 |
| (local.get 1) |
| ) |
| ) |
| (drop |
| (struct.get $used-pair 1 |
| (local.get 1) |
| ) |
| ) |
| ) |
| ) |
| |
| ;; The descriptor here is not needed, but we now optimize descriptors in |
| ;; Unsubtyping, so we do nothing here. |
| (module |
| (rec |
| ;; CHECK: (rec |
| ;; CHECK-NEXT: (type $A (descriptor $B) (struct)) |
| (type $A (descriptor $B) (struct)) |
| ;; CHECK: (type $B (describes $A) (struct)) |
| (type $B (describes $A) (struct)) |
| ) |
| |
| ;; CHECK: (type $2 (func)) |
| |
| ;; CHECK: (func $test (type $2) |
| ;; CHECK-NEXT: (local $A (ref $A)) |
| ;; CHECK-NEXT: (local $B (ref $B)) |
| ;; CHECK-NEXT: ) |
| (func $test |
| (local $A (ref $A)) |
| (local $B (ref $B)) |
| ) |
| ) |
| |
| |