SPU: Add some comments clarifying very obtuse code

This commit is contained in:
Malcolm 2026-06-01 16:45:22 -04:00 committed by Elad
parent 3f27cb8ff5
commit 1b54e8910c
2 changed files with 22 additions and 0 deletions

View File

@ -1847,8 +1847,11 @@ public:
if ((end - starta) >= 192 && !g_cfg.core.precise_spu_verification)
{
#ifdef ARCH_ARM64
// Loop if there is at least 288 bytes of data to checksum on ARM.
// Each ARM checksum block consumes 6 NEON vectors: 2 direct adds and 2 UABD accumulates.
constexpr u32 checksum_block_size = 96;
#else
// Loop if there is atleast (16 * stride) bytes of data to checksum to save some instruction cache
constexpr u32 checksum_block_size = 64;
#endif
constexpr u32 checksum_loop_vectors = 16;
@ -2003,6 +2006,13 @@ public:
const auto cond = m_ir->CreateICmpNE(elem, m_ir->getInt64(0));
m_ir->CreateCondBr(cond, label_diff, label_body, m_md_unlikely);
#else
// Very cursed "checksumming" code
// 96 bytes per ARM checksum step
//vls[0] -> add
//vls[1], vls[2] -> uaba
//vls[3] -> add
//vls[4], vls[5] -> uaba
//This allows us to save on some ALU ops relative to load instructions
const auto acc_init = ConstantAggregateZero::get(get_type<u32[4]>());
llvm::Value* checksum_parts[4] = {acc_init, acc_init, acc_init, acc_init};
u32 checksum[16] = {0};
@ -2237,6 +2247,9 @@ public:
m_ir->CreateBitCast(expected, get_type<u16[8]>())), get_type<s16[8]>());
};
// Multiply accumulate based comparison
// See comment above cmp16_pair_accum_arm64 in SPUThread.cpp
// Dotproduct instructions have slightly higher throughput on many common ARM cores
const auto accumulate_pair = [&](llvm::Value* lhs, llvm::Value* rhs)
{
llvm::Value*& acc = *accs[acc_index];

View File

@ -245,6 +245,15 @@ static FORCE_INLINE bool cmp_rdata_avx(const __m256i* lhs, const __m256i* rhs)
}
#endif
// Insane idea to accelerate comparisons on Neon with a fixed length
// Common ARM chips like the a78 and a715 can Perform 3 128b loads/clock
// But only execute 2 128b instructions on the ALU per clock
// To consume data any faster, we need to use ALU instructions that take 3 inputs
// Idea: compare data, filling each lane with either -1 or 0
// Then multiply each pair of comparisons together, resulting in 1 if both pairs were -1
// Accummulate those results, and compare the accumulated value to the expected count
// Benchmarks showed this to be faster even on arm machines that aren't capable of more loads than ALU operations
// Tested on Tensor G1, Snapdragon 8 gen 2, and the Snapdragon 8 Elite gen 5
#if defined(ARCH_ARM64)
static FORCE_INLINE int16x8_t cmp16_pair_accum_arm64(
int16x8_t acc, const v128& lhs0, const v128& rhs0, const v128& lhs1, const v128& rhs1)