SPU LLVM: Discourage memory mirrors use on LQD/STQD
This commit is contained in:
@@ -9219,6 +9219,11 @@ public:
|
|||||||
return byteswap(data);
|
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)
|
void STQX(spu_opcode_t op)
|
||||||
{
|
{
|
||||||
const auto a = get_vr(op.ra);
|
const auto a = get_vr(op.ra);
|
||||||
@@ -9228,17 +9233,20 @@ public:
|
|||||||
{
|
{
|
||||||
if (auto [ok, data] = get_const_vector(pair.first.value, m_pos); ok)
|
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)
|
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));
|
make_store_ls(addr, get_vr<u8[16]>(op.rt));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
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));
|
make_store_ls(addr, get_vr<u8[16]>(op.rt));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -9258,17 +9266,20 @@ public:
|
|||||||
{
|
{
|
||||||
if (auto [ok, data] = get_const_vector(pair.first.value, m_pos); ok)
|
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)
|
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));
|
set_vr(op.rt, make_load_ls(addr));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
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));
|
set_vr(op.rt, make_load_ls(addr));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -9329,18 +9340,22 @@ public:
|
|||||||
|
|
||||||
if (auto [ok, x, y] = 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(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)));
|
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 (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));
|
make_store_ls(addr, get_vr<u8[16]>(op.rt));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -9352,20 +9367,22 @@ public:
|
|||||||
{
|
{
|
||||||
const auto a = get_vr(op.ra);
|
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)));
|
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 (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));
|
set_vr(op.rt, make_load_ls(addr));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user