summaryrefslogtreecommitdiff
path: root/test/lit/passes/optimize-instructions-gc.wast
diff options
context:
space:
mode:
authorAlon Zakai <azakai@google.com>2021-08-24 13:41:39 -0700
committerGitHub <noreply@github.com>2021-08-24 13:41:39 -0700
commit0a6de1700938c419d0e549232c35a56c5718be2c (patch)
treea1be1439d2e370eac3bf30a9e3772deb524cd3ab /test/lit/passes/optimize-instructions-gc.wast
parenta2323f2cfd90089c54100ab98c439b9438cc4dc1 (diff)
downloadbinaryen-0a6de1700938c419d0e549232c35a56c5718be2c.tar.gz
binaryen-0a6de1700938c419d0e549232c35a56c5718be2c.tar.bz2
binaryen-0a6de1700938c419d0e549232c35a56c5718be2c.zip
OptimizeInstructions: Handle trivial ref.cast and ref.test (#4097)
If the types are completely incompatible, we know the cast will fail. However, ref.cast does allow a null to pass through, which makes it a little more complicated.
Diffstat (limited to 'test/lit/passes/optimize-instructions-gc.wast')
-rw-r--r--test/lit/passes/optimize-instructions-gc.wast232
1 files changed, 225 insertions, 7 deletions
diff --git a/test/lit/passes/optimize-instructions-gc.wast b/test/lit/passes/optimize-instructions-gc.wast
index 27c966f52..2f6ae858d 100644
--- a/test/lit/passes/optimize-instructions-gc.wast
+++ b/test/lit/passes/optimize-instructions-gc.wast
@@ -14,22 +14,23 @@
(field $i64 (mut i64))
))
- ;; CHECK: (type $empty (struct ))
- ;; NOMNL: (type $empty (struct ))
- (type $empty (struct))
+ ;; CHECK: (type $array (array (mut i8)))
+ ;; NOMNL: (type $array (array (mut i8)))
+ (type $array (array (mut i8)))
;; CHECK: (type $B (struct (field i32) (field i32) (field f32)))
;; NOMNL: (type $B (struct (field i32) (field i32) (field f32)) (extends $A))
(type $B (struct (field i32) (field i32) (field f32)) (extends $A))
+ ;; CHECK: (type $empty (struct ))
+ ;; NOMNL: (type $empty (struct ))
+ (type $empty (struct))
+
;; CHECK: (type $C (struct (field i32) (field i32) (field f64)))
;; NOMNL: (type $C (struct (field i32) (field i32) (field f64)) (extends $A))
(type $C (struct (field i32) (field i32) (field f64)) (extends $A))
- ;; CHECK: (type $array (array (mut i8)))
- ;; NOMNL: (type $array (array (mut i8)))
- (type $array (array (mut i8)))
-
+ ;; CHECK: (type $A (struct (field i32)))
;; NOMNL: (type $A (struct (field i32)))
(type $A (struct (field i32)))
@@ -1665,4 +1666,221 @@
)
)
)
+
+ ;; CHECK: (func $incompatible-cast-of-non-null (param $struct (ref $struct))
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (local.get $struct)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (rtt.canon $array)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (unreachable)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; NOMNL: (func $incompatible-cast-of-non-null (param $struct (ref $struct))
+ ;; NOMNL-NEXT: (drop
+ ;; NOMNL-NEXT: (block
+ ;; NOMNL-NEXT: (drop
+ ;; NOMNL-NEXT: (local.get $struct)
+ ;; NOMNL-NEXT: )
+ ;; NOMNL-NEXT: (drop
+ ;; NOMNL-NEXT: (rtt.canon $array)
+ ;; NOMNL-NEXT: )
+ ;; NOMNL-NEXT: (unreachable)
+ ;; NOMNL-NEXT: )
+ ;; NOMNL-NEXT: )
+ ;; NOMNL-NEXT: )
+ (func $incompatible-cast-of-non-null (param $struct (ref $struct))
+ (drop
+ (ref.cast
+ (local.get $struct)
+ (rtt.canon $array)
+ )
+ )
+ )
+
+ ;; CHECK: (func $incompatible-cast-of-null
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (block (result (ref null $array))
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (ref.null $struct)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (rtt.canon $array)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (ref.null $array)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (ref.as_non_null
+ ;; CHECK-NEXT: (block (result (ref null $array))
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (ref.as_non_null
+ ;; CHECK-NEXT: (ref.null $struct)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (rtt.canon $array)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (ref.null $array)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; NOMNL: (func $incompatible-cast-of-null
+ ;; NOMNL-NEXT: (drop
+ ;; NOMNL-NEXT: (block (result (ref null $array))
+ ;; NOMNL-NEXT: (drop
+ ;; NOMNL-NEXT: (ref.null $struct)
+ ;; NOMNL-NEXT: )
+ ;; NOMNL-NEXT: (drop
+ ;; NOMNL-NEXT: (rtt.canon $array)
+ ;; NOMNL-NEXT: )
+ ;; NOMNL-NEXT: (ref.null $array)
+ ;; NOMNL-NEXT: )
+ ;; NOMNL-NEXT: )
+ ;; NOMNL-NEXT: (drop
+ ;; NOMNL-NEXT: (ref.as_non_null
+ ;; NOMNL-NEXT: (block (result (ref null $array))
+ ;; NOMNL-NEXT: (drop
+ ;; NOMNL-NEXT: (ref.as_non_null
+ ;; NOMNL-NEXT: (ref.null $struct)
+ ;; NOMNL-NEXT: )
+ ;; NOMNL-NEXT: )
+ ;; NOMNL-NEXT: (drop
+ ;; NOMNL-NEXT: (rtt.canon $array)
+ ;; NOMNL-NEXT: )
+ ;; NOMNL-NEXT: (ref.null $array)
+ ;; NOMNL-NEXT: )
+ ;; NOMNL-NEXT: )
+ ;; NOMNL-NEXT: )
+ ;; NOMNL-NEXT: )
+ (func $incompatible-cast-of-null
+ (drop
+ (ref.cast
+ (ref.null $struct)
+ (rtt.canon $array)
+ )
+ )
+ (drop
+ (ref.cast
+ ;; The fallthrough is null, but the node's child's type is non-nullable,
+ ;; so we must add a ref.as_non_null on the outside to keep the type
+ ;; identical.
+ (ref.as_non_null
+ (ref.null $struct)
+ )
+ (rtt.canon $array)
+ )
+ )
+ )
+
+ ;; CHECK: (func $incompatible-cast-of-unknown (param $struct (ref null $struct))
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (ref.cast
+ ;; CHECK-NEXT: (local.get $struct)
+ ;; CHECK-NEXT: (rtt.canon $array)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; NOMNL: (func $incompatible-cast-of-unknown (param $struct (ref null $struct))
+ ;; NOMNL-NEXT: (drop
+ ;; NOMNL-NEXT: (ref.cast
+ ;; NOMNL-NEXT: (local.get $struct)
+ ;; NOMNL-NEXT: (rtt.canon $array)
+ ;; NOMNL-NEXT: )
+ ;; NOMNL-NEXT: )
+ ;; NOMNL-NEXT: )
+ (func $incompatible-cast-of-unknown (param $struct (ref null $struct))
+ (drop
+ (ref.cast
+ (local.get $struct)
+ (rtt.canon $array)
+ )
+ )
+ )
+
+ ;; CHECK: (func $incompatible-test (param $struct (ref null $struct))
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (block (result i32)
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (local.get $struct)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (rtt.canon $array)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; NOMNL: (func $incompatible-test (param $struct (ref null $struct))
+ ;; NOMNL-NEXT: (drop
+ ;; NOMNL-NEXT: (block (result i32)
+ ;; NOMNL-NEXT: (drop
+ ;; NOMNL-NEXT: (local.get $struct)
+ ;; NOMNL-NEXT: )
+ ;; NOMNL-NEXT: (drop
+ ;; NOMNL-NEXT: (rtt.canon $array)
+ ;; NOMNL-NEXT: )
+ ;; NOMNL-NEXT: (i32.const 0)
+ ;; NOMNL-NEXT: )
+ ;; NOMNL-NEXT: )
+ ;; NOMNL-NEXT: )
+ (func $incompatible-test (param $struct (ref null $struct))
+ (drop
+ ;; This test will definitely fail, so we can turn it into 0.
+ (ref.test
+ (local.get $struct)
+ (rtt.canon $array)
+ )
+ )
+ )
+
+ ;; CHECK: (func $subtype-compatible (param $A (ref null $A)) (param $B (ref null $B))
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (ref.test
+ ;; CHECK-NEXT: (local.get $A)
+ ;; CHECK-NEXT: (rtt.canon $B)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (ref.test
+ ;; CHECK-NEXT: (local.get $B)
+ ;; CHECK-NEXT: (rtt.canon $A)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; NOMNL: (func $subtype-compatible (param $A (ref null $A)) (param $B (ref null $B))
+ ;; NOMNL-NEXT: (drop
+ ;; NOMNL-NEXT: (ref.test
+ ;; NOMNL-NEXT: (local.get $A)
+ ;; NOMNL-NEXT: (rtt.canon $B)
+ ;; NOMNL-NEXT: )
+ ;; NOMNL-NEXT: )
+ ;; NOMNL-NEXT: (drop
+ ;; NOMNL-NEXT: (ref.test
+ ;; NOMNL-NEXT: (local.get $B)
+ ;; NOMNL-NEXT: (rtt.canon $A)
+ ;; NOMNL-NEXT: )
+ ;; NOMNL-NEXT: )
+ ;; NOMNL-NEXT: )
+ (func $subtype-compatible (param $A (ref null $A)) (param $B (ref null $B))
+ (drop
+ ;; B is a subtype of A, so this can work.
+ (ref.test
+ (local.get $A)
+ (rtt.canon $B)
+ )
+ )
+ (drop
+ ;; The other direction works too.
+ (ref.test
+ (local.get $B)
+ (rtt.canon $A)
+ )
+ )
+ )
)