AArch64: Add Neon path for convertSequences_noRepcodes
Add a 4-way Neon implementation for the convertSequences_noRepcodes function. Remove 'static' keywords from all of its implementations to be able to add unit tests. Relative performance to Clang-18 using: `./fullbench -b18 -l5 enwik5` Neoverse-V2 before after Clang-18: 100.000% 311.703% Clang-19: 100.191% 311.714% Clang-20: 100.181% 311.723% GCC-13: 107.520% 252.309% GCC-14: 107.652% 253.158% GCC-15: 107.674% 253.168% Cortex-A720 before after Clang-18: 100.000% 204.512% Clang-19: 102.825% 204.600% Clang-20: 102.807% 204.558% GCC-13: 110.668% 203.594% GCC-14: 110.684% 203.978% GCC-15: 102.864% 204.299% Co-authored by, Thomas Daubney <Thomas.Daubney@arm.com>
This commit is contained in:
+126
@@ -770,6 +770,130 @@ static void test_blockSplitter_incompressibleExpansionProtection(unsigned testNb
|
||||
DISPLAYLEVEL(3, "OK \n");
|
||||
}
|
||||
|
||||
size_t convertSequences_noRepcodes(SeqDef* dstSeqs, const ZSTD_Sequence* inSeqs,
|
||||
size_t nbSequences);
|
||||
|
||||
static size_t convertSequences_noRepcodes_ref(
|
||||
SeqDef* dstSeqs,
|
||||
const ZSTD_Sequence* inSeqs,
|
||||
size_t nbSequences)
|
||||
{
|
||||
size_t longLen = 0;
|
||||
size_t n;
|
||||
for (n=0; n<nbSequences; n++) {
|
||||
dstSeqs[n].offBase = OFFSET_TO_OFFBASE(inSeqs[n].offset);
|
||||
dstSeqs[n].litLength = (U16)inSeqs[n].litLength;
|
||||
dstSeqs[n].mlBase = (U16)(inSeqs[n].matchLength - MINMATCH);
|
||||
/* Check for long length > 65535. */
|
||||
if (UNLIKELY(inSeqs[n].matchLength > 65535+MINMATCH)) {
|
||||
assert(longLen == 0);
|
||||
longLen = n + 1;
|
||||
}
|
||||
if (UNLIKELY(inSeqs[n].litLength > 65535)) {
|
||||
assert(longLen == 0);
|
||||
longLen = n + nbSequences + 1;
|
||||
}
|
||||
}
|
||||
return longLen;
|
||||
}
|
||||
|
||||
static unsigned test_convertSequences_noRepcodes(unsigned seed, unsigned testNb)
|
||||
{
|
||||
ZSTD_Sequence nsrc[12];
|
||||
SeqDef ndst[12], rdst[12];
|
||||
size_t ref, ret, i, j;
|
||||
|
||||
seed += 0xDEADBEEF;
|
||||
for (i = 0; i < COUNTOF(nsrc); ++i) {
|
||||
seed = 48271 * ((unsigned)i + seed);
|
||||
nsrc[i].offset = (seed & 0xFFFF) | 1; /* Offset shall not be zero. */
|
||||
seed = 48271 * ((unsigned)i + seed);
|
||||
nsrc[i].litLength = seed & 0xFFFF;
|
||||
seed = 48271 * ((unsigned)i + seed);
|
||||
nsrc[i].matchLength = (seed & 0xFFFFFF) % (65536 + MINMATCH);
|
||||
seed = 48271 * ((unsigned)i + seed);
|
||||
nsrc[i].rep = seed & 0xFF;
|
||||
}
|
||||
|
||||
/* For near overflow and proper negative value handling. */
|
||||
nsrc[5].matchLength = 65535 + MINMATCH;
|
||||
nsrc[6].litLength = 65535;
|
||||
nsrc[6].matchLength = 0;
|
||||
nsrc[7].litLength = 0;
|
||||
nsrc[7].matchLength = MINMATCH;
|
||||
|
||||
for (i = 0; i <= COUNTOF(nsrc); ++i) {
|
||||
DISPLAYLEVEL(3, "test%3u : convertSequences_noRepcodes with %u inputs : ",
|
||||
testNb++, (unsigned)i);
|
||||
memset(ndst, 0, sizeof(ndst));
|
||||
memset(rdst, 0, sizeof(rdst));
|
||||
ref = convertSequences_noRepcodes_ref(rdst, nsrc, i);
|
||||
ret = convertSequences_noRepcodes(ndst, nsrc, i);
|
||||
CHECK_EQ(ret, ref);
|
||||
CHECK_EQ(memcmp(rdst, ndst, sizeof(ndst)), 0);
|
||||
DISPLAYLEVEL(3, "OK \n");
|
||||
}
|
||||
|
||||
nsrc[7].matchLength = 65536 + MINMATCH;
|
||||
for (i = 8; i <= COUNTOF(nsrc); ++i) {
|
||||
DISPLAYLEVEL(3, "test%3u : convertSequences_noRepcodes with %u inputs and "
|
||||
"matchLength overflow : ",
|
||||
testNb++, (unsigned)i);
|
||||
memset(ndst, 0, sizeof(ndst));
|
||||
memset(rdst, 0, sizeof(rdst));
|
||||
ref = convertSequences_noRepcodes_ref(rdst, nsrc, i);
|
||||
ret = convertSequences_noRepcodes(ndst, nsrc, i);
|
||||
CHECK_EQ(ret, ref);
|
||||
CHECK_EQ(memcmp(rdst, ndst, sizeof(ndst)), 0);
|
||||
DISPLAYLEVEL(3, "OK \n");
|
||||
|
||||
assert(COUNTOF(nsrc) > 8);
|
||||
for (j = 4; j < 8; ++j) {
|
||||
DISPLAYLEVEL(3, "test%3u : convertSequences_noRepcodes with %u inputs and "
|
||||
"matchLength overflow #%u : ",
|
||||
testNb++, (unsigned)i, (unsigned)(i - j));
|
||||
memset(ndst, 0, sizeof(ndst));
|
||||
memset(rdst, 0, sizeof(rdst));
|
||||
ref = convertSequences_noRepcodes_ref(rdst, nsrc + j, i - j);
|
||||
ret = convertSequences_noRepcodes(ndst, nsrc + j, i - j);
|
||||
CHECK_EQ(ret, ref);
|
||||
CHECK_EQ(memcmp(rdst, ndst, sizeof(ndst)), 0);
|
||||
DISPLAYLEVEL(3, "OK \n");
|
||||
}
|
||||
}
|
||||
nsrc[7].matchLength = 1;
|
||||
|
||||
nsrc[7].litLength = 65536;
|
||||
for (i = 8; i <= COUNTOF(nsrc); ++i) {
|
||||
DISPLAYLEVEL(3, "test%3u : convertSequences_noRepcodes with %u inputs and "
|
||||
"litLength overflow: ",
|
||||
testNb++, (unsigned)i);
|
||||
memset(ndst, 0, sizeof(ndst));
|
||||
memset(rdst, 0, sizeof(rdst));
|
||||
ref = convertSequences_noRepcodes_ref(rdst, nsrc, i);
|
||||
ret = convertSequences_noRepcodes(ndst, nsrc, i);
|
||||
CHECK_EQ(ret, ref);
|
||||
CHECK_EQ(memcmp(rdst, ndst, sizeof(ndst)), 0);
|
||||
DISPLAYLEVEL(3, "OK \n");
|
||||
|
||||
assert(COUNTOF(nsrc) > 8);
|
||||
for (j = 4; j < 8; ++j) {
|
||||
DISPLAYLEVEL(3, "test%3u : convertSequences_noRepcodes with %u inputs and "
|
||||
"litLength overflow #%u: ",
|
||||
testNb++, (unsigned)i, (unsigned)(i - j));
|
||||
memset(ndst, 0, sizeof(ndst));
|
||||
memset(rdst, 0, sizeof(rdst));
|
||||
ref = convertSequences_noRepcodes_ref(rdst, nsrc + j, i - j);
|
||||
ret = convertSequences_noRepcodes(ndst, nsrc + j, i - j);
|
||||
CHECK_EQ(ret, ref);
|
||||
CHECK_EQ(memcmp(rdst, ndst, sizeof(ndst)), 0);
|
||||
DISPLAYLEVEL(3, "OK \n");
|
||||
}
|
||||
}
|
||||
|
||||
return testNb;
|
||||
}
|
||||
|
||||
static unsigned test_get1BlockSummary(unsigned testNb)
|
||||
{
|
||||
static const ZSTD_Sequence nseqs[] = {
|
||||
@@ -4085,6 +4209,8 @@ static int basicUnitTests(U32 const seed, double compressibility)
|
||||
}
|
||||
DISPLAYLEVEL(3, "OK \n");
|
||||
|
||||
testNb = test_convertSequences_noRepcodes(seed, testNb);
|
||||
|
||||
testNb = test_get1BlockSummary(testNb);
|
||||
|
||||
DISPLAYLEVEL(3, "test%3i : ZSTD_compressSequencesAndLiterals : ", testNb++);
|
||||
|
||||
Reference in New Issue
Block a user