From e8527714809fa07427fbdf4560d78077aba35b71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 5 Oct 2023 18:52:50 +0200 Subject: [PATCH 1/4] Integrate the voffset shuffle in ReadVector --- Core/MIPS/MIPS.cpp | 2 +- Core/MIPS/MIPSVFPUUtils.cpp | 13 +++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/Core/MIPS/MIPS.cpp b/Core/MIPS/MIPS.cpp index b68aebddf5..91223bd637 100644 --- a/Core/MIPS/MIPS.cpp +++ b/Core/MIPS/MIPS.cpp @@ -122,7 +122,7 @@ MIPSState::MIPSState() { // * 4x4 Matrices are contiguous in RAM, making them, too, fast-loadable in NEON // Disadvantages: - // * Extra indirection, can be confusing and slower (interpreter only) + // * Extra indirection, can be confusing and slower (interpreter only, however we can often skip the table by rerranging formulas) // * Flushing and reloading row registers is now slower int i = 0; diff --git a/Core/MIPS/MIPSVFPUUtils.cpp b/Core/MIPS/MIPSVFPUUtils.cpp index 87d9875399..ebb91d863b 100644 --- a/Core/MIPS/MIPSVFPUUtils.cpp +++ b/Core/MIPS/MIPSVFPUUtils.cpp @@ -175,16 +175,17 @@ void ReadVector(float *rd, VectorSize size, int reg) { default: length = 0; break; } int transpose = (reg >> 5) & 1; - const int mtx = reg & (7 << 2); + const int mtx = ((reg << 2) & 0x70); const int col = reg & 3; + // NOTE: We now skip the voffset lookups. if (transpose) { - const int base = mtx + col * 32; - for (int i = 0; i < length; i++) - rd[i] = V(base + ((row+i)&3)); - } else { const int base = mtx + col; for (int i = 0; i < length; i++) - rd[i] = V(base + ((row+i)&3)*32); + rd[i] = currentMIPS->v[base + ((row+i)&3) * 4]; + } else { + const int base = mtx + col * 4; + for (int i = 0; i < length; i++) + rd[i] = currentMIPS->v[base + ((row+i)&3)]; } } From f21523ff7413d882cf71fe9cff50b28b7745368c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 5 Oct 2023 18:56:15 +0200 Subject: [PATCH 2/4] WriteVector: Pluck transpose out of the loop --- Core/MIPS/MIPSVFPUUtils.cpp | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/Core/MIPS/MIPSVFPUUtils.cpp b/Core/MIPS/MIPSVFPUUtils.cpp index ebb91d863b..0f547be819 100644 --- a/Core/MIPS/MIPSVFPUUtils.cpp +++ b/Core/MIPS/MIPSVFPUUtils.cpp @@ -215,14 +215,19 @@ void WriteVector(const float *rd, VectorSize size, int reg) { V(base + ((row+i)&3)*32) = rd[i]; } } else { - for (int i = 0; i < length; i++) { - if (!currentMIPS->VfpuWriteMask(i)) { - int index = mtx; - if (transpose) - index += ((row+i)&3) + col*32; - else - index += col + ((row+i)&3)*32; - V(index) = rd[i]; + if (transpose) { + for (int i = 0; i < length; i++) { + if (!currentMIPS->VfpuWriteMask(i)) { + int index = mtx + ((row + i) & 3) + col * 32; + V(index) = rd[i]; + } + } + } else { + for (int i = 0; i < length; i++) { + if (!currentMIPS->VfpuWriteMask(i)) { + int index = mtx + col + ((row + i) & 3) * 32; + V(index) = rd[i]; + } } } } From 60a304f29b44b16b3acf7e4d344f6d8fe76f41f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 5 Oct 2023 18:58:21 +0200 Subject: [PATCH 3/4] Turn the ifs inside out --- Core/MIPS/MIPSVFPUUtils.cpp | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/Core/MIPS/MIPSVFPUUtils.cpp b/Core/MIPS/MIPSVFPUUtils.cpp index 0f547be819..32f2c66bbf 100644 --- a/Core/MIPS/MIPSVFPUUtils.cpp +++ b/Core/MIPS/MIPSVFPUUtils.cpp @@ -204,29 +204,27 @@ void WriteVector(const float *rd, VectorSize size, int reg) { const int mtx = reg & (7 << 2); const int col = reg & 3; bool transpose = (reg >> 5) & 1; - if (currentMIPS->VfpuWriteMask() == 0) { - if (transpose) { - const int base = mtx + col * 32; + if (transpose) { + const int base = mtx + col * 32; + if (currentMIPS->VfpuWriteMask() == 0) { for (int i = 0; i < length; i++) V(base + ((row+i)&3)) = rd[i]; } else { - const int base = mtx + col; - for (int i = 0; i < length; i++) - V(base + ((row+i)&3)*32) = rd[i]; - } - } else { - if (transpose) { for (int i = 0; i < length; i++) { if (!currentMIPS->VfpuWriteMask(i)) { - int index = mtx + ((row + i) & 3) + col * 32; - V(index) = rd[i]; + V(base + ((row + i) & 3)) = rd[i]; } } + } + } else { + const int base = mtx + col; + if (currentMIPS->VfpuWriteMask() == 0) { + for (int i = 0; i < length; i++) + V(base + ((row + i) & 3) * 32) = rd[i]; } else { for (int i = 0; i < length; i++) { if (!currentMIPS->VfpuWriteMask(i)) { - int index = mtx + col + ((row + i) & 3) * 32; - V(index) = rd[i]; + V(base + ((row + i) & 3) * 32) = rd[i]; } } } From 0d06af87b6a979df4fb97bf9b833d66c692f2fba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 5 Oct 2023 19:07:01 +0200 Subject: [PATCH 4/4] Interpreter: Optimize ReadVector/WriteVector by removing voffset lookups Drops these functions down the ranking of top functions by quite a bit in GTA, speedup at most 0.5% though. But enough of these small ones and they start adding up. Not sure why GTA falls back to the interpreter for these so much though. I guess some "uneaten" prefix.. --- Core/MIPS/MIPSVFPUUtils.cpp | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/Core/MIPS/MIPSVFPUUtils.cpp b/Core/MIPS/MIPSVFPUUtils.cpp index 32f2c66bbf..2ba4efaa09 100644 --- a/Core/MIPS/MIPSVFPUUtils.cpp +++ b/Core/MIPS/MIPSVFPUUtils.cpp @@ -164,6 +164,7 @@ void GetMatrixRows(int matrixReg, MatrixSize msize, u8 vecs[4]) { } } + void ReadVector(float *rd, VectorSize size, int reg) { int row; int length; @@ -181,11 +182,11 @@ void ReadVector(float *rd, VectorSize size, int reg) { if (transpose) { const int base = mtx + col; for (int i = 0; i < length; i++) - rd[i] = currentMIPS->v[base + ((row+i)&3) * 4]; + rd[i] = currentMIPS->v[base + ((row + i) & 3) * 4]; } else { const int base = mtx + col * 4; for (int i = 0; i < length; i++) - rd[i] = currentMIPS->v[base + ((row+i)&3)]; + rd[i] = currentMIPS->v[base + ((row + i) & 3)]; } } @@ -201,30 +202,31 @@ void WriteVector(const float *rd, VectorSize size, int reg) { default: length = 0; break; } - const int mtx = reg & (7 << 2); + const int mtx = ((reg << 2) & 0x70); const int col = reg & 3; bool transpose = (reg >> 5) & 1; + // NOTE: We now skip the voffset lookups. if (transpose) { - const int base = mtx + col * 32; + const int base = mtx + col; if (currentMIPS->VfpuWriteMask() == 0) { for (int i = 0; i < length; i++) - V(base + ((row+i)&3)) = rd[i]; + currentMIPS->v[base + ((row+i) & 3) * 4] = rd[i]; } else { for (int i = 0; i < length; i++) { if (!currentMIPS->VfpuWriteMask(i)) { - V(base + ((row + i) & 3)) = rd[i]; + currentMIPS->v[base + ((row+i) & 3) * 4] = rd[i]; } } } } else { - const int base = mtx + col; + const int base = mtx + col * 4; if (currentMIPS->VfpuWriteMask() == 0) { for (int i = 0; i < length; i++) - V(base + ((row + i) & 3) * 32) = rd[i]; + currentMIPS->v[base + ((row + i) & 3)] = rd[i]; } else { for (int i = 0; i < length; i++) { if (!currentMIPS->VfpuWriteMask(i)) { - V(base + ((row + i) & 3) * 32) = rd[i]; + currentMIPS->v[base + ((row + i) & 3)] = rd[i]; } } }