From 0e77a2d1cdbef7cfa39fb91ef27b3cb7476e92dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 14 Oct 2026 17:44:54 +0200 Subject: [PATCH] VFPU: Make AccurateVdot the default The accurate dot products cost a few percent at most in the IR JIT, apart from GTA (about 20% on a game that's cheap to run anyway). The fuzzer follows the default too, unless PPSSPP_CPUFUZZ_ACCURATE_VDOT=0. Co-Authored-By: Claude Opus 5.5 --- Core/CmdLine.cpp | 2 +- Core/Config.cpp | 2 +- docs/cpu-equivalence.md | 2 +- unittest/JitHarness.cpp | 5 +++-- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Core/CmdLine.cpp b/Core/CmdLine.cpp index 861bfc755f..de55ed159f 100644 --- a/Core/CmdLine.cpp +++ b/Core/CmdLine.cpp @@ -199,7 +199,7 @@ static const CommandLineParam g_autoParams[] = { {POFF(compare), CmdParamType::Bool, "compare", 'c', "Enable comparison mode", CmdLineMode::Headless}, {POFF(bench), CmdParamType::Bool, "bench", 'b', "Enable benchmark mode", CmdLineMode::Headless}, {POFF(oldAtrac), CmdParamType::Bool, "old-atrac", '\0', "Use old ATRAC decoder"}, - {POFF(accurateVdot), CmdParamType::Bool, "accurate-vdot", '\0', "Compute VFPU dot products bit-exactly like the PSP (slower)"}, + {POFF(accurateVdot), CmdParamType::Bool, "accurate-vdot", '\0', "Compute VFPU dot products bit-exactly like the PSP (default; =false for the faster approximation)"}, {POFF(memStickInserted), CmdParamType::BoolInverse, "no-memstick", '\0', "Run with the memory stick removed"}, {POFF(log), CmdParamType::String, "log", '\0', "Output log to FILE", CmdLineMode::Application}, {POFF(enableLogging), CmdParamType::Bool, "log", '\0', "Full log output, not just emulated printfs", CmdLineMode::Headless}, diff --git a/Core/Config.cpp b/Core/Config.cpp index 2b8cb2e513..5961e2d207 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -436,7 +436,7 @@ static const ConfigSetting cpuSettings[] = { ConfigSetting("IOTimingMethod", SETTING(g_Config, iIOTimingMethod), IOTIMING_FAST, CfgFlag::PER_GAME | CfgFlag::REPORT), ConfigSetting("FastMemoryAccess", SETTING(g_Config, bFastMemory), true, CfgFlag::PER_GAME), ConfigSetting("FunctionReplacements", SETTING(g_Config, bFuncReplacements), true, CfgFlag::PER_GAME | CfgFlag::REPORT), - ConfigSetting("AccurateVdot", SETTING(g_Config, bAccurateVdot), false, CfgFlag::PER_GAME | CfgFlag::REPORT), + ConfigSetting("AccurateVdot", SETTING(g_Config, bAccurateVdot), true, CfgFlag::PER_GAME | CfgFlag::REPORT), ConfigSetting("HideSlowWarnings", SETTING(g_Config, bHideSlowWarnings), false, CfgFlag::DEFAULT), ConfigSetting("HideStateWarnings", SETTING(g_Config, bHideStateWarnings), false, CfgFlag::DEFAULT), ConfigSetting("JitDisableFlags", SETTING(g_Config, uJitDisableFlags), (uint32_t)0, CfgFlag::PER_GAME), diff --git a/docs/cpu-equivalence.md b/docs/cpu-equivalence.md index 7c8a73b386..804f26b375 100644 --- a/docs/cpu-equivalence.md +++ b/docs/cpu-equivalence.md @@ -33,7 +33,7 @@ Environment variables: | `PPSSPP_CPUFUZZ_DUMP` | write every core's end state of every case to a file | | `PPSSPP_CPUFUZZ_STRICT` | fail on any difference, not only on a crash | | `PPSSPP_CPUFUZZ_OPS` | comma-separated instruction name prefixes to generate only; `dot` is the dot products and the prefix ops | -| `PPSSPP_CPUFUZZ_ACCURATE_VDOT` | run with the accurate dot products | +| `PPSSPP_CPUFUZZ_ACCURATE_VDOT` | `0` to run without the accurate dot products, which are on by default | For quick rounds while working on some instructions, fuzz just those, on every core of the machine: `PPSSPP_CPUFUZZ_OPS=dot Tools/cpu_fuzz_parallel.py build/PPSSPPUnitTest --count 2000` splits the seeds diff --git a/unittest/JitHarness.cpp b/unittest/JitHarness.cpp index 1c39d7d668..ccbcca9782 100644 --- a/unittest/JitHarness.cpp +++ b/unittest/JitHarness.cpp @@ -398,7 +398,7 @@ bool TestJitReplacementHooks() { // PPSSPP_CPUFUZZ_SKIP cores not to run, by digit: 1 IR interpreter, 2 JIT, 3 JIT IR. // PPSSPP_CPUFUZZ_REPORTS how many differences to minimize and print (default 20). // PPSSPP_CPUFUZZ_STRICT fail the test on any difference, not only on a crash. -// PPSSPP_CPUFUZZ_ACCURATE_VDOT run with AccurateVdot, the VFPU's own dot products. +// PPSSPP_CPUFUZZ_ACCURATE_VDOT 0 to run without AccurateVdot (the VFPU's own dot products), which is on by default. // PPSSPP_CPUFUZZ_OPS comma-separated instruction name prefixes to generate only, for fast // runs on the instructions being worked on. "dot" is the dot products // and the prefixes. Without PPSSPP_CPUFUZZ_CLASSES, the class is "v". @@ -901,7 +901,8 @@ bool TestCPUEquivalence() { const bool oldSkipDeadbeef = g_Config.bSkipDeadbeefFilling; g_Config.bSkipDeadbeefFilling = true; const bool oldAccurateVdot = g_Config.bAccurateVdot; - g_Config.bAccurateVdot = getenv("PPSSPP_CPUFUZZ_ACCURATE_VDOT") != nullptr; + const char *accurateVdot = getenv("PPSSPP_CPUFUZZ_ACCURATE_VDOT"); + g_Config.bAccurateVdot = !accurateVdot || strcmp(accurateVdot, "0") != 0; const char *countStr = getenv("PPSSPP_CPUFUZZ_COUNT"); const char *seedStr = getenv("PPSSPP_CPUFUZZ_SEED");