summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/asmjs/shared-constants.cpp1
-rw-r--r--src/asmjs/shared-constants.h1
-rw-r--r--src/ast/localize.h47
-rw-r--r--src/passes/PostEmscripten.cpp23
-rw-r--r--test/passes/post-emscripten.txt71
-rw-r--r--test/passes/post-emscripten.wast56
6 files changed, 197 insertions, 2 deletions
diff --git a/src/asmjs/shared-constants.cpp b/src/asmjs/shared-constants.cpp
index e30fd939c..d704c8009 100644
--- a/src/asmjs/shared-constants.cpp
+++ b/src/asmjs/shared-constants.cpp
@@ -49,6 +49,7 @@ cashew::IString GLOBAL("global"),
FLOOR("floor"),
CEIL("ceil"),
SQRT("sqrt"),
+ POW("pow"),
I32_TEMP("asm2wasm_i32_temp"),
DEBUGGER("debugger"),
USE_ASM("use asm"),
diff --git a/src/asmjs/shared-constants.h b/src/asmjs/shared-constants.h
index e0c627511..7b48c3df5 100644
--- a/src/asmjs/shared-constants.h
+++ b/src/asmjs/shared-constants.h
@@ -52,6 +52,7 @@ extern cashew::IString GLOBAL,
FLOOR,
CEIL,
SQRT,
+ POW,
I32_TEMP,
DEBUGGER,
USE_ASM,
diff --git a/src/ast/localize.h b/src/ast/localize.h
new file mode 100644
index 000000000..9e7dd6653
--- /dev/null
+++ b/src/ast/localize.h
@@ -0,0 +1,47 @@
+/*
+ * 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_localizer_h
+#define wasm_ast_localizer_h
+
+#include <wasm-builder.h>
+
+namespace wasm {
+
+// Make an expression available in a local. If already in one, just
+// use that local, otherwise use a new local
+
+struct Localizer {
+ Index index;
+ Expression* expr;
+
+ Localizer(Expression* input, Function* func, Module* wasm) {
+ expr = input;
+ if (auto* get = expr->dynCast<GetLocal>()) {
+ index = get->index;
+ } else if (auto* set = expr->dynCast<SetLocal>()) {
+ index = set->index;
+ } else {
+ index = Builder::addVar(func, expr->type);
+ expr = Builder(*wasm).makeTeeLocal(index, expr);
+ }
+ }
+};
+
+} // namespace wasm
+
+#endif // wasm_ast_localizer_h
+
diff --git a/src/passes/PostEmscripten.cpp b/src/passes/PostEmscripten.cpp
index 51b8c2ec1..937a70e36 100644
--- a/src/passes/PostEmscripten.cpp
+++ b/src/passes/PostEmscripten.cpp
@@ -21,6 +21,9 @@
#include <wasm.h>
#include <pass.h>
+#include <wasm-builder.h>
+#include <ast/localize.h>
+#include <asmjs/shared-constants.h>
namespace wasm {
@@ -88,6 +91,26 @@ struct PostEmscripten : public WalkerPass<PostWalker<PostEmscripten>> {
void visitStore(Store* curr) {
optimizeMemoryAccess(curr->ptr, curr->offset);
}
+
+ void visitCallImport(CallImport* curr) {
+ // special asm.js imports can be optimized
+ auto* import = getModule()->getImport(curr->target);
+ if (import->module == GLOBAL_MATH) {
+ if (import->base == POW) {
+ if (auto* exponent = curr->operands[1]->dynCast<Const>()) {
+ if (exponent->value == Literal(double(2.0))) {
+ // This is just a square operation, do a multiply
+ Localizer localizer(curr->operands[0], getFunction(), getModule());
+ Builder builder(*getModule());
+ replaceCurrent(builder.makeBinary(MulFloat64, localizer.expr, builder.makeGetLocal(localizer.index, localizer.expr->type)));
+ } else if (exponent->value == Literal(double(0.5))) {
+ // This is just a square root operation
+ replaceCurrent(Builder(*getModule()).makeUnary(SqrtFloat64, curr->operands[0]));
+ }
+ }
+ }
+ }
+ }
};
Pass *createPostEmscriptenPass() {
diff --git a/test/passes/post-emscripten.txt b/test/passes/post-emscripten.txt
index 179dec8c8..947318051 100644
--- a/test/passes/post-emscripten.txt
+++ b/test/passes/post-emscripten.txt
@@ -1,6 +1,9 @@
(module
(type $0 (func (param i32)))
- (type $1 (func (param i32) (result i32)))
+ (type $FUNCSIG$ddd (func (param f64 f64) (result f64)))
+ (type $2 (func (param i32) (result i32)))
+ (type $3 (func))
+ (import "global.Math" "pow" (func $Math_pow (param f64 f64) (result f64)))
(memory $0 256 256)
(export "load-off-2" (func $load-off-2))
(func $b0 (type $0) (param $x i32)
@@ -41,7 +44,7 @@
)
)
)
- (func $load-off-2 (type $1) (param $0 i32) (result i32)
+ (func $load-off-2 (type $2) (param $0 i32) (result i32)
(i32.store
(i32.const 6)
(get_local $0)
@@ -112,4 +115,68 @@
(get_local $0)
)
)
+ (func $pow2 (type $3)
+ (local $x f64)
+ (local $y f64)
+ (local $2 f64)
+ (local $3 f64)
+ (drop
+ (f64.mul
+ (tee_local $2
+ (f64.const 1)
+ )
+ (get_local $2)
+ )
+ )
+ (drop
+ (call $Math_pow
+ (f64.const 1)
+ (f64.const 3)
+ )
+ )
+ (drop
+ (call $Math_pow
+ (f64.const 2)
+ (f64.const 1)
+ )
+ )
+ (set_local $x
+ (f64.const 5)
+ )
+ (drop
+ (f64.mul
+ (get_local $x)
+ (get_local $x)
+ )
+ )
+ (drop
+ (f64.mul
+ (tee_local $y
+ (f64.const 7)
+ )
+ (get_local $y)
+ )
+ )
+ (drop
+ (f64.mul
+ (tee_local $3
+ (f64.const 8)
+ )
+ (get_local $3)
+ )
+ )
+ )
+ (func $pow.2 (type $3)
+ (drop
+ (f64.sqrt
+ (f64.const 1)
+ )
+ )
+ (drop
+ (call $Math_pow
+ (f64.const 1)
+ (f64.const 0.51)
+ )
+ )
+ )
)
diff --git a/test/passes/post-emscripten.wast b/test/passes/post-emscripten.wast
index f262975f5..5c255ffca 100644
--- a/test/passes/post-emscripten.wast
+++ b/test/passes/post-emscripten.wast
@@ -1,6 +1,7 @@
(module
(memory 256 256)
(type $0 (func (param i32)))
+ (import "global.Math" "pow" (func $Math_pow (param f64 f64) (result f64)))
(func $b0 (type $0) (param $x i32)
(drop
(i32.load
@@ -152,4 +153,59 @@
)
)
)
+ (func $pow2
+ (local $x f64)
+ (local $y f64)
+ (drop
+ (call $Math_pow
+ (f64.const 1)
+ (f64.const 2)
+ )
+ )
+ (drop
+ (call $Math_pow
+ (f64.const 1)
+ (f64.const 3)
+ )
+ )
+ (drop
+ (call $Math_pow
+ (f64.const 2)
+ (f64.const 1)
+ )
+ )
+ (set_local $x (f64.const 5))
+ (drop
+ (call $Math_pow
+ (get_local $x)
+ (f64.const 2)
+ )
+ )
+ (drop
+ (call $Math_pow
+ (tee_local $y (f64.const 7))
+ (f64.const 2)
+ )
+ )
+ (drop
+ (call $Math_pow
+ (f64.const 8)
+ (f64.const 2)
+ )
+ )
+ )
+ (func $pow.2
+ (drop
+ (call $Math_pow
+ (f64.const 1)
+ (f64.const 0.5)
+ )
+ )
+ (drop
+ (call $Math_pow
+ (f64.const 1)
+ (f64.const 0.51)
+ )
+ )
+ )
)