summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ir/bits.h10
-rw-r--r--src/ir/boolean.h38
-rw-r--r--src/ir/properties.h9
-rw-r--r--src/passes/OptimizeInstructions.cpp1
-rw-r--r--test/lit/passes/optimize-instructions-gc.wast66
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)
+ )
+ )
+ )
)