diff options
author | Alon Zakai <azakai@google.com> | 2021-08-09 17:25:11 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-08-09 17:25:11 -0700 |
commit | 0732425cd876127f22abd0a36e883caa5c8f7857 (patch) | |
tree | e0b54cac2edadd46e2ef23e04eca37be2677352c | |
parent | 86634774be6e060efec8f3048f82d61b8d91d5d7 (diff) | |
download | binaryen-0732425cd876127f22abd0a36e883caa5c8f7857.tar.gz binaryen-0732425cd876127f22abd0a36e883caa5c8f7857.tar.bz2 binaryen-0732425cd876127f22abd0a36e883caa5c8f7857.zip |
[Wasm GC] RefEq(x, null) => RefIsNull(x) (#4066)
-rw-r--r-- | src/passes/OptimizeInstructions.cpp | 12 | ||||
-rw-r--r-- | test/lit/passes/optimize-instructions-gc.wast | 41 |
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) + ) + ) + ) ) |