summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/passes/CMakeLists.txt1
-rw-r--r--src/passes/RemoveCopysign.cpp106
-rw-r--r--src/passes/pass.cpp1
-rw-r--r--src/passes/passes.h1
-rw-r--r--src/wasm2asm.h1
5 files changed, 110 insertions, 0 deletions
diff --git a/src/passes/CMakeLists.txt b/src/passes/CMakeLists.txt
index d4fff78df..784a46032 100644
--- a/src/passes/CMakeLists.txt
+++ b/src/passes/CMakeLists.txt
@@ -30,6 +30,7 @@ SET(passes_SOURCES
RedundantSetElimination.cpp
RelooperJumpThreading.cpp
ReReloop.cpp
+ RemoveCopysign.cpp
RemoveImports.cpp
RemoveMemory.cpp
RemoveUnusedBrs.cpp
diff --git a/src/passes/RemoveCopysign.cpp b/src/passes/RemoveCopysign.cpp
new file mode 100644
index 000000000..2b57441ee
--- /dev/null
+++ b/src/passes/RemoveCopysign.cpp
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2018 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.
+ */
+
+//
+// Removes the `f32.copysign` and `f64.copysign` instructions and replaces them
+// with equivalent bit operations. Primarily intended to be used with `wasm2asm`
+// where `Math.copysign` doesn't exist.
+//
+
+#include <wasm.h>
+#include <pass.h>
+
+#include "wasm-builder.h"
+
+namespace wasm {
+
+struct RemoveCopysignPass : public WalkerPass<PostWalker<RemoveCopysignPass>> {
+ bool isFunctionParallel() override { return false; }
+
+ Pass* create() override { return new RemoveCopysignPass; }
+
+ void doWalkModule(Module* module) {
+ if (!builder) builder = make_unique<Builder>(*module);
+ PostWalker<RemoveCopysignPass>::doWalkModule(module);
+ }
+
+ void doWalkFunction(Function* func) {
+ if (!builder) builder = make_unique<Builder>(*getModule());
+ PostWalker<RemoveCopysignPass>::doWalkFunction(func);
+ }
+
+ void visitBinary(Binary *curr) {
+ Literal signBit, otherBits;
+ UnaryOp int2float, float2int;
+ BinaryOp bitAnd, bitOr;
+ switch (curr->op) {
+ case CopySignFloat32:
+ float2int = ReinterpretFloat32;
+ int2float = ReinterpretInt32;
+ bitAnd = AndInt32;
+ bitOr = OrInt32;
+ signBit = Literal(uint32_t(1 << 31));
+ otherBits = Literal(uint32_t(1 << 31) - 1);
+ break;
+
+ case CopySignFloat64:
+ float2int = ReinterpretFloat64;
+ int2float = ReinterpretInt64;
+ bitAnd = AndInt64;
+ bitOr = OrInt64;
+ signBit = Literal(uint64_t(1) << 63);
+ otherBits = Literal((uint64_t(1) << 63) - 1);
+ break;
+
+ default: return;
+ }
+
+ replaceCurrent(
+ builder->makeUnary(
+ int2float,
+ builder->makeBinary(
+ bitOr,
+ builder->makeBinary(
+ bitAnd,
+ builder->makeUnary(
+ float2int,
+ curr->left
+ ),
+ builder->makeConst(otherBits)
+ ),
+ builder->makeBinary(
+ bitAnd,
+ builder->makeUnary(
+ float2int,
+ curr->right
+ ),
+ builder->makeConst(signBit)
+ )
+ )
+ )
+ );
+ }
+
+private:
+ std::unique_ptr<Builder> builder;
+};
+
+Pass *createRemoveCopysignPass() {
+ return new RemoveCopysignPass();
+}
+
+} // namespace wasm
+
diff --git a/src/passes/pass.cpp b/src/passes/pass.cpp
index 5c43aaa4e..e820cd1fa 100644
--- a/src/passes/pass.cpp
+++ b/src/passes/pass.cpp
@@ -99,6 +99,7 @@ void PassRegistry::registerPasses() {
registerPass("print-full", "print in full s-expression format", createFullPrinterPass);
registerPass("print-call-graph", "print call graph", createPrintCallGraphPass);
registerPass("relooper-jump-threading", "thread relooper jumps (fastcomp output only)", createRelooperJumpThreadingPass);
+ registerPass("remove-copysign", "removes the copysign instruction", createRemoveCopysignPass);
registerPass("remove-imports", "removes imports and replaces them with nops", createRemoveImportsPass);
registerPass("remove-memory", "removes memory segments", createRemoveMemoryPass);
registerPass("remove-unused-brs", "removes breaks from locations that are not needed", createRemoveUnusedBrsPass);
diff --git a/src/passes/passes.h b/src/passes/passes.h
index cf77f9fac..410b8fe11 100644
--- a/src/passes/passes.h
+++ b/src/passes/passes.h
@@ -56,6 +56,7 @@ Pass* createPrecomputePropagatePass();
Pass* createPrinterPass();
Pass* createPrintCallGraphPass();
Pass* createRelooperJumpThreadingPass();
+Pass* createRemoveCopysignPass();
Pass* createRemoveImportsPass();
Pass* createRemoveMemoryPass();
Pass* createRemoveUnusedBrsPass();
diff --git a/src/wasm2asm.h b/src/wasm2asm.h
index 357896654..9e3abaa25 100644
--- a/src/wasm2asm.h
+++ b/src/wasm2asm.h
@@ -384,6 +384,7 @@ Ref Wasm2AsmBuilder::processWasm(Module* wasm) {
addWasmCompatibilityFuncs(wasm);
PassRunner runner(wasm);
runner.add<AutoDrop>();
+ runner.add("remove-copysign"); // must be before i64-to-i32
runner.add("i64-to-i32-lowering");
runner.add("flatten");
runner.add("simplify-locals-notee-nostructure");