Commit 849b2239 authored by Andreas Haas's avatar Andreas Haas Committed by Commit Bot

[wasm][arm] Correctly handle AtomicExchange without used outputs

The existing implementation needed uses of the outputs of an
AtomicExchange to allocate registers for the result value. However,
these uses are not guaranteed to exist. With this CL temp registers
get allocated if the uses don't exist.

R=gdeepti@chromium.org

Bug: chromium:1077130
Change-Id: I058ee53b87c6e995c9f490f3aebbfdba69934f3c
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2179503Reviewed-by: 's avatarDeepti Gandluri <gdeepti@chromium.org>
Commit-Queue: Andreas Haas <ahaas@chromium.org>
Cr-Commit-Position: refs/heads/master@{#67556}
parent 701b3171
......@@ -2439,23 +2439,24 @@ void InstructionSelector::VisitWord32AtomicPairExchange(Node* node) {
AddressingModeField::encode(addressing_mode);
Node* projection0 = NodeProperties::FindProjection(node, 0);
Node* projection1 = NodeProperties::FindProjection(node, 1);
InstructionOperand outputs[2];
size_t output_count = 0;
InstructionOperand temps[4];
size_t temp_count = 0;
temps[temp_count++] = g.TempRegister();
temps[temp_count++] = g.TempRegister();
if (projection0) {
outputs[output_count++] = g.DefineAsFixed(projection0, r6);
} else {
temps[temp_count++] = g.TempRegister(r6);
}
if (projection1) {
InstructionOperand outputs[] = {g.DefineAsFixed(projection0, r6),
g.DefineAsFixed(projection1, r7)};
InstructionOperand temps[] = {g.TempRegister(), g.TempRegister()};
Emit(code, arraysize(outputs), outputs, arraysize(inputs), inputs,
arraysize(temps), temps);
} else if (projection0) {
InstructionOperand outputs[] = {g.DefineAsFixed(projection0, r6)};
InstructionOperand temps[] = {g.TempRegister(), g.TempRegister(),
g.TempRegister(r7)};
Emit(code, arraysize(outputs), outputs, arraysize(inputs), inputs,
arraysize(temps), temps);
outputs[output_count++] = g.DefineAsFixed(projection1, r7);
} else {
InstructionOperand temps[] = {g.TempRegister(), g.TempRegister(),
g.TempRegister(r6), g.TempRegister(r7)};
Emit(code, 0, nullptr, arraysize(inputs), inputs, arraysize(temps), temps);
temps[temp_count++] = g.TempRegister(r7);
}
Emit(code, output_count, outputs, arraysize(inputs), inputs, temp_count,
temps);
}
void InstructionSelector::VisitWord32AtomicPairCompareExchange(Node* node) {
......
......@@ -782,6 +782,35 @@ WASM_EXEC_TEST(I64AtomicCompareExchangeUseOnlyHighWord) {
CHECK_EQ(0x12345678, r.Call());
}
WASM_EXEC_TEST(I64AtomicExchangeUseOnlyLowWord) {
EXPERIMENTAL_FLAG_SCOPE(threads);
WasmRunner<uint32_t> r(execution_tier);
uint64_t* memory =
r.builder().AddMemoryElems<uint64_t>(kWasmPageSize / sizeof(uint64_t));
memory[1] = 0x1234567890abcdeful;
r.builder().SetHasSharedMemory();
// Test that we can use just the low word of an I64AtomicLoad.
BUILD(r, WASM_I32_CONVERT_I64(WASM_ATOMICS_BINOP(
kExprI64AtomicExchange, WASM_I32V(8), WASM_I64V(1),
MachineRepresentation::kWord64)));
CHECK_EQ(0x90abcdef, r.Call());
}
WASM_EXEC_TEST(I64AtomicExchangeUseOnlyHighWord) {
EXPERIMENTAL_FLAG_SCOPE(threads);
WasmRunner<uint32_t> r(execution_tier);
uint64_t* memory =
r.builder().AddMemoryElems<uint64_t>(kWasmPageSize / sizeof(uint64_t));
memory[1] = 0x1234567890abcdeful;
r.builder().SetHasSharedMemory();
// Test that we can use just the high word of an I64AtomicLoad.
BUILD(r, WASM_I32_CONVERT_I64(WASM_I64_ROR(
WASM_ATOMICS_BINOP(kExprI64AtomicExchange, WASM_I32V(8),
WASM_I64V(1), MachineRepresentation::kWord64),
WASM_I64V(32))));
CHECK_EQ(0x12345678, r.Call());
}
WASM_EXEC_TEST(I64AtomicCompareExchange32UZeroExtended) {
EXPERIMENTAL_FLAG_SCOPE(threads);
WasmRunner<uint32_t> r(execution_tier);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment