summaryrefslogtreecommitdiff
path: root/test/lit
diff options
context:
space:
mode:
Diffstat (limited to 'test/lit')
-rw-r--r--test/lit/passes/gufa-refs.wast375
1 files changed, 306 insertions, 69 deletions
diff --git a/test/lit/passes/gufa-refs.wast b/test/lit/passes/gufa-refs.wast
index e02fdc70a..9e17a3a69 100644
--- a/test/lit/passes/gufa-refs.wast
+++ b/test/lit/passes/gufa-refs.wast
@@ -2452,11 +2452,11 @@
(type $substruct (struct_subtype (field i32) (field i32) $struct))
;; CHECK: (type $none_=>_none (func_subtype func))
+ ;; CHECK: (type $i32_=>_none (func_subtype (param i32) func))
+
;; CHECK: (type $subsubstruct (struct_subtype (field i32) (field i32) (field i32) $substruct))
(type $subsubstruct (struct_subtype (field i32) (field i32) (field i32) $substruct))
- ;; CHECK: (type $i32_=>_none (func_subtype (param i32) func))
-
;; CHECK: (type $other (struct_subtype data))
(type $other (struct_subtype data))
@@ -2469,12 +2469,16 @@
;; CHECK: (import "a" "b" (func $import (result i32)))
(import "a" "b" (func $import (result i32)))
+ ;; CHECK: (export "test-cones" (func $test-cones))
+
;; CHECK: (export "ref.test-inexact" (func $ref.test-inexact))
;; CHECK: (export "ref.eq-zero" (func $ref.eq-zero))
;; CHECK: (export "ref.eq-unknown" (func $ref.eq-unknown))
+ ;; CHECK: (export "ref.eq-cone" (func $ref.eq-cone))
+
;; CHECK: (export "local-no" (func $ref.eq-local-no))
;; CHECK: (func $test (type $none_=>_none)
@@ -2608,6 +2612,114 @@
)
)
+ ;; CHECK: (func $test-cones (type $i32_=>_none) (param $x i32)
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (ref.cast_static $struct
+ ;; CHECK-NEXT: (select (result (ref null $struct))
+ ;; CHECK-NEXT: (struct.new $struct
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (ref.null none)
+ ;; CHECK-NEXT: (local.get $x)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (ref.cast_static $struct
+ ;; CHECK-NEXT: (select (result (ref $struct))
+ ;; CHECK-NEXT: (struct.new $struct
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (struct.new $substruct
+ ;; CHECK-NEXT: (i32.const 2)
+ ;; CHECK-NEXT: (i32.const 3)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.get $x)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (ref.cast_static $substruct
+ ;; CHECK-NEXT: (select (result (ref $struct))
+ ;; CHECK-NEXT: (struct.new $struct
+ ;; CHECK-NEXT: (i32.const 4)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (struct.new $substruct
+ ;; CHECK-NEXT: (i32.const 5)
+ ;; CHECK-NEXT: (i32.const 6)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.get $x)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (unreachable)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $test-cones (export "test-cones") (param $x i32)
+ ;; The input to the ref.cast is potentially null, so we cannot infer here.
+ (drop
+ (ref.cast_static $struct
+ (select
+ (struct.new $struct
+ (i32.const 0)
+ )
+ (ref.null any)
+ (local.get $x)
+ )
+ )
+ )
+ ;; The input to the ref.cast is either $struct or $substruct, both of which
+ ;; work, so we cannot optimize anything here away.
+ (drop
+ (ref.cast_static $struct
+ (select
+ (struct.new $struct
+ (i32.const 1)
+ )
+ (struct.new $substruct
+ (i32.const 2)
+ (i32.const 3)
+ )
+ (local.get $x)
+ )
+ )
+ )
+ ;; As above, but now we test with $substruct, so one possibility fails and
+ ;; one succeeds. We cannot infer here either.
+ (drop
+ (ref.cast_static $substruct
+ (select
+ (struct.new $struct
+ (i32.const 4)
+ )
+ (struct.new $substruct
+ (i32.const 5)
+ (i32.const 6)
+ )
+ (local.get $x)
+ )
+ )
+ )
+ ;; Two possible types, both are supertypes, so neither is a subtype, and we
+ ;; can infer an unreachable. The combination of these two is a cone from
+ ;; $struct of depth 1, which does not overlap with $subsubstruct.
+ (drop
+ (ref.cast_static $subsubstruct
+ (select
+ (struct.new $struct
+ (i32.const 7)
+ )
+ (struct.new $substruct
+ (i32.const 8)
+ (i32.const 9)
+ )
+ (local.get $x)
+ )
+ )
+ )
+ )
+
;; CHECK: (func $ref.test-exact (type $none_=>_none)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 0)
@@ -2663,18 +2775,7 @@
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
- ;; CHECK-NEXT: (ref.test_static $struct
- ;; CHECK-NEXT: (select (result (ref $struct))
- ;; CHECK-NEXT: (struct.new $struct
- ;; CHECK-NEXT: (i32.const 1)
- ;; CHECK-NEXT: )
- ;; CHECK-NEXT: (struct.new $substruct
- ;; CHECK-NEXT: (i32.const 2)
- ;; CHECK-NEXT: (i32.const 3)
- ;; CHECK-NEXT: )
- ;; CHECK-NEXT: (local.get $x)
- ;; CHECK-NEXT: )
- ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (ref.test_static $substruct
@@ -2691,18 +2792,7 @@
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
- ;; CHECK-NEXT: (ref.test_static $subsubstruct
- ;; CHECK-NEXT: (select (result (ref $struct))
- ;; CHECK-NEXT: (struct.new $struct
- ;; CHECK-NEXT: (i32.const 7)
- ;; CHECK-NEXT: )
- ;; CHECK-NEXT: (struct.new $substruct
- ;; CHECK-NEXT: (i32.const 8)
- ;; CHECK-NEXT: (i32.const 9)
- ;; CHECK-NEXT: )
- ;; CHECK-NEXT: (local.get $x)
- ;; CHECK-NEXT: )
- ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $ref.test-inexact (export "ref.test-inexact") (param $x i32)
@@ -2719,7 +2809,9 @@
)
)
;; The input to the ref.test is either $struct or $substruct, both of which
- ;; work, so here we can infer a 1 - but we need a cone type for that TODO
+ ;; work, so here we can infer a 1. We do so using a cone type: the
+ ;; combination of those two types is a cone on $struct of depth 1, and that
+ ;; cone is 100% a subtype of $struct, so the test will succeed.
(drop
(ref.test_static $struct
(select
@@ -2751,7 +2843,8 @@
)
)
;; Two possible types, both are supertypes, so neither is a subtype, and we
- ;; can infer a 0 - but we need more precise type info than we have TODO
+ ;; can infer a 0. The combination of these two is a cone from $struct of
+ ;; depth 1, which does not overlap with $subsubstruct.
(drop
(ref.test_static $subsubstruct
(select
@@ -2832,25 +2925,6 @@
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (ref.eq
- ;; CHECK-NEXT: (struct.new $struct
- ;; CHECK-NEXT: (i32.const 1)
- ;; CHECK-NEXT: )
- ;; CHECK-NEXT: (select (result (ref $substruct))
- ;; CHECK-NEXT: (struct.new $substruct
- ;; CHECK-NEXT: (i32.const 2)
- ;; CHECK-NEXT: (i32.const 3)
- ;; CHECK-NEXT: )
- ;; CHECK-NEXT: (struct.new $subsubstruct
- ;; CHECK-NEXT: (i32.const 4)
- ;; CHECK-NEXT: (i32.const 5)
- ;; CHECK-NEXT: (i32.const 6)
- ;; CHECK-NEXT: )
- ;; CHECK-NEXT: (local.get $x)
- ;; CHECK-NEXT: )
- ;; CHECK-NEXT: )
- ;; CHECK-NEXT: )
- ;; CHECK-NEXT: (drop
- ;; CHECK-NEXT: (ref.eq
;; CHECK-NEXT: (local.get $struct)
;; CHECK-NEXT: (local.get $other)
;; CHECK-NEXT: )
@@ -2918,28 +2992,6 @@
(ref.null $struct)
)
)
- ;; One side has two possible types, which we see as Many, and so we cannot
- ;; infer anything here. With a cone type, however, we could infer a 0.
- ;; TODO: add more tests for cone types here when we get them
- (drop
- (ref.eq
- (struct.new $struct
- (i32.const 1)
- )
- (select
- (struct.new $substruct
- (i32.const 2)
- (i32.const 3)
- )
- (struct.new $subsubstruct
- (i32.const 4)
- (i32.const 5)
- (i32.const 6)
- )
- (local.get $x)
- )
- )
- )
;; When nulls are possible, we cannot infer anything (with or without the
;; same type on both sides).
(drop
@@ -2998,6 +3050,191 @@
)
)
+ ;; CHECK: (func $ref.eq-cone (type $i32_=>_none) (param $x i32)
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (ref.eq
+ ;; CHECK-NEXT: (struct.new $substruct
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: (i32.const 2)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (select (result (ref $struct))
+ ;; CHECK-NEXT: (struct.new $struct
+ ;; CHECK-NEXT: (i32.const 3)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (struct.new $subsubstruct
+ ;; CHECK-NEXT: (i32.const 4)
+ ;; CHECK-NEXT: (i32.const 5)
+ ;; CHECK-NEXT: (i32.const 6)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.get $x)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (ref.eq
+ ;; CHECK-NEXT: (struct.new $substruct
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: (i32.const 2)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (select (result (ref $struct))
+ ;; CHECK-NEXT: (struct.new $struct
+ ;; CHECK-NEXT: (i32.const 3)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (struct.new $substruct
+ ;; CHECK-NEXT: (i32.const 4)
+ ;; CHECK-NEXT: (i32.const 5)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.get $x)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (ref.eq
+ ;; CHECK-NEXT: (struct.new $substruct
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: (i32.const 2)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (select (result (ref $substruct))
+ ;; CHECK-NEXT: (struct.new $substruct
+ ;; CHECK-NEXT: (i32.const 3)
+ ;; CHECK-NEXT: (i32.const 4)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (struct.new $subsubstruct
+ ;; CHECK-NEXT: (i32.const 5)
+ ;; CHECK-NEXT: (i32.const 6)
+ ;; CHECK-NEXT: (i32.const 7)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.get $x)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (ref.eq
+ ;; CHECK-NEXT: (struct.new $substruct
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: (i32.const 2)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (select (result (ref $substruct))
+ ;; CHECK-NEXT: (struct.new $substruct
+ ;; CHECK-NEXT: (i32.const 3)
+ ;; CHECK-NEXT: (i32.const 4)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (struct.new $substruct
+ ;; CHECK-NEXT: (i32.const 5)
+ ;; CHECK-NEXT: (i32.const 6)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.get $x)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $ref.eq-cone (export "ref.eq-cone") (param $x i32)
+ ;; One side has two possible types, so we have a cone there. This cone is
+ ;; of subtypes of the other type, which is exact, so we cannot intersect
+ ;; here and we infer a 0.
+ (drop
+ (ref.eq
+ (struct.new $struct
+ (i32.const 1)
+ )
+ (select
+ (struct.new $substruct
+ (i32.const 2)
+ (i32.const 3)
+ )
+ (struct.new $subsubstruct
+ (i32.const 4)
+ (i32.const 5)
+ (i32.const 6)
+ )
+ (local.get $x)
+ )
+ )
+ )
+ ;; Now the cone is large enough, so there might be an intersection, and we
+ ;; do not optimize (the cone of $struct and $subsubstruct contains
+ ;; $substruct which is in the middle).
+ (drop
+ (ref.eq
+ (struct.new $substruct
+ (i32.const 1)
+ (i32.const 2)
+ )
+ (select
+ (struct.new $struct
+ (i32.const 3)
+ )
+ (struct.new $subsubstruct
+ (i32.const 4)
+ (i32.const 5)
+ (i32.const 6)
+ )
+ (local.get $x)
+ )
+ )
+ )
+ (drop
+ (ref.eq
+ (struct.new $substruct
+ (i32.const 1)
+ (i32.const 2)
+ )
+ (select
+ (struct.new $struct
+ (i32.const 3)
+ )
+ (struct.new $substruct ;; As above, but with this changed. We still
+ (i32.const 4) ;; cannot optimize.
+ (i32.const 5)
+ )
+ (local.get $x)
+ )
+ )
+ )
+ (drop
+ (ref.eq
+ (struct.new $substruct
+ (i32.const 1)
+ (i32.const 2)
+ )
+ (select
+ (struct.new $substruct ;; As above, but with this changed. We still
+ (i32.const 3) ;; cannot optimize.
+ (i32.const 4)
+ )
+ (struct.new $subsubstruct
+ (i32.const 5)
+ (i32.const 6)
+ (i32.const 7)
+ )
+ (local.get $x)
+ )
+ )
+ )
+ (drop
+ (ref.eq
+ (struct.new $substruct
+ (i32.const 1)
+ (i32.const 2)
+ )
+ (select
+ (struct.new $substruct
+ (i32.const 3)
+ (i32.const 4)
+ )
+ (struct.new $substruct ;; As above, but with this changed. We still
+ (i32.const 5) ;; cannot optimize (here the type is actually
+ (i32.const 6) ;; exact, despite the select).
+ )
+ (local.get $x)
+ )
+ )
+ )
+ )
+
;; CHECK: (func $unreachable (type $none_=>_ref|eq|) (result (ref eq))
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )