Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,12 @@ StaticRecompLockstepVerifier::~StaticRecompLockstepVerifier()
{
std::fprintf(stderr,
"[lockstep] summary: checks=%llu reports=%llu skipped_fallback=%llu "
"skipped_zero=%llu undercharges=%llu max_deficit=%lld distinct_pcs=%zu\n",
"skipped_zero=%llu cap_hits=%llu undercharges=%llu "
"max_deficit=%lld distinct_pcs=%zu
",
(unsigned long long)m_ls_checks, (unsigned long long)m_ls_reports,
(unsigned long long)m_ls_skipped_fallback, (unsigned long long)m_ls_skipped_zero,
(unsigned long long)m_ls_cap_hits,
(unsigned long long)m_ls_undercharges, (long long)m_ls_max_undercharge,
m_ls_checked.size());
if (m_set_mem_journal)
Expand Down
10 changes: 9 additions & 1 deletion Source/Core/Core/PowerPC/StaticRecomp/StaticRecompLockstep.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,15 @@ class StaticRecompLockstepVerifier
u64 m_ls_start = 0; // begin checking at this native-dispatch index
u64 m_ls_limit = 0; // stop checking after this index (0 = no bound)
u64 m_ls_max_report = 0; // cap divergence reports (0 = unlimited)
int m_ls_step_cap = 512; // interpreter single-steps before giving up on end PC
// Interpreter single-steps before giving up on end PC. 512 is far too low,
// and it makes a default run misleading in BOTH directions: it manufactures
// CTRLFLOW "divergences" that are only the shadow running out of steps, and
// it hides real register divergences in every block longer than the cap,
// because the walk stops before it ever reaches the comparison. Measured on
// a full retail title, raising it to 20000 took CTRLFLOW reports 631 -> 22
// and FP divergences 463 -> 622 -- 159 real reports the old default hid.
int m_ls_step_cap = 20000;
u64 m_ls_cap_hits = 0; // gave up on end PC at the step cap -- NOT a divergence
u64 m_ls_checks = 0; // distinct blocks differentially checked
u64 m_ls_reports = 0; // divergences reported
u64 m_ls_skipped_fallback = 0; // blocks skipped (native used instruction fallback)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,18 @@ void StaticRecompLockstepVerifier::LockstepCheck(u32 entry_pc, u32 end_pc, const
StaticRecompLockstep::g_tb_override_active = false;

const bool reached = (ppc.pc == end_pc && ppc.Exceptions == 0);

// Running out of steps is the shadow interpreter giving up, not the module
// diverging. No register has been compared at this point, so there is no
// evidence either way. Reporting it as CTRLFLOW made a default run show
// hundreds of faults that no codegen change could fix, and buried the real
// ones among them. Count it separately and stay quiet.
if (!reached && ppc.Exceptions == 0 && steps >= m_ls_step_cap)
{
++m_ls_cap_hits;
return;
}

const bool undercharged = reached && (interp_cycles > native_charge + LS_UNDERCHARGE_GRACE) && !end_is_loop_header;

std::string diff;
Expand Down