summaryrefslogtreecommitdiff
path: root/test/lit/passes/optimize-instructions-gc-tnh.wast
diff options
context:
space:
mode:
authorAlon Zakai <azakai@google.com>2022-06-24 12:08:38 -0700
committerGitHub <noreply@github.com>2022-06-24 12:08:38 -0700
commit10523fa2468a21b0add13ccfda2d42888be72040 (patch)
tree90be1851169f313c7bc154a2597775e055b83fed /test/lit/passes/optimize-instructions-gc-tnh.wast
parent93b8849d9f98ef7ed812938ff0b3219819c2be77 (diff)
downloadbinaryen-10523fa2468a21b0add13ccfda2d42888be72040.tar.gz
binaryen-10523fa2468a21b0add13ccfda2d42888be72040.tar.bz2
binaryen-10523fa2468a21b0add13ccfda2d42888be72040.zip
[WasmGC] OptimizeInstructions: Improve RefIs cast ordering (#4752)
#4748 regressed us in some cases, because it removed casts first: (ref.is_func (ref.as_func (local.get $anyref))) If the cast is removed first, and the local has no useful type info, then we'd have removed the cast but could not remove the ref.is. But the ref.is could be optimized to 1, as it must be a func - the type info proves it thanks to the cast. To avoid this, remove casts after everything else.
Diffstat (limited to 'test/lit/passes/optimize-instructions-gc-tnh.wast')
-rw-r--r--test/lit/passes/optimize-instructions-gc-tnh.wast86
1 files changed, 84 insertions, 2 deletions
diff --git a/test/lit/passes/optimize-instructions-gc-tnh.wast b/test/lit/passes/optimize-instructions-gc-tnh.wast
index 73ce3acf4..aad02c17c 100644
--- a/test/lit/passes/optimize-instructions-gc-tnh.wast
+++ b/test/lit/passes/optimize-instructions-gc-tnh.wast
@@ -136,9 +136,14 @@
)
;; TNH: (func $ref.is (type $eqref_=>_i32) (param $a eqref) (result i32)
- ;; TNH-NEXT: (ref.is_null
- ;; TNH-NEXT: (local.get $a)
+ ;; TNH-NEXT: (drop
+ ;; TNH-NEXT: (ref.cast_static $struct
+ ;; TNH-NEXT: (ref.as_data
+ ;; TNH-NEXT: (local.get $a)
+ ;; TNH-NEXT: )
+ ;; TNH-NEXT: )
;; TNH-NEXT: )
+ ;; TNH-NEXT: (i32.const 0)
;; TNH-NEXT: )
;; NO_TNH: (func $ref.is (type $eqref_=>_i32) (param $a eqref) (result i32)
;; NO_TNH-NEXT: (drop
@@ -151,6 +156,8 @@
;; NO_TNH-NEXT: (i32.const 0)
;; NO_TNH-NEXT: )
(func $ref.is (param $a (ref null eq)) (result i32)
+ ;; In this case non-nullability is enough to tell that the ref.is will
+ ;; return 0. TNH does not help here.
(ref.is_null
(ref.cast_static $struct
(ref.as_non_null
@@ -161,4 +168,79 @@
)
)
)
+
+ ;; TNH: (func $ref.is_b (type $eqref_=>_i32) (param $a eqref) (result i32)
+ ;; TNH-NEXT: (ref.is_null
+ ;; TNH-NEXT: (local.get $a)
+ ;; TNH-NEXT: )
+ ;; TNH-NEXT: )
+ ;; NO_TNH: (func $ref.is_b (type $eqref_=>_i32) (param $a eqref) (result i32)
+ ;; NO_TNH-NEXT: (ref.is_null
+ ;; NO_TNH-NEXT: (ref.cast_static $struct
+ ;; NO_TNH-NEXT: (local.get $a)
+ ;; NO_TNH-NEXT: )
+ ;; NO_TNH-NEXT: )
+ ;; NO_TNH-NEXT: )
+ (func $ref.is_b(param $a (ref null eq)) (result i32)
+ ;; Here we only have a cast, and no ref.as operations that force the value
+ ;; to be non-nullable. That means we cannot remove the ref.is, but we can
+ ;; remove the cast in TNH.
+ (ref.is_null
+ (ref.cast_static $struct
+ (local.get $a)
+ )
+ )
+ )
+
+ ;; TNH: (func $ref.is_func_a (type $anyref_=>_i32) (param $a anyref) (result i32)
+ ;; TNH-NEXT: (drop
+ ;; TNH-NEXT: (ref.as_func
+ ;; TNH-NEXT: (local.get $a)
+ ;; TNH-NEXT: )
+ ;; TNH-NEXT: )
+ ;; TNH-NEXT: (i32.const 1)
+ ;; TNH-NEXT: )
+ ;; NO_TNH: (func $ref.is_func_a (type $anyref_=>_i32) (param $a anyref) (result i32)
+ ;; NO_TNH-NEXT: (drop
+ ;; NO_TNH-NEXT: (ref.as_func
+ ;; NO_TNH-NEXT: (local.get $a)
+ ;; NO_TNH-NEXT: )
+ ;; NO_TNH-NEXT: )
+ ;; NO_TNH-NEXT: (i32.const 1)
+ ;; NO_TNH-NEXT: )
+ (func $ref.is_func_a (param $a (ref null any)) (result i32)
+ ;; The check must succeed. We can return 1 here, and drop the rest, with or
+ ;; without TNH (in particular, TNH should not just remove the cast but not
+ ;; return a 1).
+ (ref.is_func
+ (ref.as_func
+ (local.get $a)
+ )
+ )
+ )
+
+ ;; TNH: (func $ref.is_func_b (type $anyref_=>_i32) (param $a anyref) (result i32)
+ ;; TNH-NEXT: (drop
+ ;; TNH-NEXT: (ref.as_data
+ ;; TNH-NEXT: (local.get $a)
+ ;; TNH-NEXT: )
+ ;; TNH-NEXT: )
+ ;; TNH-NEXT: (i32.const 0)
+ ;; TNH-NEXT: )
+ ;; NO_TNH: (func $ref.is_func_b (type $anyref_=>_i32) (param $a anyref) (result i32)
+ ;; NO_TNH-NEXT: (drop
+ ;; NO_TNH-NEXT: (ref.as_data
+ ;; NO_TNH-NEXT: (local.get $a)
+ ;; NO_TNH-NEXT: )
+ ;; NO_TNH-NEXT: )
+ ;; NO_TNH-NEXT: (i32.const 0)
+ ;; NO_TNH-NEXT: )
+ (func $ref.is_func_b (param $a (ref null any)) (result i32)
+ ;; A case where the type cannot match, and we return 0.
+ (ref.is_func
+ (ref.as_data
+ (local.get $a)
+ )
+ )
+ )
)