cfl_sse2.c (3573B)
1 /* 2 * Copyright (c) 2017, Alliance for Open Media. All rights reserved. 3 * 4 * This source code is subject to the terms of the BSD 2 Clause License and 5 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License 6 * was not distributed with this source code in the LICENSE file, you can 7 * obtain it at www.aomedia.org/license/software. If the Alliance for Open 8 * Media Patent License 1.0 was not distributed with this source code in the 9 * PATENTS file, you can obtain it at www.aomedia.org/license/patent. 10 */ 11 12 #include <emmintrin.h> 13 14 #include "av1/common/cfl.h" 15 #include "config/av1_rtcd.h" 16 17 static inline __m128i fill_sum_epi32(__m128i l0) { 18 l0 = _mm_add_epi32(l0, _mm_shuffle_epi32(l0, _MM_SHUFFLE(1, 0, 3, 2))); 19 return _mm_add_epi32(l0, _mm_shuffle_epi32(l0, _MM_SHUFFLE(2, 3, 0, 1))); 20 } 21 22 static inline void subtract_average_sse2(const uint16_t *src_ptr, 23 int16_t *dst_ptr, int width, 24 int height, int round_offset, 25 int num_pel_log2) { 26 const __m128i zeros = _mm_setzero_si128(); 27 const __m128i round_offset_epi32 = _mm_set1_epi32(round_offset); 28 const __m128i *src = (__m128i *)src_ptr; 29 const __m128i *const end = src + height * CFL_BUF_LINE_I128; 30 const int step = CFL_BUF_LINE_I128 * (1 + (width == 8) + 3 * (width == 4)); 31 32 __m128i sum = zeros; 33 do { 34 __m128i l0; 35 if (width == 4) { 36 l0 = _mm_add_epi16(_mm_loadl_epi64(src), 37 _mm_loadl_epi64(src + CFL_BUF_LINE_I128)); 38 __m128i l1 = _mm_add_epi16(_mm_loadl_epi64(src + 2 * CFL_BUF_LINE_I128), 39 _mm_loadl_epi64(src + 3 * CFL_BUF_LINE_I128)); 40 sum = _mm_add_epi32(sum, _mm_add_epi32(_mm_unpacklo_epi16(l0, zeros), 41 _mm_unpacklo_epi16(l1, zeros))); 42 } else { 43 if (width == 8) { 44 l0 = _mm_add_epi16(_mm_loadu_si128(src), 45 _mm_loadu_si128(src + CFL_BUF_LINE_I128)); 46 } else { 47 l0 = _mm_add_epi16(_mm_loadu_si128(src), _mm_loadu_si128(src + 1)); 48 } 49 sum = _mm_add_epi32(sum, _mm_add_epi32(_mm_unpacklo_epi16(l0, zeros), 50 _mm_unpackhi_epi16(l0, zeros))); 51 if (width == 32) { 52 l0 = _mm_add_epi16(_mm_loadu_si128(src + 2), _mm_loadu_si128(src + 3)); 53 sum = _mm_add_epi32(sum, _mm_add_epi32(_mm_unpacklo_epi16(l0, zeros), 54 _mm_unpackhi_epi16(l0, zeros))); 55 } 56 } 57 src += step; 58 } while (src < end); 59 60 sum = fill_sum_epi32(sum); 61 62 __m128i avg_epi16 = 63 _mm_srli_epi32(_mm_add_epi32(sum, round_offset_epi32), num_pel_log2); 64 avg_epi16 = _mm_packs_epi32(avg_epi16, avg_epi16); 65 66 src = (__m128i *)src_ptr; 67 __m128i *dst = (__m128i *)dst_ptr; 68 do { 69 if (width == 4) { 70 _mm_storel_epi64(dst, _mm_sub_epi16(_mm_loadl_epi64(src), avg_epi16)); 71 } else { 72 _mm_storeu_si128(dst, _mm_sub_epi16(_mm_loadu_si128(src), avg_epi16)); 73 if (width > 8) { 74 _mm_storeu_si128(dst + 1, 75 _mm_sub_epi16(_mm_loadu_si128(src + 1), avg_epi16)); 76 if (width == 32) { 77 _mm_storeu_si128(dst + 2, 78 _mm_sub_epi16(_mm_loadu_si128(src + 2), avg_epi16)); 79 _mm_storeu_si128(dst + 3, 80 _mm_sub_epi16(_mm_loadu_si128(src + 3), avg_epi16)); 81 } 82 } 83 } 84 src += CFL_BUF_LINE_I128; 85 dst += CFL_BUF_LINE_I128; 86 } while (src < end); 87 } 88 89 CFL_SUB_AVG_FN(sse2)