summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <azakai@google.com>2021-08-09 17:25:11 -0700
committerGitHub <noreply@github.com>2021-08-09 17:25:11 -0700
commit0732425cd876127f22abd0a36e883caa5c8f7857 (patch)
treee0b54cac2edadd46e2ef23e04eca37be2677352c
parent86634774be6e060efec8f3048f82d61b8d91d5d7 (diff)
downloadbinaryen-0732425cd876127f22abd0a36e883caa5c8f7857.tar.gz
binaryen-0732425cd876127f22abd0a36e883caa5c8f7857.tar.bz2
binaryen-0732425cd876127f22abd0a36e883caa5c8f7857.zip
[Wasm GC] RefEq(x, null) => RefIsNull(x) (#4066)
-rw-r--r--src/passes/OptimizeInstructions.cpp12
-rw-r--r--test/lit/passes/optimize-instructions-gc.wast41
2 files changed, 53 insertions, 0 deletions
diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp
index 7d9111e0b..51a2095ea 100644
--- a/src/passes/OptimizeInstructions.cpp
+++ b/src/passes/OptimizeInstructions.cpp
@@ -1121,6 +1121,18 @@ struct OptimizeInstructions
if (areConsecutiveInputsEqual(curr->left, curr->right)) {
replaceCurrent(
Builder(*getModule()).makeConst(Literal::makeOne(Type::i32)));
+ return;
+ }
+
+ // Canonicalize to the pattern of a null on the right-hand side, if there is
+ // one. This makes pattern matching simpler.
+ if (curr->left->is<RefNull>()) {
+ std::swap(curr->left, curr->right);
+ }
+
+ // RefEq of a value to Null can be replaced with RefIsNull.
+ if (curr->right->is<RefNull>()) {
+ replaceCurrent(Builder(*getModule()).makeRefIs(RefIsNull, curr->left));
}
}
diff --git a/test/lit/passes/optimize-instructions-gc.wast b/test/lit/passes/optimize-instructions-gc.wast
index 5e40c781f..01c0befb8 100644
--- a/test/lit/passes/optimize-instructions-gc.wast
+++ b/test/lit/passes/optimize-instructions-gc.wast
@@ -1059,4 +1059,45 @@
(func $get-rtt (result (rtt $empty))
(unreachable)
)
+
+ ;; CHECK: (func $ref-eq-null (param $x eqref)
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (ref.is_null
+ ;; CHECK-NEXT: (local.get $x)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (ref.is_null
+ ;; CHECK-NEXT: (local.get $x)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $ref-eq-null (param $x eqref)
+ ;; Equality to null can be done with ref.is_null.
+ (drop
+ (ref.eq
+ (local.get $x)
+ (ref.null eq)
+ )
+ )
+ (drop
+ (ref.eq
+ (ref.null eq)
+ (local.get $x)
+ )
+ )
+ ;; Also check that we turn a comparison of two nulls into 1, using the rule
+ ;; for comparing the same thing to itself (i.e., that we run that rule first
+ ;; and not the check for one of them being null, which would require more
+ ;; work afterwards).
+ (drop
+ (ref.eq
+ (ref.null eq)
+ (ref.null eq)
+ )
+ )
+ )
)