From fc93e2e5d53484f2562c3dea4dea1462d575c889 Mon Sep 17 00:00:00 2001 From: Nathan Bossart Date: Thu, 2 Oct 2025 22:27:43 -0500 Subject: [PATCH v1 2/2] simd-ify GetPrivateRefCountEntry() --- src/backend/storage/buffer/bufmgr.c | 45 +++++++++++++++++++++++++++++ src/include/port/simd.h | 25 ++++++++++++++++ 2 files changed, 70 insertions(+) diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c index 14222516237..8257fde22fd 100644 --- a/src/backend/storage/buffer/bufmgr.c +++ b/src/backend/storage/buffer/bufmgr.c @@ -50,6 +50,8 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "port/pg_bitutils.h" +#include "port/simd.h" #include "postmaster/bgwriter.h" #include "storage/aio.h" #include "storage/buf_internals.h" @@ -358,11 +360,54 @@ GetPrivateRefCountEntry(Buffer buffer, bool do_move) * First search for references in the array, that'll be sufficient in the * majority of cases. */ +#ifndef USE_NO_SIMD + + { + const Vector32 keys = vector32_broadcast(buffer); + Vector32 bufs1; + Vector32 bufs2; + Vector32 res1; + Vector32 res2; + Vector32 res; + uint32 msk; + +#ifdef USE_ASSERT_CHECKING + PrivateRefCountEntry *ret = NULL; + + for (int i = 0; i < REFCOUNT_ARRAY_ENTRIES; i++) + { + if (PrivateRefCountArrayBuffers[i] == buffer) + { + ret = &PrivateRefCountArray[i]; + break; + } + } +#endif + + vector32_load(&bufs1, (uint32 *) &PrivateRefCountArrayBuffers[0]); + vector32_load(&bufs2, (uint32 *) &PrivateRefCountArrayBuffers[sizeof(Vector32) / sizeof(int)]); + + res1 = vector32_eq(bufs1, keys); + res2 = vector32_eq(bufs2, keys); + res = vector32_pack_32(res1, res2); + + msk = vector32_highbit_mask(res); + if (likely(msk)) + { + Assert(ret == &PrivateRefCountArray[pg_rightmost_one_pos32(msk) / 2]); + return &PrivateRefCountArray[pg_rightmost_one_pos32(msk) / 2]; + } + else + Assert(ret == NULL); + } + +#else for (int i = 0; i < REFCOUNT_ARRAY_ENTRIES; i++) { if (PrivateRefCountArrayBuffers[i] == buffer) return &PrivateRefCountArray[i]; } +#endif /* * By here we know that the buffer, if already pinned, isn't residing in diff --git a/src/include/port/simd.h b/src/include/port/simd.h index 97c5f353022..5a8933f45e0 100644 --- a/src/include/port/simd.h +++ b/src/include/port/simd.h @@ -331,6 +331,18 @@ vector8_highbit_mask(const Vector8 v) } #endif /* ! USE_NO_SIMD */ +#ifndef USE_NO_SIMD +static inline uint32 +vector32_highbit_mask(const Vector32 v) +{ +#ifdef USE_NEON + return vector8_highbit_mask((Vector8) v); +#else + return vector8_highbit_mask(v); +#endif +} +#endif /* ! USE_NO_SIMD */ + /* * Return the bitwise OR of the inputs */ @@ -419,4 +431,17 @@ vector8_min(const Vector8 v1, const Vector8 v2) } #endif /* ! USE_NO_SIMD */ + +#ifndef USE_NO_SIMD +static inline Vector32 +vector32_pack_32(const Vector32 v1, const Vector32 v2) +{ +#ifdef USE_SSE2 + return _mm_packus_epi32(v1, v2); +#elif defined(USE_NEON) + return (Vector32) vuzp1q_u16((uint16x8_t) v1, (uint16x8_t) v2); +#endif +} +#endif /* ! USE_NO_SIMD */ + #endif /* SIMD_H */ -- 2.39.5 (Apple Git-154)