Add Neon implementations of mse functions for more block sizes
Add Neon implementations of aom_mse<w>x<h>_neon for the following
block sizes that only had scalar C implementations on Arm:
* 8x8, 8x16
* 16x8
Also add test coverage for the new Neon functions.
Change-Id: Ia1294beb1aad2e3ee52c823836186fd451d191b7
diff --git a/aom_dsp/aom_dsp_rtcd_defs.pl b/aom_dsp/aom_dsp_rtcd_defs.pl
index f5c9b03..d672d77 100755
--- a/aom_dsp/aom_dsp_rtcd_defs.pl
+++ b/aom_dsp/aom_dsp_rtcd_defs.pl
@@ -1279,9 +1279,9 @@
add_proto qw/unsigned int aom_mse8x8/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int recon_stride, unsigned int *sse";
specialize qw/aom_mse16x16 sse2 avx2 neon msa/;
- specialize qw/aom_mse16x8 sse2 msa/;
- specialize qw/aom_mse8x16 sse2 msa/;
- specialize qw/aom_mse8x8 sse2 msa/;
+ specialize qw/aom_mse16x8 sse2 neon msa/;
+ specialize qw/aom_mse8x16 sse2 neon msa/;
+ specialize qw/aom_mse8x8 sse2 neon msa/;
if (aom_config("CONFIG_AV1_HIGHBITDEPTH") eq "yes") {
foreach $bd (8, 10, 12) {
diff --git a/aom_dsp/arm/variance_neon.c b/aom_dsp/arm/variance_neon.c
index e1f4978..17d815c 100644
--- a/aom_dsp/arm/variance_neon.c
+++ b/aom_dsp/arm/variance_neon.c
@@ -401,9 +401,50 @@
}
}
-unsigned int aom_mse16x16_neon(const uint8_t *src, int src_stride,
- const uint8_t *ref, int ref_stride,
- unsigned int *sse) {
+static INLINE unsigned int mse8xh_neon(const uint8_t *src, int src_stride,
+ const uint8_t *ref, int ref_stride,
+ unsigned int *sse, int h) {
+ uint8x8_t s[2], r[2];
+ int16x4_t diff_lo[2], diff_hi[2];
+ uint16x8_t diff[2];
+ int32x4_t sse_s32[2] = { vdupq_n_s32(0), vdupq_n_s32(0) };
+
+ int i = 0;
+ do {
+ s[0] = vld1_u8(src);
+ src += src_stride;
+ s[1] = vld1_u8(src);
+ src += src_stride;
+ r[0] = vld1_u8(ref);
+ ref += ref_stride;
+ r[1] = vld1_u8(ref);
+ ref += ref_stride;
+
+ diff[0] = vsubl_u8(s[0], r[0]);
+ diff[1] = vsubl_u8(s[1], r[1]);
+
+ diff_lo[0] = vreinterpret_s16_u16(vget_low_u16(diff[0]));
+ diff_lo[1] = vreinterpret_s16_u16(vget_low_u16(diff[1]));
+ sse_s32[0] = vmlal_s16(sse_s32[0], diff_lo[0], diff_lo[0]);
+ sse_s32[1] = vmlal_s16(sse_s32[1], diff_lo[1], diff_lo[1]);
+
+ diff_hi[0] = vreinterpret_s16_u16(vget_high_u16(diff[0]));
+ diff_hi[1] = vreinterpret_s16_u16(vget_high_u16(diff[1]));
+ sse_s32[0] = vmlal_s16(sse_s32[0], diff_hi[0], diff_hi[0]);
+ sse_s32[1] = vmlal_s16(sse_s32[1], diff_hi[1], diff_hi[1]);
+
+ i += 2;
+ } while (i < h);
+
+ sse_s32[0] = vaddq_s32(sse_s32[0], sse_s32[1]);
+
+ *sse = horizontal_add_u32x4(vreinterpretq_u32_s32(sse_s32[0]));
+ return horizontal_add_u32x4(vreinterpretq_u32_s32(sse_s32[0]));
+}
+
+static INLINE unsigned int mse16xh_neon(const uint8_t *src, int src_stride,
+ const uint8_t *ref, int ref_stride,
+ unsigned int *sse, int h) {
uint8x16_t s[2], r[2];
int16x4_t diff_lo[4], diff_hi[4];
uint16x8_t diff[4];
@@ -447,7 +488,7 @@
sse_s32[3] = vmlal_s16(sse_s32[3], diff_hi[3], diff_hi[3]);
i += 2;
- } while (i < 16);
+ } while (i < h);
sse_s32[0] = vaddq_s32(sse_s32[0], sse_s32[1]);
sse_s32[2] = vaddq_s32(sse_s32[2], sse_s32[3]);
@@ -457,6 +498,21 @@
return horizontal_add_u32x4(vreinterpretq_u32_s32(sse_s32[0]));
}
+#define MSE_WXH_NEON(w, h) \
+ unsigned int aom_mse##w##x##h##_neon(const uint8_t *src, int src_stride, \
+ const uint8_t *ref, int ref_stride, \
+ unsigned int *sse) { \
+ return mse##w##xh_neon(src, src_stride, ref, ref_stride, sse, h); \
+ }
+
+MSE_WXH_NEON(8, 8)
+MSE_WXH_NEON(8, 16)
+
+MSE_WXH_NEON(16, 8)
+MSE_WXH_NEON(16, 16)
+
+#undef MSE_WXH_NEON
+
unsigned int aom_get4x4sse_cs_neon(const uint8_t *src, int src_stride,
const uint8_t *ref, int ref_stride) {
uint8x8_t s[4], r[4];
diff --git a/test/variance_test.cc b/test/variance_test.cc
index d41b4be..46b87b1 100644
--- a/test/variance_test.cc
+++ b/test/variance_test.cc
@@ -2819,8 +2819,10 @@
&aom_get4x4sse_cs_neon)));
INSTANTIATE_TEST_SUITE_P(NEON, AvxMseTest,
- ::testing::Values(MseParams(4, 4,
- &aom_mse16x16_neon)));
+ ::testing::Values(MseParams(3, 3, &aom_mse8x8_neon),
+ MseParams(3, 4, &aom_mse8x16_neon),
+ MseParams(4, 4, &aom_mse16x16_neon),
+ MseParams(4, 3, &aom_mse16x8_neon)));
const VarianceParams kArrayVariance_neon[] = {
VarianceParams(7, 7, &aom_variance128x128_neon),