diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/asm2wasm.h | 12 | ||||
-rw-r--r-- | src/ast/properties.h | 60 | ||||
-rw-r--r-- | src/passes/OptimizeInstructions.cpp | 10 |
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; } } } |