diff options
-rw-r--r-- | src/ir/bits.h | 10 | ||||
-rw-r--r-- | src/ir/boolean.h | 38 | ||||
-rw-r--r-- | src/ir/properties.h | 9 | ||||
-rw-r--r-- | src/passes/OptimizeInstructions.cpp | 1 | ||||
-rw-r--r-- | test/lit/passes/optimize-instructions-gc.wast | 66 |
5 files changed, 112 insertions, 12 deletions
diff --git a/src/ir/bits.h b/src/ir/bits.h index 21146b3d1..96b36a846 100644 --- a/src/ir/bits.h +++ b/src/ir/bits.h @@ -17,10 +17,11 @@ #ifndef wasm_ir_bits_h #define wasm_ir_bits_h +#include "ir/boolean.h" #include "ir/literal-utils.h" +#include "ir/load-utils.h" #include "support/bits.h" #include "wasm-builder.h" -#include <ir/load-utils.h> namespace wasm::Bits { @@ -125,6 +126,9 @@ struct DummyLocalInfoProvider { template<typename LocalInfoProvider = DummyLocalInfoProvider> Index getMaxBits(Expression* curr, LocalInfoProvider* localInfoProvider = nullptr) { + if (Properties::emitsBoolean(curr)) { + return 1; + } if (auto* c = curr->dynCast<Const>()) { switch (curr->type.getBasic()) { case Type::i32: @@ -363,7 +367,7 @@ Index getMaxBits(Expression* curr, case LeFloat64: case GtFloat64: case GeFloat64: - return 1; + WASM_UNREACHABLE("relationals handled before"); default: { } } @@ -379,7 +383,7 @@ Index getMaxBits(Expression* curr, return 7; case EqZInt32: case EqZInt64: - return 1; + WASM_UNREACHABLE("relationals handled before"); case WrapInt64: case ExtendUInt32: return std::min(Index(32), getMaxBits(unary->value, localInfoProvider)); diff --git a/src/ir/boolean.h b/src/ir/boolean.h new file mode 100644 index 000000000..58601c2ce --- /dev/null +++ b/src/ir/boolean.h @@ -0,0 +1,38 @@ +/* + * Copyright 2022 WebAssembly Community Group participants + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef wasm_ir_boolean_h +#define wasm_ir_boolean_h + +#include "wasm.h" + +namespace wasm::Properties { + +inline bool emitsBoolean(Expression* curr) { + if (auto* unary = curr->dynCast<Unary>()) { + return unary->isRelational(); + } else if (auto* binary = curr->dynCast<Binary>()) { + return binary->isRelational(); + } else if (curr->is<RefIs>() || curr->is<RefEq>() || curr->is<RefTest>() || + curr->is<StringEq>()) { + return true; + } + return false; +} + +} // namespace wasm::Properties + +#endif // wasm_ir_boolean_h diff --git a/src/ir/properties.h b/src/ir/properties.h index 4f7fb96ca..3278d9e41 100644 --- a/src/ir/properties.h +++ b/src/ir/properties.h @@ -24,15 +24,6 @@ namespace wasm::Properties { -inline bool emitsBoolean(Expression* curr) { - if (auto* unary = curr->dynCast<Unary>()) { - return unary->isRelational(); - } else if (auto* binary = curr->dynCast<Binary>()) { - return binary->isRelational(); - } - return false; -} - inline bool isSymmetric(Binary* binary) { switch (binary->op) { case AddInt32: diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index a88e2a87f..5f18beb73 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -24,6 +24,7 @@ #include <ir/abstract.h> #include <ir/bits.h> +#include <ir/boolean.h> #include <ir/cost.h> #include <ir/drop.h> #include <ir/effects.h> diff --git a/test/lit/passes/optimize-instructions-gc.wast b/test/lit/passes/optimize-instructions-gc.wast index 2c6498ec3..643aad5ed 100644 --- a/test/lit/passes/optimize-instructions-gc.wast +++ b/test/lit/passes/optimize-instructions-gc.wast @@ -2876,4 +2876,70 @@ ) ) ) + + ;; CHECK: (func $ref-boolean (param $x eqref) (param $y eqref) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (ref.eq + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: (local.get $y) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (ref.is_func + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (ref.test_static $A + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; NOMNL: (func $ref-boolean (type $eqref_eqref_=>_none) (param $x eqref) (param $y eqref) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (ref.eq + ;; NOMNL-NEXT: (local.get $x) + ;; NOMNL-NEXT: (local.get $y) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (ref.is_func + ;; NOMNL-NEXT: (local.get $x) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: (drop + ;; NOMNL-NEXT: (ref.test_static $A + ;; NOMNL-NEXT: (local.get $x) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + ;; NOMNL-NEXT: ) + (func $ref-boolean (param $x eqref) (param $y eqref) + ;; ref.eq returns a boolean, so &1 on it is not needed. + (drop + (i32.and + (ref.eq + (local.get $x) + (local.get $y) + ) + (i32.const 1) + ) + ) + ;; likewise ref.is and ref.test + (drop + (i32.and + (ref.is_func + (local.get $x) + ) + (i32.const 1) + ) + ) + (drop + (i32.and + (ref.test_static $A + (local.get $x) + ) + (i32.const 1) + ) + ) + ) ) |