mirror of
https://github.com/RPCS3/rpcs3.git
synced 2026-07-10 01:54:46 -06:00
SPU LLVM: Discourage memory mirrors use on LQD/STQD
This commit is contained in:
parent
bb5dc93bec
commit
09a39fac5d
@ -9288,6 +9288,11 @@ public:
|
||||
return byteswap(data);
|
||||
}
|
||||
|
||||
static constexpr u64 make_negative_LS_offset(u32 original)
|
||||
{
|
||||
return original | ~u64{SPU_LS_SIZE - 1};
|
||||
}
|
||||
|
||||
void STQX(spu_opcode_t op)
|
||||
{
|
||||
const auto a = get_vr(op.ra);
|
||||
@ -9297,17 +9302,20 @@ public:
|
||||
{
|
||||
if (auto [ok, data] = get_const_vector(pair.first.value, m_pos); ok)
|
||||
{
|
||||
data._u32[3] %= SPU_LS_SIZE;
|
||||
// "sign extend" offset addend
|
||||
// Discourage the use of multiple addresses to refer to the same block of memory (due to memory mirrors use)
|
||||
// Which may confuse LLVM's optimization
|
||||
const u64 addend = (data._u32[3] >= SPU_LS_SIZE) ? make_negative_LS_offset(data._u32[3]) : data._u32[3];
|
||||
|
||||
if (const u32 remainder = data._u32[3] % 0x10; remainder == 0)
|
||||
{
|
||||
value_t<u64> addr = eval(splat<u64>(data._u32[3]) + zext<u64>(extract(pair.second, 3) & 0x3fff0));
|
||||
value_t<u64> addr = eval(splat<u64>(addend) + zext<u64>(extract(pair.second, 3) & 0x3fff0));
|
||||
make_store_ls(addr, get_vr<u8[16]>(op.rt));
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
value_t<u64> addr = eval(splat<u64>(data._u32[3] - remainder) + zext<u64>((extract(pair.second, 3) + remainder) & 0x3fff0));
|
||||
value_t<u64> addr = eval(splat<u64>(addend - remainder) + zext<u64>((extract(pair.second, 3) + remainder) & 0x3fff0));
|
||||
make_store_ls(addr, get_vr<u8[16]>(op.rt));
|
||||
return;
|
||||
}
|
||||
@ -9327,17 +9335,20 @@ public:
|
||||
{
|
||||
if (auto [ok, data] = get_const_vector(pair.first.value, m_pos); ok)
|
||||
{
|
||||
data._u32[3] %= SPU_LS_SIZE;
|
||||
// "sign extend" offset addend
|
||||
// Discourage the use of multiple addresses to refer to the same block of memory
|
||||
// Which may confuse LLVM's optimization
|
||||
const u64 addend = (data._u32[3] >= SPU_LS_SIZE) ? make_negative_LS_offset(data._u32[3]) : data._u32[3];
|
||||
|
||||
if (const u32 remainder = data._u32[3] % 0x10; remainder == 0)
|
||||
{
|
||||
value_t<u64> addr = eval(splat<u64>(data._u32[3]) + zext<u64>(extract(pair.second, 3) & 0x3fff0));
|
||||
value_t<u64> addr = eval(splat<u64>(addend) + zext<u64>(extract(pair.second, 3) & 0x3fff0));
|
||||
set_vr(op.rt, make_load_ls(addr));
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
value_t<u64> addr = eval(splat<u64>(data._u32[3] - remainder) + zext<u64>((extract(pair.second, 3) + remainder) & 0x3fff0));
|
||||
value_t<u64> addr = eval(splat<u64>(addend - remainder) + zext<u64>((extract(pair.second, 3) + remainder) & 0x3fff0));
|
||||
set_vr(op.rt, make_load_ls(addr));
|
||||
return;
|
||||
}
|
||||
@ -9398,18 +9409,22 @@ public:
|
||||
|
||||
if (auto [ok, x, y] = match_expr(a, match<u32[4]>() + match<u32[4]>()); ok)
|
||||
{
|
||||
if (auto [ok1, data] = get_const_vector(x.value, m_pos + 1); ok1 && data._u32[3] % 16 == 0)
|
||||
for (auto pair : std::initializer_list<std::pair<llvm_match_t<u32[4]>, llvm_match_t<u32[4]>>>{{x, y}, {y, x}})
|
||||
{
|
||||
value_t<u64> addr = eval(zext<u64>(extract(y, 3) & 0x3fff0) + ((get_imm<u64>(op.si10) << 4) + splat<u64>(data._u32[3] & 0x3fff0)));
|
||||
make_store_ls(addr, get_vr<u8[16]>(op.rt));
|
||||
return;
|
||||
}
|
||||
if (auto [ok, data] = get_const_vector(pair.first.value, m_pos); ok)
|
||||
{
|
||||
// "sign extend" offset addend
|
||||
// Discourage the use of multiple addresses to refer to the same block of memory
|
||||
// Which may confuse LLVM's optimization
|
||||
const u64 addend = (data._u32[3] >= SPU_LS_SIZE) ? make_negative_LS_offset(data._u32[3]) : data._u32[3];
|
||||
|
||||
if (auto [ok2, data] = get_const_vector(y.value, m_pos + 2); ok2 && data._u32[3] % 16 == 0)
|
||||
{
|
||||
value_t<u64> addr = eval(zext<u64>(extract(x, 3) & 0x3fff0) + ((get_imm<u64>(op.si10) << 4) + splat<u64>(data._u32[3] & 0x3fff0)));
|
||||
make_store_ls(addr, get_vr<u8[16]>(op.rt));
|
||||
return;
|
||||
if (const u32 remainder = data._u32[3] % 0x10; remainder == 0)
|
||||
{
|
||||
value_t<u64> addr = eval(zext<u64>(extract(pair.second, 3) & 0x3fff0) + ((get_imm<u64>(op.si10) << 4) + splat<u64>(addend)));
|
||||
make_store_ls(addr, get_vr<u8[16]>(op.rt));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -9421,20 +9436,22 @@ public:
|
||||
{
|
||||
const auto a = get_vr(op.ra);
|
||||
|
||||
if (auto [ok, x1, y1] = match_expr(a, match<u32[4]>() + match<u32[4]>()); ok)
|
||||
if (auto [ok, x, y] = match_expr(a, match<u32[4]>() + match<u32[4]>()); ok)
|
||||
{
|
||||
if (auto [ok1, data] = get_const_vector(x1.value, m_pos + 1); ok1 && data._u32[3] % 16 == 0)
|
||||
for (auto pair : std::initializer_list<std::pair<llvm_match_t<u32[4]>, llvm_match_t<u32[4]>>>{{x, y}, {y, x}})
|
||||
{
|
||||
value_t<u64> addr = eval(zext<u64>(extract(y1, 3) & 0x3fff0) + ((get_imm<u64>(op.si10) << 4) + splat<u64>(data._u32[3] & 0x3fff0)));
|
||||
set_vr(op.rt, make_load_ls(addr));
|
||||
return;
|
||||
}
|
||||
if (auto [ok, data] = get_const_vector(pair.first.value, m_pos); ok)
|
||||
{
|
||||
// "sign extend" offset addend
|
||||
const u64 addend = (data._u32[3] >= SPU_LS_SIZE) ? data._u32[3] | ~u64{SPU_LS_SIZE - 1} : data._u32[3];
|
||||
|
||||
if (auto [ok2, data] = get_const_vector(y1.value, m_pos + 2); ok2 && data._u32[3] % 16 == 0)
|
||||
{
|
||||
value_t<u64> addr = eval(zext<u64>(extract(x1, 3) & 0x3fff0) + ((get_imm<u64>(op.si10) << 4) + splat<u64>(data._u32[3] & 0x3fff0)));
|
||||
set_vr(op.rt, make_load_ls(addr));
|
||||
return;
|
||||
if (const u32 remainder = data._u32[3] % 0x10; remainder == 0)
|
||||
{
|
||||
value_t<u64> addr = eval(zext<u64>(extract(pair.second, 3) & 0x3fff0) + ((get_imm<u64>(op.si10) << 4) + splat<u64>(addend)));
|
||||
set_vr(op.rt, make_load_ls(addr));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user