summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2017-11-14 16:42:25 -0800
committerGitHub <noreply@github.com>2017-11-14 16:42:25 -0800
commit4deed1eb310993391fa0e7e06a18cf2303674f98 (patch)
tree16028717e26ec439fe0e8f5b2e40988fcc92f2e9 /src
parent82d693b2bd23778b29bbd1019936a2857580c7ed (diff)
downloadbinaryen-4deed1eb310993391fa0e7e06a18cf2303674f98.tar.gz
binaryen-4deed1eb310993391fa0e7e06a18cf2303674f98.tar.bz2
binaryen-4deed1eb310993391fa0e7e06a18cf2303674f98.zip
add i64_atomics_* support to asm2wasm (#1262)
* add i64_atomics_* support to asm2wasm * OptimizeInstructions: atomic loads can't be signed
Diffstat (limited to 'src')
-rw-r--r--src/asm2wasm.h44
-rw-r--r--src/ir/load-utils.h5
-rw-r--r--src/passes/OptimizeInstructions.cpp3
3 files changed, 51 insertions, 1 deletions
diff --git a/src/asm2wasm.h b/src/asm2wasm.h
index a030a2024..71c7447e0 100644
--- a/src/asm2wasm.h
+++ b/src/asm2wasm.h
@@ -119,6 +119,15 @@ Name I32_CTTZ("i32_cttz"),
ATOMICS_AND("and"),
ATOMICS_OR("or"),
ATOMICS_XOR("xor"),
+ I64_ATOMICS_LOAD("i64_atomics_load"),
+ I64_ATOMICS_STORE("i64_atomics_store"),
+ I64_ATOMICS_AND("i64_atomics_and"),
+ I64_ATOMICS_OR("i64_atomics_or"),
+ I64_ATOMICS_XOR("i64_atomics_xor"),
+ I64_ATOMICS_ADD("i64_atomics_add"),
+ I64_ATOMICS_SUB("i64_atomics_sub"),
+ I64_ATOMICS_EXCHANGE("i64_atomics_exchange"),
+ I64_ATOMICS_COMPAREEXCHANGE("i64_atomics_compareExchange"),
EMSCRIPTEN_DEBUGINFO("emscripten_debuginfo");
// Utilities
@@ -1994,6 +2003,7 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) {
if (name == I64_CTTZ) return builder.makeUnary(UnaryOp::CtzInt64, value);
if (name == I64_CTLZ) return builder.makeUnary(UnaryOp::ClzInt64, value);
if (name == I64_CTPOP) return builder.makeUnary(UnaryOp::PopcntInt64, value);
+ if (name == I64_ATOMICS_LOAD) return builder.makeAtomicLoad(8, 0, value, i64);
} else if (num == 2) { // 2 params,binary
if (name == I64_CONST) return builder.makeConst(getLiteral(ast));
auto* left = process(ast[2][0]);
@@ -2035,6 +2045,40 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) {
if (name == I64_SLT) return builder.makeBinary(BinaryOp::LtSInt64, left, right);
if (name == I64_UGT) return builder.makeBinary(BinaryOp::GtUInt64, left, right);
if (name == I64_SGT) return builder.makeBinary(BinaryOp::GtSInt64, left, right);
+ // atomics
+ if (name == I64_ATOMICS_STORE) {
+ wasm.memory.shared = true;
+ return builder.makeAtomicStore(8, 0, left, right, i64);
+ }
+ if (name == I64_ATOMICS_ADD) {
+ wasm.memory.shared = true;
+ return builder.makeAtomicRMW(AtomicRMWOp::Add, 8, 0, left, right, i64);
+ }
+ if (name == I64_ATOMICS_SUB) {
+ wasm.memory.shared = true;
+ return builder.makeAtomicRMW(AtomicRMWOp::Sub, 8, 0, left, right, i64);
+ }
+ if (name == I64_ATOMICS_AND) {
+ wasm.memory.shared = true;
+ return builder.makeAtomicRMW(AtomicRMWOp::And, 8, 0, left, right, i64);
+ }
+ if (name == I64_ATOMICS_OR) {
+ wasm.memory.shared = true;
+ return builder.makeAtomicRMW(AtomicRMWOp::Or, 8, 0, left, right, i64);
+ }
+ if (name == I64_ATOMICS_XOR) {
+ wasm.memory.shared = true;
+ return builder.makeAtomicRMW(AtomicRMWOp::Xor, 8, 0, left, right, i64);
+ }
+ if (name == I64_ATOMICS_EXCHANGE) {
+ wasm.memory.shared = true;
+ return builder.makeAtomicRMW(AtomicRMWOp::Xchg, 8, 0, left, right, i64);
+ }
+ } else if (num == 3) {
+ if (name == I64_ATOMICS_COMPAREEXCHANGE) {
+ wasm.memory.shared = true;
+ return builder.makeAtomicCmpxchg(8, 0, process(ast[2][0]), process(ast[2][1]), process(ast[2][2]), i64);
+ }
}
break;
}
diff --git a/src/ir/load-utils.h b/src/ir/load-utils.h
index edc7eb90f..45882dc6c 100644
--- a/src/ir/load-utils.h
+++ b/src/ir/load-utils.h
@@ -32,6 +32,11 @@ inline bool isSignRelevant(Load* load) {
return !isWasmTypeFloat(type) && load->bytes < getWasmTypeSize(type);
}
+// check if a load can be signed (which some opts want to do)
+inline bool canBeSigned(Load* load) {
+ return !load->isAtomic;
+}
+
} // namespace LoadUtils
} // namespace wasm
diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp
index 5194c8ce7..37fb37ace 100644
--- a/src/passes/OptimizeInstructions.cpp
+++ b/src/passes/OptimizeInstructions.cpp
@@ -422,7 +422,8 @@ struct OptimizeInstructions : public WalkerPass<PostWalker<OptimizeInstructions,
if (extraShifts == 0) {
if (auto* load = getFallthrough(ext)->dynCast<Load>()) {
// 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 ((load->bytes == 1 && bits == 8) || (load->bytes == 2 && bits == 16)) {
+ if (LoadUtils::canBeSigned(load) &&
+ ((load->bytes == 1 && bits == 8) || (load->bytes == 2 && bits == 16))) {
// if the value falls through, we can't alter the load, as it might be captured in a tee
if (load->signed_ == true || load == ext) {
load->signed_ = true;