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: Avoid sinking stores out of non-loops #15714

Merged
merged 3 commits into from
Jun 19, 2024
Merged
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
9 changes: 9 additions & 0 deletions rpcs3/Emu/Cell/SPULLVMRecompiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2340,6 +2340,7 @@ class spu_llvm_recompiler : public spu_recompiler_base, public cpu_translator
}

bool has_gpr_barriers_in_the_way = false;
bool potential_loop = false;

for (auto [a2, b2] : sucs)
{
Expand All @@ -2351,6 +2352,7 @@ class spu_llvm_recompiler : public spu_recompiler_base, public cpu_translator
break;
}

potential_loop = true;
continue;
}

Expand Down Expand Up @@ -2390,6 +2392,7 @@ class spu_llvm_recompiler : public spu_recompiler_base, public cpu_translator
break;
}

potential_loop = true;
continue;
}

Expand Down Expand Up @@ -2424,6 +2427,12 @@ class spu_llvm_recompiler : public spu_recompiler_base, public cpu_translator
continue;
}

if (!potential_loop)
{
spu_log.trace("Avoided postponing r%u store from block 0x%x (not loop)", i, block_q[bi].first);
continue;
}

for (auto [a2, b2] : sucs)
{
if (b2 != bqbi)
Expand Down
75 changes: 56 additions & 19 deletions rpcs3/Emu/Cell/SPUThread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4583,13 +4583,11 @@ bool spu_thread::process_mfc_cmd()
busy_wait(300);
}

last_gtsc = utils::get_tsc();
}
else
{
last_gtsc = perf0.get();
// Reset perf
perf0.restart();
}

last_gtsc = perf0.get();
return true;
}

Expand All @@ -4603,9 +4601,6 @@ bool spu_thread::process_mfc_cmd()

get_resrv_waiters_count(addr)--;

// Reset perf
perf0.restart();

// Quick check if there were reservation changes
const u64 new_time = res;

Expand All @@ -4630,17 +4625,19 @@ bool spu_thread::process_mfc_cmd()
u8& val = getllar_wait_time[pc / 32].front();
val = static_cast<u8>(std::min<u32>(val + 1, u8{umax}));

last_gtsc = utils::get_tsc();
// Reset perf
perf0.restart();
last_gtsc = perf0.get();
return true;
}

static atomic_t<u32> g_ctr, g_fail;
static atomic_t<u32> g_changed, g_unchanged;

if (new_time == this_time && res == this_time)
{
spu_log.trace("RTIME unchanged on address 0x%x", addr);

g_fail++;
g_unchanged++;

// Try to forcefully change timestamp in order to notify threads
if (get_resrv_waiters_count(addr) && res.compare_and_swap_test(this_time, this_time + 128))
Expand All @@ -4650,11 +4647,13 @@ bool spu_thread::process_mfc_cmd()
}
else
{
g_ctr++;
g_changed++;
}

if ((g_ctr + g_fail) % 200 == 0)
spu_log.trace("SPU 100WAIT: fail=%d, ok=%d", +g_fail, +g_ctr);
if ((g_changed + g_unchanged) % 200 == 0)
{
spu_log.trace("SPU GETLLAR wait on RTIME stats: unchanged=%d, changed=%d", +g_unchanged, +g_changed);
}
}
}

Expand All @@ -4670,6 +4669,9 @@ bool spu_thread::process_mfc_cmd()
// We can't, LR needs to be set now
set_events(SPU_EVENT_LR);
static_cast<void>(test_stopped());

// Reset perf
perf0.restart();
}

last_getllar = pc;
Expand Down Expand Up @@ -5505,7 +5507,9 @@ s64 spu_thread::get_ch_value(u32 ch)
}
}
#ifdef __linux__
get_resrv_waiters_count(raddr)++;
vm::reservation_notifier(raddr).wait(rtime, atomic_wait_timeout{50'000});
get_resrv_waiters_count(raddr)--;
#else
if (raddr - spurs_addr <= 0x80 && !g_cfg.core.spu_accurate_reservations && mask1 == SPU_EVENT_LR)
{
Expand All @@ -5523,6 +5527,11 @@ s64 spu_thread::get_ch_value(u32 ch)
continue;
}

static thread_local bool s_tls_try_notify = false;
s_tls_try_notify = false;

const u32 _raddr = this->raddr;

atomic_wait_engine::set_one_time_use_wait_callback(mask1 != SPU_EVENT_LR ? nullptr : +[](u64 attempts) -> bool
{
const auto _this = static_cast<spu_thread*>(cpu_thread::get_current());
Expand All @@ -5541,19 +5550,47 @@ s64 spu_thread::get_ch_value(u32 ch)
return true;
}

if (!vm::check_addr(_this->raddr) || !cmp_rdata(_this->rdata, *_this->resrv_mem))
bool set_lr = false;
const u32 raddr = _this->raddr;

if (!raddr)
{
return true;
}

if (!vm::check_addr(raddr))
{
set_lr = true;
}
else if (!cmp_rdata(_this->rdata, *_this->resrv_mem))
{
// Only data changed, try to notify waiters
if (get_resrv_waiters_count(raddr) >= 2 && vm::reservation_acquire(raddr).compare_and_swap_test(_this->rtime, _this->rtime + 128))
{
s_tls_try_notify = true;
}

set_lr = true;
}

if (set_lr)
{
_this->set_events(SPU_EVENT_LR);
_this->raddr = 0;
_this->set_events(SPU_EVENT_LR);
return false;
}

return true;
});

get_resrv_waiters_count(raddr)++;
vm::reservation_notifier(raddr).wait(rtime, atomic_wait_timeout{80'000});
get_resrv_waiters_count(raddr)--;
get_resrv_waiters_count(_raddr)++;
vm::reservation_notifier(_raddr).wait(rtime, atomic_wait_timeout{80'000});
get_resrv_waiters_count(_raddr)--;

if (s_tls_try_notify && get_resrv_waiters_count(_raddr) && vm::reservation_acquire(_raddr) == rtime + 128)
{
vm::reservation_notifier(_raddr).notify_all();
}
#endif
}
else
Expand Down