Add some jit benchmarking code.

This commit is contained in:
Unknown W. Brackets 2014-11-07 22:40:28 -08:00
parent 47b731b882
commit 2efecc5c38
5 changed files with 244 additions and 10 deletions

127
unittest/JitHarness.cpp Normal file
View File

@ -0,0 +1,127 @@
// Copyright (c) 2012- PPSSPP Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0 or later versions.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#include "base/timeutil.h"
#include "Core/MIPS/JitCommon/JitCommon.h"
#include "Core/MIPS/MIPSCodeUtils.h"
#include "Core/MemMap.h"
#include "Core/Core.h"
#include "Core/CoreTiming.h"
#include "Core/HLE/HLE.h"
struct InputState;
// Temporary hacks around annoying linking errors. Copied from Headless.
void D3D9_SwapBuffers() { }
void GL_SwapBuffers() { }
void NativeUpdate(InputState &input_state) { }
void NativeRender() { }
void NativeResized() { }
void System_SendMessage(const char *command, const char *parameter) {}
bool System_InputBoxGetWString(const wchar_t *title, const std::wstring &defaultvalue, std::wstring &outvalue) { return false; }
#ifndef _WIN32
InputState input_state;
#endif
void UnitTestTerminator() {
Core_Stop();
}
HLEFunction UnitTestFakeSyscalls[] = {
{0x1234BEEF, &UnitTestTerminator, "UnitTestTerminator"},
};
double ExecCPUTest() {
int blockTicks = 1000000;
int total = 0;
double st = real_time_now();
do {
for (int j = 0; j < 1000; ++j) {
currentMIPS->pc = PSP_GetUserMemoryBase();
coreState = CORE_RUNNING;
while (coreState == CORE_RUNNING) {
mipsr4k.RunLoopUntil(blockTicks);
}
++total;
}
}
while (real_time_now() - st < 0.5);
double elapsed = real_time_now() - st;
return total / elapsed;
}
static void SetupJitHarness() {
// We register a syscall so we have an easy way to finish the test.
RegisterModule("UnitTestFakeSyscalls", ARRAY_SIZE(UnitTestFakeSyscalls), UnitTestFakeSyscalls);
// This is pretty much the bare minimum required to setup jit.
coreState = CORE_POWERUP;
currentMIPS = &mipsr4k;
Memory::g_MemorySize = Memory::RAM_NORMAL_SIZE;
PSP_CoreParameter().cpuCore = CPU_INTERPRETER;
PSP_CoreParameter().unthrottle = true;
Memory::Init();
mipsr4k.Reset();
CoreTiming::Init();
}
static void DestroyJitHarness() {
// Clear our custom module out to be safe.
HLEShutdown();
CoreTiming::Shutdown();
Memory::Shutdown();
mipsr4k.Shutdown();
coreState = CORE_POWERDOWN;
currentMIPS = nullptr;
}
bool TestJit() {
SetupJitHarness();
currentMIPS->pc = PSP_GetUserMemoryBase();
u32 *p = (u32 *)Memory::GetPointer(currentMIPS->pc);
// TODO: Smarter way of seeding in the code sequence.
for (int i = 0; i < 100; ++i) {
*p++ = 0xD03B0000 | (1 >> 7) | (7 << 8);
*p++ = 0xD03B0000 | (1 >> 7);
*p++ = 0xD03B0000 | (7 << 8);
*p++ = 0xD03B0000 | (1 >> 7) | (7 << 8);
*p++ = 0xD03B0000 | (1 >> 7) | (7 << 8);
*p++ = 0xD03B0000 | (1 >> 7) | (7 << 8);
*p++ = 0xD03B0000 | (1 >> 7) | (7 << 8);
}
*p++ = MIPS_MAKE_SYSCALL("UnitTestFakeSyscalls", "UnitTestTerminator");
*p++ = MIPS_MAKE_BREAK(1);
double interp_speed = ExecCPUTest();
mipsr4k.UpdateCore(CPU_JIT);
double jit_speed = ExecCPUTest();
printf("Jit was %fx faster than interp.\n", jit_speed / interp_speed);
DestroyJitHarness();
return jit_speed >= interp_speed;
}

20
unittest/JitHarness.h Normal file
View File

@ -0,0 +1,20 @@
// Copyright (c) 2012- PPSSPP Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0 or later versions.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#pragma once
bool TestJit();

View File

@ -39,6 +39,8 @@
#include "Core/Config.h"
#include "Core/MIPS/MIPSVFPUUtils.h"
#include "unittest/JitHarness.h"
#define EXPECT_TRUE(a) if (!(a)) { printf("%s:%i: Test Fail\n", __FUNCTION__, __LINE__); return false; }
#define EXPECT_FALSE(a) if ((a)) { printf("%s:%i: Test Fail\n", __FUNCTION__, __LINE__); return false; }
#define EXPECT_EQ_FLOAT(a, b) if ((a) != (b)) { printf("%s:%i: Test Fail\n%f\nvs\n%f\n", __FUNCTION__, __LINE__, a, b); return false; }
@ -417,17 +419,75 @@ bool TestVFPUSinCos() {
return true;
}
typedef bool (*TestFunc)();
struct TestItem {
const char *name;
TestFunc func;
};
#define TEST_ITEM(name) { #name, &Test ##name, }
TestItem availableTests[] = {
TEST_ITEM(Asin),
TEST_ITEM(SinCos),
TEST_ITEM(ArmEmitter),
TEST_ITEM(VFPUSinCos),
TEST_ITEM(MathUtil),
TEST_ITEM(Parsers),
TEST_ITEM(Jit),
};
int main(int argc, const char *argv[]) {
cpu_info.bNEON = true;
cpu_info.bVFP = true;
cpu_info.bVFPv3 = true;
cpu_info.bVFPv4 = true;
g_Config.bEnableLogging = true;
//TestAsin();
//TestSinCos();
//TestArmEmitter();
TestVFPUSinCos();
//TestMathUtil();
//TestParsers();
bool allTests = false;
TestFunc testFunc = nullptr;
if (argc >= 2) {
if (!strcasecmp(argv[1], "all")) {
allTests = true;
}
for (auto f : availableTests) {
if (!strcasecmp(argv[1], f.name)) {
testFunc = f.func;
break;
}
}
}
if (allTests) {
int passes = 0;
int fails = 0;
for (auto f : availableTests) {
if (f.func()) {
++passes;
} else {
printf("%s: FAILED\n", f.name);
++fails;
}
}
if (passes > 0) {
printf("%d tests passed.\n", passes);
}
if (fails > 0) {
return 2;
}
} else if (testFunc == nullptr) {
fprintf(stderr, "You may select a test to run by passing an argument.\n");
fprintf(stderr, "\n");
fprintf(stderr, "Available tests:\n");
for (auto f : availableTests) {
fprintf(stderr, " * %s\n", f.name);
}
return 1;
} else {
if (!testFunc()) {
return 2;
}
}
return 0;
}

View File

@ -94,7 +94,9 @@
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>Ws2_32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>Ws2_32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;opengl32.lib;dsound.lib;glu32.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;comctl32.lib;d3d9.lib;dxguid.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalOptions>/ignore:4049 /ignore:4217 %(AdditionalOptions)</AdditionalOptions>
<AdditionalLibraryDirectories>..\ffmpeg\Windows\x86\lib</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
@ -112,7 +114,9 @@
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>Ws2_32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>Ws2_32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;opengl32.lib;dsound.lib;glu32.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;comctl32.lib;d3d9.lib;dxguid.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalOptions>/ignore:4049 /ignore:4217 %(AdditionalOptions)</AdditionalOptions>
<AdditionalLibraryDirectories>..\ffmpeg\Windows\x86_64\lib</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
@ -135,7 +139,9 @@
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>Ws2_32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>Ws2_32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;opengl32.lib;dsound.lib;glu32.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;comctl32.lib;d3d9.lib;dxguid.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalOptions>/ignore:4049 /ignore:4217 %(AdditionalOptions)</AdditionalOptions>
<AdditionalLibraryDirectories>..\ffmpeg\Windows\x86\lib</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@ -157,10 +163,14 @@
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>Ws2_32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>Ws2_32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;opengl32.lib;dsound.lib;glu32.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;comctl32.lib;d3d9.lib;dxguid.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalOptions>/ignore:4049 /ignore:4217 %(AdditionalOptions)</AdditionalOptions>
<AdditionalLibraryDirectories>..\ffmpeg\Windows\x86_64\lib</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\native\ext\glew\glew.c" />
<ClCompile Include="JitHarness.cpp" />
<ClCompile Include="UnitTest.cpp" />
</ItemGroup>
<ItemGroup>
@ -170,12 +180,24 @@
<ProjectReference Include="..\Core\Core.vcxproj">
<Project>{533f1d30-d04d-47cc-ad71-20f658907e36}</Project>
</ProjectReference>
<ProjectReference Include="..\ext\libkirk\libkirk.vcxproj">
<Project>{3baae095-e0ab-4b0e-b5df-ce39c8ae31de}</Project>
</ProjectReference>
<ProjectReference Include="..\ext\zlib\zlib.vcxproj">
<Project>{f761046e-6c38-4428-a5f1-38391a37bb34}</Project>
</ProjectReference>
<ProjectReference Include="..\GPU\GPU.vcxproj">
<Project>{457f45d2-556f-47bc-a31d-aff0d15beaed}</Project>
</ProjectReference>
<ProjectReference Include="..\native\native.vcxproj">
<Project>{c4df647e-80ea-4111-a0a8-218b1b711e18}</Project>
</ProjectReference>
<ProjectReference Include="..\UI\UI.vcxproj">
<Project>{004b8d11-2be3-4bd9-ab40-2be04cf2096f}</Project>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<ClInclude Include="JitHarness.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">

View File

@ -2,5 +2,10 @@
<Project ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ClCompile Include="UnitTest.cpp" />
<ClCompile Include="..\native\ext\glew\glew.c" />
<ClCompile Include="JitHarness.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="JitHarness.h" />
</ItemGroup>
</Project>