Skip to content

Commit

Permalink
irjit: Add tests for IR passes.
Browse files Browse the repository at this point in the history
  • Loading branch information
unknownbrackets committed Jul 24, 2022
1 parent 3c88183 commit 8f23025
Show file tree
Hide file tree
Showing 9 changed files with 158 additions and 3 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2321,6 +2321,7 @@ if(UNITTEST)
unittest/TestShaderGenerators.cpp
unittest/TestArmEmitter.cpp
unittest/TestArm64Emitter.cpp
unittest/TestIRPassSimplify.cpp
unittest/TestX64Emitter.cpp
unittest/TestVertexJit.cpp
unittest/TestSoftwareGPUJit.cpp
Expand Down
1 change: 1 addition & 0 deletions Core/MIPS/IR/IRPassSimplify.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -738,6 +738,7 @@ bool PropagateConstants(const IRWriter &in, IRWriter &out, const IROptions &opts
}
}
}
gpr.FlushAll();
return logBlocks;
}

Expand Down
3 changes: 1 addition & 2 deletions Core/MIPS/IR/IRRegCache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,7 @@ IRRegCache::IRRegCache(IRWriter *ir) : ir_(ir) {

void IRRegCache::FlushAll() {
for (int i = 0; i < TOTAL_MAPPABLE_MIPSREGS; i++) {
//if (i < IRTEMP_0)
Flush(i);
Flush(i);
}
}

Expand Down
2 changes: 1 addition & 1 deletion Core/MIPS/MIPSAnalyst.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1462,7 +1462,7 @@ namespace MIPSAnalyst {
}
break;
case 0x08: // addi
case 0x09: // adiu
case 0x09: // addiu
info.hasRelevantAddress = true;
info.relevantAddress = cpu->GetRegValue(0,MIPS_GET_RS(op))+((s16)(op & 0xFFFF));
break;
Expand Down
1 change: 1 addition & 0 deletions android/jni/Android.mk
Original file line number Diff line number Diff line change
Expand Up @@ -734,6 +734,7 @@ ifeq ($(UNITTEST),1)
LOCAL_MODULE := ppsspp_unittest
LOCAL_SRC_FILES := \
$(SRC)/unittest/JitHarness.cpp \
$(SRC)/unittest/TestIRPassSimplify.cpp \
$(SRC)/unittest/TestShaderGenerators.cpp \
$(SRC)/unittest/TestSoftwareGPUJit.cpp \
$(SRC)/unittest/TestThreadManager.cpp \
Expand Down
149 changes: 149 additions & 0 deletions unittest/TestIRPassSimplify.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
// Copyright (c) 2022- 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 <cstdio>
#include <cstring>
#include "Core/MIPS/IR/IRInst.h"
#include "Core/MIPS/IR/IRPassSimplify.h"

struct IRVerification {
const char *name;
const std::vector<IRInst> input;
const std::vector<IRInst> expected;
const std::vector<IRPassFunc> passes;
};

static void LogInstructions(const std::vector<IRInst> &insts) {
for (size_t i = 0; i < insts.size(); ++i) {
char buf[256];
DisassembleIR(buf, sizeof(buf), insts[i]);
printf(" %s\n", buf);
}
}

static bool VerifyPass(const IRVerification &v) {
IRWriter in, out;
IROptions opts{};
opts.unalignedLoadStore = true;

for (const auto &inst : v.input)
in.Write(inst);
if (IRApplyPasses(v.passes.data(), v.passes.size(), in, out, opts)) {
printf("%s FAILED: Unable to apply passes (or wanted to log)\n", v.name);
return false;
}

const std::vector<IRInst> actual = out.GetInstructions();
if (actual.size() != v.expected.size()) {
printf("%s FAILED: produced %d instructions, expected %d\n", v.name, (int)actual.size(), (int)v.expected.size());
printf("Actual:\n");
LogInstructions(actual);
printf("Expected:\n");
LogInstructions(v.expected);
return false;
}

for (size_t i = 0; i < actual.size(); ++i) {
if (memcmp(&v.expected[i], &actual[i], sizeof(IRInst)) != 0) {
char actualBuf[256];
DisassembleIR(actualBuf, sizeof(actualBuf), actual[i]);
char expectedBuf[256];
DisassembleIR(expectedBuf, sizeof(expectedBuf), v.expected[i]);

if (strcmp(expectedBuf, actualBuf) == 0) {
// This means a field (like src2) was left set but isn't relevant. Ignore.
continue;
}

printf("%s FAILED: #%d expected '%s' but was '%s'", v.name, (int)i, expectedBuf, actualBuf);
return false;
}
}

return true;
}

static const IRVerification tests[] = {
{
"SimplePurgeTemps",
{
{ IROp::Add, IRTEMP_0, MIPS_REG_A0, MIPS_REG_A1 },
{ IROp::Mov, MIPS_REG_V0, IRTEMP_0 },
{ IROp::Add, IRTEMP_0, MIPS_REG_A2, MIPS_REG_A3 },
{ IROp::Mov, MIPS_REG_V1, IRTEMP_0 },
},
{
{ IROp::Add, MIPS_REG_V0, MIPS_REG_A0, MIPS_REG_A1 },
{ IROp::Add, MIPS_REG_V1, MIPS_REG_A2, MIPS_REG_A3 },
},
{ &PurgeTemps },
},
{
"SwapClobberTemp",
{
{ IROp::Sub, MIPS_REG_A0, MIPS_REG_A1, MIPS_REG_A2 },
{ IROp::Mov, MIPS_REG_S0, MIPS_REG_A0 },
{ IROp::Slt, MIPS_REG_A0, MIPS_REG_V0, MIPS_REG_V1 },
},
{
{ IROp::Sub, MIPS_REG_S0, MIPS_REG_A1, MIPS_REG_A2 },
{ IROp::Slt, MIPS_REG_A0, MIPS_REG_V0, MIPS_REG_V1 },
},
{ &PurgeTemps },
},
{
"SimplePropagateConstants",
{
{ IROp::SetConst, MIPS_REG_A0, 0, 0, 0x12340000 },
{ IROp::OrConst, MIPS_REG_A0, MIPS_REG_A0, 0, 0x00005678 },
{ IROp::AddConst, MIPS_REG_A1, MIPS_REG_A0, 0, 0 },
{ IROp::AddConst, MIPS_REG_A2, MIPS_REG_A0, 0, 0x00001111 },
},
{
{ IROp::SetConst, MIPS_REG_A0, 0, 0, 0x12345678 },
{ IROp::SetConst, MIPS_REG_A1, 0, 0, 0x12345678 },
{ IROp::SetConst, MIPS_REG_A2, 0, 0, 0x12346789 },
},
{ &PropagateConstants },
},
{
// Needed for PurgeTemps optimizations to work.
"OrToMov",
{
{ IROp::Sub, MIPS_REG_A0, MIPS_REG_A1, MIPS_REG_A2 },
{ IROp::Or, MIPS_REG_S0, MIPS_REG_A0, MIPS_REG_ZERO },
{ IROp::Add, MIPS_REG_S1, MIPS_REG_A0, MIPS_REG_ZERO },
},
{
{ IROp::Sub, MIPS_REG_A0, MIPS_REG_A1, MIPS_REG_A2 },
{ IROp::Mov, MIPS_REG_S0, MIPS_REG_A0 },
{ IROp::Mov, MIPS_REG_S1, MIPS_REG_A0 },
},
{ &PropagateConstants },
},
};

bool TestIRPassSimplify() {
InitIR();

for (const auto &test : tests) {
if (!VerifyPass(test))
return false;
}

return true;
}
2 changes: 2 additions & 0 deletions unittest/UnitTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -756,6 +756,7 @@ bool TestArm64Emitter();
bool TestX64Emitter();
bool TestShaderGenerators();
bool TestSoftwareGPUJit();
bool TestIRPassSimplify();
bool TestThreadManager();

TestItem availableTests[] = {
Expand All @@ -774,6 +775,7 @@ TestItem availableTests[] = {
TEST_ITEM(VFPUSinCos),
TEST_ITEM(MathUtil),
TEST_ITEM(Parsers),
TEST_ITEM(IRPassSimplify),
TEST_ITEM(Jit),
TEST_ITEM(MatrixTranspose),
TEST_ITEM(ParseLBN),
Expand Down
1 change: 1 addition & 0 deletions unittest/UnitTests.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,7 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="TestIRPassSimplify.cpp" />
<ClCompile Include="TestShaderGenerators.cpp" />
<ClCompile Include="TestSoftwareGPUJit.cpp" />
<ClCompile Include="TestThreadManager.cpp" />
Expand Down
1 change: 1 addition & 0 deletions unittest/UnitTests.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
<ClCompile Include="TestShaderGenerators.cpp" />
<ClCompile Include="TestThreadManager.cpp" />
<ClCompile Include="TestSoftwareGPUJit.cpp" />
<ClCompile Include="TestIRPassSimplify.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="JitHarness.h" />
Expand Down

0 comments on commit 8f23025

Please sign in to comment.