LCOV - code coverage report
Current view: top level - third_party/aom/aom_dsp/x86 - highbd_convolve_avx2.c (source / functions) Hit Total Coverage
Test: output.info Lines: 0 663 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 63 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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             : #include <immintrin.h>
      12             : #include <string.h>
      13             : 
      14             : #include "./aom_dsp_rtcd.h"
      15             : #include "aom_dsp/x86/convolve.h"
      16             : 
      17             : // -----------------------------------------------------------------------------
      18             : // Copy and average
      19             : 
      20           0 : void aom_highbd_convolve_copy_avx2(const uint8_t *src8, ptrdiff_t src_stride,
      21             :                                    uint8_t *dst8, ptrdiff_t dst_stride,
      22             :                                    const int16_t *filter_x, int filter_x_stride,
      23             :                                    const int16_t *filter_y, int filter_y_stride,
      24             :                                    int width, int h, int bd) {
      25           0 :   const uint16_t *src = CONVERT_TO_SHORTPTR(src8);
      26           0 :   uint16_t *dst = CONVERT_TO_SHORTPTR(dst8);
      27             :   (void)filter_x;
      28             :   (void)filter_y;
      29             :   (void)filter_x_stride;
      30             :   (void)filter_y_stride;
      31             :   (void)bd;
      32             : 
      33           0 :   assert(width % 4 == 0);
      34           0 :   if (width > 32) {  // width = 64
      35             :     do {
      36           0 :       const __m256i p0 = _mm256_loadu_si256((const __m256i *)src);
      37           0 :       const __m256i p1 = _mm256_loadu_si256((const __m256i *)(src + 16));
      38           0 :       const __m256i p2 = _mm256_loadu_si256((const __m256i *)(src + 32));
      39           0 :       const __m256i p3 = _mm256_loadu_si256((const __m256i *)(src + 48));
      40           0 :       src += src_stride;
      41             :       _mm256_storeu_si256((__m256i *)dst, p0);
      42           0 :       _mm256_storeu_si256((__m256i *)(dst + 16), p1);
      43           0 :       _mm256_storeu_si256((__m256i *)(dst + 32), p2);
      44           0 :       _mm256_storeu_si256((__m256i *)(dst + 48), p3);
      45           0 :       dst += dst_stride;
      46           0 :       h--;
      47           0 :     } while (h > 0);
      48           0 :   } else if (width > 16) {  // width = 32
      49             :     do {
      50           0 :       const __m256i p0 = _mm256_loadu_si256((const __m256i *)src);
      51           0 :       const __m256i p1 = _mm256_loadu_si256((const __m256i *)(src + 16));
      52           0 :       src += src_stride;
      53             :       _mm256_storeu_si256((__m256i *)dst, p0);
      54           0 :       _mm256_storeu_si256((__m256i *)(dst + 16), p1);
      55           0 :       dst += dst_stride;
      56           0 :       h--;
      57           0 :     } while (h > 0);
      58           0 :   } else if (width > 8) {  // width = 16
      59             :     __m256i p0, p1;
      60             :     do {
      61           0 :       p0 = _mm256_loadu_si256((const __m256i *)src);
      62           0 :       src += src_stride;
      63           0 :       p1 = _mm256_loadu_si256((const __m256i *)src);
      64           0 :       src += src_stride;
      65             : 
      66             :       _mm256_storeu_si256((__m256i *)dst, p0);
      67           0 :       dst += dst_stride;
      68             :       _mm256_storeu_si256((__m256i *)dst, p1);
      69           0 :       dst += dst_stride;
      70           0 :       h -= 2;
      71           0 :     } while (h > 0);
      72           0 :   } else if (width > 4) {  // width = 8
      73             :     __m128i p0, p1;
      74             :     do {
      75           0 :       p0 = _mm_loadu_si128((const __m128i *)src);
      76           0 :       src += src_stride;
      77           0 :       p1 = _mm_loadu_si128((const __m128i *)src);
      78           0 :       src += src_stride;
      79             : 
      80             :       _mm_storeu_si128((__m128i *)dst, p0);
      81           0 :       dst += dst_stride;
      82             :       _mm_storeu_si128((__m128i *)dst, p1);
      83           0 :       dst += dst_stride;
      84           0 :       h -= 2;
      85           0 :     } while (h > 0);
      86             :   } else {  // width = 4
      87             :     __m128i p0, p1;
      88             :     do {
      89           0 :       p0 = _mm_loadl_epi64((const __m128i *)src);
      90           0 :       src += src_stride;
      91           0 :       p1 = _mm_loadl_epi64((const __m128i *)src);
      92           0 :       src += src_stride;
      93             : 
      94             :       _mm_storel_epi64((__m128i *)dst, p0);
      95           0 :       dst += dst_stride;
      96             :       _mm_storel_epi64((__m128i *)dst, p1);
      97           0 :       dst += dst_stride;
      98           0 :       h -= 2;
      99           0 :     } while (h > 0);
     100             :   }
     101           0 : }
     102             : 
     103           0 : void aom_highbd_convolve_avg_avx2(const uint8_t *src8, ptrdiff_t src_stride,
     104             :                                   uint8_t *dst8, ptrdiff_t dst_stride,
     105             :                                   const int16_t *filter_x, int filter_x_stride,
     106             :                                   const int16_t *filter_y, int filter_y_stride,
     107             :                                   int width, int h, int bd) {
     108           0 :   uint16_t *src = CONVERT_TO_SHORTPTR(src8);
     109           0 :   uint16_t *dst = CONVERT_TO_SHORTPTR(dst8);
     110             :   (void)filter_x;
     111             :   (void)filter_y;
     112             :   (void)filter_x_stride;
     113             :   (void)filter_y_stride;
     114             :   (void)bd;
     115             : 
     116           0 :   assert(width % 4 == 0);
     117           0 :   if (width > 32) {  // width = 64
     118             :     __m256i p0, p1, p2, p3, u0, u1, u2, u3;
     119             :     do {
     120           0 :       p0 = _mm256_loadu_si256((const __m256i *)src);
     121           0 :       p1 = _mm256_loadu_si256((const __m256i *)(src + 16));
     122           0 :       p2 = _mm256_loadu_si256((const __m256i *)(src + 32));
     123           0 :       p3 = _mm256_loadu_si256((const __m256i *)(src + 48));
     124           0 :       src += src_stride;
     125           0 :       u0 = _mm256_loadu_si256((const __m256i *)dst);
     126           0 :       u1 = _mm256_loadu_si256((const __m256i *)(dst + 16));
     127           0 :       u2 = _mm256_loadu_si256((const __m256i *)(dst + 32));
     128           0 :       u3 = _mm256_loadu_si256((const __m256i *)(dst + 48));
     129           0 :       _mm256_storeu_si256((__m256i *)dst, _mm256_avg_epu16(p0, u0));
     130           0 :       _mm256_storeu_si256((__m256i *)(dst + 16), _mm256_avg_epu16(p1, u1));
     131           0 :       _mm256_storeu_si256((__m256i *)(dst + 32), _mm256_avg_epu16(p2, u2));
     132           0 :       _mm256_storeu_si256((__m256i *)(dst + 48), _mm256_avg_epu16(p3, u3));
     133           0 :       dst += dst_stride;
     134           0 :       h--;
     135           0 :     } while (h > 0);
     136           0 :   } else if (width > 16) {  // width = 32
     137             :     __m256i p0, p1, u0, u1;
     138             :     do {
     139           0 :       p0 = _mm256_loadu_si256((const __m256i *)src);
     140           0 :       p1 = _mm256_loadu_si256((const __m256i *)(src + 16));
     141           0 :       src += src_stride;
     142           0 :       u0 = _mm256_loadu_si256((const __m256i *)dst);
     143           0 :       u1 = _mm256_loadu_si256((const __m256i *)(dst + 16));
     144           0 :       _mm256_storeu_si256((__m256i *)dst, _mm256_avg_epu16(p0, u0));
     145           0 :       _mm256_storeu_si256((__m256i *)(dst + 16), _mm256_avg_epu16(p1, u1));
     146           0 :       dst += dst_stride;
     147           0 :       h--;
     148           0 :     } while (h > 0);
     149           0 :   } else if (width > 8) {  // width = 16
     150             :     __m256i p0, p1, u0, u1;
     151             :     do {
     152           0 :       p0 = _mm256_loadu_si256((const __m256i *)src);
     153           0 :       p1 = _mm256_loadu_si256((const __m256i *)(src + src_stride));
     154           0 :       src += src_stride << 1;
     155           0 :       u0 = _mm256_loadu_si256((const __m256i *)dst);
     156           0 :       u1 = _mm256_loadu_si256((const __m256i *)(dst + dst_stride));
     157             : 
     158           0 :       _mm256_storeu_si256((__m256i *)dst, _mm256_avg_epu16(p0, u0));
     159           0 :       _mm256_storeu_si256((__m256i *)(dst + dst_stride),
     160             :                           _mm256_avg_epu16(p1, u1));
     161           0 :       dst += dst_stride << 1;
     162           0 :       h -= 2;
     163           0 :     } while (h > 0);
     164           0 :   } else if (width > 4) {  // width = 8
     165             :     __m128i p0, p1, u0, u1;
     166             :     do {
     167           0 :       p0 = _mm_loadu_si128((const __m128i *)src);
     168           0 :       p1 = _mm_loadu_si128((const __m128i *)(src + src_stride));
     169           0 :       src += src_stride << 1;
     170           0 :       u0 = _mm_loadu_si128((const __m128i *)dst);
     171           0 :       u1 = _mm_loadu_si128((const __m128i *)(dst + dst_stride));
     172             : 
     173           0 :       _mm_storeu_si128((__m128i *)dst, _mm_avg_epu16(p0, u0));
     174           0 :       _mm_storeu_si128((__m128i *)(dst + dst_stride), _mm_avg_epu16(p1, u1));
     175           0 :       dst += dst_stride << 1;
     176           0 :       h -= 2;
     177           0 :     } while (h > 0);
     178             :   } else {  // width = 4
     179             :     __m128i p0, p1, u0, u1;
     180             :     do {
     181           0 :       p0 = _mm_loadl_epi64((const __m128i *)src);
     182           0 :       p1 = _mm_loadl_epi64((const __m128i *)(src + src_stride));
     183           0 :       src += src_stride << 1;
     184           0 :       u0 = _mm_loadl_epi64((const __m128i *)dst);
     185           0 :       u1 = _mm_loadl_epi64((const __m128i *)(dst + dst_stride));
     186             : 
     187           0 :       _mm_storel_epi64((__m128i *)dst, _mm_avg_epu16(u0, p0));
     188           0 :       _mm_storel_epi64((__m128i *)(dst + dst_stride), _mm_avg_epu16(u1, p1));
     189           0 :       dst += dst_stride << 1;
     190           0 :       h -= 2;
     191           0 :     } while (h > 0);
     192             :   }
     193           0 : }
     194             : 
     195             : // -----------------------------------------------------------------------------
     196             : // Horizontal and vertical filtering
     197             : 
     198             : #define CONV8_ROUNDING_BITS (7)
     199             : 
     200             : static const uint8_t signal_pattern_0[32] = { 0, 1, 2, 3, 2, 3, 4, 5, 4, 5, 6,
     201             :                                               7, 6, 7, 8, 9, 0, 1, 2, 3, 2, 3,
     202             :                                               4, 5, 4, 5, 6, 7, 6, 7, 8, 9 };
     203             : 
     204             : static const uint8_t signal_pattern_1[32] = { 4, 5, 6,  7,  6,  7,  8,  9,
     205             :                                               8, 9, 10, 11, 10, 11, 12, 13,
     206             :                                               4, 5, 6,  7,  6,  7,  8,  9,
     207             :                                               8, 9, 10, 11, 10, 11, 12, 13 };
     208             : 
     209             : static const uint8_t signal_pattern_2[32] = { 6,  7,  8,  9,  8,  9,  10, 11,
     210             :                                               10, 11, 12, 13, 12, 13, 14, 15,
     211             :                                               6,  7,  8,  9,  8,  9,  10, 11,
     212             :                                               10, 11, 12, 13, 12, 13, 14, 15 };
     213             : 
     214             : static const uint32_t signal_index[8] = { 2, 3, 4, 5, 2, 3, 4, 5 };
     215             : 
     216             : // -----------------------------------------------------------------------------
     217             : // Horizontal Filtering
     218             : 
     219           0 : static INLINE void pack_pixels(const __m256i *s, __m256i *p /*p[4]*/) {
     220           0 :   const __m256i idx = _mm256_loadu_si256((const __m256i *)signal_index);
     221           0 :   const __m256i sf0 = _mm256_loadu_si256((const __m256i *)signal_pattern_0);
     222           0 :   const __m256i sf1 = _mm256_loadu_si256((const __m256i *)signal_pattern_1);
     223           0 :   const __m256i c = _mm256_permutevar8x32_epi32(*s, idx);
     224             : 
     225           0 :   p[0] = _mm256_shuffle_epi8(*s, sf0);  // x0x6
     226           0 :   p[1] = _mm256_shuffle_epi8(*s, sf1);  // x1x7
     227           0 :   p[2] = _mm256_shuffle_epi8(c, sf0);   // x2x4
     228           0 :   p[3] = _mm256_shuffle_epi8(c, sf1);   // x3x5
     229           0 : }
     230             : 
     231             : // Note:
     232             : //  Shared by 8x2 and 16x1 block
     233           0 : static INLINE void pack_16_pixels(const __m256i *s0, const __m256i *s1,
     234             :                                   __m256i *x /*x[8]*/) {
     235             :   __m256i pp[8];
     236           0 :   pack_pixels(s0, pp);
     237           0 :   pack_pixels(s1, &pp[4]);
     238           0 :   x[0] = _mm256_permute2x128_si256(pp[0], pp[4], 0x20);
     239           0 :   x[1] = _mm256_permute2x128_si256(pp[1], pp[5], 0x20);
     240           0 :   x[2] = _mm256_permute2x128_si256(pp[2], pp[6], 0x20);
     241           0 :   x[3] = _mm256_permute2x128_si256(pp[3], pp[7], 0x20);
     242           0 :   x[4] = x[2];
     243           0 :   x[5] = x[3];
     244           0 :   x[6] = _mm256_permute2x128_si256(pp[0], pp[4], 0x31);
     245           0 :   x[7] = _mm256_permute2x128_si256(pp[1], pp[5], 0x31);
     246           0 : }
     247             : 
     248           0 : static INLINE void pack_8x1_pixels(const uint16_t *src, __m256i *x) {
     249             :   __m256i pp[8];
     250             :   __m256i s0;
     251           0 :   s0 = _mm256_loadu_si256((const __m256i *)src);
     252           0 :   pack_pixels(&s0, pp);
     253           0 :   x[0] = _mm256_permute2x128_si256(pp[0], pp[2], 0x30);
     254           0 :   x[1] = _mm256_permute2x128_si256(pp[1], pp[3], 0x30);
     255           0 :   x[2] = _mm256_permute2x128_si256(pp[2], pp[0], 0x30);
     256           0 :   x[3] = _mm256_permute2x128_si256(pp[3], pp[1], 0x30);
     257           0 : }
     258             : 
     259           0 : static INLINE void pack_8x2_pixels(const uint16_t *src, ptrdiff_t stride,
     260             :                                    __m256i *x) {
     261             :   __m256i s0, s1;
     262           0 :   s0 = _mm256_loadu_si256((const __m256i *)src);
     263           0 :   s1 = _mm256_loadu_si256((const __m256i *)(src + stride));
     264           0 :   pack_16_pixels(&s0, &s1, x);
     265           0 : }
     266             : 
     267           0 : static INLINE void pack_16x1_pixels(const uint16_t *src, __m256i *x) {
     268             :   __m256i s0, s1;
     269           0 :   s0 = _mm256_loadu_si256((const __m256i *)src);
     270           0 :   s1 = _mm256_loadu_si256((const __m256i *)(src + 8));
     271           0 :   pack_16_pixels(&s0, &s1, x);
     272           0 : }
     273             : 
     274             : // Note:
     275             : //  Shared by horizontal and vertical filtering
     276           0 : static INLINE void pack_filters(const int16_t *filter, __m256i *f /*f[4]*/) {
     277           0 :   const __m128i h = _mm_loadu_si128((const __m128i *)filter);
     278           0 :   const __m256i hh = _mm256_insertf128_si256(_mm256_castsi128_si256(h), h, 1);
     279           0 :   const __m256i p0 = _mm256_set1_epi32(0x03020100);
     280           0 :   const __m256i p1 = _mm256_set1_epi32(0x07060504);
     281           0 :   const __m256i p2 = _mm256_set1_epi32(0x0b0a0908);
     282           0 :   const __m256i p3 = _mm256_set1_epi32(0x0f0e0d0c);
     283           0 :   f[0] = _mm256_shuffle_epi8(hh, p0);
     284           0 :   f[1] = _mm256_shuffle_epi8(hh, p1);
     285           0 :   f[2] = _mm256_shuffle_epi8(hh, p2);
     286           0 :   f[3] = _mm256_shuffle_epi8(hh, p3);
     287           0 : }
     288             : 
     289           0 : static INLINE void filter_8x1_pixels(const __m256i *sig /*sig[4]*/,
     290             :                                      const __m256i *fil /*fil[4]*/,
     291             :                                      __m256i *y) {
     292             :   __m256i a, a0, a1;
     293             : 
     294           0 :   a0 = _mm256_madd_epi16(fil[0], sig[0]);
     295           0 :   a1 = _mm256_madd_epi16(fil[3], sig[3]);
     296           0 :   a = _mm256_add_epi32(a0, a1);
     297             : 
     298           0 :   a0 = _mm256_madd_epi16(fil[1], sig[1]);
     299           0 :   a1 = _mm256_madd_epi16(fil[2], sig[2]);
     300             : 
     301             :   {
     302           0 :     const __m256i min = _mm256_min_epi32(a0, a1);
     303           0 :     a = _mm256_add_epi32(a, min);
     304             :   }
     305             :   {
     306           0 :     const __m256i max = _mm256_max_epi32(a0, a1);
     307           0 :     a = _mm256_add_epi32(a, max);
     308             :   }
     309             :   {
     310           0 :     const __m256i rounding = _mm256_set1_epi32(1 << (CONV8_ROUNDING_BITS - 1));
     311           0 :     a = _mm256_add_epi32(a, rounding);
     312           0 :     *y = _mm256_srai_epi32(a, CONV8_ROUNDING_BITS);
     313             :   }
     314           0 : }
     315             : 
     316           0 : static INLINE void store_8x1_pixels(const __m256i *y, const __m256i *mask,
     317             :                                     uint16_t *dst) {
     318           0 :   const __m128i a0 = _mm256_castsi256_si128(*y);
     319           0 :   const __m128i a1 = _mm256_extractf128_si256(*y, 1);
     320           0 :   __m128i res = _mm_packus_epi32(a0, a1);
     321           0 :   res = _mm_min_epi16(res, _mm256_castsi256_si128(*mask));
     322             :   _mm_storeu_si128((__m128i *)dst, res);
     323           0 : }
     324             : 
     325           0 : static INLINE void store_8x2_pixels(const __m256i *y0, const __m256i *y1,
     326             :                                     const __m256i *mask, uint16_t *dst,
     327             :                                     ptrdiff_t pitch) {
     328           0 :   __m256i a = _mm256_packus_epi32(*y0, *y1);
     329           0 :   a = _mm256_min_epi16(a, *mask);
     330           0 :   _mm_storeu_si128((__m128i *)dst, _mm256_castsi256_si128(a));
     331           0 :   _mm_storeu_si128((__m128i *)(dst + pitch), _mm256_extractf128_si256(a, 1));
     332           0 : }
     333             : 
     334           0 : static INLINE void store_16x1_pixels(const __m256i *y0, const __m256i *y1,
     335             :                                      const __m256i *mask, uint16_t *dst) {
     336           0 :   __m256i a = _mm256_packus_epi32(*y0, *y1);
     337           0 :   a = _mm256_min_epi16(a, *mask);
     338             :   _mm256_storeu_si256((__m256i *)dst, a);
     339           0 : }
     340             : 
     341           0 : static void aom_highbd_filter_block1d8_h8_avx2(
     342             :     const uint16_t *src_ptr, ptrdiff_t src_pitch, uint16_t *dst_ptr,
     343             :     ptrdiff_t dst_pitch, uint32_t height, const int16_t *filter, int bd) {
     344             :   __m256i signal[8], res0, res1;
     345           0 :   const __m256i max = _mm256_set1_epi16((1 << bd) - 1);
     346             : 
     347             :   __m256i ff[4];
     348           0 :   pack_filters(filter, ff);
     349             : 
     350           0 :   src_ptr -= 3;
     351             :   do {
     352           0 :     pack_8x2_pixels(src_ptr, src_pitch, signal);
     353           0 :     filter_8x1_pixels(signal, ff, &res0);
     354           0 :     filter_8x1_pixels(&signal[4], ff, &res1);
     355           0 :     store_8x2_pixels(&res0, &res1, &max, dst_ptr, dst_pitch);
     356           0 :     height -= 2;
     357           0 :     src_ptr += src_pitch << 1;
     358           0 :     dst_ptr += dst_pitch << 1;
     359           0 :   } while (height > 1);
     360             : 
     361           0 :   if (height > 0) {
     362           0 :     pack_8x1_pixels(src_ptr, signal);
     363           0 :     filter_8x1_pixels(signal, ff, &res0);
     364           0 :     store_8x1_pixels(&res0, &max, dst_ptr);
     365             :   }
     366           0 : }
     367             : 
     368           0 : static void aom_highbd_filter_block1d16_h8_avx2(
     369             :     const uint16_t *src_ptr, ptrdiff_t src_pitch, uint16_t *dst_ptr,
     370             :     ptrdiff_t dst_pitch, uint32_t height, const int16_t *filter, int bd) {
     371             :   __m256i signal[8], res0, res1;
     372           0 :   const __m256i max = _mm256_set1_epi16((1 << bd) - 1);
     373             : 
     374             :   __m256i ff[4];
     375           0 :   pack_filters(filter, ff);
     376             : 
     377           0 :   src_ptr -= 3;
     378             :   do {
     379           0 :     pack_16x1_pixels(src_ptr, signal);
     380           0 :     filter_8x1_pixels(signal, ff, &res0);
     381           0 :     filter_8x1_pixels(&signal[4], ff, &res1);
     382           0 :     store_16x1_pixels(&res0, &res1, &max, dst_ptr);
     383           0 :     height -= 1;
     384           0 :     src_ptr += src_pitch;
     385           0 :     dst_ptr += dst_pitch;
     386           0 :   } while (height > 0);
     387           0 : }
     388             : 
     389             : // -----------------------------------------------------------------------------
     390             : // 2-tap horizontal filtering
     391             : 
     392           0 : static INLINE void pack_2t_filter(const int16_t *filter, __m256i *f) {
     393           0 :   const __m128i h = _mm_loadu_si128((const __m128i *)filter);
     394           0 :   const __m256i hh = _mm256_insertf128_si256(_mm256_castsi128_si256(h), h, 1);
     395           0 :   const __m256i p = _mm256_set1_epi32(0x09080706);
     396           0 :   f[0] = _mm256_shuffle_epi8(hh, p);
     397           0 : }
     398             : 
     399             : // can be used by pack_8x2_2t_pixels() and pack_16x1_2t_pixels()
     400             : // the difference is s0/s1 specifies first and second rows or,
     401             : // first 16 samples and 8-sample shifted 16 samples
     402           0 : static INLINE void pack_16_2t_pixels(const __m256i *s0, const __m256i *s1,
     403             :                                      __m256i *sig) {
     404           0 :   const __m256i idx = _mm256_loadu_si256((const __m256i *)signal_index);
     405           0 :   const __m256i sf2 = _mm256_loadu_si256((const __m256i *)signal_pattern_2);
     406           0 :   __m256i x0 = _mm256_shuffle_epi8(*s0, sf2);
     407           0 :   __m256i x1 = _mm256_shuffle_epi8(*s1, sf2);
     408           0 :   __m256i r0 = _mm256_permutevar8x32_epi32(*s0, idx);
     409           0 :   __m256i r1 = _mm256_permutevar8x32_epi32(*s1, idx);
     410           0 :   r0 = _mm256_shuffle_epi8(r0, sf2);
     411           0 :   r1 = _mm256_shuffle_epi8(r1, sf2);
     412           0 :   sig[0] = _mm256_permute2x128_si256(x0, x1, 0x20);
     413           0 :   sig[1] = _mm256_permute2x128_si256(r0, r1, 0x20);
     414           0 : }
     415             : 
     416           0 : static INLINE void pack_8x2_2t_pixels(const uint16_t *src,
     417             :                                       const ptrdiff_t pitch, __m256i *sig) {
     418           0 :   const __m256i r0 = _mm256_loadu_si256((const __m256i *)src);
     419           0 :   const __m256i r1 = _mm256_loadu_si256((const __m256i *)(src + pitch));
     420           0 :   pack_16_2t_pixels(&r0, &r1, sig);
     421           0 : }
     422             : 
     423           0 : static INLINE void pack_16x1_2t_pixels(const uint16_t *src,
     424             :                                        __m256i *sig /*sig[2]*/) {
     425           0 :   const __m256i r0 = _mm256_loadu_si256((const __m256i *)src);
     426           0 :   const __m256i r1 = _mm256_loadu_si256((const __m256i *)(src + 8));
     427           0 :   pack_16_2t_pixels(&r0, &r1, sig);
     428           0 : }
     429             : 
     430           0 : static INLINE void pack_8x1_2t_pixels(const uint16_t *src,
     431             :                                       __m256i *sig /*sig[2]*/) {
     432           0 :   const __m256i idx = _mm256_loadu_si256((const __m256i *)signal_index);
     433           0 :   const __m256i sf2 = _mm256_loadu_si256((const __m256i *)signal_pattern_2);
     434           0 :   __m256i r0 = _mm256_loadu_si256((const __m256i *)src);
     435           0 :   __m256i x0 = _mm256_shuffle_epi8(r0, sf2);
     436           0 :   r0 = _mm256_permutevar8x32_epi32(r0, idx);
     437           0 :   r0 = _mm256_shuffle_epi8(r0, sf2);
     438           0 :   sig[0] = _mm256_permute2x128_si256(x0, r0, 0x20);
     439           0 : }
     440             : 
     441             : // can be used by filter_8x2_2t_pixels() and filter_16x1_2t_pixels()
     442           0 : static INLINE void filter_16_2t_pixels(const __m256i *sig, const __m256i *f,
     443             :                                        __m256i *y0, __m256i *y1) {
     444           0 :   const __m256i rounding = _mm256_set1_epi32(1 << (CONV8_ROUNDING_BITS - 1));
     445           0 :   __m256i x0 = _mm256_madd_epi16(sig[0], *f);
     446           0 :   __m256i x1 = _mm256_madd_epi16(sig[1], *f);
     447           0 :   x0 = _mm256_add_epi32(x0, rounding);
     448           0 :   x1 = _mm256_add_epi32(x1, rounding);
     449           0 :   *y0 = _mm256_srai_epi32(x0, CONV8_ROUNDING_BITS);
     450           0 :   *y1 = _mm256_srai_epi32(x1, CONV8_ROUNDING_BITS);
     451           0 : }
     452             : 
     453           0 : static INLINE void filter_8x1_2t_pixels(const __m256i *sig, const __m256i *f,
     454             :                                         __m256i *y0) {
     455           0 :   const __m256i rounding = _mm256_set1_epi32(1 << (CONV8_ROUNDING_BITS - 1));
     456           0 :   __m256i x0 = _mm256_madd_epi16(sig[0], *f);
     457           0 :   x0 = _mm256_add_epi32(x0, rounding);
     458           0 :   *y0 = _mm256_srai_epi32(x0, CONV8_ROUNDING_BITS);
     459           0 : }
     460             : 
     461           0 : static void aom_highbd_filter_block1d8_h2_avx2(
     462             :     const uint16_t *src_ptr, ptrdiff_t src_pitch, uint16_t *dst_ptr,
     463             :     ptrdiff_t dst_pitch, uint32_t height, const int16_t *filter, int bd) {
     464             :   __m256i signal[2], res0, res1;
     465           0 :   const __m256i max = _mm256_set1_epi16((1 << bd) - 1);
     466             : 
     467             :   __m256i ff;
     468           0 :   pack_2t_filter(filter, &ff);
     469             : 
     470           0 :   src_ptr -= 3;
     471             :   do {
     472           0 :     pack_8x2_2t_pixels(src_ptr, src_pitch, signal);
     473           0 :     filter_16_2t_pixels(signal, &ff, &res0, &res1);
     474           0 :     store_8x2_pixels(&res0, &res1, &max, dst_ptr, dst_pitch);
     475           0 :     height -= 2;
     476           0 :     src_ptr += src_pitch << 1;
     477           0 :     dst_ptr += dst_pitch << 1;
     478           0 :   } while (height > 1);
     479             : 
     480           0 :   if (height > 0) {
     481           0 :     pack_8x1_2t_pixels(src_ptr, signal);
     482           0 :     filter_8x1_2t_pixels(signal, &ff, &res0);
     483           0 :     store_8x1_pixels(&res0, &max, dst_ptr);
     484             :   }
     485           0 : }
     486             : 
     487           0 : static void aom_highbd_filter_block1d16_h2_avx2(
     488             :     const uint16_t *src_ptr, ptrdiff_t src_pitch, uint16_t *dst_ptr,
     489             :     ptrdiff_t dst_pitch, uint32_t height, const int16_t *filter, int bd) {
     490             :   __m256i signal[2], res0, res1;
     491           0 :   const __m256i max = _mm256_set1_epi16((1 << bd) - 1);
     492             : 
     493             :   __m256i ff;
     494           0 :   pack_2t_filter(filter, &ff);
     495             : 
     496           0 :   src_ptr -= 3;
     497             :   do {
     498           0 :     pack_16x1_2t_pixels(src_ptr, signal);
     499           0 :     filter_16_2t_pixels(signal, &ff, &res0, &res1);
     500           0 :     store_16x1_pixels(&res0, &res1, &max, dst_ptr);
     501           0 :     height -= 1;
     502           0 :     src_ptr += src_pitch;
     503           0 :     dst_ptr += dst_pitch;
     504           0 :   } while (height > 0);
     505           0 : }
     506             : 
     507             : // -----------------------------------------------------------------------------
     508             : // Vertical Filtering
     509             : 
     510           0 : static void pack_8x9_init(const uint16_t *src, ptrdiff_t pitch, __m256i *sig) {
     511           0 :   __m256i s0 = _mm256_castsi128_si256(_mm_loadu_si128((const __m128i *)src));
     512           0 :   __m256i s1 =
     513           0 :       _mm256_castsi128_si256(_mm_loadu_si128((const __m128i *)(src + pitch)));
     514           0 :   __m256i s2 = _mm256_castsi128_si256(
     515           0 :       _mm_loadu_si128((const __m128i *)(src + 2 * pitch)));
     516           0 :   __m256i s3 = _mm256_castsi128_si256(
     517           0 :       _mm_loadu_si128((const __m128i *)(src + 3 * pitch)));
     518           0 :   __m256i s4 = _mm256_castsi128_si256(
     519           0 :       _mm_loadu_si128((const __m128i *)(src + 4 * pitch)));
     520           0 :   __m256i s5 = _mm256_castsi128_si256(
     521           0 :       _mm_loadu_si128((const __m128i *)(src + 5 * pitch)));
     522           0 :   __m256i s6 = _mm256_castsi128_si256(
     523           0 :       _mm_loadu_si128((const __m128i *)(src + 6 * pitch)));
     524             : 
     525           0 :   s0 = _mm256_inserti128_si256(s0, _mm256_castsi256_si128(s1), 1);
     526           0 :   s1 = _mm256_inserti128_si256(s1, _mm256_castsi256_si128(s2), 1);
     527           0 :   s2 = _mm256_inserti128_si256(s2, _mm256_castsi256_si128(s3), 1);
     528           0 :   s3 = _mm256_inserti128_si256(s3, _mm256_castsi256_si128(s4), 1);
     529           0 :   s4 = _mm256_inserti128_si256(s4, _mm256_castsi256_si128(s5), 1);
     530           0 :   s5 = _mm256_inserti128_si256(s5, _mm256_castsi256_si128(s6), 1);
     531             : 
     532           0 :   sig[0] = _mm256_unpacklo_epi16(s0, s1);
     533           0 :   sig[4] = _mm256_unpackhi_epi16(s0, s1);
     534           0 :   sig[1] = _mm256_unpacklo_epi16(s2, s3);
     535           0 :   sig[5] = _mm256_unpackhi_epi16(s2, s3);
     536           0 :   sig[2] = _mm256_unpacklo_epi16(s4, s5);
     537           0 :   sig[6] = _mm256_unpackhi_epi16(s4, s5);
     538           0 :   sig[8] = s6;
     539           0 : }
     540             : 
     541           0 : static INLINE void pack_8x9_pixels(const uint16_t *src, ptrdiff_t pitch,
     542             :                                    __m256i *sig) {
     543             :   // base + 7th row
     544           0 :   __m256i s0 = _mm256_castsi128_si256(
     545           0 :       _mm_loadu_si128((const __m128i *)(src + 7 * pitch)));
     546             :   // base + 8th row
     547           0 :   __m256i s1 = _mm256_castsi128_si256(
     548           0 :       _mm_loadu_si128((const __m128i *)(src + 8 * pitch)));
     549           0 :   __m256i s2 = _mm256_inserti128_si256(sig[8], _mm256_castsi256_si128(s0), 1);
     550           0 :   __m256i s3 = _mm256_inserti128_si256(s0, _mm256_castsi256_si128(s1), 1);
     551           0 :   sig[3] = _mm256_unpacklo_epi16(s2, s3);
     552           0 :   sig[7] = _mm256_unpackhi_epi16(s2, s3);
     553           0 :   sig[8] = s1;
     554           0 : }
     555             : 
     556           0 : static INLINE void filter_8x9_pixels(const __m256i *sig, const __m256i *f,
     557             :                                      __m256i *y0, __m256i *y1) {
     558           0 :   filter_8x1_pixels(sig, f, y0);
     559           0 :   filter_8x1_pixels(&sig[4], f, y1);
     560           0 : }
     561             : 
     562           0 : static INLINE void update_pixels(__m256i *sig) {
     563             :   int i;
     564           0 :   for (i = 0; i < 3; ++i) {
     565           0 :     sig[i] = sig[i + 1];
     566           0 :     sig[i + 4] = sig[i + 5];
     567             :   }
     568           0 : }
     569             : 
     570           0 : static void aom_highbd_filter_block1d8_v8_avx2(
     571             :     const uint16_t *src_ptr, ptrdiff_t src_pitch, uint16_t *dst_ptr,
     572             :     ptrdiff_t dst_pitch, uint32_t height, const int16_t *filter, int bd) {
     573             :   __m256i signal[9], res0, res1;
     574           0 :   const __m256i max = _mm256_set1_epi16((1 << bd) - 1);
     575             : 
     576             :   __m256i ff[4];
     577           0 :   pack_filters(filter, ff);
     578             : 
     579           0 :   pack_8x9_init(src_ptr, src_pitch, signal);
     580             : 
     581             :   do {
     582           0 :     pack_8x9_pixels(src_ptr, src_pitch, signal);
     583             : 
     584           0 :     filter_8x9_pixels(signal, ff, &res0, &res1);
     585           0 :     store_8x2_pixels(&res0, &res1, &max, dst_ptr, dst_pitch);
     586           0 :     update_pixels(signal);
     587             : 
     588           0 :     src_ptr += src_pitch << 1;
     589           0 :     dst_ptr += dst_pitch << 1;
     590           0 :     height -= 2;
     591           0 :   } while (height > 0);
     592           0 : }
     593             : 
     594           0 : static void pack_16x9_init(const uint16_t *src, ptrdiff_t pitch, __m256i *sig) {
     595             :   __m256i u0, u1, u2, u3;
     596             :   // load 0-6 rows
     597           0 :   const __m256i s0 = _mm256_loadu_si256((const __m256i *)src);
     598           0 :   const __m256i s1 = _mm256_loadu_si256((const __m256i *)(src + pitch));
     599           0 :   const __m256i s2 = _mm256_loadu_si256((const __m256i *)(src + 2 * pitch));
     600           0 :   const __m256i s3 = _mm256_loadu_si256((const __m256i *)(src + 3 * pitch));
     601           0 :   const __m256i s4 = _mm256_loadu_si256((const __m256i *)(src + 4 * pitch));
     602           0 :   const __m256i s5 = _mm256_loadu_si256((const __m256i *)(src + 5 * pitch));
     603           0 :   const __m256i s6 = _mm256_loadu_si256((const __m256i *)(src + 6 * pitch));
     604             : 
     605           0 :   u0 = _mm256_permute2x128_si256(s0, s1, 0x20);  // 0, 1 low
     606           0 :   u1 = _mm256_permute2x128_si256(s0, s1, 0x31);  // 0, 1 high
     607             : 
     608           0 :   u2 = _mm256_permute2x128_si256(s1, s2, 0x20);  // 1, 2 low
     609           0 :   u3 = _mm256_permute2x128_si256(s1, s2, 0x31);  // 1, 2 high
     610             : 
     611           0 :   sig[0] = _mm256_unpacklo_epi16(u0, u2);
     612           0 :   sig[4] = _mm256_unpackhi_epi16(u0, u2);
     613             : 
     614           0 :   sig[8] = _mm256_unpacklo_epi16(u1, u3);
     615           0 :   sig[12] = _mm256_unpackhi_epi16(u1, u3);
     616             : 
     617           0 :   u0 = _mm256_permute2x128_si256(s2, s3, 0x20);
     618           0 :   u1 = _mm256_permute2x128_si256(s2, s3, 0x31);
     619             : 
     620           0 :   u2 = _mm256_permute2x128_si256(s3, s4, 0x20);
     621           0 :   u3 = _mm256_permute2x128_si256(s3, s4, 0x31);
     622             : 
     623           0 :   sig[1] = _mm256_unpacklo_epi16(u0, u2);
     624           0 :   sig[5] = _mm256_unpackhi_epi16(u0, u2);
     625             : 
     626           0 :   sig[9] = _mm256_unpacklo_epi16(u1, u3);
     627           0 :   sig[13] = _mm256_unpackhi_epi16(u1, u3);
     628             : 
     629           0 :   u0 = _mm256_permute2x128_si256(s4, s5, 0x20);
     630           0 :   u1 = _mm256_permute2x128_si256(s4, s5, 0x31);
     631             : 
     632           0 :   u2 = _mm256_permute2x128_si256(s5, s6, 0x20);
     633           0 :   u3 = _mm256_permute2x128_si256(s5, s6, 0x31);
     634             : 
     635           0 :   sig[2] = _mm256_unpacklo_epi16(u0, u2);
     636           0 :   sig[6] = _mm256_unpackhi_epi16(u0, u2);
     637             : 
     638           0 :   sig[10] = _mm256_unpacklo_epi16(u1, u3);
     639           0 :   sig[14] = _mm256_unpackhi_epi16(u1, u3);
     640             : 
     641           0 :   sig[16] = s6;
     642           0 : }
     643             : 
     644           0 : static void pack_16x9_pixels(const uint16_t *src, ptrdiff_t pitch,
     645             :                              __m256i *sig) {
     646             :   // base + 7th row
     647           0 :   const __m256i s7 = _mm256_loadu_si256((const __m256i *)(src + 7 * pitch));
     648             :   // base + 8th row
     649           0 :   const __m256i s8 = _mm256_loadu_si256((const __m256i *)(src + 8 * pitch));
     650             : 
     651             :   __m256i u0, u1, u2, u3;
     652           0 :   u0 = _mm256_permute2x128_si256(sig[16], s7, 0x20);
     653           0 :   u1 = _mm256_permute2x128_si256(sig[16], s7, 0x31);
     654             : 
     655           0 :   u2 = _mm256_permute2x128_si256(s7, s8, 0x20);
     656           0 :   u3 = _mm256_permute2x128_si256(s7, s8, 0x31);
     657             : 
     658           0 :   sig[3] = _mm256_unpacklo_epi16(u0, u2);
     659           0 :   sig[7] = _mm256_unpackhi_epi16(u0, u2);
     660             : 
     661           0 :   sig[11] = _mm256_unpacklo_epi16(u1, u3);
     662           0 :   sig[15] = _mm256_unpackhi_epi16(u1, u3);
     663             : 
     664           0 :   sig[16] = s8;
     665           0 : }
     666             : 
     667           0 : static INLINE void filter_16x9_pixels(const __m256i *sig, const __m256i *f,
     668             :                                       __m256i *y0, __m256i *y1) {
     669             :   __m256i res[4];
     670             :   int i;
     671           0 :   for (i = 0; i < 4; ++i) {
     672           0 :     filter_8x1_pixels(&sig[i << 2], f, &res[i]);
     673             :   }
     674             : 
     675             :   {
     676           0 :     const __m256i l0l1 = _mm256_packus_epi32(res[0], res[1]);
     677           0 :     const __m256i h0h1 = _mm256_packus_epi32(res[2], res[3]);
     678           0 :     *y0 = _mm256_permute2x128_si256(l0l1, h0h1, 0x20);
     679           0 :     *y1 = _mm256_permute2x128_si256(l0l1, h0h1, 0x31);
     680             :   }
     681           0 : }
     682             : 
     683           0 : static INLINE void store_16x2_pixels(const __m256i *y0, const __m256i *y1,
     684             :                                      const __m256i *mask, uint16_t *dst,
     685             :                                      ptrdiff_t pitch) {
     686           0 :   __m256i p = _mm256_min_epi16(*y0, *mask);
     687             :   _mm256_storeu_si256((__m256i *)dst, p);
     688           0 :   p = _mm256_min_epi16(*y1, *mask);
     689           0 :   _mm256_storeu_si256((__m256i *)(dst + pitch), p);
     690           0 : }
     691             : 
     692           0 : static void update_16x9_pixels(__m256i *sig) {
     693           0 :   update_pixels(&sig[0]);
     694           0 :   update_pixels(&sig[8]);
     695           0 : }
     696             : 
     697           0 : static void aom_highbd_filter_block1d16_v8_avx2(
     698             :     const uint16_t *src_ptr, ptrdiff_t src_pitch, uint16_t *dst_ptr,
     699             :     ptrdiff_t dst_pitch, uint32_t height, const int16_t *filter, int bd) {
     700             :   __m256i signal[17], res0, res1;
     701           0 :   const __m256i max = _mm256_set1_epi16((1 << bd) - 1);
     702             : 
     703             :   __m256i ff[4];
     704           0 :   pack_filters(filter, ff);
     705             : 
     706           0 :   pack_16x9_init(src_ptr, src_pitch, signal);
     707             : 
     708             :   do {
     709           0 :     pack_16x9_pixels(src_ptr, src_pitch, signal);
     710           0 :     filter_16x9_pixels(signal, ff, &res0, &res1);
     711           0 :     store_16x2_pixels(&res0, &res1, &max, dst_ptr, dst_pitch);
     712           0 :     update_16x9_pixels(signal);
     713             : 
     714           0 :     src_ptr += src_pitch << 1;
     715           0 :     dst_ptr += dst_pitch << 1;
     716           0 :     height -= 2;
     717           0 :   } while (height > 0);
     718           0 : }
     719             : 
     720             : // -----------------------------------------------------------------------------
     721             : // 2-tap vertical filtering
     722             : 
     723           0 : static void pack_16x2_init(const uint16_t *src, __m256i *sig) {
     724           0 :   sig[2] = _mm256_loadu_si256((const __m256i *)src);
     725           0 : }
     726             : 
     727           0 : static INLINE void pack_16x2_2t_pixels(const uint16_t *src, ptrdiff_t pitch,
     728             :                                        __m256i *sig) {
     729             :   // load the next row
     730           0 :   const __m256i u = _mm256_loadu_si256((const __m256i *)(src + pitch));
     731           0 :   sig[0] = _mm256_unpacklo_epi16(sig[2], u);
     732           0 :   sig[1] = _mm256_unpackhi_epi16(sig[2], u);
     733           0 :   sig[2] = u;
     734           0 : }
     735             : 
     736           0 : static INLINE void filter_16x2_2t_pixels(const __m256i *sig, const __m256i *f,
     737             :                                          __m256i *y0, __m256i *y1) {
     738           0 :   filter_16_2t_pixels(sig, f, y0, y1);
     739           0 : }
     740             : 
     741           0 : static void aom_highbd_filter_block1d16_v2_avx2(
     742             :     const uint16_t *src_ptr, ptrdiff_t src_pitch, uint16_t *dst_ptr,
     743             :     ptrdiff_t dst_pitch, uint32_t height, const int16_t *filter, int bd) {
     744             :   __m256i signal[3], res0, res1;
     745           0 :   const __m256i max = _mm256_set1_epi16((1 << bd) - 1);
     746             :   __m256i ff;
     747             : 
     748           0 :   pack_2t_filter(filter, &ff);
     749           0 :   pack_16x2_init(src_ptr, signal);
     750             : 
     751             :   do {
     752           0 :     pack_16x2_2t_pixels(src_ptr, src_pitch, signal);
     753           0 :     filter_16x2_2t_pixels(signal, &ff, &res0, &res1);
     754           0 :     store_16x1_pixels(&res0, &res1, &max, dst_ptr);
     755             : 
     756           0 :     src_ptr += src_pitch;
     757           0 :     dst_ptr += dst_pitch;
     758           0 :     height -= 1;
     759           0 :   } while (height > 0);
     760           0 : }
     761             : 
     762           0 : static INLINE void pack_8x1_2t_filter(const int16_t *filter, __m128i *f) {
     763           0 :   const __m128i h = _mm_loadu_si128((const __m128i *)filter);
     764           0 :   const __m128i p = _mm_set1_epi32(0x09080706);
     765           0 :   f[0] = _mm_shuffle_epi8(h, p);
     766           0 : }
     767             : 
     768           0 : static void pack_8x2_init(const uint16_t *src, __m128i *sig) {
     769           0 :   sig[2] = _mm_loadu_si128((const __m128i *)src);
     770           0 : }
     771             : 
     772           0 : static INLINE void pack_8x2_2t_pixels_ver(const uint16_t *src, ptrdiff_t pitch,
     773             :                                           __m128i *sig) {
     774             :   // load the next row
     775           0 :   const __m128i u = _mm_loadu_si128((const __m128i *)(src + pitch));
     776           0 :   sig[0] = _mm_unpacklo_epi16(sig[2], u);
     777           0 :   sig[1] = _mm_unpackhi_epi16(sig[2], u);
     778           0 :   sig[2] = u;
     779           0 : }
     780             : 
     781           0 : static INLINE void filter_8_2t_pixels(const __m128i *sig, const __m128i *f,
     782             :                                       __m128i *y0, __m128i *y1) {
     783           0 :   const __m128i rounding = _mm_set1_epi32(1 << (CONV8_ROUNDING_BITS - 1));
     784           0 :   __m128i x0 = _mm_madd_epi16(sig[0], *f);
     785           0 :   __m128i x1 = _mm_madd_epi16(sig[1], *f);
     786           0 :   x0 = _mm_add_epi32(x0, rounding);
     787           0 :   x1 = _mm_add_epi32(x1, rounding);
     788           0 :   *y0 = _mm_srai_epi32(x0, CONV8_ROUNDING_BITS);
     789           0 :   *y1 = _mm_srai_epi32(x1, CONV8_ROUNDING_BITS);
     790           0 : }
     791             : 
     792           0 : static INLINE void store_8x1_2t_pixels_ver(const __m128i *y0, const __m128i *y1,
     793             :                                            const __m128i *mask, uint16_t *dst) {
     794           0 :   __m128i res = _mm_packus_epi32(*y0, *y1);
     795           0 :   res = _mm_min_epi16(res, *mask);
     796             :   _mm_storeu_si128((__m128i *)dst, res);
     797           0 : }
     798             : 
     799           0 : static void aom_highbd_filter_block1d8_v2_avx2(
     800             :     const uint16_t *src_ptr, ptrdiff_t src_pitch, uint16_t *dst_ptr,
     801             :     ptrdiff_t dst_pitch, uint32_t height, const int16_t *filter, int bd) {
     802             :   __m128i signal[3], res0, res1;
     803           0 :   const __m128i max = _mm_set1_epi16((1 << bd) - 1);
     804             :   __m128i ff;
     805             : 
     806           0 :   pack_8x1_2t_filter(filter, &ff);
     807           0 :   pack_8x2_init(src_ptr, signal);
     808             : 
     809             :   do {
     810           0 :     pack_8x2_2t_pixels_ver(src_ptr, src_pitch, signal);
     811           0 :     filter_8_2t_pixels(signal, &ff, &res0, &res1);
     812           0 :     store_8x1_2t_pixels_ver(&res0, &res1, &max, dst_ptr);
     813             : 
     814           0 :     src_ptr += src_pitch;
     815           0 :     dst_ptr += dst_pitch;
     816           0 :     height -= 1;
     817           0 :   } while (height > 0);
     818           0 : }
     819             : 
     820             : // Calculation with averaging the input pixels
     821             : 
     822           0 : static INLINE void store_8x1_avg_pixels(const __m256i *y0, const __m256i *mask,
     823             :                                         uint16_t *dst) {
     824           0 :   const __m128i a0 = _mm256_castsi256_si128(*y0);
     825           0 :   const __m128i a1 = _mm256_extractf128_si256(*y0, 1);
     826           0 :   __m128i res = _mm_packus_epi32(a0, a1);
     827           0 :   const __m128i pix = _mm_loadu_si128((const __m128i *)dst);
     828           0 :   res = _mm_min_epi16(res, _mm256_castsi256_si128(*mask));
     829           0 :   res = _mm_avg_epu16(res, pix);
     830             :   _mm_storeu_si128((__m128i *)dst, res);
     831           0 : }
     832             : 
     833           0 : static INLINE void store_8x2_avg_pixels(const __m256i *y0, const __m256i *y1,
     834             :                                         const __m256i *mask, uint16_t *dst,
     835             :                                         ptrdiff_t pitch) {
     836           0 :   __m256i a = _mm256_packus_epi32(*y0, *y1);
     837           0 :   const __m128i pix0 = _mm_loadu_si128((const __m128i *)dst);
     838           0 :   const __m128i pix1 = _mm_loadu_si128((const __m128i *)(dst + pitch));
     839           0 :   const __m256i pix =
     840           0 :       _mm256_insertf128_si256(_mm256_castsi128_si256(pix0), pix1, 1);
     841           0 :   a = _mm256_min_epi16(a, *mask);
     842           0 :   a = _mm256_avg_epu16(a, pix);
     843           0 :   _mm_storeu_si128((__m128i *)dst, _mm256_castsi256_si128(a));
     844           0 :   _mm_storeu_si128((__m128i *)(dst + pitch), _mm256_extractf128_si256(a, 1));
     845           0 : }
     846             : 
     847           0 : static INLINE void store_16x1_avg_pixels(const __m256i *y0, const __m256i *y1,
     848             :                                          const __m256i *mask, uint16_t *dst) {
     849           0 :   __m256i a = _mm256_packus_epi32(*y0, *y1);
     850           0 :   const __m256i pix = _mm256_loadu_si256((const __m256i *)dst);
     851           0 :   a = _mm256_min_epi16(a, *mask);
     852           0 :   a = _mm256_avg_epu16(a, pix);
     853             :   _mm256_storeu_si256((__m256i *)dst, a);
     854           0 : }
     855             : 
     856           0 : static INLINE void store_16x2_avg_pixels(const __m256i *y0, const __m256i *y1,
     857             :                                          const __m256i *mask, uint16_t *dst,
     858             :                                          ptrdiff_t pitch) {
     859           0 :   const __m256i pix0 = _mm256_loadu_si256((const __m256i *)dst);
     860           0 :   const __m256i pix1 = _mm256_loadu_si256((const __m256i *)(dst + pitch));
     861           0 :   __m256i p = _mm256_min_epi16(*y0, *mask);
     862           0 :   p = _mm256_avg_epu16(p, pix0);
     863             :   _mm256_storeu_si256((__m256i *)dst, p);
     864             : 
     865           0 :   p = _mm256_min_epi16(*y1, *mask);
     866           0 :   p = _mm256_avg_epu16(p, pix1);
     867           0 :   _mm256_storeu_si256((__m256i *)(dst + pitch), p);
     868           0 : }
     869             : 
     870           0 : static INLINE void store_8x1_2t_avg_pixels_ver(const __m128i *y0,
     871             :                                                const __m128i *y1,
     872             :                                                const __m128i *mask,
     873             :                                                uint16_t *dst) {
     874           0 :   __m128i res = _mm_packus_epi32(*y0, *y1);
     875           0 :   const __m128i pix = _mm_loadu_si128((const __m128i *)dst);
     876           0 :   res = _mm_min_epi16(res, *mask);
     877           0 :   res = _mm_avg_epu16(res, pix);
     878             :   _mm_storeu_si128((__m128i *)dst, res);
     879           0 : }
     880             : 
     881           0 : static void aom_highbd_filter_block1d8_h8_avg_avx2(
     882             :     const uint16_t *src_ptr, ptrdiff_t src_pitch, uint16_t *dst_ptr,
     883             :     ptrdiff_t dst_pitch, uint32_t height, const int16_t *filter, int bd) {
     884             :   __m256i signal[8], res0, res1;
     885           0 :   const __m256i max = _mm256_set1_epi16((1 << bd) - 1);
     886             : 
     887             :   __m256i ff[4];
     888           0 :   pack_filters(filter, ff);
     889             : 
     890           0 :   src_ptr -= 3;
     891             :   do {
     892           0 :     pack_8x2_pixels(src_ptr, src_pitch, signal);
     893           0 :     filter_8x1_pixels(signal, ff, &res0);
     894           0 :     filter_8x1_pixels(&signal[4], ff, &res1);
     895           0 :     store_8x2_avg_pixels(&res0, &res1, &max, dst_ptr, dst_pitch);
     896           0 :     height -= 2;
     897           0 :     src_ptr += src_pitch << 1;
     898           0 :     dst_ptr += dst_pitch << 1;
     899           0 :   } while (height > 1);
     900             : 
     901           0 :   if (height > 0) {
     902           0 :     pack_8x1_pixels(src_ptr, signal);
     903           0 :     filter_8x1_pixels(signal, ff, &res0);
     904           0 :     store_8x1_avg_pixels(&res0, &max, dst_ptr);
     905             :   }
     906           0 : }
     907             : 
     908           0 : static void aom_highbd_filter_block1d16_h8_avg_avx2(
     909             :     const uint16_t *src_ptr, ptrdiff_t src_pitch, uint16_t *dst_ptr,
     910             :     ptrdiff_t dst_pitch, uint32_t height, const int16_t *filter, int bd) {
     911             :   __m256i signal[8], res0, res1;
     912           0 :   const __m256i max = _mm256_set1_epi16((1 << bd) - 1);
     913             : 
     914             :   __m256i ff[4];
     915           0 :   pack_filters(filter, ff);
     916             : 
     917           0 :   src_ptr -= 3;
     918             :   do {
     919           0 :     pack_16x1_pixels(src_ptr, signal);
     920           0 :     filter_8x1_pixels(signal, ff, &res0);
     921           0 :     filter_8x1_pixels(&signal[4], ff, &res1);
     922           0 :     store_16x1_avg_pixels(&res0, &res1, &max, dst_ptr);
     923           0 :     height -= 1;
     924           0 :     src_ptr += src_pitch;
     925           0 :     dst_ptr += dst_pitch;
     926           0 :   } while (height > 0);
     927           0 : }
     928             : 
     929           0 : static void aom_highbd_filter_block1d8_v8_avg_avx2(
     930             :     const uint16_t *src_ptr, ptrdiff_t src_pitch, uint16_t *dst_ptr,
     931             :     ptrdiff_t dst_pitch, uint32_t height, const int16_t *filter, int bd) {
     932             :   __m256i signal[9], res0, res1;
     933           0 :   const __m256i max = _mm256_set1_epi16((1 << bd) - 1);
     934             : 
     935             :   __m256i ff[4];
     936           0 :   pack_filters(filter, ff);
     937             : 
     938           0 :   pack_8x9_init(src_ptr, src_pitch, signal);
     939             : 
     940             :   do {
     941           0 :     pack_8x9_pixels(src_ptr, src_pitch, signal);
     942             : 
     943           0 :     filter_8x9_pixels(signal, ff, &res0, &res1);
     944           0 :     store_8x2_avg_pixels(&res0, &res1, &max, dst_ptr, dst_pitch);
     945           0 :     update_pixels(signal);
     946             : 
     947           0 :     src_ptr += src_pitch << 1;
     948           0 :     dst_ptr += dst_pitch << 1;
     949           0 :     height -= 2;
     950           0 :   } while (height > 0);
     951           0 : }
     952             : 
     953           0 : static void aom_highbd_filter_block1d16_v8_avg_avx2(
     954             :     const uint16_t *src_ptr, ptrdiff_t src_pitch, uint16_t *dst_ptr,
     955             :     ptrdiff_t dst_pitch, uint32_t height, const int16_t *filter, int bd) {
     956             :   __m256i signal[17], res0, res1;
     957           0 :   const __m256i max = _mm256_set1_epi16((1 << bd) - 1);
     958             : 
     959             :   __m256i ff[4];
     960           0 :   pack_filters(filter, ff);
     961             : 
     962           0 :   pack_16x9_init(src_ptr, src_pitch, signal);
     963             : 
     964             :   do {
     965           0 :     pack_16x9_pixels(src_ptr, src_pitch, signal);
     966           0 :     filter_16x9_pixels(signal, ff, &res0, &res1);
     967           0 :     store_16x2_avg_pixels(&res0, &res1, &max, dst_ptr, dst_pitch);
     968           0 :     update_16x9_pixels(signal);
     969             : 
     970           0 :     src_ptr += src_pitch << 1;
     971           0 :     dst_ptr += dst_pitch << 1;
     972           0 :     height -= 2;
     973           0 :   } while (height > 0);
     974           0 : }
     975             : 
     976           0 : static void aom_highbd_filter_block1d8_h2_avg_avx2(
     977             :     const uint16_t *src_ptr, ptrdiff_t src_pitch, uint16_t *dst_ptr,
     978             :     ptrdiff_t dst_pitch, uint32_t height, const int16_t *filter, int bd) {
     979             :   __m256i signal[2], res0, res1;
     980           0 :   const __m256i max = _mm256_set1_epi16((1 << bd) - 1);
     981             : 
     982             :   __m256i ff;
     983           0 :   pack_2t_filter(filter, &ff);
     984             : 
     985           0 :   src_ptr -= 3;
     986             :   do {
     987           0 :     pack_8x2_2t_pixels(src_ptr, src_pitch, signal);
     988           0 :     filter_16_2t_pixels(signal, &ff, &res0, &res1);
     989           0 :     store_8x2_avg_pixels(&res0, &res1, &max, dst_ptr, dst_pitch);
     990           0 :     height -= 2;
     991           0 :     src_ptr += src_pitch << 1;
     992           0 :     dst_ptr += dst_pitch << 1;
     993           0 :   } while (height > 1);
     994             : 
     995           0 :   if (height > 0) {
     996           0 :     pack_8x1_2t_pixels(src_ptr, signal);
     997           0 :     filter_8x1_2t_pixels(signal, &ff, &res0);
     998           0 :     store_8x1_avg_pixels(&res0, &max, dst_ptr);
     999             :   }
    1000           0 : }
    1001             : 
    1002           0 : static void aom_highbd_filter_block1d16_h2_avg_avx2(
    1003             :     const uint16_t *src_ptr, ptrdiff_t src_pitch, uint16_t *dst_ptr,
    1004             :     ptrdiff_t dst_pitch, uint32_t height, const int16_t *filter, int bd) {
    1005             :   __m256i signal[2], res0, res1;
    1006           0 :   const __m256i max = _mm256_set1_epi16((1 << bd) - 1);
    1007             : 
    1008             :   __m256i ff;
    1009           0 :   pack_2t_filter(filter, &ff);
    1010             : 
    1011           0 :   src_ptr -= 3;
    1012             :   do {
    1013           0 :     pack_16x1_2t_pixels(src_ptr, signal);
    1014           0 :     filter_16_2t_pixels(signal, &ff, &res0, &res1);
    1015           0 :     store_16x1_avg_pixels(&res0, &res1, &max, dst_ptr);
    1016           0 :     height -= 1;
    1017           0 :     src_ptr += src_pitch;
    1018           0 :     dst_ptr += dst_pitch;
    1019           0 :   } while (height > 0);
    1020           0 : }
    1021             : 
    1022           0 : static void aom_highbd_filter_block1d16_v2_avg_avx2(
    1023             :     const uint16_t *src_ptr, ptrdiff_t src_pitch, uint16_t *dst_ptr,
    1024             :     ptrdiff_t dst_pitch, uint32_t height, const int16_t *filter, int bd) {
    1025             :   __m256i signal[3], res0, res1;
    1026           0 :   const __m256i max = _mm256_set1_epi16((1 << bd) - 1);
    1027             :   __m256i ff;
    1028             : 
    1029           0 :   pack_2t_filter(filter, &ff);
    1030           0 :   pack_16x2_init(src_ptr, signal);
    1031             : 
    1032             :   do {
    1033           0 :     pack_16x2_2t_pixels(src_ptr, src_pitch, signal);
    1034           0 :     filter_16x2_2t_pixels(signal, &ff, &res0, &res1);
    1035           0 :     store_16x1_avg_pixels(&res0, &res1, &max, dst_ptr);
    1036             : 
    1037           0 :     src_ptr += src_pitch;
    1038           0 :     dst_ptr += dst_pitch;
    1039           0 :     height -= 1;
    1040           0 :   } while (height > 0);
    1041           0 : }
    1042             : 
    1043           0 : static void aom_highbd_filter_block1d8_v2_avg_avx2(
    1044             :     const uint16_t *src_ptr, ptrdiff_t src_pitch, uint16_t *dst_ptr,
    1045             :     ptrdiff_t dst_pitch, uint32_t height, const int16_t *filter, int bd) {
    1046             :   __m128i signal[3], res0, res1;
    1047           0 :   const __m128i max = _mm_set1_epi16((1 << bd) - 1);
    1048             :   __m128i ff;
    1049             : 
    1050           0 :   pack_8x1_2t_filter(filter, &ff);
    1051           0 :   pack_8x2_init(src_ptr, signal);
    1052             : 
    1053             :   do {
    1054           0 :     pack_8x2_2t_pixels_ver(src_ptr, src_pitch, signal);
    1055           0 :     filter_8_2t_pixels(signal, &ff, &res0, &res1);
    1056           0 :     store_8x1_2t_avg_pixels_ver(&res0, &res1, &max, dst_ptr);
    1057             : 
    1058           0 :     src_ptr += src_pitch;
    1059           0 :     dst_ptr += dst_pitch;
    1060           0 :     height -= 1;
    1061           0 :   } while (height > 0);
    1062           0 : }
    1063             : 
    1064             : void aom_highbd_filter_block1d4_h8_sse2(const uint16_t *, ptrdiff_t, uint16_t *,
    1065             :                                         ptrdiff_t, uint32_t, const int16_t *,
    1066             :                                         int);
    1067             : void aom_highbd_filter_block1d4_h2_sse2(const uint16_t *, ptrdiff_t, uint16_t *,
    1068             :                                         ptrdiff_t, uint32_t, const int16_t *,
    1069             :                                         int);
    1070             : void aom_highbd_filter_block1d4_v8_sse2(const uint16_t *, ptrdiff_t, uint16_t *,
    1071             :                                         ptrdiff_t, uint32_t, const int16_t *,
    1072             :                                         int);
    1073             : void aom_highbd_filter_block1d4_v2_sse2(const uint16_t *, ptrdiff_t, uint16_t *,
    1074             :                                         ptrdiff_t, uint32_t, const int16_t *,
    1075             :                                         int);
    1076             : #define aom_highbd_filter_block1d4_h8_avx2 aom_highbd_filter_block1d4_h8_sse2
    1077             : #define aom_highbd_filter_block1d4_h2_avx2 aom_highbd_filter_block1d4_h2_sse2
    1078             : #define aom_highbd_filter_block1d4_v8_avx2 aom_highbd_filter_block1d4_v8_sse2
    1079             : #define aom_highbd_filter_block1d4_v2_avx2 aom_highbd_filter_block1d4_v2_sse2
    1080             : 
    1081           0 : HIGH_FUN_CONV_1D(horiz, x_step_q4, filter_x, h, src, , avx2);
    1082           0 : HIGH_FUN_CONV_1D(vert, y_step_q4, filter_y, v, src - src_stride * 3, , avx2);
    1083           0 : HIGH_FUN_CONV_2D(, avx2);
    1084             : 
    1085             : void aom_highbd_filter_block1d4_h8_avg_sse2(const uint16_t *, ptrdiff_t,
    1086             :                                             uint16_t *, ptrdiff_t, uint32_t,
    1087             :                                             const int16_t *, int);
    1088             : void aom_highbd_filter_block1d4_h2_avg_sse2(const uint16_t *, ptrdiff_t,
    1089             :                                             uint16_t *, ptrdiff_t, uint32_t,
    1090             :                                             const int16_t *, int);
    1091             : void aom_highbd_filter_block1d4_v8_avg_sse2(const uint16_t *, ptrdiff_t,
    1092             :                                             uint16_t *, ptrdiff_t, uint32_t,
    1093             :                                             const int16_t *, int);
    1094             : void aom_highbd_filter_block1d4_v2_avg_sse2(const uint16_t *, ptrdiff_t,
    1095             :                                             uint16_t *, ptrdiff_t, uint32_t,
    1096             :                                             const int16_t *, int);
    1097             : #define aom_highbd_filter_block1d4_h8_avg_avx2 \
    1098             :   aom_highbd_filter_block1d4_h8_avg_sse2
    1099             : #define aom_highbd_filter_block1d4_h2_avg_avx2 \
    1100             :   aom_highbd_filter_block1d4_h2_avg_sse2
    1101             : #define aom_highbd_filter_block1d4_v8_avg_avx2 \
    1102             :   aom_highbd_filter_block1d4_v8_avg_sse2
    1103             : #define aom_highbd_filter_block1d4_v2_avg_avx2 \
    1104             :   aom_highbd_filter_block1d4_v2_avg_sse2
    1105             : 
    1106           0 : HIGH_FUN_CONV_1D(avg_horiz, x_step_q4, filter_x, h, src, avg_, avx2);
    1107           0 : HIGH_FUN_CONV_1D(avg_vert, y_step_q4, filter_y, v, src - src_stride * 3, avg_,
    1108             :                  avx2);
    1109           0 : HIGH_FUN_CONV_2D(avg_, avx2);
    1110             : 
    1111             : #undef HIGHBD_FUNC

Generated by: LCOV version 1.13