[CPU] Remove ATOMIC_EXCHANGE opcode (dead code)
This commit is contained in:
@@ -867,101 +867,6 @@ struct MEMSET_I64
|
||||
EMITTER_OPCODE_TABLE(OPCODE_MEMSET, MEMSET_I64);
|
||||
|
||||
// ============================================================================
|
||||
// OPCODE_ATOMIC_EXCHANGE
|
||||
// ============================================================================
|
||||
// Note: src1 is a HOST address (not guest), matching the x64 backend.
|
||||
struct ATOMIC_EXCHANGE_I8
|
||||
: Sequence<ATOMIC_EXCHANGE_I8,
|
||||
I<OPCODE_ATOMIC_EXCHANGE, I8Op, I64Op, I8Op>> {
|
||||
static void Emit(A64Emitter& e, const EmitArgType& i) {
|
||||
// src1 is already a host address.
|
||||
if (i.src1.is_constant) {
|
||||
e.mov(e.x4, i.src1.constant());
|
||||
} else {
|
||||
e.mov(e.x4, i.src1);
|
||||
}
|
||||
if (i.src2.is_constant) {
|
||||
e.mov(e.w0, static_cast<uint64_t>(
|
||||
static_cast<uint32_t>(i.src2.constant()) & 0xFF));
|
||||
} else {
|
||||
e.and_(e.w0, i.src2, 0xFF);
|
||||
}
|
||||
|
||||
if (e.IsFeatureEnabled(kA64EmitLSE)) {
|
||||
e.swpalb(e.w0, i.dest, ptr(e.x4));
|
||||
return;
|
||||
}
|
||||
|
||||
auto& retry = e.NewCachedLabel();
|
||||
e.L(retry);
|
||||
e.ldaxrb(e.w1, ptr(e.x4));
|
||||
e.stlxrb(e.w2, e.w0, ptr(e.x4));
|
||||
e.cbnz(e.w2, retry);
|
||||
e.mov(i.dest, e.w1);
|
||||
}
|
||||
};
|
||||
struct ATOMIC_EXCHANGE_I16
|
||||
: Sequence<ATOMIC_EXCHANGE_I16,
|
||||
I<OPCODE_ATOMIC_EXCHANGE, I16Op, I64Op, I16Op>> {
|
||||
static void Emit(A64Emitter& e, const EmitArgType& i) {
|
||||
if (i.src1.is_constant) {
|
||||
e.mov(e.x4, i.src1.constant());
|
||||
} else {
|
||||
e.mov(e.x4, i.src1);
|
||||
}
|
||||
if (i.src2.is_constant) {
|
||||
e.mov(e.w0, static_cast<uint64_t>(
|
||||
static_cast<uint32_t>(i.src2.constant()) & 0xFFFF));
|
||||
} else {
|
||||
e.and_(e.w0, i.src2, 0xFFFF);
|
||||
}
|
||||
|
||||
if (e.IsFeatureEnabled(kA64EmitLSE)) {
|
||||
e.swpalh(e.w0, i.dest, ptr(e.x4));
|
||||
return;
|
||||
}
|
||||
|
||||
auto& retry = e.NewCachedLabel();
|
||||
e.L(retry);
|
||||
e.ldaxrh(e.w1, ptr(e.x4));
|
||||
e.stlxrh(e.w2, e.w0, ptr(e.x4));
|
||||
e.cbnz(e.w2, retry);
|
||||
e.mov(i.dest, e.w1);
|
||||
}
|
||||
};
|
||||
struct ATOMIC_EXCHANGE_I32
|
||||
: Sequence<ATOMIC_EXCHANGE_I32,
|
||||
I<OPCODE_ATOMIC_EXCHANGE, I32Op, I64Op, I32Op>> {
|
||||
static void Emit(A64Emitter& e, const EmitArgType& i) {
|
||||
// src1 is a host address (not guest).
|
||||
if (i.src1.is_constant) {
|
||||
e.mov(e.x4, i.src1.constant());
|
||||
} else {
|
||||
e.mov(e.x4, i.src1);
|
||||
}
|
||||
if (i.src2.is_constant) {
|
||||
e.mov(e.w0,
|
||||
static_cast<uint64_t>(static_cast<uint32_t>(i.src2.constant())));
|
||||
} else {
|
||||
e.mov(e.w0, i.src2);
|
||||
}
|
||||
|
||||
if (e.IsFeatureEnabled(kA64EmitLSE)) {
|
||||
e.swpal(e.w0, i.dest, ptr(e.x4));
|
||||
return;
|
||||
}
|
||||
|
||||
auto& retry = e.NewCachedLabel();
|
||||
e.L(retry);
|
||||
e.ldaxr(e.w1, ptr(e.x4));
|
||||
e.stlxr(e.w2, e.w0, ptr(e.x4));
|
||||
e.cbnz(e.w2, retry);
|
||||
e.mov(i.dest, e.w1);
|
||||
}
|
||||
};
|
||||
EMITTER_OPCODE_TABLE(OPCODE_ATOMIC_EXCHANGE, ATOMIC_EXCHANGE_I8,
|
||||
ATOMIC_EXCHANGE_I16, ATOMIC_EXCHANGE_I32);
|
||||
|
||||
// ============================================================================
|
||||
// OPCODE_ATOMIC_COMPARE_EXCHANGE
|
||||
// ============================================================================
|
||||
|
||||
@@ -295,68 +295,6 @@ RegExp ComputeMemoryAddressOffset(X64Emitter& e, const T& guest,
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// OPCODE_ATOMIC_EXCHANGE
|
||||
// ============================================================================
|
||||
// Note that the address we use here is a real, host address!
|
||||
// This is weird, and should be fixed.
|
||||
template <typename SEQ, typename REG, typename ARGS>
|
||||
void EmitAtomicExchangeXX(X64Emitter& e, const ARGS& i) {
|
||||
if (i.dest == i.src1) {
|
||||
e.mov(e.rax, i.src1);
|
||||
if (i.dest != i.src2) {
|
||||
if (i.src2.is_constant) {
|
||||
e.mov(i.dest, i.src2.constant());
|
||||
} else {
|
||||
e.mov(i.dest, i.src2);
|
||||
}
|
||||
}
|
||||
e.lock();
|
||||
e.xchg(e.dword[e.rax], i.dest);
|
||||
} else {
|
||||
if (i.dest != i.src2) {
|
||||
if (i.src2.is_constant) {
|
||||
e.mov(i.dest, i.src2.constant());
|
||||
} else {
|
||||
e.mov(i.dest, i.src2);
|
||||
}
|
||||
}
|
||||
e.lock();
|
||||
e.xchg(e.dword[i.src1.reg()], i.dest);
|
||||
}
|
||||
}
|
||||
struct ATOMIC_EXCHANGE_I8
|
||||
: Sequence<ATOMIC_EXCHANGE_I8,
|
||||
I<OPCODE_ATOMIC_EXCHANGE, I8Op, I64Op, I8Op>> {
|
||||
static void Emit(X64Emitter& e, const EmitArgType& i) {
|
||||
EmitAtomicExchangeXX<ATOMIC_EXCHANGE_I8, Reg8>(e, i);
|
||||
}
|
||||
};
|
||||
struct ATOMIC_EXCHANGE_I16
|
||||
: Sequence<ATOMIC_EXCHANGE_I16,
|
||||
I<OPCODE_ATOMIC_EXCHANGE, I16Op, I64Op, I16Op>> {
|
||||
static void Emit(X64Emitter& e, const EmitArgType& i) {
|
||||
EmitAtomicExchangeXX<ATOMIC_EXCHANGE_I16, Reg16>(e, i);
|
||||
}
|
||||
};
|
||||
struct ATOMIC_EXCHANGE_I32
|
||||
: Sequence<ATOMIC_EXCHANGE_I32,
|
||||
I<OPCODE_ATOMIC_EXCHANGE, I32Op, I64Op, I32Op>> {
|
||||
static void Emit(X64Emitter& e, const EmitArgType& i) {
|
||||
EmitAtomicExchangeXX<ATOMIC_EXCHANGE_I32, Reg32>(e, i);
|
||||
}
|
||||
};
|
||||
struct ATOMIC_EXCHANGE_I64
|
||||
: Sequence<ATOMIC_EXCHANGE_I64,
|
||||
I<OPCODE_ATOMIC_EXCHANGE, I64Op, I64Op, I64Op>> {
|
||||
static void Emit(X64Emitter& e, const EmitArgType& i) {
|
||||
EmitAtomicExchangeXX<ATOMIC_EXCHANGE_I64, Reg64>(e, i);
|
||||
}
|
||||
};
|
||||
EMITTER_OPCODE_TABLE(OPCODE_ATOMIC_EXCHANGE, ATOMIC_EXCHANGE_I8,
|
||||
ATOMIC_EXCHANGE_I16, ATOMIC_EXCHANGE_I32,
|
||||
ATOMIC_EXCHANGE_I64);
|
||||
|
||||
struct LVL_V128 : Sequence<LVL_V128, I<OPCODE_LVL, V128Op, I64Op>> {
|
||||
static void Emit(X64Emitter& e, const EmitArgType& i) {
|
||||
e.mov(e.edx, 0xf);
|
||||
|
||||
@@ -2225,17 +2225,6 @@ Value* HIRBuilder::Unpack(Value* value, uint32_t pack_flags) {
|
||||
return i->dest;
|
||||
}
|
||||
|
||||
Value* HIRBuilder::AtomicExchange(Value* address, Value* new_value) {
|
||||
ASSERT_ADDRESS_TYPE(address);
|
||||
ASSERT_INTEGER_TYPE(new_value);
|
||||
Instr* i =
|
||||
AppendInstr(OPCODE_ATOMIC_EXCHANGE_info, 0, AllocValue(new_value->type));
|
||||
i->set_src1(address);
|
||||
i->set_src2(new_value);
|
||||
i->src3.value = NULL;
|
||||
return i->dest;
|
||||
}
|
||||
|
||||
Value* HIRBuilder::AtomicCompareExchange(Value* address, Value* old_value,
|
||||
Value* new_value) {
|
||||
ASSERT_ADDRESS_TYPE(address);
|
||||
|
||||
@@ -297,7 +297,6 @@ class HIRBuilder {
|
||||
Value* Pack(Value* value1, Value* value2, uint32_t pack_flags = 0);
|
||||
Value* Unpack(Value* value, uint32_t pack_flags = 0);
|
||||
|
||||
Value* AtomicExchange(Value* address, Value* new_value);
|
||||
Value* AtomicCompareExchange(Value* address, Value* old_value,
|
||||
Value* new_value);
|
||||
Value* AtomicAdd(Value* address, Value* value);
|
||||
|
||||
@@ -282,7 +282,6 @@ enum Opcode {
|
||||
OPCODE_PACK, // break up into smaller operations and add a float16 convert
|
||||
// opcode
|
||||
OPCODE_UNPACK,
|
||||
OPCODE_ATOMIC_EXCHANGE,
|
||||
OPCODE_ATOMIC_COMPARE_EXCHANGE,
|
||||
OPCODE_SET_ROUNDING_MODE,
|
||||
OPCODE_VECTOR_DENORMFLUSH, // converts denormals to signed zeros in a vector
|
||||
|
||||
@@ -650,12 +650,6 @@ DEFINE_OPCODE(
|
||||
OPCODE_SIG_V_V,
|
||||
0)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_ATOMIC_EXCHANGE,
|
||||
"atomic_exchange",
|
||||
OPCODE_SIG_V_V_V,
|
||||
OPCODE_FLAG_VOLATILE)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_ATOMIC_COMPARE_EXCHANGE,
|
||||
"atomic_compare_exchange",
|
||||
|
||||
@@ -646,45 +646,6 @@ TEST_CASE("SET_NJM_OFF", "[backend]") {
|
||||
#endif
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Atomic Exchange I32
|
||||
// =============================================================================
|
||||
// Tests that AtomicExchange correctly swaps a value in memory and returns
|
||||
// the old value.
|
||||
// NOTE: OPCODE_ATOMIC_EXCHANGE uses a HOST address (not guest), per the
|
||||
// x64 backend comment: "the address we use here is a real, host address!"
|
||||
TEST_CASE("ATOMIC_EXCHANGE_I32", "[backend]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
// r[4] holds the host address directly.
|
||||
auto addr = LoadGPR(b, 4);
|
||||
auto new_val = b.Truncate(LoadGPR(b, 5), hir::INT32_TYPE);
|
||||
auto old_val = b.AtomicExchange(addr, new_val);
|
||||
StoreGPR(b, 3, b.ZeroExtend(old_val, hir::INT64_TYPE));
|
||||
b.Return();
|
||||
});
|
||||
|
||||
// Allocate guest memory and compute the host pointer.
|
||||
uint32_t guest_addr = test.memory->SystemHeapAlloc(4);
|
||||
REQUIRE(guest_addr != 0);
|
||||
auto* host_ptr = test.memory->TranslateVirtual(guest_addr);
|
||||
|
||||
test.Run(
|
||||
[&](PPCContext* ctx) {
|
||||
*reinterpret_cast<uint32_t*>(host_ptr) = 0xAABBCCDD;
|
||||
// Pass the HOST address in r[4].
|
||||
ctx->r[4] = reinterpret_cast<uint64_t>(host_ptr);
|
||||
ctx->r[5] = 0x11223344;
|
||||
},
|
||||
[&](PPCContext* ctx) {
|
||||
// r[3] should have the old value.
|
||||
REQUIRE(static_cast<uint32_t>(ctx->r[3]) == 0xAABBCCDD);
|
||||
// Memory should now have the new value.
|
||||
REQUIRE(*reinterpret_cast<uint32_t*>(host_ptr) == 0x11223344);
|
||||
});
|
||||
|
||||
test.memory->SystemHeapFree(guest_addr);
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// DOT_PRODUCT_3 — inline NEON dot product of first 3 vector elements
|
||||
// =============================================================================
|
||||
|
||||
Reference in New Issue
Block a user