diff options
author | Alon Zakai <alonzakai@gmail.com> | 2017-11-14 16:42:25 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-11-14 16:42:25 -0800 |
commit | 4deed1eb310993391fa0e7e06a18cf2303674f98 (patch) | |
tree | 16028717e26ec439fe0e8f5b2e40988fcc92f2e9 /src | |
parent | 82d693b2bd23778b29bbd1019936a2857580c7ed (diff) | |
download | binaryen-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.h | 44 | ||||
-rw-r--r-- | src/ir/load-utils.h | 5 | ||||
-rw-r--r-- | src/passes/OptimizeInstructions.cpp | 3 |
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; |