Exit early from pg_comp_crc32c_pmull for small inputs

The vectorized path in commit fbc57f2bc had a side effect of putting
more branches in the path taken for small inputs. To reduce risk
of regressions, only proceed with the vectorized path if we can
guarantee that the remaining input after the alignment preamble is
greater than 64 bytes. That also allows removing length checks in
the alignment preamble.

Reviewed-by: Nathan Bossart <nathandbossart@gmail.com>
Discussion: https://postgr.es/m/CANWCAZZ48GuLYhJCcTy8TXysjrMVJL6n1n7NP94=iG+t80YKPw@mail.gmail.com
This commit is contained in:
John Naylor 2026-04-08 13:52:14 +07:00
parent ce11e63f81
commit 948ef7cdc4

View file

@ -91,6 +91,7 @@ pg_comp_crc32c_armv8(pg_crc32c crc, const void *data, size_t len)
* - match our function declaration
* - match whitespace to our project style
* - be more friendly for pgindent
* - exit early for small inputs
*/
/* Generated by https://github.com/corsix/fast-crc32/ using: */
@ -127,19 +128,28 @@ pg_comp_crc32c_pmull(pg_crc32c crc, const void *data, size_t len)
pg_crc32c crc0 = crc;
const char *buf = data;
/*
* Immediately fall back to the scalar path if the vector path is not
* guaranteed to perform at least one iteration after the alignment
* preamble.
*/
if (len < 5 * sizeof(uint64x2_t))
return pg_comp_crc32c_armv8(crc, data, len);
/* align to 16 bytes */
for (; len && ((uintptr_t) buf & 7); --len)
for (; (uintptr_t) buf & 7; --len)
{
crc0 = __crc32cb(crc0, *buf++);
}
if (((uintptr_t) buf & 8) && len >= 8)
if ((uintptr_t) buf & 8)
{
crc0 = __crc32cd(crc0, *(const uint64_t *) buf);
buf += 8;
len -= 8;
}
if (len >= 64)
Assert(len >= 64);
{
const char *end = buf + len;
const char *limit = buf + len - 64;