diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/lit/passes/optimize-instructions-gc-tnh.wast | 290 |
1 files changed, 287 insertions, 3 deletions
diff --git a/test/lit/passes/optimize-instructions-gc-tnh.wast b/test/lit/passes/optimize-instructions-gc-tnh.wast index e1bbe65cd..d9520b18c 100644 --- a/test/lit/passes/optimize-instructions-gc-tnh.wast +++ b/test/lit/passes/optimize-instructions-gc-tnh.wast @@ -3,9 +3,9 @@ ;; RUN: wasm-opt %s --optimize-instructions -all --nominal -S -o - | filecheck %s --check-prefix NO_TNH (module - ;; TNH: (type $struct (struct )) - ;; NO_TNH: (type $struct (struct )) - (type $struct (struct_subtype data)) + ;; TNH: (type $struct (struct (field (mut i32)))) + ;; NO_TNH: (type $struct (struct (field (mut i32)))) + (type $struct (struct_subtype (field (mut i32)) data)) ;; TNH: (func $ref.eq (type $eqref_eqref_=>_i32) (param $a eqref) (param $b eqref) (result i32) ;; TNH-NEXT: (ref.eq @@ -191,4 +191,288 @@ ) ) ) + + ;; TNH: (func $if.arm.null (type $i32_ref|$struct|_=>_none) (param $x i32) (param $ref (ref $struct)) + ;; TNH-NEXT: (struct.set $struct 0 + ;; TNH-NEXT: (block (result (ref $struct)) + ;; TNH-NEXT: (drop + ;; TNH-NEXT: (local.get $x) + ;; TNH-NEXT: ) + ;; TNH-NEXT: (local.get $ref) + ;; TNH-NEXT: ) + ;; TNH-NEXT: (i32.const 1) + ;; TNH-NEXT: ) + ;; TNH-NEXT: (struct.set $struct 0 + ;; TNH-NEXT: (block (result (ref $struct)) + ;; TNH-NEXT: (drop + ;; TNH-NEXT: (local.get $x) + ;; TNH-NEXT: ) + ;; TNH-NEXT: (local.get $ref) + ;; TNH-NEXT: ) + ;; TNH-NEXT: (i32.const 2) + ;; TNH-NEXT: ) + ;; TNH-NEXT: ) + ;; NO_TNH: (func $if.arm.null (type $i32_ref|$struct|_=>_none) (param $x i32) (param $ref (ref $struct)) + ;; NO_TNH-NEXT: (struct.set $struct 0 + ;; NO_TNH-NEXT: (if (result (ref null $struct)) + ;; NO_TNH-NEXT: (local.get $x) + ;; NO_TNH-NEXT: (local.get $ref) + ;; NO_TNH-NEXT: (ref.null none) + ;; NO_TNH-NEXT: ) + ;; NO_TNH-NEXT: (i32.const 1) + ;; NO_TNH-NEXT: ) + ;; NO_TNH-NEXT: (struct.set $struct 0 + ;; NO_TNH-NEXT: (if (result (ref null $struct)) + ;; NO_TNH-NEXT: (local.get $x) + ;; NO_TNH-NEXT: (ref.null none) + ;; NO_TNH-NEXT: (local.get $ref) + ;; NO_TNH-NEXT: ) + ;; NO_TNH-NEXT: (i32.const 2) + ;; NO_TNH-NEXT: ) + ;; NO_TNH-NEXT: ) + (func $if.arm.null (param $x i32) (param $ref (ref $struct)) + ;; A set will trap on a null, so in tnh mode we know the null arm is not + ;; executed, and the other one is. + (struct.set $struct 0 + (if (result (ref null $struct)) + (local.get $x) + (local.get $ref) + (ref.null none) + ) + (i32.const 1) + ) + (struct.set $struct 0 + (if (result (ref null $struct)) + (local.get $x) + (ref.null none) + (local.get $ref) + ) + (i32.const 2) + ) + ) + + ;; TNH: (func $select.arm.null (type $i32_ref|$struct|_=>_none) (param $x i32) (param $ref (ref $struct)) + ;; TNH-NEXT: (struct.set $struct 0 + ;; TNH-NEXT: (block (result (ref $struct)) + ;; TNH-NEXT: (block + ;; TNH-NEXT: (drop + ;; TNH-NEXT: (ref.null none) + ;; TNH-NEXT: ) + ;; TNH-NEXT: (drop + ;; TNH-NEXT: (local.get $x) + ;; TNH-NEXT: ) + ;; TNH-NEXT: ) + ;; TNH-NEXT: (local.get $ref) + ;; TNH-NEXT: ) + ;; TNH-NEXT: (i32.const 1) + ;; TNH-NEXT: ) + ;; TNH-NEXT: (struct.set $struct 0 + ;; TNH-NEXT: (block (result (ref $struct)) + ;; TNH-NEXT: (drop + ;; TNH-NEXT: (ref.null none) + ;; TNH-NEXT: ) + ;; TNH-NEXT: (block (result (ref $struct)) + ;; TNH-NEXT: (drop + ;; TNH-NEXT: (local.get $x) + ;; TNH-NEXT: ) + ;; TNH-NEXT: (local.get $ref) + ;; TNH-NEXT: ) + ;; TNH-NEXT: ) + ;; TNH-NEXT: (i32.const 2) + ;; TNH-NEXT: ) + ;; TNH-NEXT: ) + ;; NO_TNH: (func $select.arm.null (type $i32_ref|$struct|_=>_none) (param $x i32) (param $ref (ref $struct)) + ;; NO_TNH-NEXT: (struct.set $struct 0 + ;; NO_TNH-NEXT: (select (result (ref null $struct)) + ;; NO_TNH-NEXT: (local.get $ref) + ;; NO_TNH-NEXT: (ref.null none) + ;; NO_TNH-NEXT: (local.get $x) + ;; NO_TNH-NEXT: ) + ;; NO_TNH-NEXT: (i32.const 1) + ;; NO_TNH-NEXT: ) + ;; NO_TNH-NEXT: (struct.set $struct 0 + ;; NO_TNH-NEXT: (select (result (ref null $struct)) + ;; NO_TNH-NEXT: (ref.null none) + ;; NO_TNH-NEXT: (local.get $ref) + ;; NO_TNH-NEXT: (local.get $x) + ;; NO_TNH-NEXT: ) + ;; NO_TNH-NEXT: (i32.const 2) + ;; NO_TNH-NEXT: ) + ;; NO_TNH-NEXT: ) + (func $select.arm.null (param $x i32) (param $ref (ref $struct)) + ;; As above but with a select. + (struct.set $struct 0 + (select (result (ref null $struct)) + (local.get $ref) + (ref.null none) + (local.get $x) + ) + (i32.const 1) + ) + (struct.set $struct 0 + (select (result (ref null $struct)) + (ref.null none) + (local.get $ref) + (local.get $x) + ) + (i32.const 2) + ) + ) + + ;; TNH: (func $select.arm.null.effects (type $none_=>_none) + ;; TNH-NEXT: (local $0 (ref $struct)) + ;; TNH-NEXT: (local $1 (ref $struct)) + ;; TNH-NEXT: (struct.set $struct 0 + ;; TNH-NEXT: (block (result (ref $struct)) + ;; TNH-NEXT: (local.set $0 + ;; TNH-NEXT: (call $get-ref) + ;; TNH-NEXT: ) + ;; TNH-NEXT: (block + ;; TNH-NEXT: (drop + ;; TNH-NEXT: (call $get-null) + ;; TNH-NEXT: ) + ;; TNH-NEXT: (drop + ;; TNH-NEXT: (call $get-i32) + ;; TNH-NEXT: ) + ;; TNH-NEXT: ) + ;; TNH-NEXT: (local.get $0) + ;; TNH-NEXT: ) + ;; TNH-NEXT: (i32.const 1) + ;; TNH-NEXT: ) + ;; TNH-NEXT: (struct.set $struct 0 + ;; TNH-NEXT: (block (result (ref $struct)) + ;; TNH-NEXT: (drop + ;; TNH-NEXT: (call $get-null) + ;; TNH-NEXT: ) + ;; TNH-NEXT: (block (result (ref $struct)) + ;; TNH-NEXT: (local.set $1 + ;; TNH-NEXT: (call $get-ref) + ;; TNH-NEXT: ) + ;; TNH-NEXT: (drop + ;; TNH-NEXT: (call $get-i32) + ;; TNH-NEXT: ) + ;; TNH-NEXT: (local.get $1) + ;; TNH-NEXT: ) + ;; TNH-NEXT: ) + ;; TNH-NEXT: (i32.const 2) + ;; TNH-NEXT: ) + ;; TNH-NEXT: ) + ;; NO_TNH: (func $select.arm.null.effects (type $none_=>_none) + ;; NO_TNH-NEXT: (struct.set $struct 0 + ;; NO_TNH-NEXT: (select (result (ref null $struct)) + ;; NO_TNH-NEXT: (call $get-ref) + ;; NO_TNH-NEXT: (call $get-null) + ;; NO_TNH-NEXT: (call $get-i32) + ;; NO_TNH-NEXT: ) + ;; NO_TNH-NEXT: (i32.const 1) + ;; NO_TNH-NEXT: ) + ;; NO_TNH-NEXT: (struct.set $struct 0 + ;; NO_TNH-NEXT: (select (result (ref null $struct)) + ;; NO_TNH-NEXT: (call $get-null) + ;; NO_TNH-NEXT: (call $get-ref) + ;; NO_TNH-NEXT: (call $get-i32) + ;; NO_TNH-NEXT: ) + ;; NO_TNH-NEXT: (i32.const 2) + ;; NO_TNH-NEXT: ) + ;; NO_TNH-NEXT: ) + (func $select.arm.null.effects + ;; As above but there are conflicting effects and we must add a local when + ;; we optimize. + (struct.set $struct 0 + (select (result (ref null $struct)) + (call $get-ref) + (call $get-null) + (call $get-i32) + ) + (i32.const 1) + ) + (struct.set $struct 0 + (select (result (ref null $struct)) + (call $get-null) + (call $get-ref) + (call $get-i32) + ) + (i32.const 2) + ) + ) + + ;; TNH: (func $null.arm.null.effects (type $none_=>_none) + ;; TNH-NEXT: (block ;; (replaces something unreachable we can't emit) + ;; TNH-NEXT: (drop + ;; TNH-NEXT: (block (result nullref) + ;; TNH-NEXT: (drop + ;; TNH-NEXT: (ref.as_non_null + ;; TNH-NEXT: (ref.null none) + ;; TNH-NEXT: ) + ;; TNH-NEXT: ) + ;; TNH-NEXT: (block (result nullref) + ;; TNH-NEXT: (drop + ;; TNH-NEXT: (call $get-i32) + ;; TNH-NEXT: ) + ;; TNH-NEXT: (ref.null none) + ;; TNH-NEXT: ) + ;; TNH-NEXT: ) + ;; TNH-NEXT: ) + ;; TNH-NEXT: (drop + ;; TNH-NEXT: (i32.const 1) + ;; TNH-NEXT: ) + ;; TNH-NEXT: (unreachable) + ;; TNH-NEXT: ) + ;; TNH-NEXT: ) + ;; NO_TNH: (func $null.arm.null.effects (type $none_=>_none) + ;; NO_TNH-NEXT: (struct.set $struct 0 + ;; NO_TNH-NEXT: (select (result (ref null $struct)) + ;; NO_TNH-NEXT: (ref.as_non_null + ;; NO_TNH-NEXT: (ref.null none) + ;; NO_TNH-NEXT: ) + ;; NO_TNH-NEXT: (ref.null none) + ;; NO_TNH-NEXT: (call $get-i32) + ;; NO_TNH-NEXT: ) + ;; NO_TNH-NEXT: (i32.const 1) + ;; NO_TNH-NEXT: ) + ;; NO_TNH-NEXT: ) + (func $null.arm.null.effects + ;; Verify we do not error on a null reference in a select, even if cast to + ;; non-null. + (struct.set $struct 0 + (select (result (ref null $struct)) + (ref.as_non_null + (ref.null none) + ) + (ref.null none) + (call $get-i32) + ) + (i32.const 1) + ) + ) + + ;; Helper functions. + + ;; TNH: (func $get-i32 (type $none_=>_i32) (result i32) + ;; TNH-NEXT: (unreachable) + ;; TNH-NEXT: ) + ;; NO_TNH: (func $get-i32 (type $none_=>_i32) (result i32) + ;; NO_TNH-NEXT: (unreachable) + ;; NO_TNH-NEXT: ) + (func $get-i32 (result i32) + (unreachable) + ) + ;; TNH: (func $get-ref (type $none_=>_ref|$struct|) (result (ref $struct)) + ;; TNH-NEXT: (unreachable) + ;; TNH-NEXT: ) + ;; NO_TNH: (func $get-ref (type $none_=>_ref|$struct|) (result (ref $struct)) + ;; NO_TNH-NEXT: (unreachable) + ;; NO_TNH-NEXT: ) + (func $get-ref (result (ref $struct)) + (unreachable) + ) + ;; TNH: (func $get-null (type $none_=>_nullref) (result nullref) + ;; TNH-NEXT: (unreachable) + ;; TNH-NEXT: ) + ;; NO_TNH: (func $get-null (type $none_=>_nullref) (result nullref) + ;; NO_TNH-NEXT: (unreachable) + ;; NO_TNH-NEXT: ) + (func $get-null (result (ref null none)) + (unreachable) + ) ) |