diff --git a/src/ir/bits.h b/src/ir/bits.h index 21146b3d1ea..96b36a846e7 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 namespace wasm::Bits { @@ -125,6 +126,9 @@ struct DummyLocalInfoProvider { template Index getMaxBits(Expression* curr, LocalInfoProvider* localInfoProvider = nullptr) { + if (Properties::emitsBoolean(curr)) { + return 1; + } if (auto* c = curr->dynCast()) { 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 00000000000..58601c2ce4a --- /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()) { + return unary->isRelational(); + } else if (auto* binary = curr->dynCast()) { + return binary->isRelational(); + } else if (curr->is() || curr->is() || curr->is() || + curr->is()) { + 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 4f7fb96ca75..3278d9e4128 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()) { - return unary->isRelational(); - } else if (auto* binary = curr->dynCast()) { - 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 a88e2a87fa8..5f18beb73be 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -24,6 +24,7 @@ #include #include +#include #include #include #include diff --git a/test/lit/passes/optimize-instructions-gc.wast b/test/lit/passes/optimize-instructions-gc.wast index 2c6498ec3f9..643aad5edaa 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) + ) + ) + ) )