[wasm] Add I64Atomic Load/Store ops

Bug:v8:6532

Change-Id: I62e62f6584d1d42dc8af713b874daafa1f8d4436
Reviewed-on: https://chromium-review.googlesource.com/969991
Reviewed-by: Ben Smith <binji@chromium.org>
Reviewed-by: Jaroslav Sevcik <jarin@chromium.org>
Commit-Queue: Deepti Gandluri <gdeepti@chromium.org>
Cr-Commit-Position: refs/heads/master@{#52253}
This commit is contained in:
Deepti Gandluri 2018-03-27 10:10:42 -07:00 committed by Commit Bot
parent fae1ab03a9
commit 8d29d92f4d
12 changed files with 340 additions and 34 deletions

View File

@ -1669,8 +1669,15 @@ void InstructionSelector::VisitNode(Node* node) {
MarkAsRepresentation(type.representation(), node);
return VisitWord32AtomicLoad(node);
}
case IrOpcode::kWord64AtomicLoad: {
LoadRepresentation type = LoadRepresentationOf(node->op());
MarkAsRepresentation(type.representation(), node);
return VisitWord64AtomicLoad(node);
}
case IrOpcode::kWord32AtomicStore:
return VisitWord32AtomicStore(node);
case IrOpcode::kWord64AtomicStore:
return VisitWord64AtomicStore(node);
#define ATOMIC_CASE(name, rep) \
case IrOpcode::k##rep##Atomic##name: { \
MachineType type = AtomicOpRepresentationOf(node->op()); \
@ -2311,6 +2318,12 @@ void InstructionSelector::VisitF32x4UConvertI32x4(Node* node) {
// && !V8_TARGET_ARCH_MIPS64
#if !V8_TARGET_ARCH_X64
void InstructionSelector::VisitWord64AtomicLoad(Node* node) { UNIMPLEMENTED(); }
void InstructionSelector::VisitWord64AtomicStore(Node* node) {
UNIMPLEMENTED();
}
void InstructionSelector::VisitWord64AtomicAdd(Node* node) { UNIMPLEMENTED(); }
void InstructionSelector::VisitWord64AtomicSub(Node* node) { UNIMPLEMENTED(); }

View File

@ -38,6 +38,7 @@ LoadRepresentation LoadRepresentationOf(Operator const* op) {
DCHECK(IrOpcode::kLoad == op->opcode() ||
IrOpcode::kProtectedLoad == op->opcode() ||
IrOpcode::kWord32AtomicLoad == op->opcode() ||
IrOpcode::kWord64AtomicLoad == op->opcode() ||
IrOpcode::kPoisonedLoad == op->opcode() ||
IrOpcode::kUnalignedLoad == op->opcode());
return OpParameter<LoadRepresentation>(op);
@ -78,7 +79,8 @@ StackSlotRepresentation const& StackSlotRepresentationOf(Operator const* op) {
}
MachineRepresentation AtomicStoreRepresentationOf(Operator const* op) {
DCHECK_EQ(IrOpcode::kWord32AtomicStore, op->opcode());
DCHECK(IrOpcode::kWord32AtomicStore == op->opcode() ||
IrOpcode::kWord64AtomicStore == op->opcode());
return OpParameter<MachineRepresentation>(op);
}
@ -408,6 +410,10 @@ MachineType AtomicOpRepresentationOf(Operator const* op) {
V(kWord16) \
V(kWord32)
#define ATOMIC64_REPRESENTATION_LIST(V) \
ATOMIC_REPRESENTATION_LIST(V) \
V(kWord64)
#define SIMD_LANE_OP_LIST(V) \
V(F32x4, 4) \
V(I32x4, 4) \
@ -577,6 +583,19 @@ struct MachineOperatorGlobalCache {
ATOMIC_TYPE_LIST(ATOMIC_LOAD)
#undef ATOMIC_LOAD
#define ATOMIC_LOAD(Type) \
struct Word64AtomicLoad##Type##Operator final \
: public Operator1<LoadRepresentation> { \
Word64AtomicLoad##Type##Operator() \
: Operator1<LoadRepresentation>( \
IrOpcode::kWord64AtomicLoad, \
Operator::kNoDeopt | Operator::kNoThrow | Operator::kNoWrite, \
"Word64AtomicLoad", 2, 1, 1, 1, 1, 0, MachineType::Type()) {} \
}; \
Word64AtomicLoad##Type##Operator kWord64AtomicLoad##Type;
ATOMIC64_TYPE_LIST(ATOMIC_LOAD)
#undef ATOMIC_LOAD
#define ATOMIC_STORE(Type) \
struct Word32AtomicStore##Type##Operator \
: public Operator1<MachineRepresentation> { \
@ -591,6 +610,20 @@ struct MachineOperatorGlobalCache {
ATOMIC_REPRESENTATION_LIST(ATOMIC_STORE)
#undef ATOMIC_STORE
#define ATOMIC_STORE(Type) \
struct Word64AtomicStore##Type##Operator \
: public Operator1<MachineRepresentation> { \
Word64AtomicStore##Type##Operator() \
: Operator1<MachineRepresentation>( \
IrOpcode::kWord64AtomicStore, \
Operator::kNoDeopt | Operator::kNoRead | Operator::kNoThrow, \
"Word64AtomicStore", 3, 1, 1, 0, 1, 0, \
MachineRepresentation::Type) {} \
}; \
Word64AtomicStore##Type##Operator kWord64AtomicStore##Type;
ATOMIC64_REPRESENTATION_LIST(ATOMIC_STORE)
#undef ATOMIC_STORE
#define ATOMIC_OP(op, type) \
struct op##type##Operator : public Operator1<MachineType> { \
op##type##Operator() \
@ -992,6 +1025,28 @@ const Operator* MachineOperatorBuilder::PoisonOnSpeculationWord() {
return &cache_.kPoisonOnSpeculationWord;
}
const Operator* MachineOperatorBuilder::Word64AtomicLoad(
LoadRepresentation rep) {
#define LOAD(Type) \
if (rep == MachineType::Type()) { \
return &cache_.kWord64AtomicLoad##Type; \
}
ATOMIC64_TYPE_LIST(LOAD)
#undef LOAD
UNREACHABLE();
}
const Operator* MachineOperatorBuilder::Word64AtomicStore(
MachineRepresentation rep) {
#define STORE(kRep) \
if (rep == MachineRepresentation::kRep) { \
return &cache_.kWord64AtomicStore##kRep; \
}
ATOMIC64_REPRESENTATION_LIST(STORE)
#undef STORE
UNREACHABLE();
}
const Operator* MachineOperatorBuilder::Word64AtomicAdd(MachineType rep) {
#define ADD(kRep) \
if (rep == MachineType::kRep()) { \
@ -1127,6 +1182,7 @@ const Operator* MachineOperatorBuilder::S8x16Shuffle(
#undef ATOMIC_TYPE_LIST
#undef ATOMIC64_TYPE_LIST
#undef ATOMIC_REPRESENTATION_LIST
#undef ATOMIC64_REPRESENTATION_LIST
#undef SIMD_LANE_OP_LIST
#undef SIMD_FORMAT_LIST
#undef STACK_SLOT_CACHED_SIZES_ALIGNMENTS_LIST

View File

@ -614,8 +614,12 @@ class V8_EXPORT_PRIVATE MachineOperatorBuilder final
// atomic-load [base + index]
const Operator* Word32AtomicLoad(LoadRepresentation rep);
// atomic-load [base + index]
const Operator* Word64AtomicLoad(LoadRepresentation rep);
// atomic-store [base + index], value
const Operator* Word32AtomicStore(MachineRepresentation rep);
// atomic-store [base + index], value
const Operator* Word64AtomicStore(MachineRepresentation rep);
// atomic-exchange [base + index], value
const Operator* Word32AtomicExchange(MachineType rep);
// atomic-exchange [base + index], value

View File

@ -636,6 +636,8 @@
V(Word32AtomicAnd) \
V(Word32AtomicOr) \
V(Word32AtomicXor) \
V(Word64AtomicLoad) \
V(Word64AtomicStore) \
V(Word64AtomicAdd) \
V(Word64AtomicSub) \
V(Word64AtomicAnd) \

View File

@ -1702,6 +1702,8 @@ void Verifier::Visitor::Check(Node* node, const AllNodes& all) {
case IrOpcode::kWord32AtomicAnd:
case IrOpcode::kWord32AtomicOr:
case IrOpcode::kWord32AtomicXor:
case IrOpcode::kWord64AtomicLoad:
case IrOpcode::kWord64AtomicStore:
case IrOpcode::kWord64AtomicAdd:
case IrOpcode::kWord64AtomicSub:
case IrOpcode::kWord64AtomicAnd:

View File

@ -4514,24 +4514,32 @@ Node* WasmGraphBuilder::Simd8x16ShuffleOp(const uint8_t shuffle[16],
V(I64AtomicExchange16U, Exchange, Uint16, Word64) \
V(I64AtomicExchange32U, Exchange, Uint32, Word64)
#define ATOMIC_TERNARY_LIST(V) \
V(I32AtomicCompareExchange, CompareExchange, Uint32, Word32) \
V(I64AtomicCompareExchange, CompareExchange, Uint64, Word64) \
V(I32AtomicCompareExchange8U, CompareExchange, Uint8, Word32) \
V(I32AtomicCompareExchange16U, CompareExchange, Uint16, Word32) \
V(I64AtomicCompareExchange8U, CompareExchange, Uint8, Word64) \
V(I64AtomicCompareExchange16U, CompareExchange, Uint16, Word64) \
V(I64AtomicCompareExchange32U, CompareExchange, Uint32, Word64)
#define ATOMIC_CMP_EXCHG_LIST(V) \
V(I32AtomicCompareExchange, Uint32, Word32) \
V(I64AtomicCompareExchange, Uint64, Word64) \
V(I32AtomicCompareExchange8U, Uint8, Word32) \
V(I32AtomicCompareExchange16U, Uint16, Word32) \
V(I64AtomicCompareExchange8U, Uint8, Word64) \
V(I64AtomicCompareExchange16U, Uint16, Word64) \
V(I64AtomicCompareExchange32U, Uint32, Word64)
#define ATOMIC_LOAD_LIST(V) \
V(I32AtomicLoad, Uint32) \
V(I32AtomicLoad8U, Uint8) \
V(I32AtomicLoad16U, Uint16)
#define ATOMIC_LOAD_LIST(V) \
V(I32AtomicLoad, Uint32, Word32) \
V(I64AtomicLoad, Uint64, Word64) \
V(I32AtomicLoad8U, Uint8, Word32) \
V(I32AtomicLoad16U, Uint16, Word32) \
V(I64AtomicLoad8U, Uint8, Word64) \
V(I64AtomicLoad16U, Uint16, Word64) \
V(I64AtomicLoad32U, Uint32, Word64)
#define ATOMIC_STORE_LIST(V) \
V(I32AtomicStore, Uint32, kWord32) \
V(I32AtomicStore8U, Uint8, kWord8) \
V(I32AtomicStore16U, Uint16, kWord16)
#define ATOMIC_STORE_LIST(V) \
V(I32AtomicStore, Uint32, kWord32, Word32) \
V(I64AtomicStore, Uint64, kWord64, Word64) \
V(I32AtomicStore8U, Uint8, kWord8, Word32) \
V(I32AtomicStore16U, Uint16, kWord16, Word32) \
V(I64AtomicStore8U, Uint8, kWord8, Word64) \
V(I64AtomicStore16U, Uint16, kWord16, Word64) \
V(I64AtomicStore32U, Uint32, kWord32, Word64)
Node* WasmGraphBuilder::AtomicOp(wasm::WasmOpcode opcode, Node* const* inputs,
uint32_t alignment, uint32_t offset,
@ -4552,41 +4560,42 @@ Node* WasmGraphBuilder::AtomicOp(wasm::WasmOpcode opcode, Node* const* inputs,
ATOMIC_BINOP_LIST(BUILD_ATOMIC_BINOP)
#undef BUILD_ATOMIC_BINOP
#define BUILD_ATOMIC_TERNARY_OP(Name, Operation, Type, Prefix) \
#define BUILD_ATOMIC_CMP_EXCHG(Name, Type, Prefix) \
case wasm::kExpr##Name: { \
Node* index = \
BoundsCheckMem(wasm::WasmOpcodes::MemSize(MachineType::Type()), \
inputs[0], offset, position, kNeedsBoundsCheck); \
node = graph()->NewNode( \
jsgraph()->machine()->Prefix##Atomic##Operation(MachineType::Type()), \
jsgraph()->machine()->Prefix##AtomicCompareExchange( \
MachineType::Type()), \
MemBuffer(offset), index, inputs[1], inputs[2], *effect_, *control_); \
break; \
}
ATOMIC_TERNARY_LIST(BUILD_ATOMIC_TERNARY_OP)
#undef BUILD_ATOMIC_TERNARY_OP
ATOMIC_CMP_EXCHG_LIST(BUILD_ATOMIC_CMP_EXCHG)
#undef BUILD_ATOMIC_CMP_EXCHG
#define BUILD_ATOMIC_LOAD_OP(Name, Type) \
#define BUILD_ATOMIC_LOAD_OP(Name, Type, Prefix) \
case wasm::kExpr##Name: { \
Node* index = \
BoundsCheckMem(wasm::WasmOpcodes::MemSize(MachineType::Type()), \
inputs[0], offset, position, kNeedsBoundsCheck); \
node = graph()->NewNode( \
jsgraph()->machine()->Word32AtomicLoad(MachineType::Type()), \
jsgraph()->machine()->Prefix##AtomicLoad(MachineType::Type()), \
MemBuffer(offset), index, *effect_, *control_); \
break; \
}
ATOMIC_LOAD_LIST(BUILD_ATOMIC_LOAD_OP)
#undef BUILD_ATOMIC_LOAD_OP
#define BUILD_ATOMIC_STORE_OP(Name, Type, Rep) \
case wasm::kExpr##Name: { \
Node* index = \
BoundsCheckMem(wasm::WasmOpcodes::MemSize(MachineType::Type()), \
inputs[0], offset, position, kNeedsBoundsCheck); \
node = graph()->NewNode( \
jsgraph()->machine()->Word32AtomicStore(MachineRepresentation::Rep), \
MemBuffer(offset), index, inputs[1], *effect_, *control_); \
break; \
#define BUILD_ATOMIC_STORE_OP(Name, Type, Rep, Prefix) \
case wasm::kExpr##Name: { \
Node* index = \
BoundsCheckMem(wasm::WasmOpcodes::MemSize(MachineType::Type()), \
inputs[0], offset, position, kNeedsBoundsCheck); \
node = graph()->NewNode( \
jsgraph()->machine()->Prefix##AtomicStore(MachineRepresentation::Rep), \
MemBuffer(offset), index, inputs[1], *effect_, *control_); \
break; \
}
ATOMIC_STORE_LIST(BUILD_ATOMIC_STORE_OP)
#undef BUILD_ATOMIC_STORE_OP
@ -4598,7 +4607,7 @@ Node* WasmGraphBuilder::AtomicOp(wasm::WasmOpcode opcode, Node* const* inputs,
}
#undef ATOMIC_BINOP_LIST
#undef ATOMIC_TERNARY_LIST
#undef ATOMIC_CMP_EXCHG_LIST
#undef ATOMIC_LOAD_LIST
#undef ATOMIC_STORE_LIST

View File

@ -2825,6 +2825,14 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
case kWord32AtomicStoreWord8:
case kWord32AtomicStoreWord16:
case kWord32AtomicStoreWord32:
case kX64Word64AtomicLoadUint8:
case kX64Word64AtomicLoadUint16:
case kX64Word64AtomicLoadUint32:
case kX64Word64AtomicLoadUint64:
case kX64Word64AtomicStoreWord8:
case kX64Word64AtomicStoreWord16:
case kX64Word64AtomicStoreWord32:
case kX64Word64AtomicStoreWord64:
UNREACHABLE(); // Won't be generated by instruction selector.
break;
}

View File

@ -235,6 +235,14 @@ namespace compiler {
V(X64S128Not) \
V(X64S128Select) \
V(X64S128Zero) \
V(X64Word64AtomicLoadUint8) \
V(X64Word64AtomicLoadUint16) \
V(X64Word64AtomicLoadUint32) \
V(X64Word64AtomicLoadUint64) \
V(X64Word64AtomicStoreWord8) \
V(X64Word64AtomicStoreWord16) \
V(X64Word64AtomicStoreWord32) \
V(X64Word64AtomicStoreWord64) \
V(X64Word64AtomicAddUint8) \
V(X64Word64AtomicAddUint16) \
V(X64Word64AtomicAddUint32) \

View File

@ -267,6 +267,16 @@ int InstructionScheduler::GetTargetInstructionFlags(
case kLFence:
return kHasSideEffect;
case kX64Word64AtomicLoadUint8:
case kX64Word64AtomicLoadUint16:
case kX64Word64AtomicLoadUint32:
case kX64Word64AtomicLoadUint64:
return kIsLoadOperation;
case kX64Word64AtomicStoreWord8:
case kX64Word64AtomicStoreWord16:
case kX64Word64AtomicStoreWord32:
case kX64Word64AtomicStoreWord64:
case kX64Word64AtomicAddUint8:
case kX64Word64AtomicAddUint16:
case kX64Word64AtomicAddUint32:

View File

@ -2119,6 +2119,12 @@ void InstructionSelector::VisitWord32AtomicLoad(Node* node) {
VisitLoad(node);
}
void InstructionSelector::VisitWord64AtomicLoad(Node* node) {
LoadRepresentation load_rep = LoadRepresentationOf(node->op());
USE(load_rep);
VisitLoad(node);
}
void InstructionSelector::VisitWord32AtomicStore(Node* node) {
X64OperandGenerator g(this);
Node* base = node->InputAt(0);
@ -2157,6 +2163,48 @@ void InstructionSelector::VisitWord32AtomicStore(Node* node) {
Emit(code, 0, static_cast<InstructionOperand*>(nullptr), input_count, inputs);
}
void InstructionSelector::VisitWord64AtomicStore(Node* node) {
X64OperandGenerator g(this);
Node* base = node->InputAt(0);
Node* index = node->InputAt(1);
Node* value = node->InputAt(2);
MachineRepresentation rep = AtomicStoreRepresentationOf(node->op());
ArchOpcode opcode = kArchNop;
switch (rep) {
case MachineRepresentation::kWord8:
opcode = kX64Word64AtomicExchangeUint8;
break;
case MachineRepresentation::kWord16:
opcode = kX64Word64AtomicExchangeUint16;
break;
case MachineRepresentation::kWord32:
opcode = kX64Word64AtomicExchangeUint32;
break;
case MachineRepresentation::kWord64:
opcode = kX64Word64AtomicExchangeUint64;
break;
default:
UNREACHABLE();
return;
}
AddressingMode addressing_mode;
InstructionOperand inputs[4];
size_t input_count = 0;
inputs[input_count++] = g.UseUniqueRegister(value);
inputs[input_count++] = g.UseUniqueRegister(base);
if (g.CanBeImmediate(index)) {
inputs[input_count++] = g.UseImmediate(index);
addressing_mode = kMode_MRI;
} else {
inputs[input_count++] = g.UseUniqueRegister(index);
addressing_mode = kMode_MR1;
}
InstructionCode code = opcode | AddressingModeField::encode(addressing_mode);
DCHECK_LE(input_count, arraysize(inputs));
Emit(code, 0, static_cast<InstructionOperand*>(nullptr), input_count, inputs);
}
void InstructionSelector::VisitWord32AtomicExchange(Node* node) {
X64OperandGenerator g(this);
Node* base = node->InputAt(0);

View File

@ -56,8 +56,12 @@ struct WasmException;
#define ATOMIC_OP_LIST(V) \
V(I32AtomicLoad, Uint32) \
V(I64AtomicLoad, Uint64) \
V(I32AtomicLoad8U, Uint8) \
V(I32AtomicLoad16U, Uint16) \
V(I64AtomicLoad8U, Uint8) \
V(I64AtomicLoad16U, Uint16) \
V(I64AtomicLoad32U, Uint32) \
V(I32AtomicAdd, Uint32) \
V(I32AtomicAdd8U, Uint8) \
V(I32AtomicAdd16U, Uint16) \
@ -110,8 +114,12 @@ struct WasmException;
#define ATOMIC_STORE_OP_LIST(V) \
V(I32AtomicStore, Uint32) \
V(I64AtomicStore, Uint64) \
V(I32AtomicStore8U, Uint8) \
V(I32AtomicStore16U, Uint16)
V(I32AtomicStore16U, Uint16) \
V(I64AtomicStore8U, Uint8) \
V(I64AtomicStore16U, Uint16) \
V(I64AtomicStore32U, Uint32)
template <typename T, typename Allocator>
Vector<T> vec2vec(std::vector<T, Allocator>& vec) {

View File

@ -251,6 +251,144 @@ WASM_COMPILED_EXEC_TEST(I32AtomicCompareExchange8U) {
}
}
}
WASM_COMPILED_EXEC_TEST(I64AtomicLoad) {
EXPERIMENTAL_FLAG_SCOPE(threads);
WasmRunner<uint64_t> r(execution_mode);
r.builder().SetHasSharedMemory();
uint64_t* memory = r.builder().AddMemoryElems<uint64_t>(8);
BUILD(r, WASM_ATOMICS_LOAD_OP(kExprI64AtomicLoad, WASM_ZERO,
MachineRepresentation::kWord64));
FOR_UINT64_INPUTS(i) {
uint64_t expected = *i;
r.builder().WriteMemory(&memory[0], expected);
CHECK_EQ(expected, r.Call());
}
}
WASM_COMPILED_EXEC_TEST(I64AtomicLoad32U) {
EXPERIMENTAL_FLAG_SCOPE(threads);
WasmRunner<uint64_t> r(execution_mode);
r.builder().SetHasSharedMemory();
uint32_t* memory = r.builder().AddMemoryElems<uint32_t>(8);
BUILD(r, WASM_ATOMICS_LOAD_OP(kExprI64AtomicLoad32U, WASM_ZERO,
MachineRepresentation::kWord32));
FOR_UINT32_INPUTS(i) {
uint32_t expected = *i;
r.builder().WriteMemory(&memory[0], expected);
CHECK_EQ(expected, r.Call());
}
}
WASM_COMPILED_EXEC_TEST(I64AtomicLoad16U) {
EXPERIMENTAL_FLAG_SCOPE(threads);
WasmRunner<uint64_t> r(execution_mode);
r.builder().SetHasSharedMemory();
uint16_t* memory = r.builder().AddMemoryElems<uint16_t>(8);
BUILD(r, WASM_ATOMICS_LOAD_OP(kExprI64AtomicLoad16U, WASM_ZERO,
MachineRepresentation::kWord16));
FOR_UINT16_INPUTS(i) {
uint16_t expected = *i;
r.builder().WriteMemory(&memory[0], expected);
CHECK_EQ(expected, r.Call());
}
}
WASM_COMPILED_EXEC_TEST(I64AtomicLoad8U) {
EXPERIMENTAL_FLAG_SCOPE(threads);
WasmRunner<uint64_t> r(execution_mode);
r.builder().SetHasSharedMemory();
uint8_t* memory = r.builder().AddMemoryElems<uint8_t>(8);
BUILD(r, WASM_ATOMICS_LOAD_OP(kExprI64AtomicLoad8U, WASM_ZERO,
MachineRepresentation::kWord8));
FOR_UINT8_INPUTS(i) {
uint8_t expected = *i;
r.builder().WriteMemory(&memory[0], expected);
CHECK_EQ(expected, r.Call());
}
}
WASM_COMPILED_EXEC_TEST(I64AtomicStoreLoad) {
EXPERIMENTAL_FLAG_SCOPE(threads);
WasmRunner<uint64_t, uint64_t> r(execution_mode);
r.builder().SetHasSharedMemory();
uint64_t* memory = r.builder().AddMemoryElems<uint64_t>(8);
BUILD(r,
WASM_ATOMICS_STORE_OP(kExprI64AtomicStore, WASM_ZERO, WASM_GET_LOCAL(0),
MachineRepresentation::kWord64),
WASM_ATOMICS_LOAD_OP(kExprI64AtomicLoad, WASM_ZERO,
MachineRepresentation::kWord64));
FOR_UINT64_INPUTS(i) {
uint64_t expected = *i;
CHECK_EQ(expected, r.Call(*i));
CHECK_EQ(expected, r.builder().ReadMemory(&memory[0]));
}
}
WASM_COMPILED_EXEC_TEST(I64AtomicStoreLoad32U) {
EXPERIMENTAL_FLAG_SCOPE(threads);
WasmRunner<uint64_t, uint64_t> r(execution_mode);
r.builder().SetHasSharedMemory();
uint32_t* memory = r.builder().AddMemoryElems<uint32_t>(8);
BUILD(
r,
WASM_ATOMICS_STORE_OP(kExprI64AtomicStore32U, WASM_ZERO,
WASM_GET_LOCAL(0), MachineRepresentation::kWord32),
WASM_ATOMICS_LOAD_OP(kExprI64AtomicLoad32U, WASM_ZERO,
MachineRepresentation::kWord32));
FOR_UINT32_INPUTS(i) {
uint32_t expected = *i;
CHECK_EQ(expected, r.Call(*i));
CHECK_EQ(expected, r.builder().ReadMemory(&memory[0]));
}
}
WASM_COMPILED_EXEC_TEST(I64AtomicStoreLoad16U) {
EXPERIMENTAL_FLAG_SCOPE(threads);
WasmRunner<uint64_t, uint64_t> r(execution_mode);
r.builder().SetHasSharedMemory();
uint16_t* memory = r.builder().AddMemoryElems<uint16_t>(8);
BUILD(
r,
WASM_ATOMICS_STORE_OP(kExprI64AtomicStore16U, WASM_ZERO,
WASM_GET_LOCAL(0), MachineRepresentation::kWord16),
WASM_ATOMICS_LOAD_OP(kExprI64AtomicLoad16U, WASM_ZERO,
MachineRepresentation::kWord16));
FOR_UINT16_INPUTS(i) {
uint16_t expected = *i;
CHECK_EQ(expected, r.Call(*i));
CHECK_EQ(expected, r.builder().ReadMemory(&memory[0]));
}
}
WASM_COMPILED_EXEC_TEST(I64AtomicStoreLoad8U) {
EXPERIMENTAL_FLAG_SCOPE(threads);
WasmRunner<uint64_t, uint64_t> r(execution_mode);
r.builder().SetHasSharedMemory();
uint8_t* memory = r.builder().AddMemoryElems<uint8_t>(8);
BUILD(r,
WASM_ATOMICS_STORE_OP(kExprI64AtomicStore8U, WASM_ZERO,
WASM_GET_LOCAL(0), MachineRepresentation::kWord8),
WASM_ATOMICS_LOAD_OP(kExprI64AtomicLoad8U, WASM_ZERO,
MachineRepresentation::kWord8));
FOR_UINT8_INPUTS(i) {
uint8_t expected = *i;
CHECK_EQ(expected, r.Call(*i));
CHECK_EQ(*i, r.builder().ReadMemory(&memory[0]));
}
}
} // namespace test_run_wasm_atomics_64
} // namespace wasm
} // namespace internal