Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SPU LLVM: Upgrade constants propagation #16023

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
169 changes: 47 additions & 122 deletions rpcs3/Emu/Cell/SPUCommonRecompiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2680,12 +2680,13 @@ reg_state_t reg_state_t::merge(const reg_state_t& rhs, u32 current_pc) const
res.tag = reg_state_t::alloc_tag();
res.origin = current_pc;
res.is_instruction = false;
res.is_phi = true;
return res;
}
}
}

return make_unknown(current_pc);
return make_unknown(current_pc, current_pc, true);
}

reg_state_t reg_state_t::build_on_top_of(const reg_state_t& rhs) const
Expand Down Expand Up @@ -4190,23 +4191,6 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s

for (u32 i = 0; i < s_reg_max; i++)
{
if (tb.chunk == block.chunk && tb.reg_origin[i] + 1)
{
const u32 expected = block.reg_mod[i] ? addr : block.reg_origin[i];

if (tb.reg_origin[i] == 0x80000000)
{
tb.reg_origin[i] = expected;
}
else if (tb.reg_origin[i] != expected)
{
// Set -1 if multiple origins merged (requires PHI node)
tb.reg_origin[i] = -1;

must_repeat |= !tb.targets.empty();
}
}

if (g_cfg.core.spu_block_size == spu_block_size_type::giga && tb.func == block.func && tb.reg_origin_abs[i] + 2)
{
const u32 expected = block.reg_mod[i] ? addr : block.reg_origin_abs[i];
Expand Down Expand Up @@ -4277,13 +4261,6 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s
{
const u32 orig = bb.reg_origin_abs[i];

if (orig < 0x40000)
{
auto& src = ::at32(m_bbs, orig);
bb.reg_const[i] = src.reg_const[i];
bb.reg_val32[i] = src.reg_val32[i];
}

if (!bb.reg_save_dom[i] && bb.reg_use[i] && (orig == 0x40000 || orig + 2 == 0))
{
// Destroy offset if external reg value is used
Expand Down Expand Up @@ -4317,71 +4294,6 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s
// Propagate some constants
switch (last_inst)
{
case spu_itype::IL:
{
bb.reg_const[op.rt] = true;
bb.reg_val32[op.rt] = op.si16;
break;
}
case spu_itype::ILA:
{
bb.reg_const[op.rt] = true;
bb.reg_val32[op.rt] = op.i18;
break;
}
case spu_itype::ILHU:
{
bb.reg_const[op.rt] = true;
bb.reg_val32[op.rt] = op.i16 << 16;
break;
}
case spu_itype::ILH:
{
bb.reg_const[op.rt] = true;
bb.reg_val32[op.rt] = op.i16 << 16 | op.i16;
break;
}
case spu_itype::IOHL:
{
bb.reg_val32[op.rt] = bb.reg_val32[op.rt] | op.i16;
break;
}
case spu_itype::ORI:
{
bb.reg_const[op.rt] = bb.reg_const[op.ra];
bb.reg_val32[op.rt] = bb.reg_val32[op.ra] | op.si10;
break;
}
case spu_itype::OR:
{
bb.reg_const[op.rt] = bb.reg_const[op.ra] && bb.reg_const[op.rb];
bb.reg_val32[op.rt] = bb.reg_val32[op.ra] | bb.reg_val32[op.rb];
break;
}
case spu_itype::AI:
{
bb.reg_const[op.rt] = bb.reg_const[op.ra];
bb.reg_val32[op.rt] = bb.reg_val32[op.ra] + op.si10;
break;
}
case spu_itype::A:
{
bb.reg_const[op.rt] = bb.reg_const[op.ra] && bb.reg_const[op.rb];
bb.reg_val32[op.rt] = bb.reg_val32[op.ra] + bb.reg_val32[op.rb];
break;
}
case spu_itype::SFI:
{
bb.reg_const[op.rt] = bb.reg_const[op.ra];
bb.reg_val32[op.rt] = op.si10 - bb.reg_val32[op.ra];
break;
}
case spu_itype::SF:
{
bb.reg_const[op.rt] = bb.reg_const[op.ra] && bb.reg_const[op.rb];
bb.reg_val32[op.rt] = bb.reg_val32[op.rb] - bb.reg_val32[op.ra];
break;
}
case spu_itype::STQD:
{
if (op.ra == s_reg_sp && bb.stack_sub != 0x80000000 && bb.reg_save_dom[op.rt])
Expand Down Expand Up @@ -4410,28 +4322,17 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s
bb.reg_load_mod[op.rt] = 0x80000000 + op.si10 * 16 - bb.stack_sub;
}

// Clear const
bb.reg_const[op.rt] = false;
break;
}
default:
{
// Clear const if reg is modified here
if (u8 reg = m_regmod[ia / 4]; reg < s_reg_max)
bb.reg_const[reg] = false;
break;
}
}

// $SP is modified
if (m_regmod[ia / 4] == s_reg_sp)
{
if (bb.reg_const[s_reg_sp])
{
// Making $SP a constant is a funny thing too.
bb.stack_sub = 0x80000000;
}

if (bb.stack_sub != 0x80000000)
{
switch (last_inst)
Expand Down Expand Up @@ -5876,7 +5777,7 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s
}
case MFC_Cmd:
{
const auto [af, av, atagg, _3, _5, apc, ainst] = get_reg(op.rt);
const auto [af, av, atagg, _3, _5, apc, ainst, aphi] = get_reg(op.rt);

if (!is_pattern_match)
{
Expand Down Expand Up @@ -6227,7 +6128,7 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s
atomic16.get_rdatomic = true;

// Go above and beyond and also set the constant for it
set_const_value(op.rt, MFC_GETLLAR_SUCCESS);
//set_const_value(op.rt, MFC_GETLLAR_SUCCESS);
invalidate = false;
}
}
Expand Down Expand Up @@ -6674,7 +6575,7 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s
case spu_itype::HBR:
{
hbr_loc = spu_branch_target(pos, op.roh << 7 | op.rt);
const auto [af, av, at, ao, az, apc, ainst] = get_reg(op.ra);
const auto [af, av, at, ao, az, apc, ainst, aphi] = get_reg(op.ra);
hbr_tg = af & vf::is_const && !op.c ? av & 0x3fffc : -1;
break;
}
Expand Down Expand Up @@ -6742,8 +6643,8 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s
const auto ra = get_reg(op.ra);
const auto rb = get_reg(op.rb);

const auto [af, av, at, ao, az, apc, ainst] = ra;
const auto [bf, bv, bt, bo, bz, bpc, binst] = rb;
const auto [af, av, at, ao, az, apc, ainst, aphi] = ra;
const auto [bf, bv, bt, bo, bz, bpc, binst, bphi] = rb;

inherit_const_value(op.rt, ra, rb, av | bv, pos);
break;
Expand All @@ -6758,7 +6659,7 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s

const auto ra = get_reg(op.ra);

const auto [af, av, at, ao, az, apc, ainst] = ra;
const auto [af, av, at, ao, az, apc, ainst, aphi] = ra;

inherit_const_value(op.rt, ra, ra, av ^ op.si10, pos);
break;
Expand All @@ -6774,8 +6675,8 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s
const auto ra = get_reg(op.ra);
const auto rb = get_reg(op.rb);

const auto [af, av, at, ao, az, apc, ainst] = ra;
const auto [bf, bv, bt, bo, bz, bpc, binst] = rb;
const auto [af, av, at, ao, az, apc, ainst, aphi] = ra;
const auto [bf, bv, bt, bo, bz, bpc, binst, bphi] = rb;

inherit_const_value(op.rt, ra, rb, bv ^ av, pos);
break;
Expand All @@ -6785,8 +6686,8 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s
const auto ra = get_reg(op.ra);
const auto rb = get_reg(op.rb);

const auto [af, av, at, ao, az, apc, ainst] = ra;
const auto [bf, bv, bt, bo, bz, bpc, binst] = rb;
const auto [af, av, at, ao, az, apc, ainst, aphi] = ra;
const auto [bf, bv, bt, bo, bz, bpc, binst, bphi] = rb;

inherit_const_value(op.rt, ra, rb, ~(bv | av), pos);
break;
Expand All @@ -6808,8 +6709,8 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s
const auto ra = get_reg(op.ra);
const auto rb = get_reg(op.rb);

const auto [af, av, at, ao, az, apc, ainst] = ra;
const auto [bf, bv, bt, bo, bz, bpc, binst] = rb;
const auto [af, av, at, ao, az, apc, ainst, aphi] = ra;
const auto [bf, bv, bt, bo, bz, bpc, binst, bphi] = rb;

inherit_const_value(op.rt, ra, rb, bv & av, pos);
break;
Expand All @@ -6823,7 +6724,7 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s
}

const auto ra = get_reg(op.ra);
const auto [af, av, at, ao, az, apc, ainst] = ra;
const auto [af, av, at, ao, az, apc, ainst, aphi] = ra;

inherit_const_value(op.rt, ra, ra, av + op.si10, pos);

Expand All @@ -6840,8 +6741,8 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s
const auto ra = get_reg(op.ra);
const auto rb = get_reg(op.rb);

const auto [af, av, at, ao, az, apc, ainst] = ra;
const auto [bf, bv, bt, bo, bz, bpc, binst] = rb;
const auto [af, av, at, ao, az, apc, ainst, aphi] = ra;
const auto [bf, bv, bt, bo, bz, bpc, binst, bphi] = rb;

inherit_const_value(op.rt, ra, rb, bv + av, pos);

Expand All @@ -6856,7 +6757,7 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s
case spu_itype::SFI:
{
const auto ra = get_reg(op.ra);
const auto [af, av, at, ao, az, apc, ainst] = get_reg(op.ra);
const auto [af, av, at, ao, az, apc, ainst, aphi] = get_reg(op.ra);

inherit_const_value(op.rt, ra, ra, op.si10 - av, pos);
break;
Expand All @@ -6866,8 +6767,8 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s
const auto ra = get_reg(op.ra);
const auto rb = get_reg(op.rb);

const auto [af, av, at, ao, az, apc, ainst] = ra;
const auto [bf, bv, bt, bo, bz, bpc, binst] = rb;
const auto [af, av, at, ao, az, apc, ainst, aphi] = ra;
const auto [bf, bv, bt, bo, bz, bpc, binst, bphi] = rb;

inherit_const_value(op.rt, ra, rb, bv - av, pos);

Expand Down Expand Up @@ -6906,7 +6807,7 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s
}

const auto ra = get_reg(op.ra);
const auto [af, av, at, ao, az, apc, ainst] = get_reg(op.ra);
const auto [af, av, at, ao, az, apc, ainst, aphi] = get_reg(op.ra);

inherit_const_value(op.rt, ra, ra, av >> ((0 - op.i7) & 0x1f), pos);
break;
Expand All @@ -6926,7 +6827,7 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s
}

const auto ra = get_reg(op.ra);
const auto [af, av, at, ao, az, apc, ainst] = ra;
const auto [af, av, at, ao, az, apc, ainst, aphi] = ra;

inherit_const_value(op.rt, ra, ra, av << (op.i7 & 0x1f), pos);
break;
Expand All @@ -6943,7 +6844,7 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s
case spu_itype::CEQI:
{
const auto ra = get_reg(op.ra);
const auto [af, av, at, ao, az, apc, ainst] = ra;
const auto [af, av, at, ao, az, apc, ainst, aphi] = ra;

inherit_const_value(op.rt, ra, ra, av == op.si10 + 0u, pos);

Expand Down Expand Up @@ -7066,6 +6967,30 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s
fmt::append(func_hash, "%s", fmt::base57(output));
}

for (auto& [addr, block] : infos)
{
auto& bb = ::at32(m_bbs, addr);

for (u32 i = 0; i < s_reg_max; i++)
{
const auto& reg = block->start_reg_state[i];

if (reg.is_const())
{
bb.reg_const[i] = true;
bb.reg_val32[i] = reg.value;
}
else if (reg.is_instruction)
{
bb.reg_origin[i] = reg.origin;
}
else if (reg.is_phi)
{
bb.reg_origin[i] = -1;
}
}
}

for (const auto& [pc_commited, pattern] : atomic16_all)
{
if (!pattern.active)
Expand Down
6 changes: 4 additions & 2 deletions rpcs3/Emu/Cell/SPURecompiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,7 @@ class spu_recompiler_base
u32 known_zeroes{};
u32 origin = SPU_LS_SIZE;
bool is_instruction = false;
bool is_phi = false;

bool is_const() const;

Expand Down Expand Up @@ -243,7 +244,7 @@ class spu_recompiler_base
void invalidate_if_created(u32 current_pc);

template <usz Count = 1>
static std::conditional_t<Count == 1, reg_state_t, std::array<reg_state_t, Count>> make_unknown(u32 pc, u32 current_pc = SPU_LS_SIZE) noexcept
static std::conditional_t<Count == 1, reg_state_t, std::array<reg_state_t, Count>> make_unknown(u32 pc, u32 current_pc = SPU_LS_SIZE, bool is_phi = false) noexcept
{
if constexpr (Count == 1)
{
Expand All @@ -252,6 +253,7 @@ class spu_recompiler_base
v.flag = {};
v.origin = pc;
v.is_instruction = pc == current_pc;
v.is_phi = is_phi;
return v;
}
else
Expand All @@ -260,7 +262,7 @@ class spu_recompiler_base

for (reg_state_t& state : result)
{
state = make_unknown<1>(pc, current_pc);
state = make_unknown<1>(pc, current_pc, is_phi);
}

return result;
Expand Down
3 changes: 2 additions & 1 deletion rpcs3/Input/hid_pad_handler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,8 @@ void hid_pad_handler<Device>::enumerate_devices()
}
hid_free_enumeration(head);
}
hid_log.notice("%s enumeration found %d devices (%f ms)", m_type, device_paths.size(), timer.GetElapsedTimeInMilliSec());

(device_paths.empty() ? hid_log.trace : hid_log.notice)("%s enumeration found %d devices (%f ms)", m_type, device_paths.size(), timer.GetElapsedTimeInMilliSec());

std::lock_guard lock(m_enumeration_mutex);
m_new_enumerated_devices = device_paths;
Expand Down