NEON: simplify updates in NNUE accumulator

Reduce # instructions using widening add/sub calls on AArch64.
Add shims for 32-bit ARM.

Passed non-regression STC:
https://tests.stockfishchess.org/tests/view/69c093d3f690a4b7f5fb0d6e
LLR: 5.15 (-2.94,2.94) <-1.75,0.25>
Total: 338624 W: 86931 L: 86853 D: 164840
Ptnml(0-2): 667, 35888, 96079, 36056, 622

closes https://github.com/official-stockfish/Stockfish/pull/6692

No functional change
This commit is contained in:
Linmiao Xu
2026-04-02 20:32:43 +02:00
committed by Disservin
parent c41c9bb973
commit 171afd2b4d
2 changed files with 9 additions and 8 deletions
+6 -6
View File
@@ -379,8 +379,8 @@ struct AccumulatorUpdateContext {
#ifdef USE_NEON
for (IndexType k = 0; k < Tiling::NumRegs; k += 2)
{
acc[k] = vec_sub_16(acc[k], vmovl_s8(vget_low_s8(column[k / 2])));
acc[k + 1] = vec_sub_16(acc[k + 1], vmovl_high_s8(column[k / 2]));
acc[k] = vsubw_s8(acc[k], vget_low_s8(column[k / 2]));
acc[k + 1] = vsubw_high_s8(acc[k + 1], column[k / 2]);
}
#else
for (IndexType k = 0; k < Tiling::NumRegs; ++k)
@@ -397,8 +397,8 @@ struct AccumulatorUpdateContext {
#ifdef USE_NEON
for (IndexType k = 0; k < Tiling::NumRegs; k += 2)
{
acc[k] = vec_add_16(acc[k], vmovl_s8(vget_low_s8(column[k / 2])));
acc[k + 1] = vec_add_16(acc[k + 1], vmovl_high_s8(column[k / 2]));
acc[k] = vaddw_s8(acc[k], vget_low_s8(column[k / 2]));
acc[k + 1] = vaddw_high_s8(acc[k + 1], column[k / 2]);
}
#else
for (IndexType k = 0; k < Tiling::NumRegs; ++k)
@@ -890,8 +890,8 @@ void update_threats_accumulator_full(Color persp
#ifdef USE_NEON
for (IndexType k = 0; k < Tiling::NumRegs; k += 2)
{
acc[k] = vec_add_16(acc[k], vmovl_s8(vget_low_s8(column[k / 2])));
acc[k + 1] = vec_add_16(acc[k + 1], vmovl_high_s8(column[k / 2]));
acc[k] = vaddw_s8(acc[k], vget_low_s8(column[k / 2]));
acc[k + 1] = vaddw_high_s8(acc[k + 1], column[k / 2]);
}
#else
for (IndexType k = 0; k < Tiling::NumRegs; ++k)
+3 -2
View File
@@ -221,8 +221,9 @@ static constexpr std::uint32_t Mask[4] = {1, 2, 4, 8};
#define MaxChunkSize 16
#ifndef __aarch64__
// Single instruction doesn't exist on 32-bit ARM
inline int16x8_t vmovl_high_s8(int8x16_t val) { return vmovl_s8(vget_high_s8(val)); }
// Instructions that don't exist on 32-bit ARM
inline int16x8_t vaddw_high_s8(int16x8_t a, int8x16_t b) { return vaddw_s8(a, vget_high_s8(b)); }
inline int16x8_t vsubw_high_s8(int16x8_t a, int8x16_t b) { return vsubw_s8(a, vget_high_s8(b)); }
#endif
#else