summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/asm2wasm.h12
-rw-r--r--src/ast/properties.h60
-rw-r--r--src/passes/OptimizeInstructions.cpp10
3 files changed, 79 insertions, 3 deletions
diff --git a/src/asm2wasm.h b/src/asm2wasm.h
index 5bdb2a9bf..377b6b20b 100644
--- a/src/asm2wasm.h
+++ b/src/asm2wasm.h
@@ -954,9 +954,15 @@ void Asm2WasmBuilder::processAsm(Ref ast) {
void visitCallIndirect(CallIndirect* curr) {
// we already call into target = something + offset, where offset is a callImport with the name of the table. replace that with the table offset
auto add = curr->target->cast<Binary>();
- auto offset = add->right->cast<CallImport>();
- auto tableName = offset->target;
- add->right = parent->builder.makeConst(Literal((int32_t)parent->functionTableStarts[tableName]));
+ if (add->right->is<CallImport>()) {
+ auto offset = add->right->cast<CallImport>();
+ auto tableName = offset->target;
+ add->right = parent->builder.makeConst(Literal((int32_t)parent->functionTableStarts[tableName]));
+ } else {
+ auto offset = add->left->cast<CallImport>();
+ auto tableName = offset->target;
+ add->left = parent->builder.makeConst(Literal((int32_t)parent->functionTableStarts[tableName]));
+ }
}
};
diff --git a/src/ast/properties.h b/src/ast/properties.h
new file mode 100644
index 000000000..9834c73d0
--- /dev/null
+++ b/src/ast/properties.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2016 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_ast_properties_h
+#define wasm_ast_properties_h
+
+#include "wasm.h"
+
+namespace wasm {
+
+struct Properties {
+ static 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;
+ }
+
+ static bool isSymmetric(Binary* binary) {
+ switch (binary->op) {
+ case AddInt32:
+ case MulInt32:
+ case AndInt32:
+ case OrInt32:
+ case XorInt32:
+ case EqInt32:
+ case NeInt32:
+
+ case AddInt64:
+ case MulInt64:
+ case AndInt64:
+ case OrInt64:
+ case XorInt64:
+ case EqInt64:
+ case NeInt64: return true;
+
+ default: return false;
+ }
+ }
+};
+
+} // wasm
+
+#endif // wams_ast_properties_h
+
diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp
index 7f1483371..a5c665458 100644
--- a/src/passes/OptimizeInstructions.cpp
+++ b/src/passes/OptimizeInstructions.cpp
@@ -25,6 +25,7 @@
#include <wasm-s-parser.h>
#include <support/threads.h>
#include <ast_utils.h>
+#include <ast/properties.h>
namespace wasm {
@@ -197,6 +198,12 @@ struct OptimizeInstructions : public WalkerPass<PostWalker<OptimizeInstructions,
// Optimizations that don't yet fit in the pattern DSL, but could be eventually maybe
Expression* handOptimize(Expression* curr) {
if (auto* binary = curr->dynCast<Binary>()) {
+ if (Properties::isSymmetric(binary)) {
+ // canonicalize a const to the second position
+ if (binary->left->is<Const>() && !binary->right->is<Const>()) {
+ std::swap(binary->left, binary->right);
+ }
+ }
// pattern match a load of 8 bits and a sign extend using a shl of 24 then shr_s of 24 as well, etc.
if (binary->op == BinaryOp::ShrSInt32 && binary->right->is<Const>()) {
auto shifts = binary->right->cast<Const>()->value.geti32();
@@ -238,6 +245,9 @@ struct OptimizeInstructions : public WalkerPass<PostWalker<OptimizeInstructions,
load->signed_ = false;
return load;
}
+ } else if (mask == 1 && Properties::emitsBoolean(binary->left)) {
+ // (bool) & 1 does not need the outer mask
+ return binary->left;
}
}
}