Add Neon implementation of aom_sum_squares_i16 Add Neon implementation of aom_sum_squares_i16 as well as the corresponding tests. Change-Id: I813e2bd89124e0d9cf48fcf933e5cd0e379aecfc
diff --git a/aom_dsp/aom_dsp_rtcd_defs.pl b/aom_dsp/aom_dsp_rtcd_defs.pl index 76827cd..de6573d 100755 --- a/aom_dsp/aom_dsp_rtcd_defs.pl +++ b/aom_dsp/aom_dsp_rtcd_defs.pl
@@ -747,7 +747,7 @@ specialize qw/aom_sum_squares_2d_i16 sse2 avx2 neon/; add_proto qw/uint64_t aom_sum_squares_i16/, "const int16_t *src, uint32_t N"; - specialize qw/aom_sum_squares_i16 sse2/; + specialize qw/aom_sum_squares_i16 sse2 neon/; add_proto qw/uint64_t aom_var_2d_u8/, "uint8_t *src, int src_stride, int width, int height"; specialize qw/aom_var_2d_u8 sse2 avx2/;
diff --git a/aom_dsp/arm/sum_squares_neon.c b/aom_dsp/arm/sum_squares_neon.c index 095a2c6..20c9c0d 100644 --- a/aom_dsp/arm/sum_squares_neon.c +++ b/aom_dsp/arm/sum_squares_neon.c
@@ -223,3 +223,66 @@ return sse; } + +static INLINE uint64_t aom_sum_squares_i16_4xn_neon(const int16_t *src, + uint32_t n) { + uint64x2_t sum_u64 = vdupq_n_u64(0); + + int i = n; + do { + uint32x4_t sum; + int16x4_t s0 = vld1_s16(src); + + sum = vreinterpretq_u32_s32(vmull_s16(s0, s0)); + + sum_u64 = vpadalq_u32(sum_u64, sum); + + src += 4; + i -= 4; + } while (i >= 4); + + if (i > 0) { + return horizontal_add_u64x2(sum_u64) + aom_sum_squares_i16_c(src, i); + } + return horizontal_add_u64x2(sum_u64); +} + +static INLINE uint64_t aom_sum_squares_i16_8xn_neon(const int16_t *src, + uint32_t n) { + uint64x2_t sum_u64[2] = { vdupq_n_u64(0), vdupq_n_u64(0) }; + + int i = n; + do { + uint32x4_t sum[2]; + int16x8_t s0 = vld1q_s16(src); + + sum[0] = + vreinterpretq_u32_s32(vmull_s16(vget_low_s16(s0), vget_low_s16(s0))); + sum[1] = + vreinterpretq_u32_s32(vmull_s16(vget_high_s16(s0), vget_high_s16(s0))); + + sum_u64[0] = vpadalq_u32(sum_u64[0], sum[0]); + sum_u64[1] = vpadalq_u32(sum_u64[1], sum[1]); + + src += 8; + i -= 8; + } while (i >= 8); + + if (i > 0) { + return horizontal_add_u64x2(vaddq_u64(sum_u64[0], sum_u64[1])) + + aom_sum_squares_i16_c(src, i); + } + return horizontal_add_u64x2(vaddq_u64(sum_u64[0], sum_u64[1])); +} + +uint64_t aom_sum_squares_i16_neon(const int16_t *src, uint32_t n) { + // This function seems to be called only for values of N >= 64. See + // av1/encoder/compound_type.c. + if (LIKELY(n >= 8)) { + return aom_sum_squares_i16_8xn_neon(src, n); + } + if (n >= 4) { + return aom_sum_squares_i16_4xn_neon(src, n); + } + return aom_sum_squares_i16_c(src, n); +}
diff --git a/test/sum_squares_test.cc b/test/sum_squares_test.cc index 5c049a5..a89e58c 100644 --- a/test/sum_squares_test.cc +++ b/test/sum_squares_test.cc
@@ -238,6 +238,13 @@ #endif // HAVE_SSE2 +#if HAVE_NEON +INSTANTIATE_TEST_SUITE_P(NEON, SumSquares1DTest, + ::testing::Values(TestFuncs1D( + aom_sum_squares_i16_c, aom_sum_squares_i16_neon))); + +#endif // HAVE_NEON + typedef int64_t (*sse_func)(const uint8_t *a, int a_stride, const uint8_t *b, int b_stride, int width, int height); typedef libaom_test::FuncParam<sse_func> TestSSEFuncs;