Index: source/libvpx/vp9/encoder/x86/vp9_avg_intrin_sse2.c |
diff --git a/source/libvpx/vp9/encoder/x86/vp9_avg_intrin_sse2.c b/source/libvpx/vp9/encoder/x86/vp9_avg_intrin_sse2.c |
index 4e80b255e88fb318e31f25b504d380d46fb6afe7..4672aa6b8cf2300d123ebbae22a1daf8b2112490 100644 |
--- a/source/libvpx/vp9/encoder/x86/vp9_avg_intrin_sse2.c |
+++ b/source/libvpx/vp9/encoder/x86/vp9_avg_intrin_sse2.c |
@@ -11,6 +11,83 @@ |
#include <emmintrin.h> |
#include "vpx_ports/mem.h" |
+void vp9_minmax_8x8_sse2(const uint8_t *s, int p, const uint8_t *d, int dp, |
+ int *min, int *max) { |
+ __m128i u0, s0, d0, diff, maxabsdiff, minabsdiff, negdiff, absdiff0, absdiff; |
+ u0 = _mm_setzero_si128(); |
+ // Row 0 |
+ s0 = _mm_unpacklo_epi8(_mm_loadl_epi64((const __m128i *)(s)), u0); |
+ d0 = _mm_unpacklo_epi8(_mm_loadl_epi64((const __m128i *)(d)), u0); |
+ diff = _mm_subs_epi16(s0, d0); |
+ negdiff = _mm_subs_epi16(u0, diff); |
+ absdiff0 = _mm_max_epi16(diff, negdiff); |
+ // Row 1 |
+ s0 = _mm_unpacklo_epi8(_mm_loadl_epi64((const __m128i *)(s + p)), u0); |
+ d0 = _mm_unpacklo_epi8(_mm_loadl_epi64((const __m128i *)(d + dp)), u0); |
+ diff = _mm_subs_epi16(s0, d0); |
+ negdiff = _mm_subs_epi16(u0, diff); |
+ absdiff = _mm_max_epi16(diff, negdiff); |
+ maxabsdiff = _mm_max_epi16(absdiff0, absdiff); |
+ minabsdiff = _mm_min_epi16(absdiff0, absdiff); |
+ // Row 2 |
+ s0 = _mm_unpacklo_epi8(_mm_loadl_epi64((const __m128i *)(s + 2 * p)), u0); |
+ d0 = _mm_unpacklo_epi8(_mm_loadl_epi64((const __m128i *)(d + 2 * dp)), u0); |
+ diff = _mm_subs_epi16(s0, d0); |
+ negdiff = _mm_subs_epi16(u0, diff); |
+ absdiff = _mm_max_epi16(diff, negdiff); |
+ maxabsdiff = _mm_max_epi16(maxabsdiff, absdiff); |
+ minabsdiff = _mm_min_epi16(minabsdiff, absdiff); |
+ // Row 3 |
+ s0 = _mm_unpacklo_epi8(_mm_loadl_epi64((const __m128i *)(s + 3 * p)), u0); |
+ d0 = _mm_unpacklo_epi8(_mm_loadl_epi64((const __m128i *)(d + 3 * dp)), u0); |
+ diff = _mm_subs_epi16(s0, d0); |
+ negdiff = _mm_subs_epi16(u0, diff); |
+ absdiff = _mm_max_epi16(diff, negdiff); |
+ maxabsdiff = _mm_max_epi16(maxabsdiff, absdiff); |
+ minabsdiff = _mm_min_epi16(minabsdiff, absdiff); |
+ // Row 4 |
+ s0 = _mm_unpacklo_epi8(_mm_loadl_epi64((const __m128i *)(s + 4 * p)), u0); |
+ d0 = _mm_unpacklo_epi8(_mm_loadl_epi64((const __m128i *)(d + 4 * dp)), u0); |
+ diff = _mm_subs_epi16(s0, d0); |
+ negdiff = _mm_subs_epi16(u0, diff); |
+ absdiff = _mm_max_epi16(diff, negdiff); |
+ maxabsdiff = _mm_max_epi16(maxabsdiff, absdiff); |
+ minabsdiff = _mm_min_epi16(minabsdiff, absdiff); |
+ // Row 5 |
+ s0 = _mm_unpacklo_epi8(_mm_loadl_epi64((const __m128i *)(s + 5 * p)), u0); |
+ d0 = _mm_unpacklo_epi8(_mm_loadl_epi64((const __m128i *)(d + 5 * dp)), u0); |
+ diff = _mm_subs_epi16(s0, d0); |
+ negdiff = _mm_subs_epi16(u0, diff); |
+ absdiff = _mm_max_epi16(diff, negdiff); |
+ maxabsdiff = _mm_max_epi16(maxabsdiff, absdiff); |
+ minabsdiff = _mm_min_epi16(minabsdiff, absdiff); |
+ // Row 6 |
+ s0 = _mm_unpacklo_epi8(_mm_loadl_epi64((const __m128i *)(s + 6 * p)), u0); |
+ d0 = _mm_unpacklo_epi8(_mm_loadl_epi64((const __m128i *)(d + 6 * dp)), u0); |
+ diff = _mm_subs_epi16(s0, d0); |
+ negdiff = _mm_subs_epi16(u0, diff); |
+ absdiff = _mm_max_epi16(diff, negdiff); |
+ maxabsdiff = _mm_max_epi16(maxabsdiff, absdiff); |
+ minabsdiff = _mm_min_epi16(minabsdiff, absdiff); |
+ // Row 7 |
+ s0 = _mm_unpacklo_epi8(_mm_loadl_epi64((const __m128i *)(s + 7 * p)), u0); |
+ d0 = _mm_unpacklo_epi8(_mm_loadl_epi64((const __m128i *)(d + 7 * dp)), u0); |
+ diff = _mm_subs_epi16(s0, d0); |
+ negdiff = _mm_subs_epi16(u0, diff); |
+ absdiff = _mm_max_epi16(diff, negdiff); |
+ maxabsdiff = _mm_max_epi16(maxabsdiff, absdiff); |
+ minabsdiff = _mm_min_epi16(minabsdiff, absdiff); |
+ |
+ maxabsdiff = _mm_max_epi16(maxabsdiff, _mm_srli_si128(maxabsdiff, 8)); |
+ maxabsdiff = _mm_max_epi16(maxabsdiff, _mm_srli_epi64(maxabsdiff, 32)); |
+ maxabsdiff = _mm_max_epi16(maxabsdiff, _mm_srli_epi64(maxabsdiff, 16)); |
+ *max = _mm_extract_epi16(maxabsdiff, 0); |
+ |
+ minabsdiff = _mm_min_epi16(minabsdiff, _mm_srli_si128(minabsdiff, 8)); |
+ minabsdiff = _mm_min_epi16(minabsdiff, _mm_srli_epi64(minabsdiff, 32)); |
+ minabsdiff = _mm_min_epi16(minabsdiff, _mm_srli_epi64(minabsdiff, 16)); |
+ *min = _mm_extract_epi16(minabsdiff, 0); |
+} |
unsigned int vp9_avg_8x8_sse2(const uint8_t *s, int p) { |
__m128i s0, s1, u0; |
@@ -57,6 +134,179 @@ unsigned int vp9_avg_4x4_sse2(const uint8_t *s, int p) { |
return (avg + 8) >> 4; |
} |
+static void hadamard_col8_sse2(__m128i *in, int iter) { |
+ __m128i a0 = in[0]; |
+ __m128i a1 = in[1]; |
+ __m128i a2 = in[2]; |
+ __m128i a3 = in[3]; |
+ __m128i a4 = in[4]; |
+ __m128i a5 = in[5]; |
+ __m128i a6 = in[6]; |
+ __m128i a7 = in[7]; |
+ |
+ __m128i b0 = _mm_add_epi16(a0, a1); |
+ __m128i b1 = _mm_sub_epi16(a0, a1); |
+ __m128i b2 = _mm_add_epi16(a2, a3); |
+ __m128i b3 = _mm_sub_epi16(a2, a3); |
+ __m128i b4 = _mm_add_epi16(a4, a5); |
+ __m128i b5 = _mm_sub_epi16(a4, a5); |
+ __m128i b6 = _mm_add_epi16(a6, a7); |
+ __m128i b7 = _mm_sub_epi16(a6, a7); |
+ |
+ a0 = _mm_add_epi16(b0, b2); |
+ a1 = _mm_add_epi16(b1, b3); |
+ a2 = _mm_sub_epi16(b0, b2); |
+ a3 = _mm_sub_epi16(b1, b3); |
+ a4 = _mm_add_epi16(b4, b6); |
+ a5 = _mm_add_epi16(b5, b7); |
+ a6 = _mm_sub_epi16(b4, b6); |
+ a7 = _mm_sub_epi16(b5, b7); |
+ |
+ if (iter == 0) { |
+ b0 = _mm_add_epi16(a0, a4); |
+ b7 = _mm_add_epi16(a1, a5); |
+ b3 = _mm_add_epi16(a2, a6); |
+ b4 = _mm_add_epi16(a3, a7); |
+ b2 = _mm_sub_epi16(a0, a4); |
+ b6 = _mm_sub_epi16(a1, a5); |
+ b1 = _mm_sub_epi16(a2, a6); |
+ b5 = _mm_sub_epi16(a3, a7); |
+ |
+ a0 = _mm_unpacklo_epi16(b0, b1); |
+ a1 = _mm_unpacklo_epi16(b2, b3); |
+ a2 = _mm_unpackhi_epi16(b0, b1); |
+ a3 = _mm_unpackhi_epi16(b2, b3); |
+ a4 = _mm_unpacklo_epi16(b4, b5); |
+ a5 = _mm_unpacklo_epi16(b6, b7); |
+ a6 = _mm_unpackhi_epi16(b4, b5); |
+ a7 = _mm_unpackhi_epi16(b6, b7); |
+ |
+ b0 = _mm_unpacklo_epi32(a0, a1); |
+ b1 = _mm_unpacklo_epi32(a4, a5); |
+ b2 = _mm_unpackhi_epi32(a0, a1); |
+ b3 = _mm_unpackhi_epi32(a4, a5); |
+ b4 = _mm_unpacklo_epi32(a2, a3); |
+ b5 = _mm_unpacklo_epi32(a6, a7); |
+ b6 = _mm_unpackhi_epi32(a2, a3); |
+ b7 = _mm_unpackhi_epi32(a6, a7); |
+ |
+ in[0] = _mm_unpacklo_epi64(b0, b1); |
+ in[1] = _mm_unpackhi_epi64(b0, b1); |
+ in[2] = _mm_unpacklo_epi64(b2, b3); |
+ in[3] = _mm_unpackhi_epi64(b2, b3); |
+ in[4] = _mm_unpacklo_epi64(b4, b5); |
+ in[5] = _mm_unpackhi_epi64(b4, b5); |
+ in[6] = _mm_unpacklo_epi64(b6, b7); |
+ in[7] = _mm_unpackhi_epi64(b6, b7); |
+ } else { |
+ in[0] = _mm_add_epi16(a0, a4); |
+ in[7] = _mm_add_epi16(a1, a5); |
+ in[3] = _mm_add_epi16(a2, a6); |
+ in[4] = _mm_add_epi16(a3, a7); |
+ in[2] = _mm_sub_epi16(a0, a4); |
+ in[6] = _mm_sub_epi16(a1, a5); |
+ in[1] = _mm_sub_epi16(a2, a6); |
+ in[5] = _mm_sub_epi16(a3, a7); |
+ } |
+} |
+ |
+void vp9_hadamard_8x8_sse2(int16_t const *src_diff, int src_stride, |
+ int16_t *coeff) { |
+ __m128i src[8]; |
+ src[0] = _mm_load_si128((const __m128i *)src_diff); |
+ src[1] = _mm_load_si128((const __m128i *)(src_diff += src_stride)); |
+ src[2] = _mm_load_si128((const __m128i *)(src_diff += src_stride)); |
+ src[3] = _mm_load_si128((const __m128i *)(src_diff += src_stride)); |
+ src[4] = _mm_load_si128((const __m128i *)(src_diff += src_stride)); |
+ src[5] = _mm_load_si128((const __m128i *)(src_diff += src_stride)); |
+ src[6] = _mm_load_si128((const __m128i *)(src_diff += src_stride)); |
+ src[7] = _mm_load_si128((const __m128i *)(src_diff += src_stride)); |
+ |
+ hadamard_col8_sse2(src, 0); |
+ hadamard_col8_sse2(src, 1); |
+ |
+ _mm_store_si128((__m128i *)coeff, src[0]); |
+ coeff += 8; |
+ _mm_store_si128((__m128i *)coeff, src[1]); |
+ coeff += 8; |
+ _mm_store_si128((__m128i *)coeff, src[2]); |
+ coeff += 8; |
+ _mm_store_si128((__m128i *)coeff, src[3]); |
+ coeff += 8; |
+ _mm_store_si128((__m128i *)coeff, src[4]); |
+ coeff += 8; |
+ _mm_store_si128((__m128i *)coeff, src[5]); |
+ coeff += 8; |
+ _mm_store_si128((__m128i *)coeff, src[6]); |
+ coeff += 8; |
+ _mm_store_si128((__m128i *)coeff, src[7]); |
+} |
+ |
+void vp9_hadamard_16x16_sse2(int16_t const *src_diff, int src_stride, |
+ int16_t *coeff) { |
+ int idx; |
+ for (idx = 0; idx < 4; ++idx) { |
+ int16_t const *src_ptr = src_diff + (idx >> 1) * 8 * src_stride |
+ + (idx & 0x01) * 8; |
+ vp9_hadamard_8x8_sse2(src_ptr, src_stride, coeff + idx * 64); |
+ } |
+ |
+ for (idx = 0; idx < 64; idx += 8) { |
+ __m128i coeff0 = _mm_load_si128((const __m128i *)coeff); |
+ __m128i coeff1 = _mm_load_si128((const __m128i *)(coeff + 64)); |
+ __m128i coeff2 = _mm_load_si128((const __m128i *)(coeff + 128)); |
+ __m128i coeff3 = _mm_load_si128((const __m128i *)(coeff + 192)); |
+ |
+ __m128i b0 = _mm_add_epi16(coeff0, coeff1); |
+ __m128i b1 = _mm_sub_epi16(coeff0, coeff1); |
+ __m128i b2 = _mm_add_epi16(coeff2, coeff3); |
+ __m128i b3 = _mm_sub_epi16(coeff2, coeff3); |
+ |
+ coeff0 = _mm_add_epi16(b0, b2); |
+ coeff1 = _mm_add_epi16(b1, b3); |
+ coeff0 = _mm_srai_epi16(coeff0, 1); |
+ coeff1 = _mm_srai_epi16(coeff1, 1); |
+ _mm_store_si128((__m128i *)coeff, coeff0); |
+ _mm_store_si128((__m128i *)(coeff + 64), coeff1); |
+ |
+ coeff2 = _mm_sub_epi16(b0, b2); |
+ coeff3 = _mm_sub_epi16(b1, b3); |
+ coeff2 = _mm_srai_epi16(coeff2, 1); |
+ coeff3 = _mm_srai_epi16(coeff3, 1); |
+ _mm_store_si128((__m128i *)(coeff + 128), coeff2); |
+ _mm_store_si128((__m128i *)(coeff + 192), coeff3); |
+ |
+ coeff += 8; |
+ } |
+} |
+ |
+int16_t vp9_satd_sse2(const int16_t *coeff, int length) { |
+ int i; |
+ __m128i sum = _mm_load_si128((const __m128i *)coeff); |
+ __m128i sign = _mm_srai_epi16(sum, 15); |
+ __m128i val = _mm_xor_si128(sum, sign); |
+ sum = _mm_sub_epi16(val, sign); |
+ coeff += 8; |
+ |
+ for (i = 8; i < length; i += 8) { |
+ __m128i src_line = _mm_load_si128((const __m128i *)coeff); |
+ sign = _mm_srai_epi16(src_line, 15); |
+ val = _mm_xor_si128(src_line, sign); |
+ val = _mm_sub_epi16(val, sign); |
+ sum = _mm_add_epi16(sum, val); |
+ coeff += 8; |
+ } |
+ |
+ val = _mm_srli_si128(sum, 8); |
+ sum = _mm_add_epi16(sum, val); |
+ val = _mm_srli_epi64(sum, 32); |
+ sum = _mm_add_epi16(sum, val); |
+ val = _mm_srli_epi32(sum, 16); |
+ sum = _mm_add_epi16(sum, val); |
+ |
+ return _mm_extract_epi16(sum, 0); |
+} |
+ |
void vp9_int_pro_row_sse2(int16_t *hbuf, uint8_t const*ref, |
const int ref_stride, const int height) { |
int idx; |