LCOV - code coverage report
Current view: top level - ASM_AVX2 - EbComputeSAD_Intrinsic_AVX2.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 897 4620 19.4 %
Date: 2019-11-25 17:38:06 Functions: 21 71 29.6 %

          Line data    Source code
       1             : /*
       2             : * Copyright(c) 2019 Intel Corporation
       3             : * SPDX - License - Identifier: BSD - 2 - Clause - Patent
       4             : */
       5             : 
       6             : #include <assert.h>
       7             : 
       8             : #include "EbComputeSAD_AVX2.h"
       9             : #include "EbDefinitions.h"
      10             : #include "immintrin.h"
      11             : #include "EbMemory_AVX2.h"
      12             : #include "EbComputeSAD.h"
      13             : 
      14             : #define UPDATE_BEST(s, k, offset) \
      15             :   temSum1 = _mm_extract_epi32(s, k); \
      16             :   if (temSum1 < lowSum) { \
      17             :     lowSum = temSum1; \
      18             :     xBest = j + offset + k; \
      19             :     yBest = i; \
      20             :   }
      21             : 
      22           0 : void ext_sad_calculation_8x8_16x16_avx2_intrin(
      23             :     uint8_t  *src,
      24             :     uint32_t  src_stride,
      25             :     uint8_t  *ref,
      26             :     uint32_t  ref_stride,
      27             :     uint32_t *p_best_sad8x8,
      28             :     uint32_t *p_best_sad16x16,
      29             :     uint32_t *p_best_mv8x8,
      30             :     uint32_t *p_best_mv16x16,
      31             :     uint32_t  mv,
      32             :     uint32_t *p_sad16x16,
      33             :     uint32_t *p_sad8x8,
      34             :     EbBool    sub_sad) {
      35             :     __m128i xmm_sad16x16, xmm_sad16x16_total, sad8x8_0_3;
      36             :     __m128i sad8x8_less_than_bitmask, best_mv8x8;
      37             :     __m128i best_sad8x8, xmm_best_sad8x8, xmm_best_mv8x8;
      38             :     __m256i sad8x8_0_3_256, src_256, ref_256;
      39           0 :     __m128i xmm_mv = _mm_set1_epi32(mv);
      40             : 
      41           0 :     src_256 = _mm256_setr_m128i(
      42             :         _mm_loadu_si128((__m128i const*)(src + 0 * src_stride)),
      43             :         _mm_loadu_si128((__m128i const*)(src + 8 * src_stride)));
      44           0 :     ref_256 = _mm256_setr_m128i(
      45             :         _mm_loadu_si128((__m128i const*)(ref + 0 * ref_stride)),
      46             :         _mm_loadu_si128((__m128i const*)(ref + 8 * ref_stride)));
      47           0 :     sad8x8_0_3_256 = _mm256_sad_epu8(src_256, ref_256);
      48             : 
      49           0 :     src_256 = _mm256_setr_m128i(
      50             :         _mm_loadu_si128((__m128i const*)(src + 2 * src_stride)),
      51             :         _mm_loadu_si128((__m128i const*)(src + 10 * src_stride)));
      52           0 :     ref_256 = _mm256_setr_m128i(
      53             :         _mm_loadu_si128((__m128i const*)(ref + 2 * ref_stride)),
      54             :         _mm_loadu_si128((__m128i const*)(ref + 10 * ref_stride)));
      55           0 :     sad8x8_0_3_256 = _mm256_add_epi32(_mm256_sad_epu8(src_256, ref_256),
      56             :         sad8x8_0_3_256);
      57             : 
      58           0 :     src_256 = _mm256_setr_m128i(
      59             :         _mm_loadu_si128((__m128i const*)(src + 4 * src_stride)),
      60             :         _mm_loadu_si128((__m128i const*)(src + 12 * src_stride)));
      61           0 :     ref_256 = _mm256_setr_m128i(
      62             :         _mm_loadu_si128((__m128i const*)(ref + 4 * ref_stride)),
      63             :         _mm_loadu_si128((__m128i const*)(ref + 12 * ref_stride)));
      64           0 :     sad8x8_0_3_256 = _mm256_add_epi32(_mm256_sad_epu8(src_256, ref_256),
      65             :         sad8x8_0_3_256);
      66             : 
      67           0 :     src_256 = _mm256_setr_m128i(
      68             :         _mm_loadu_si128((__m128i const*)(src + 6 * src_stride)),
      69             :         _mm_loadu_si128((__m128i const*)(src + 14 * src_stride)));
      70           0 :     ref_256 = _mm256_setr_m128i(
      71             :         _mm_loadu_si128((__m128i const*)(ref + 6 * ref_stride)),
      72             :         _mm_loadu_si128((__m128i const*)(ref + 14 * ref_stride)));
      73           0 :     sad8x8_0_3_256 = _mm256_add_epi32(_mm256_sad_epu8(src_256, ref_256),
      74             :         sad8x8_0_3_256);
      75             : 
      76           0 :     if (sub_sad)
      77           0 :         sad8x8_0_3_256 = _mm256_slli_epi32(sad8x8_0_3_256, 1);
      78             :     else {
      79           0 :         src_256 = _mm256_setr_m128i(
      80             :             _mm_loadu_si128((__m128i const*)(src + 1 * src_stride)),
      81             :             _mm_loadu_si128((__m128i const*)(src + 9 * src_stride)));
      82           0 :         ref_256 = _mm256_setr_m128i(
      83             :             _mm_loadu_si128((__m128i const*)(ref + 1 * ref_stride)),
      84             :             _mm_loadu_si128((__m128i const*)(ref + 9 * ref_stride)));
      85           0 :         sad8x8_0_3_256 = _mm256_add_epi32(_mm256_sad_epu8(src_256, ref_256),
      86             :             sad8x8_0_3_256);
      87             : 
      88           0 :         src_256 = _mm256_setr_m128i(
      89             :             _mm_loadu_si128((__m128i const*)(src + 3 * src_stride)),
      90             :             _mm_loadu_si128((__m128i const*)(src + 11 * src_stride)));
      91           0 :         ref_256 = _mm256_setr_m128i(
      92             :             _mm_loadu_si128((__m128i const*)(ref + 3 * ref_stride)),
      93             :             _mm_loadu_si128((__m128i const*)(ref + 11 * ref_stride)));
      94           0 :         sad8x8_0_3_256 = _mm256_add_epi32(_mm256_sad_epu8(src_256, ref_256),
      95             :             sad8x8_0_3_256);
      96             : 
      97           0 :         src_256 = _mm256_setr_m128i(
      98             :             _mm_loadu_si128((__m128i const*)(src + 5 * src_stride)),
      99             :             _mm_loadu_si128((__m128i const*)(src + 13 * src_stride)));
     100           0 :         ref_256 = _mm256_setr_m128i(
     101             :             _mm_loadu_si128((__m128i const*)(ref + 5 * ref_stride)),
     102             :             _mm_loadu_si128((__m128i const*)(ref + 13 * ref_stride)));
     103           0 :         sad8x8_0_3_256 = _mm256_add_epi32(_mm256_sad_epu8(src_256, ref_256),
     104             :             sad8x8_0_3_256);
     105             : 
     106           0 :         src_256 = _mm256_setr_m128i(
     107             :             _mm_loadu_si128((__m128i const*)(src + 7 * src_stride)),
     108             :             _mm_loadu_si128((__m128i const*)(src + 15 * src_stride)));
     109           0 :         ref_256 = _mm256_setr_m128i(
     110             :             _mm_loadu_si128((__m128i const*)(ref + 7 * ref_stride)),
     111             :             _mm_loadu_si128((__m128i const*)(ref + 15 * ref_stride)));
     112           0 :         sad8x8_0_3_256 = _mm256_add_epi32(_mm256_sad_epu8(src_256, ref_256),
     113             :             sad8x8_0_3_256);
     114             :     }
     115             : 
     116           0 :     sad8x8_0_3 = _mm_packs_epi32(_mm256_castsi256_si128(sad8x8_0_3_256),
     117           0 :         _mm256_extracti128_si256(sad8x8_0_3_256, 1));
     118             :     _mm_storeu_si128((__m128i*)p_sad8x8, sad8x8_0_3);
     119             : 
     120           0 :     xmm_best_sad8x8 = _mm_loadu_si128((__m128i const*)p_best_sad8x8);
     121           0 :     xmm_best_mv8x8 = _mm_loadu_si128((__m128i const*)p_best_mv8x8);
     122             : 
     123             :     // sad8x8_0 < p_best_sad8x8[0] for 0 to 3
     124           0 :     sad8x8_less_than_bitmask = _mm_cmplt_epi32(sad8x8_0_3, xmm_best_sad8x8);
     125           0 :     best_sad8x8 = _mm_blendv_epi8(xmm_best_sad8x8, sad8x8_0_3,
     126             :         sad8x8_less_than_bitmask);
     127           0 :     best_mv8x8 = _mm_blendv_epi8(xmm_best_mv8x8, xmm_mv,
     128             :         sad8x8_less_than_bitmask);
     129             :     _mm_storeu_si128((__m128i*)p_best_sad8x8, best_sad8x8);
     130             :     _mm_storeu_si128((__m128i*)p_best_mv8x8, best_mv8x8);
     131             : 
     132           0 :     xmm_sad16x16 = _mm_add_epi32(_mm256_castsi256_si128(sad8x8_0_3_256),
     133           0 :         _mm256_extracti128_si256(sad8x8_0_3_256, 1));
     134           0 :     xmm_sad16x16_total = _mm_add_epi32(
     135           0 :         _mm_srli_si128(xmm_sad16x16, 8), xmm_sad16x16);
     136           0 :     p_sad16x16[0] = _mm_cvtsi128_si32(xmm_sad16x16_total);
     137             : 
     138           0 :     if (p_sad16x16[0] < p_best_sad16x16[0]) {
     139           0 :         p_best_sad16x16[0] = p_sad16x16[0];
     140           0 :         p_best_mv16x16[0] = mv;
     141             :     }
     142           0 : }
     143             : 
     144           0 : void sad_loop_kernel_sparse_avx2_intrin(
     145             :     uint8_t  *src,                            // input parameter, source samples Ptr
     146             :     uint32_t  src_stride,                      // input parameter, source stride
     147             :     uint8_t  *ref,                            // input parameter, reference samples Ptr
     148             :     uint32_t  ref_stride,                      // input parameter, reference stride
     149             :     uint32_t  block_height,                   // input parameter, block height (M)
     150             :     uint32_t  block_width,                    // input parameter, block width (N)
     151             :     uint64_t *best_sad,
     152             :     int16_t *x_search_center,
     153             :     int16_t *y_search_center,
     154             :     uint32_t  src_stride_raw,                   // input parameter, source stride (no line skipping)
     155             :     int16_t search_area_width,
     156             :     int16_t search_area_height)
     157             : {
     158           0 :     int16_t xBest = *x_search_center, yBest = *y_search_center;
     159           0 :     uint32_t lowSum = 0xffffff;
     160           0 :     uint32_t temSum1 = 0;
     161             :     int16_t i, j;
     162             :     uint32_t k, l;
     163           0 :     uint32_t leftover = search_area_width & 7;
     164             :     const uint8_t *pRef, *pSrc;
     165           0 :     __m128i s0, s1, s2, s3, s4, s5, s6, s8 = _mm_set1_epi32(-1);
     166             :     __m256i ss0, ss1, ss2, ss3, ss4, ss5, ss6, ss7, ss8;
     167             : 
     168           0 :     if (leftover) {
     169           0 :         for (k = 0; k < leftover; k++)
     170           0 :             s8 = _mm_slli_si128(s8, 2);
     171             :     }
     172             : 
     173           0 :     switch (block_width) {
     174           0 :     case 4:
     175             : 
     176           0 :         if (!(block_height % 4)) {
     177           0 :             uint32_t srcStrideT = 3 * src_stride;
     178           0 :             uint32_t refStrideT = 3 * ref_stride;
     179           0 :             for (i = 0; i < search_area_height; i++) {
     180           0 :                 uint32_t startW = (i & 1) << 3;
     181           0 :                 for (j = startW; j <= search_area_width - 8; j += 16) {
     182           0 :                     pSrc = src;
     183           0 :                     pRef = ref + j;
     184           0 :                     ss3 = ss5 = _mm256_setzero_si256();
     185           0 :                     for (k = 0; k < block_height; k += 4) {
     186           0 :                         ss0 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pRef)), _mm_loadu_si128((__m128i*)(pRef + 2 * ref_stride)), 0x1);
     187           0 :                         ss1 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)(pRef + ref_stride))), _mm_loadu_si128((__m128i*)(pRef + refStrideT)), 0x1);
     188           0 :                         ss2 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_unpacklo_epi64(_mm_cvtsi32_si128(*(uint32_t *)pSrc), _mm_cvtsi32_si128(*(uint32_t *)(pSrc + src_stride)))), _mm_unpacklo_epi64(_mm_cvtsi32_si128(*(uint32_t *)(pSrc + 2 * src_stride)), _mm_cvtsi32_si128(*(uint32_t *)(pSrc + srcStrideT))), 0x1);
     189           0 :                         ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
     190           0 :                         ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
     191           0 :                         pSrc += src_stride << 2;
     192           0 :                         pRef += ref_stride << 2;
     193             :                     }
     194           0 :                     ss3 = _mm256_adds_epu16(ss3, ss5);
     195           0 :                     s3 = _mm_adds_epu16(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
     196           0 :                     s3 = _mm_minpos_epu16(s3);
     197           0 :                     temSum1 = _mm_extract_epi16(s3, 0);
     198           0 :                     if (temSum1 < lowSum) {
     199           0 :                         lowSum = temSum1;
     200           0 :                         xBest = (int16_t)(j + _mm_extract_epi16(s3, 1));
     201           0 :                         yBest = i;
     202             :                     }
     203             :                 }
     204             : 
     205           0 :                 if (leftover && j < search_area_width ) {
     206           0 :                     pSrc = src;
     207           0 :                     pRef = ref + j;
     208           0 :                     ss3 = ss5 = _mm256_setzero_si256();
     209           0 :                     for (k = 0; k < block_height; k += 4) {
     210           0 :                         ss0 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pRef)), _mm_loadu_si128((__m128i*)(pRef + 2 * ref_stride)), 0x1);
     211           0 :                         ss1 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)(pRef + ref_stride))), _mm_loadu_si128((__m128i*)(pRef + refStrideT)), 0x1);
     212           0 :                         ss2 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_unpacklo_epi64(_mm_cvtsi32_si128(*(uint32_t *)pSrc), _mm_cvtsi32_si128(*(uint32_t *)(pSrc + src_stride)))), _mm_unpacklo_epi64(_mm_cvtsi32_si128(*(uint32_t *)(pSrc + 2 * src_stride)), _mm_cvtsi32_si128(*(uint32_t *)(pSrc + srcStrideT))), 0x1);
     213           0 :                         ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
     214           0 :                         ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
     215           0 :                         pSrc += src_stride << 2;
     216           0 :                         pRef += ref_stride << 2;
     217             :                     }
     218           0 :                     ss3 = _mm256_adds_epu16(ss3, ss5);
     219           0 :                     s3 = _mm_adds_epu16(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
     220           0 :                     s3 = _mm_or_si128(s3, s8);
     221           0 :                     s3 = _mm_minpos_epu16(s3);
     222           0 :                     temSum1 = _mm_extract_epi16(s3, 0);
     223           0 :                     if (temSum1 < lowSum) {
     224           0 :                         lowSum = temSum1;
     225           0 :                         xBest = (int16_t)(j + _mm_extract_epi16(s3, 1));
     226           0 :                         yBest = i;
     227             :                     }
     228             :                 }
     229           0 :                 ref += src_stride_raw;
     230             :             }
     231             :         }
     232             :         else {
     233           0 :             for (i = 0; i < search_area_height; i++) {
     234           0 :                 uint32_t startW = (i & 1) << 3;
     235           0 :                 for (j = startW; j <= search_area_width - 8; j += 16) {
     236           0 :                     pSrc = src;
     237           0 :                     pRef = ref + j;
     238           0 :                     s3 = _mm_setzero_si128();
     239           0 :                     for (k = 0; k < block_height; k += 2) {
     240           0 :                         s0 = _mm_loadu_si128((__m128i*)pRef);
     241           0 :                         s1 = _mm_loadu_si128((__m128i*)(pRef + ref_stride));
     242           0 :                         s2 = _mm_cvtsi32_si128(*(uint32_t *)pSrc);
     243           0 :                         s5 = _mm_cvtsi32_si128(*(uint32_t *)(pSrc + src_stride));
     244           0 :                         s3 = _mm_adds_epu16(s3, _mm_mpsadbw_epu8(s0, s2, 0));
     245           0 :                         s3 = _mm_adds_epu16(s3, _mm_mpsadbw_epu8(s1, s5, 0));
     246           0 :                         pSrc += src_stride << 1;
     247           0 :                         pRef += ref_stride << 1;
     248             :                     }
     249           0 :                     s3 = _mm_minpos_epu16(s3);
     250           0 :                     temSum1 = _mm_extract_epi16(s3, 0);
     251           0 :                     if (temSum1 < lowSum) {
     252           0 :                         lowSum = temSum1;
     253           0 :                         xBest = (int16_t)(j + _mm_extract_epi16(s3, 1));
     254           0 :                         yBest = i;
     255             :                     }
     256             :                 }
     257             : 
     258           0 :                 if (leftover && j < search_area_width ) {
     259           0 :                     pSrc = src;
     260           0 :                     pRef = ref + j;
     261           0 :                     s3 = _mm_setzero_si128();
     262           0 :                     for (k = 0; k < block_height; k += 2) {
     263           0 :                         s0 = _mm_loadu_si128((__m128i*)pRef);
     264           0 :                         s1 = _mm_loadu_si128((__m128i*)(pRef + ref_stride));
     265           0 :                         s2 = _mm_cvtsi32_si128(*(uint32_t *)pSrc);
     266           0 :                         s5 = _mm_cvtsi32_si128(*(uint32_t *)(pSrc + src_stride));
     267           0 :                         s3 = _mm_adds_epu16(s3, _mm_mpsadbw_epu8(s0, s2, 0));
     268           0 :                         s3 = _mm_adds_epu16(s3, _mm_mpsadbw_epu8(s1, s5, 0));
     269           0 :                         pSrc += src_stride << 1;
     270           0 :                         pRef += ref_stride << 1;
     271             :                     }
     272           0 :                     s3 = _mm_or_si128(s3, s8);
     273           0 :                     s3 = _mm_minpos_epu16(s3);
     274           0 :                     temSum1 = _mm_extract_epi16(s3, 0);
     275           0 :                     if (temSum1 < lowSum) {
     276           0 :                         lowSum = temSum1;
     277           0 :                         xBest = (int16_t)(j + _mm_extract_epi16(s3, 1));
     278           0 :                         yBest = i;
     279             :                     }
     280             :                 }
     281           0 :                 ref += src_stride_raw;
     282             :             }
     283             :         }
     284             : 
     285           0 :         break;
     286             : 
     287           0 :     case 8:
     288           0 :         if (!(block_height % 4)) {
     289           0 :             uint32_t srcStrideT = 3 * src_stride;
     290           0 :             uint32_t refStrideT = 3 * ref_stride;
     291           0 :             for (i = 0; i < search_area_height; i++) {
     292           0 :                 uint32_t startW = (i & 1) << 3;
     293           0 :                 for (j = startW; j <= search_area_width - 8; j += 16) {
     294           0 :                     pSrc = src;
     295           0 :                     pRef = ref + j;
     296           0 :                     ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
     297           0 :                     for (k = 0; k < block_height; k += 4) {
     298           0 :                         ss0 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pRef)), _mm_loadu_si128((__m128i*)(pRef + 2 * ref_stride)), 0x1);
     299           0 :                         ss1 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)(pRef + ref_stride))), _mm_loadu_si128((__m128i*)(pRef + refStrideT)), 0x1);
     300           0 :                         ss2 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_unpacklo_epi64(_mm_loadl_epi64((__m128i*)pSrc), _mm_loadl_epi64((__m128i*)(pSrc + src_stride)))), _mm_unpacklo_epi64(_mm_loadl_epi64((__m128i*)(pSrc + 2 * src_stride)), _mm_loadl_epi64((__m128i*)(pSrc + srcStrideT))), 0x1);
     301           0 :                         ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
     302           0 :                         ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
     303           0 :                         ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
     304           0 :                         ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
     305           0 :                         pSrc += src_stride << 2;
     306           0 :                         pRef += ref_stride << 2;
     307             :                     }
     308           0 :                     ss3 = _mm256_adds_epu16(_mm256_adds_epu16(ss3, ss4), _mm256_adds_epu16(ss5, ss6));
     309           0 :                     s3 = _mm_adds_epu16(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
     310           0 :                     s3 = _mm_minpos_epu16(s3);
     311           0 :                     temSum1 = _mm_extract_epi16(s3, 0);
     312           0 :                     if (temSum1 < lowSum) {
     313           0 :                         lowSum = temSum1;
     314           0 :                         xBest = (int16_t)(j + _mm_extract_epi16(s3, 1));
     315           0 :                         yBest = i;
     316             :                     }
     317             :                 }
     318             : 
     319           0 :                 if (leftover && j < search_area_width ) {
     320           0 :                     pSrc = src;
     321           0 :                     pRef = ref + j;
     322           0 :                     ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
     323           0 :                     for (k = 0; k < block_height; k += 4) {
     324           0 :                         ss0 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pRef)), _mm_loadu_si128((__m128i*)(pRef + 2 * ref_stride)), 0x1);
     325           0 :                         ss1 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)(pRef + ref_stride))), _mm_loadu_si128((__m128i*)(pRef + refStrideT)), 0x1);
     326           0 :                         ss2 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_unpacklo_epi64(_mm_loadl_epi64((__m128i*)pSrc), _mm_loadl_epi64((__m128i*)(pSrc + src_stride)))), _mm_unpacklo_epi64(_mm_loadl_epi64((__m128i*)(pSrc + 2 * src_stride)), _mm_loadl_epi64((__m128i*)(pSrc + srcStrideT))), 0x1);
     327           0 :                         ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
     328           0 :                         ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
     329           0 :                         ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
     330           0 :                         ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
     331           0 :                         pSrc += src_stride << 2;
     332           0 :                         pRef += ref_stride << 2;
     333             :                     }
     334           0 :                     ss3 = _mm256_adds_epu16(_mm256_adds_epu16(ss3, ss4), _mm256_adds_epu16(ss5, ss6));
     335           0 :                     s3 = _mm_adds_epu16(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
     336           0 :                     s3 = _mm_or_si128(s3, s8);
     337           0 :                     s3 = _mm_minpos_epu16(s3);
     338           0 :                     temSum1 = _mm_extract_epi16(s3, 0);
     339           0 :                     if (temSum1 < lowSum) {
     340           0 :                         lowSum = temSum1;
     341           0 :                         xBest = (int16_t)(j + _mm_extract_epi16(s3, 1));
     342           0 :                         yBest = i;
     343             :                     }
     344             :                 }
     345           0 :                 ref += src_stride_raw;
     346             :             }
     347             :         }
     348             :         else {
     349           0 :             for (i = 0; i < search_area_height; i++) {
     350           0 :                 uint32_t startW = (i & 1) << 3;
     351           0 :                 for (j = startW; j <= search_area_width - 8; j += 16) {
     352           0 :                     pSrc = src;
     353           0 :                     pRef = ref + j;
     354           0 :                     s3 = s4 = _mm_setzero_si128();
     355           0 :                     for (k = 0; k < block_height; k += 2) {
     356           0 :                         s0 = _mm_loadu_si128((__m128i*)pRef);
     357           0 :                         s1 = _mm_loadu_si128((__m128i*)(pRef + ref_stride));
     358           0 :                         s2 = _mm_loadl_epi64((__m128i*)pSrc);
     359           0 :                         s5 = _mm_loadl_epi64((__m128i*)(pSrc + src_stride));
     360           0 :                         s3 = _mm_adds_epu16(s3, _mm_mpsadbw_epu8(s0, s2, 0));
     361           0 :                         s4 = _mm_adds_epu16(s4, _mm_mpsadbw_epu8(s0, s2, 5));
     362           0 :                         s3 = _mm_adds_epu16(s3, _mm_mpsadbw_epu8(s1, s5, 0));
     363           0 :                         s4 = _mm_adds_epu16(s4, _mm_mpsadbw_epu8(s1, s5, 5));
     364           0 :                         pSrc += src_stride << 1;
     365           0 :                         pRef += ref_stride << 1;
     366             :                     }
     367           0 :                     s3 = _mm_adds_epu16(s3, s4);
     368           0 :                     s3 = _mm_minpos_epu16(s3);
     369           0 :                     temSum1 = _mm_extract_epi16(s3, 0);
     370           0 :                     if (temSum1 < lowSum) {
     371           0 :                         lowSum = temSum1;
     372           0 :                         xBest = (int16_t)(j + _mm_extract_epi16(s3, 1));
     373           0 :                         yBest = i;
     374             :                     }
     375             :                 }
     376             : 
     377           0 :                 if (leftover && j < search_area_width ) {
     378           0 :                     pSrc = src;
     379           0 :                     pRef = ref + j;
     380           0 :                     s3 = s4 = _mm_setzero_si128();
     381           0 :                     for (k = 0; k < block_height; k += 2) {
     382           0 :                         s0 = _mm_loadu_si128((__m128i*)pRef);
     383           0 :                         s1 = _mm_loadu_si128((__m128i*)(pRef + ref_stride));
     384           0 :                         s2 = _mm_loadl_epi64((__m128i*)pSrc);
     385           0 :                         s5 = _mm_loadl_epi64((__m128i*)(pSrc + src_stride));
     386           0 :                         s3 = _mm_adds_epu16(s3, _mm_mpsadbw_epu8(s0, s2, 0));
     387           0 :                         s4 = _mm_adds_epu16(s4, _mm_mpsadbw_epu8(s0, s2, 5));
     388           0 :                         s3 = _mm_adds_epu16(s3, _mm_mpsadbw_epu8(s1, s5, 0));
     389           0 :                         s4 = _mm_adds_epu16(s4, _mm_mpsadbw_epu8(s1, s5, 5));
     390           0 :                         pSrc += src_stride << 1;
     391           0 :                         pRef += ref_stride << 1;
     392             :                     }
     393           0 :                     s3 = _mm_adds_epu16(s3, s4);
     394           0 :                     s3 = _mm_or_si128(s3, s8);
     395           0 :                     s3 = _mm_minpos_epu16(s3);
     396           0 :                     temSum1 = _mm_extract_epi16(s3, 0);
     397           0 :                     if (temSum1 < lowSum) {
     398           0 :                         lowSum = temSum1;
     399           0 :                         xBest = (int16_t)(j + _mm_extract_epi16(s3, 1));
     400           0 :                         yBest = i;
     401             :                     }
     402             :                 }
     403           0 :                 ref += src_stride_raw;
     404             :             }
     405             :         }
     406           0 :         break;
     407             : 
     408           0 :     case 16:
     409           0 :         if (block_height <= 16) {
     410           0 :             for (i = 0; i < search_area_height; i++) {
     411           0 :                 uint32_t startW = (i & 1) << 3;
     412           0 :                 for (j = startW; j <= search_area_width - 8; j += 16) {
     413           0 :                     pSrc = src;
     414           0 :                     pRef = ref + j;
     415           0 :                     ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
     416           0 :                     for (k = 0; k < block_height; k += 2) {
     417           0 :                         ss0 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pRef)), _mm_loadu_si128((__m128i*)(pRef + ref_stride)), 0x1);
     418           0 :                         ss1 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)(pRef + 8))), _mm_loadu_si128((__m128i*)(pRef + ref_stride + 8)), 0x1);
     419           0 :                         ss2 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pSrc)), _mm_loadu_si128((__m128i*)(pSrc + src_stride)), 0x1);
     420           0 :                         ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
     421           0 :                         ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
     422           0 :                         ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
     423           0 :                         ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
     424           0 :                         pSrc += 2 * src_stride;
     425           0 :                         pRef += 2 * ref_stride;
     426             :                     }
     427           0 :                     ss3 = _mm256_adds_epu16(_mm256_adds_epu16(ss3, ss4), _mm256_adds_epu16(ss5, ss6));
     428           0 :                     s3 = _mm_adds_epu16(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
     429           0 :                     s3 = _mm_minpos_epu16(s3);
     430           0 :                     temSum1 = _mm_extract_epi16(s3, 0);
     431           0 :                     if (temSum1 < lowSum) {
     432           0 :                         lowSum = temSum1;
     433           0 :                         xBest = (int16_t)(j + _mm_extract_epi16(s3, 1));
     434           0 :                         yBest = i;
     435             :                     }
     436             :                 }
     437             : 
     438           0 :                 if (leftover && j < search_area_width ) {
     439           0 :                     pSrc = src;
     440           0 :                     pRef = ref + j;
     441           0 :                     ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
     442           0 :                     for (k = 0; k < block_height; k += 2) {
     443           0 :                         ss0 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pRef)), _mm_loadu_si128((__m128i*)(pRef + ref_stride)), 0x1);
     444           0 :                         ss1 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)(pRef + 8))), _mm_loadu_si128((__m128i*)(pRef + ref_stride + 8)), 0x1);
     445           0 :                         ss2 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pSrc)), _mm_loadu_si128((__m128i*)(pSrc + src_stride)), 0x1);
     446           0 :                         ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
     447           0 :                         ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
     448           0 :                         ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
     449           0 :                         ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
     450           0 :                         pSrc += 2 * src_stride;
     451           0 :                         pRef += 2 * ref_stride;
     452             :                     }
     453           0 :                     ss3 = _mm256_adds_epu16(_mm256_adds_epu16(ss3, ss4), _mm256_adds_epu16(ss5, ss6));
     454           0 :                     s3 = _mm_adds_epu16(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
     455           0 :                     s3 = _mm_or_si128(s3, s8);
     456           0 :                     s3 = _mm_minpos_epu16(s3);
     457           0 :                     temSum1 = _mm_extract_epi16(s3, 0);
     458           0 :                     if (temSum1 < lowSum) {
     459           0 :                         lowSum = temSum1;
     460           0 :                         xBest = (int16_t)(j + _mm_extract_epi16(s3, 1));
     461           0 :                         yBest = i;
     462             :                     }
     463             :                 }
     464           0 :                 ref += src_stride_raw;
     465             :             }
     466             :         }
     467           0 :         else if (block_height <= 32) {
     468           0 :             for (i = 0; i < search_area_height; i++) {
     469           0 :                 uint32_t startW = (i & 1) << 3;
     470           0 :                 for (j = startW; j <= search_area_width - 8; j += 16) {
     471           0 :                     pSrc = src;
     472           0 :                     pRef = ref + j;
     473           0 :                     ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
     474           0 :                     for (k = 0; k < block_height; k += 2) {
     475           0 :                         ss0 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pRef)), _mm_loadu_si128((__m128i*)(pRef + ref_stride)), 0x1);
     476           0 :                         ss1 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)(pRef + 8))), _mm_loadu_si128((__m128i*)(pRef + ref_stride + 8)), 0x1);
     477           0 :                         ss2 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pSrc)), _mm_loadu_si128((__m128i*)(pSrc + src_stride)), 0x1);
     478           0 :                         ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
     479           0 :                         ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
     480           0 :                         ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
     481           0 :                         ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
     482           0 :                         pSrc += 2 * src_stride;
     483           0 :                         pRef += 2 * ref_stride;
     484             :                     }
     485           0 :                     ss3 = _mm256_adds_epu16(_mm256_adds_epu16(ss3, ss4), _mm256_adds_epu16(ss5, ss6));
     486           0 :                     s3 = _mm256_castsi256_si128(ss3);
     487           0 :                     s5 = _mm256_extracti128_si256(ss3, 1);
     488           0 :                     s4 = _mm_minpos_epu16(s3);
     489           0 :                     s6 = _mm_minpos_epu16(s5);
     490           0 :                     s4 = _mm_unpacklo_epi16(s4, s4);
     491           0 :                     s4 = _mm_unpacklo_epi32(s4, s4);
     492           0 :                     s4 = _mm_unpacklo_epi64(s4, s4);
     493           0 :                     s6 = _mm_unpacklo_epi16(s6, s6);
     494           0 :                     s6 = _mm_unpacklo_epi32(s6, s6);
     495           0 :                     s6 = _mm_unpacklo_epi64(s6, s6);
     496           0 :                     s3 = _mm_sub_epi16(s3, s4);
     497           0 :                     s5 = _mm_adds_epu16(s5, s3);
     498           0 :                     s5 = _mm_sub_epi16(s5, s6);
     499           0 :                     s5 = _mm_minpos_epu16(s5);
     500           0 :                     temSum1 = _mm_extract_epi16(s5, 0);
     501           0 :                     temSum1 += _mm_extract_epi16(s4, 0);
     502           0 :                     temSum1 += _mm_extract_epi16(s6, 0);
     503           0 :                     if (temSum1 < lowSum) {
     504           0 :                         lowSum = temSum1;
     505           0 :                         xBest = (int16_t)(j + _mm_extract_epi16(s5, 1));
     506           0 :                         yBest = i;
     507             :                     }
     508             :                 }
     509             : 
     510           0 :                 if (leftover && j < search_area_width ) {
     511           0 :                     pSrc = src;
     512           0 :                     pRef = ref + j;
     513           0 :                     ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
     514           0 :                     for (k = 0; k < block_height; k += 2) {
     515           0 :                         ss0 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pRef)), _mm_loadu_si128((__m128i*)(pRef + ref_stride)), 0x1);
     516           0 :                         ss1 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)(pRef + 8))), _mm_loadu_si128((__m128i*)(pRef + ref_stride + 8)), 0x1);
     517           0 :                         ss2 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pSrc)), _mm_loadu_si128((__m128i*)(pSrc + src_stride)), 0x1);
     518           0 :                         ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
     519           0 :                         ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
     520           0 :                         ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
     521           0 :                         ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
     522           0 :                         pSrc += 2 * src_stride;
     523           0 :                         pRef += 2 * ref_stride;
     524             :                     }
     525           0 :                     ss3 = _mm256_adds_epu16(_mm256_adds_epu16(ss3, ss4), _mm256_adds_epu16(ss5, ss6));
     526           0 :                     s3 = _mm256_castsi256_si128(ss3);
     527           0 :                     s5 = _mm256_extracti128_si256(ss3, 1);
     528           0 :                     s3 = _mm_or_si128(s3, s8);
     529           0 :                     s5 = _mm_or_si128(s5, s8);
     530           0 :                     s4 = _mm_minpos_epu16(s3);
     531           0 :                     s6 = _mm_minpos_epu16(s5);
     532           0 :                     s4 = _mm_unpacklo_epi16(s4, s4);
     533           0 :                     s4 = _mm_unpacklo_epi32(s4, s4);
     534           0 :                     s4 = _mm_unpacklo_epi64(s4, s4);
     535           0 :                     s6 = _mm_unpacklo_epi16(s6, s6);
     536           0 :                     s6 = _mm_unpacklo_epi32(s6, s6);
     537           0 :                     s6 = _mm_unpacklo_epi64(s6, s6);
     538           0 :                     s3 = _mm_sub_epi16(s3, s4);
     539           0 :                     s5 = _mm_adds_epu16(s5, s3);
     540           0 :                     s5 = _mm_sub_epi16(s5, s6);
     541           0 :                     s5 = _mm_minpos_epu16(s5);
     542           0 :                     temSum1 = _mm_extract_epi16(s5, 0);
     543           0 :                     temSum1 += _mm_extract_epi16(s4, 0);
     544           0 :                     temSum1 += _mm_extract_epi16(s6, 0);
     545           0 :                     if (temSum1 < lowSum) {
     546           0 :                         lowSum = temSum1;
     547           0 :                         xBest = (int16_t)(j + _mm_extract_epi16(s5, 1));
     548           0 :                         yBest = i;
     549             :                     }
     550             :                 }
     551           0 :                 ref += src_stride_raw;
     552             :             }
     553             :         }
     554             :         else {
     555           0 :             for (i = 0; i < search_area_height; i++) {
     556           0 :                 uint32_t startW = (i & 1) << 3;
     557           0 :                 for (j = startW; j <= search_area_width - 8; j += 16) {
     558           0 :                     pSrc = src;
     559           0 :                     pRef = ref + j;
     560           0 :                     ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
     561           0 :                     for (k = 0; k < block_height; k += 2) {
     562           0 :                         ss0 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pRef)), _mm_loadu_si128((__m128i*)(pRef + ref_stride)), 0x1);
     563           0 :                         ss1 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)(pRef + 8))), _mm_loadu_si128((__m128i*)(pRef + ref_stride + 8)), 0x1);
     564           0 :                         ss2 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pSrc)), _mm_loadu_si128((__m128i*)(pSrc + src_stride)), 0x1);
     565           0 :                         ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
     566           0 :                         ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
     567           0 :                         ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
     568           0 :                         ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
     569           0 :                         pSrc += 2 * src_stride;
     570           0 :                         pRef += 2 * ref_stride;
     571             :                     }
     572           0 :                     ss3 = _mm256_adds_epu16(ss3, ss4);
     573           0 :                     ss5 = _mm256_adds_epu16(ss5, ss6);
     574           0 :                     ss0 = _mm256_adds_epu16(ss3, ss5);
     575           0 :                     s0 = _mm_adds_epu16(_mm256_castsi256_si128(ss0), _mm256_extracti128_si256(ss0, 1));
     576           0 :                     s0 = _mm_minpos_epu16(s0);
     577           0 :                     temSum1 = _mm_extract_epi16(s0, 0);
     578           0 :                     if (temSum1 < lowSum) {
     579           0 :                         if (temSum1 != 0xFFFF) { // no overflow
     580           0 :                             lowSum = temSum1;
     581           0 :                             xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
     582           0 :                             yBest = i;
     583             :                         }
     584             :                         else {
     585           0 :                             ss4 = _mm256_unpacklo_epi16(ss3, _mm256_setzero_si256());
     586           0 :                             ss3 = _mm256_unpackhi_epi16(ss3, _mm256_setzero_si256());
     587           0 :                             ss6 = _mm256_unpacklo_epi16(ss5, _mm256_setzero_si256());
     588           0 :                             ss5 = _mm256_unpackhi_epi16(ss5, _mm256_setzero_si256());
     589           0 :                             ss4 = _mm256_add_epi32(ss4, ss6);
     590           0 :                             ss3 = _mm256_add_epi32(ss3, ss5);
     591           0 :                             s0 = _mm_add_epi32(_mm256_castsi256_si128(ss4), _mm256_extracti128_si256(ss4, 1));
     592           0 :                             s3 = _mm_add_epi32(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
     593           0 :                             UPDATE_BEST(s0, 0, 0);
     594           0 :                             UPDATE_BEST(s0, 1, 0);
     595           0 :                             UPDATE_BEST(s0, 2, 0);
     596           0 :                             UPDATE_BEST(s0, 3, 0);
     597           0 :                             UPDATE_BEST(s3, 0, 4);
     598           0 :                             UPDATE_BEST(s3, 1, 4);
     599           0 :                             UPDATE_BEST(s3, 2, 4);
     600           0 :                             UPDATE_BEST(s3, 3, 4);
     601             :                         }
     602             :                     }
     603             :                 }
     604             : 
     605           0 :                 if (leftover && j < search_area_width ) {
     606           0 :                     pSrc = src;
     607           0 :                     pRef = ref + j;
     608           0 :                     ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
     609           0 :                     for (k = 0; k < block_height; k += 2) {
     610           0 :                         ss0 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pRef)), _mm_loadu_si128((__m128i*)(pRef + ref_stride)), 0x1);
     611           0 :                         ss1 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)(pRef + 8))), _mm_loadu_si128((__m128i*)(pRef + ref_stride + 8)), 0x1);
     612           0 :                         ss2 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pSrc)), _mm_loadu_si128((__m128i*)(pSrc + src_stride)), 0x1);
     613           0 :                         ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
     614           0 :                         ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
     615           0 :                         ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
     616           0 :                         ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
     617           0 :                         pSrc += 2 * src_stride;
     618           0 :                         pRef += 2 * ref_stride;
     619             :                     }
     620           0 :                     ss3 = _mm256_adds_epu16(ss3, ss4);
     621           0 :                     ss5 = _mm256_adds_epu16(ss5, ss6);
     622           0 :                     ss0 = _mm256_adds_epu16(ss3, ss5);
     623           0 :                     s0 = _mm_adds_epu16(_mm256_castsi256_si128(ss0), _mm256_extracti128_si256(ss0, 1));
     624           0 :                     s0 = _mm_or_si128(s0, s8);
     625           0 :                     s0 = _mm_minpos_epu16(s0);
     626           0 :                     temSum1 = _mm_extract_epi16(s0, 0);
     627           0 :                     if (temSum1 < lowSum) {
     628           0 :                         if (temSum1 != 0xFFFF) { // no overflow
     629           0 :                             lowSum = temSum1;
     630           0 :                             xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
     631           0 :                             yBest = i;
     632             :                         }
     633             :                         else {
     634           0 :                             ss4 = _mm256_unpacklo_epi16(ss3, _mm256_setzero_si256());
     635           0 :                             ss3 = _mm256_unpackhi_epi16(ss3, _mm256_setzero_si256());
     636           0 :                             ss6 = _mm256_unpacklo_epi16(ss5, _mm256_setzero_si256());
     637           0 :                             ss5 = _mm256_unpackhi_epi16(ss5, _mm256_setzero_si256());
     638           0 :                             ss4 = _mm256_add_epi32(ss4, ss6);
     639           0 :                             ss3 = _mm256_add_epi32(ss3, ss5);
     640           0 :                             s0 = _mm_add_epi32(_mm256_castsi256_si128(ss4), _mm256_extracti128_si256(ss4, 1));
     641           0 :                             s3 = _mm_add_epi32(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
     642           0 :                             k = leftover;
     643           0 :                             while (k > 0) {
     644           0 :                                 for (l = 0; l < 4 && k; l++, k--) {
     645           0 :                                     temSum1 = _mm_extract_epi32(s0, 0);
     646           0 :                                     s0 = _mm_srli_si128(s0, 4);
     647           0 :                                     if (temSum1 < lowSum) {
     648           0 :                                         lowSum = temSum1;
     649           0 :                                         xBest = (int16_t)(j + leftover - k);
     650           0 :                                         yBest = i;
     651             :                                     }
     652             :                                 }
     653           0 :                                 s0 = s3;
     654             :                             }
     655             :                         }
     656             :                     }
     657             :                 }
     658           0 :                 ref += src_stride_raw;
     659             :             }
     660             :         }
     661           0 :         break;
     662             : 
     663           0 :     case 24:
     664           0 :         if (block_height <= 16) {
     665           0 :             for (i = 0; i < search_area_height; i++) {
     666           0 :                 uint32_t startW = (i & 1) << 3;
     667           0 :                 for (j = startW; j <= search_area_width - 8; j += 16) {
     668           0 :                     pSrc = src;
     669           0 :                     pRef = ref + j;
     670           0 :                     ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
     671           0 :                     for (k = 0; k < block_height; k++) {
     672           0 :                         ss0 = _mm256_loadu_si256((__m256i*)pRef);
     673           0 :                         ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
     674           0 :                         ss2 = _mm256_loadu_si256((__m256i *)pSrc);
     675           0 :                         ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
     676           0 :                         ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
     677           0 :                         ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
     678           0 :                         ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
     679           0 :                         pSrc += src_stride;
     680           0 :                         pRef += ref_stride;
     681             :                     }
     682           0 :                     ss3 = _mm256_adds_epu16(ss3, ss4);
     683           0 :                     ss5 = _mm256_adds_epu16(ss5, ss6);
     684           0 :                     s3 = _mm_adds_epu16(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
     685           0 :                     s5 = _mm256_castsi256_si128(ss5);
     686           0 :                     s4 = _mm_minpos_epu16(s3);
     687           0 :                     s6 = _mm_minpos_epu16(s5);
     688           0 :                     s4 = _mm_unpacklo_epi16(s4, s4);
     689           0 :                     s4 = _mm_unpacklo_epi32(s4, s4);
     690           0 :                     s4 = _mm_unpacklo_epi64(s4, s4);
     691           0 :                     s6 = _mm_unpacklo_epi16(s6, s6);
     692           0 :                     s6 = _mm_unpacklo_epi32(s6, s6);
     693           0 :                     s6 = _mm_unpacklo_epi64(s6, s6);
     694           0 :                     s3 = _mm_sub_epi16(s3, s4);
     695           0 :                     s5 = _mm_adds_epu16(s5, s3);
     696           0 :                     s5 = _mm_sub_epi16(s5, s6);
     697           0 :                     s5 = _mm_minpos_epu16(s5);
     698           0 :                     temSum1 = _mm_extract_epi16(s5, 0);
     699           0 :                     temSum1 += _mm_extract_epi16(s4, 0);
     700           0 :                     temSum1 += _mm_extract_epi16(s6, 0);
     701           0 :                     if (temSum1 < lowSum) {
     702           0 :                         lowSum = temSum1;
     703           0 :                         xBest = (int16_t)(j + _mm_extract_epi16(s5, 1));
     704           0 :                         yBest = i;
     705             :                     }
     706             :                 }
     707             : 
     708           0 :                 if (leftover && j < search_area_width ) {
     709           0 :                     pSrc = src;
     710           0 :                     pRef = ref + j;
     711           0 :                     ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
     712           0 :                     for (k = 0; k < block_height; k++) {
     713           0 :                         ss0 = _mm256_loadu_si256((__m256i*)pRef);
     714           0 :                         ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
     715           0 :                         ss2 = _mm256_loadu_si256((__m256i *)pSrc);
     716           0 :                         ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
     717           0 :                         ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
     718           0 :                         ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
     719           0 :                         ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
     720           0 :                         pSrc += src_stride;
     721           0 :                         pRef += ref_stride;
     722             :                     }
     723           0 :                     ss3 = _mm256_adds_epu16(ss3, ss4);
     724           0 :                     ss5 = _mm256_adds_epu16(ss5, ss6);
     725           0 :                     s3 = _mm_adds_epu16(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
     726           0 :                     s5 = _mm256_castsi256_si128(ss5);
     727           0 :                     s3 = _mm_or_si128(s3, s8);
     728           0 :                     s5 = _mm_or_si128(s5, s8);
     729           0 :                     s4 = _mm_minpos_epu16(s3);
     730           0 :                     s6 = _mm_minpos_epu16(s5);
     731           0 :                     s4 = _mm_unpacklo_epi16(s4, s4);
     732           0 :                     s4 = _mm_unpacklo_epi32(s4, s4);
     733           0 :                     s4 = _mm_unpacklo_epi64(s4, s4);
     734           0 :                     s6 = _mm_unpacklo_epi16(s6, s6);
     735           0 :                     s6 = _mm_unpacklo_epi32(s6, s6);
     736           0 :                     s6 = _mm_unpacklo_epi64(s6, s6);
     737           0 :                     s3 = _mm_sub_epi16(s3, s4);
     738           0 :                     s5 = _mm_adds_epu16(s5, s3);
     739           0 :                     s5 = _mm_sub_epi16(s5, s6);
     740           0 :                     s5 = _mm_minpos_epu16(s5);
     741           0 :                     temSum1 = _mm_extract_epi16(s5, 0);
     742           0 :                     temSum1 += _mm_extract_epi16(s4, 0);
     743           0 :                     temSum1 += _mm_extract_epi16(s6, 0);
     744           0 :                     if (temSum1 < lowSum) {
     745           0 :                         lowSum = temSum1;
     746           0 :                         xBest = (int16_t)(j + _mm_extract_epi16(s5, 1));
     747           0 :                         yBest = i;
     748             :                     }
     749             :                 }
     750           0 :                 ref += src_stride_raw;
     751             :             }
     752             :         }
     753             :         else {
     754           0 :             for (i = 0; i < search_area_height; i++) {
     755           0 :                 uint32_t startW = (i & 1) << 3;
     756           0 :                 for (j = startW; j <= search_area_width - 8; j += 16) {
     757           0 :                     pSrc = src;
     758           0 :                     pRef = ref + j;
     759           0 :                     ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
     760           0 :                     for (k = 0; k < block_height; k++) {
     761           0 :                         ss0 = _mm256_loadu_si256((__m256i*)pRef);
     762           0 :                         ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
     763           0 :                         ss2 = _mm256_loadu_si256((__m256i *)pSrc);
     764           0 :                         ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
     765           0 :                         ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
     766           0 :                         ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
     767           0 :                         ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
     768           0 :                         pSrc += src_stride;
     769           0 :                         pRef += ref_stride;
     770             :                     }
     771           0 :                     ss3 = _mm256_adds_epu16(ss3, ss4);
     772           0 :                     ss5 = _mm256_adds_epu16(ss5, ss6);
     773           0 :                     s3 = _mm256_castsi256_si128(ss3);
     774           0 :                     s4 = _mm256_extracti128_si256(ss3, 1);
     775           0 :                     s5 = _mm256_castsi256_si128(ss5);
     776           0 :                     s0 = _mm_adds_epu16(_mm_adds_epu16(s3, s4), s5);
     777           0 :                     s0 = _mm_minpos_epu16(s0);
     778           0 :                     temSum1 = _mm_extract_epi16(s0, 0);
     779           0 :                     if (temSum1 < lowSum) {
     780           0 :                         if (temSum1 != 0xFFFF) { // no overflow
     781           0 :                             lowSum = temSum1;
     782           0 :                             xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
     783           0 :                             yBest = i;
     784             :                         }
     785             :                         else {
     786           0 :                             s0 = _mm_unpacklo_epi16(s3, _mm_setzero_si128());
     787           0 :                             s3 = _mm_unpackhi_epi16(s3, _mm_setzero_si128());
     788           0 :                             s1 = _mm_unpacklo_epi16(s4, _mm_setzero_si128());
     789           0 :                             s4 = _mm_unpackhi_epi16(s4, _mm_setzero_si128());
     790           0 :                             s2 = _mm_unpacklo_epi16(s5, _mm_setzero_si128());
     791           0 :                             s5 = _mm_unpackhi_epi16(s5, _mm_setzero_si128());
     792           0 :                             s0 = _mm_add_epi32(_mm_add_epi32(s0, s1), s2);
     793           0 :                             s3 = _mm_add_epi32(_mm_add_epi32(s3, s4), s5);
     794           0 :                             UPDATE_BEST(s0, 0, 0);
     795           0 :                             UPDATE_BEST(s0, 1, 0);
     796           0 :                             UPDATE_BEST(s0, 2, 0);
     797           0 :                             UPDATE_BEST(s0, 3, 0);
     798           0 :                             UPDATE_BEST(s3, 0, 4);
     799           0 :                             UPDATE_BEST(s3, 1, 4);
     800           0 :                             UPDATE_BEST(s3, 2, 4);
     801           0 :                             UPDATE_BEST(s3, 3, 4);
     802             :                         }
     803             :                     }
     804             :                 }
     805             : 
     806           0 :                 if (leftover && j < search_area_width ) {
     807           0 :                     pSrc = src;
     808           0 :                     pRef = ref + j;
     809           0 :                     ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
     810           0 :                     for (k = 0; k < block_height; k++) {
     811           0 :                         ss0 = _mm256_loadu_si256((__m256i*)pRef);
     812           0 :                         ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
     813           0 :                         ss2 = _mm256_loadu_si256((__m256i *)pSrc);
     814           0 :                         ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
     815           0 :                         ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
     816           0 :                         ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
     817           0 :                         ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
     818           0 :                         pSrc += src_stride;
     819           0 :                         pRef += ref_stride;
     820             :                     }
     821           0 :                     ss3 = _mm256_adds_epu16(ss3, ss4);
     822           0 :                     ss5 = _mm256_adds_epu16(ss5, ss6);
     823           0 :                     s3 = _mm256_castsi256_si128(ss3);
     824           0 :                     s4 = _mm256_extracti128_si256(ss3, 1);
     825           0 :                     s5 = _mm256_castsi256_si128(ss5);
     826           0 :                     s0 = _mm_adds_epu16(_mm_adds_epu16(s3, s4), s5);
     827           0 :                     s0 = _mm_or_si128(s0, s8);
     828           0 :                     s0 = _mm_minpos_epu16(s0);
     829           0 :                     temSum1 = _mm_extract_epi16(s0, 0);
     830           0 :                     if (temSum1 < lowSum) {
     831           0 :                         if (temSum1 != 0xFFFF) { // no overflow
     832           0 :                             lowSum = temSum1;
     833           0 :                             xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
     834           0 :                             yBest = i;
     835             :                         }
     836             :                         else {
     837           0 :                             s0 = _mm_unpacklo_epi16(s3, _mm_setzero_si128());
     838           0 :                             s3 = _mm_unpackhi_epi16(s3, _mm_setzero_si128());
     839           0 :                             s1 = _mm_unpacklo_epi16(s4, _mm_setzero_si128());
     840           0 :                             s4 = _mm_unpackhi_epi16(s4, _mm_setzero_si128());
     841           0 :                             s2 = _mm_unpacklo_epi16(s5, _mm_setzero_si128());
     842           0 :                             s5 = _mm_unpackhi_epi16(s5, _mm_setzero_si128());
     843           0 :                             s0 = _mm_add_epi32(_mm_add_epi32(s0, s1), s2);
     844           0 :                             s3 = _mm_add_epi32(_mm_add_epi32(s3, s4), s5);
     845           0 :                             k = leftover;
     846           0 :                             while (k > 0) {
     847           0 :                                 for (l = 0; l < 4 && k; l++, k--) {
     848           0 :                                     temSum1 = _mm_extract_epi32(s0, 0);
     849           0 :                                     s0 = _mm_srli_si128(s0, 4);
     850           0 :                                     if (temSum1 < lowSum) {
     851           0 :                                         lowSum = temSum1;
     852           0 :                                         xBest = (int16_t)(j + leftover - k);
     853           0 :                                         yBest = i;
     854             :                                     }
     855             :                                 }
     856           0 :                                 s0 = s3;
     857             :                             }
     858             :                         }
     859             :                     }
     860             :                 }
     861           0 :                 ref += src_stride_raw;
     862             :             }
     863             :         }
     864           0 :         break;
     865             : 
     866           0 :     case 32:
     867           0 :         if (block_height <= 16) {
     868           0 :             for (i = 0; i < search_area_height; i++) {
     869           0 :                 uint32_t startW = (i & 1) << 3;
     870           0 :                 for (j = startW; j <= search_area_width - 8; j += 16) {
     871           0 :                     pSrc = src;
     872           0 :                     pRef = ref + j;
     873           0 :                     ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
     874           0 :                     for (k = 0; k < block_height; k++) {
     875           0 :                         ss0 = _mm256_loadu_si256((__m256i*)pRef);
     876           0 :                         ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
     877           0 :                         ss2 = _mm256_loadu_si256((__m256i *)pSrc);
     878           0 :                         ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
     879           0 :                         ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
     880           0 :                         ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
     881           0 :                         ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
     882           0 :                         pSrc += src_stride;
     883           0 :                         pRef += ref_stride;
     884             :                     }
     885           0 :                     ss3 = _mm256_adds_epu16(_mm256_adds_epu16(ss3, ss4), _mm256_adds_epu16(ss5, ss6));
     886           0 :                     s3 = _mm256_castsi256_si128(ss3);
     887           0 :                     s5 = _mm256_extracti128_si256(ss3, 1);
     888           0 :                     s4 = _mm_minpos_epu16(s3);
     889           0 :                     s6 = _mm_minpos_epu16(s5);
     890           0 :                     s4 = _mm_unpacklo_epi16(s4, s4);
     891           0 :                     s4 = _mm_unpacklo_epi32(s4, s4);
     892           0 :                     s4 = _mm_unpacklo_epi64(s4, s4);
     893           0 :                     s6 = _mm_unpacklo_epi16(s6, s6);
     894           0 :                     s6 = _mm_unpacklo_epi32(s6, s6);
     895           0 :                     s6 = _mm_unpacklo_epi64(s6, s6);
     896           0 :                     s3 = _mm_sub_epi16(s3, s4);
     897           0 :                     s5 = _mm_adds_epu16(s5, s3);
     898           0 :                     s5 = _mm_sub_epi16(s5, s6);
     899           0 :                     s5 = _mm_minpos_epu16(s5);
     900           0 :                     temSum1 = _mm_extract_epi16(s5, 0);
     901           0 :                     temSum1 += _mm_extract_epi16(s4, 0);
     902           0 :                     temSum1 += _mm_extract_epi16(s6, 0);
     903           0 :                     if (temSum1 < lowSum) {
     904           0 :                         lowSum = temSum1;
     905           0 :                         xBest = (int16_t)(j + _mm_extract_epi16(s5, 1));
     906           0 :                         yBest = i;
     907             :                     }
     908             :                 }
     909             : 
     910           0 :                 if (leftover && j < search_area_width ) {
     911           0 :                     pSrc = src;
     912           0 :                     pRef = ref + j;
     913           0 :                     ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
     914           0 :                     for (k = 0; k < block_height; k++) {
     915           0 :                         ss0 = _mm256_loadu_si256((__m256i*)pRef);
     916           0 :                         ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
     917           0 :                         ss2 = _mm256_loadu_si256((__m256i *)pSrc);
     918           0 :                         ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
     919           0 :                         ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
     920           0 :                         ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
     921           0 :                         ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
     922           0 :                         pSrc += src_stride;
     923           0 :                         pRef += ref_stride;
     924             :                     }
     925           0 :                     ss3 = _mm256_adds_epu16(_mm256_adds_epu16(ss3, ss4), _mm256_adds_epu16(ss5, ss6));
     926           0 :                     s3 = _mm256_castsi256_si128(ss3);
     927           0 :                     s5 = _mm256_extracti128_si256(ss3, 1);
     928           0 :                     s3 = _mm_or_si128(s3, s8);
     929           0 :                     s5 = _mm_or_si128(s5, s8);
     930           0 :                     s4 = _mm_minpos_epu16(s3);
     931           0 :                     s6 = _mm_minpos_epu16(s5);
     932           0 :                     s4 = _mm_unpacklo_epi16(s4, s4);
     933           0 :                     s4 = _mm_unpacklo_epi32(s4, s4);
     934           0 :                     s4 = _mm_unpacklo_epi64(s4, s4);
     935           0 :                     s6 = _mm_unpacklo_epi16(s6, s6);
     936           0 :                     s6 = _mm_unpacklo_epi32(s6, s6);
     937           0 :                     s6 = _mm_unpacklo_epi64(s6, s6);
     938           0 :                     s3 = _mm_sub_epi16(s3, s4);
     939           0 :                     s5 = _mm_adds_epu16(s5, s3);
     940           0 :                     s5 = _mm_sub_epi16(s5, s6);
     941           0 :                     s5 = _mm_minpos_epu16(s5);
     942           0 :                     temSum1 = _mm_extract_epi16(s5, 0);
     943           0 :                     temSum1 += _mm_extract_epi16(s4, 0);
     944           0 :                     temSum1 += _mm_extract_epi16(s6, 0);
     945           0 :                     if (temSum1 < lowSum) {
     946           0 :                         lowSum = temSum1;
     947           0 :                         xBest = (int16_t)(j + _mm_extract_epi16(s5, 1));
     948           0 :                         yBest = i;
     949             :                     }
     950             :                 }
     951           0 :                 ref += src_stride_raw;
     952             :             }
     953             :         }
     954           0 :         else if (block_height <= 32) {
     955           0 :             for (i = 0; i < search_area_height; i++) {
     956           0 :                 uint32_t startW = (i & 1) << 3;
     957           0 :                 for (j = startW; j <= search_area_width - 8; j += 16) {
     958           0 :                     pSrc = src;
     959           0 :                     pRef = ref + j;
     960           0 :                     ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
     961           0 :                     for (k = 0; k < block_height; k++) {
     962           0 :                         ss0 = _mm256_loadu_si256((__m256i*)pRef);
     963           0 :                         ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
     964           0 :                         ss2 = _mm256_loadu_si256((__m256i *)pSrc);
     965           0 :                         ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
     966           0 :                         ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
     967           0 :                         ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
     968           0 :                         ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
     969           0 :                         pSrc += src_stride;
     970           0 :                         pRef += ref_stride;
     971             :                     }
     972           0 :                     ss3 = _mm256_adds_epu16(ss3, ss4);
     973           0 :                     ss5 = _mm256_adds_epu16(ss5, ss6);
     974           0 :                     ss6 = _mm256_adds_epu16(ss3, ss5);
     975           0 :                     s3 = _mm256_castsi256_si128(ss6);
     976           0 :                     s4 = _mm256_extracti128_si256(ss6, 1);
     977           0 :                     s0 = _mm_adds_epu16(s3, s4);
     978           0 :                     s0 = _mm_minpos_epu16(s0);
     979           0 :                     temSum1 = _mm_extract_epi16(s0, 0);
     980           0 :                     if (temSum1 < lowSum) {
     981           0 :                         if (temSum1 != 0xFFFF) { // no overflow
     982           0 :                             lowSum = temSum1;
     983           0 :                             xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
     984           0 :                             yBest = i;
     985             :                         }
     986             :                         else {
     987           0 :                             ss4 = _mm256_unpacklo_epi16(ss3, _mm256_setzero_si256());
     988           0 :                             ss3 = _mm256_unpackhi_epi16(ss3, _mm256_setzero_si256());
     989           0 :                             ss6 = _mm256_unpacklo_epi16(ss5, _mm256_setzero_si256());
     990           0 :                             ss5 = _mm256_unpackhi_epi16(ss5, _mm256_setzero_si256());
     991           0 :                             ss4 = _mm256_add_epi32(ss4, ss6);
     992           0 :                             ss3 = _mm256_add_epi32(ss3, ss5);
     993           0 :                             s0 = _mm_add_epi32(_mm256_castsi256_si128(ss4), _mm256_extracti128_si256(ss4, 1));
     994           0 :                             s3 = _mm_add_epi32(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
     995           0 :                             UPDATE_BEST(s0, 0, 0);
     996           0 :                             UPDATE_BEST(s0, 1, 0);
     997           0 :                             UPDATE_BEST(s0, 2, 0);
     998           0 :                             UPDATE_BEST(s0, 3, 0);
     999           0 :                             UPDATE_BEST(s3, 0, 4);
    1000           0 :                             UPDATE_BEST(s3, 1, 4);
    1001           0 :                             UPDATE_BEST(s3, 2, 4);
    1002           0 :                             UPDATE_BEST(s3, 3, 4);
    1003             :                         }
    1004             :                     }
    1005             :                 }
    1006             : 
    1007           0 :                 if (leftover && j < search_area_width ) {
    1008           0 :                     pSrc = src;
    1009           0 :                     pRef = ref + j;
    1010           0 :                     ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
    1011           0 :                     for (k = 0; k < block_height; k++) {
    1012           0 :                         ss0 = _mm256_loadu_si256((__m256i*)pRef);
    1013           0 :                         ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
    1014           0 :                         ss2 = _mm256_loadu_si256((__m256i *)pSrc);
    1015           0 :                         ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
    1016           0 :                         ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
    1017           0 :                         ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
    1018           0 :                         ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
    1019           0 :                         pSrc += src_stride;
    1020           0 :                         pRef += ref_stride;
    1021             :                     }
    1022           0 :                     ss3 = _mm256_adds_epu16(ss3, ss4);
    1023           0 :                     ss5 = _mm256_adds_epu16(ss5, ss6);
    1024           0 :                     ss6 = _mm256_adds_epu16(ss3, ss5);
    1025           0 :                     s3 = _mm256_castsi256_si128(ss6);
    1026           0 :                     s4 = _mm256_extracti128_si256(ss6, 1);
    1027           0 :                     s0 = _mm_adds_epu16(s3, s4);
    1028             :                     //s0 = _mm_adds_epu16(_mm_adds_epu16(s3, s4), _mm_adds_epu16(s5, s6));
    1029           0 :                     s0 = _mm_or_si128(s0, s8);
    1030           0 :                     s0 = _mm_minpos_epu16(s0);
    1031           0 :                     temSum1 = _mm_extract_epi16(s0, 0);
    1032           0 :                     if (temSum1 < lowSum) {
    1033           0 :                         if (temSum1 != 0xFFFF) { // no overflow
    1034           0 :                             lowSum = temSum1;
    1035           0 :                             xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
    1036           0 :                             yBest = i;
    1037             :                         }
    1038             :                         else {
    1039           0 :                             ss4 = _mm256_unpacklo_epi16(ss3, _mm256_setzero_si256());
    1040           0 :                             ss3 = _mm256_unpackhi_epi16(ss3, _mm256_setzero_si256());
    1041           0 :                             ss6 = _mm256_unpacklo_epi16(ss5, _mm256_setzero_si256());
    1042           0 :                             ss5 = _mm256_unpackhi_epi16(ss5, _mm256_setzero_si256());
    1043           0 :                             ss4 = _mm256_add_epi32(ss4, ss6);
    1044           0 :                             ss3 = _mm256_add_epi32(ss3, ss5);
    1045           0 :                             s0 = _mm_add_epi32(_mm256_castsi256_si128(ss4), _mm256_extracti128_si256(ss4, 1));
    1046           0 :                             s3 = _mm_add_epi32(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
    1047           0 :                             k = leftover;
    1048           0 :                             while (k > 0) {
    1049           0 :                                 for (l = 0; l < 4 && k; l++, k--) {
    1050           0 :                                     temSum1 = _mm_extract_epi32(s0, 0);
    1051           0 :                                     s0 = _mm_srli_si128(s0, 4);
    1052           0 :                                     if (temSum1 < lowSum) {
    1053           0 :                                         lowSum = temSum1;
    1054           0 :                                         xBest = (int16_t)(j + leftover - k);
    1055           0 :                                         yBest = i;
    1056             :                                     }
    1057             :                                 }
    1058           0 :                                 s0 = s3;
    1059             :                             }
    1060             :                         }
    1061             :                     }
    1062             :                 }
    1063           0 :                 ref += src_stride_raw;
    1064             :             }
    1065             :         }
    1066             :         else {
    1067           0 :             for (i = 0; i < search_area_height; i++) {
    1068           0 :                 uint32_t startW = (i & 1) << 3;
    1069           0 :                 for (j = startW; j <= search_area_width - 8; j += 16) {
    1070           0 :                     pSrc = src;
    1071           0 :                     pRef = ref + j;
    1072           0 :                     ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
    1073           0 :                     for (k = 0; k < block_height; k++) {
    1074           0 :                         ss0 = _mm256_loadu_si256((__m256i*)pRef);
    1075           0 :                         ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
    1076           0 :                         ss2 = _mm256_loadu_si256((__m256i *)pSrc);
    1077           0 :                         ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
    1078           0 :                         ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
    1079           0 :                         ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
    1080           0 :                         ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
    1081           0 :                         pSrc += src_stride;
    1082           0 :                         pRef += ref_stride;
    1083             :                     }
    1084           0 :                     ss7 = _mm256_adds_epu16(_mm256_adds_epu16(ss3, ss4), _mm256_adds_epu16(ss5, ss6));
    1085           0 :                     s3 = _mm256_castsi256_si128(ss7);
    1086           0 :                     s4 = _mm256_extracti128_si256(ss7, 1);
    1087           0 :                     s0 = _mm_adds_epu16(s3, s4);
    1088           0 :                     s0 = _mm_minpos_epu16(s0);
    1089           0 :                     temSum1 = _mm_extract_epi16(s0, 0);
    1090           0 :                     if (temSum1 < lowSum) {
    1091           0 :                         if (temSum1 != 0xFFFF) { // no overflow
    1092           0 :                             lowSum = temSum1;
    1093           0 :                             xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
    1094           0 :                             yBest = i;
    1095             :                         }
    1096             :                         else {
    1097           0 :                             ss0 = _mm256_unpacklo_epi16(ss3, _mm256_setzero_si256());
    1098           0 :                             ss3 = _mm256_unpackhi_epi16(ss3, _mm256_setzero_si256());
    1099           0 :                             ss1 = _mm256_unpacklo_epi16(ss4, _mm256_setzero_si256());
    1100           0 :                             ss4 = _mm256_unpackhi_epi16(ss4, _mm256_setzero_si256());
    1101           0 :                             ss2 = _mm256_unpacklo_epi16(ss5, _mm256_setzero_si256());
    1102           0 :                             ss5 = _mm256_unpackhi_epi16(ss5, _mm256_setzero_si256());
    1103           0 :                             ss7 = _mm256_unpacklo_epi16(ss6, _mm256_setzero_si256());
    1104           0 :                             ss6 = _mm256_unpackhi_epi16(ss6, _mm256_setzero_si256());
    1105           0 :                             ss0 = _mm256_add_epi32(_mm256_add_epi32(ss0, ss1), _mm256_add_epi32(ss2, ss7));
    1106           0 :                             ss3 = _mm256_add_epi32(_mm256_add_epi32(ss3, ss4), _mm256_add_epi32(ss5, ss6));
    1107           0 :                             s0 = _mm_add_epi32(_mm256_castsi256_si128(ss0), _mm256_extracti128_si256(ss0, 1));
    1108           0 :                             s3 = _mm_add_epi32(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
    1109           0 :                             UPDATE_BEST(s0, 0, 0);
    1110           0 :                             UPDATE_BEST(s0, 1, 0);
    1111           0 :                             UPDATE_BEST(s0, 2, 0);
    1112           0 :                             UPDATE_BEST(s0, 3, 0);
    1113           0 :                             UPDATE_BEST(s3, 0, 4);
    1114           0 :                             UPDATE_BEST(s3, 1, 4);
    1115           0 :                             UPDATE_BEST(s3, 2, 4);
    1116           0 :                             UPDATE_BEST(s3, 3, 4);
    1117             :                         }
    1118             :                     }
    1119             :                 }
    1120             : 
    1121           0 :                 if (leftover && j < search_area_width ) {
    1122           0 :                     pSrc = src;
    1123           0 :                     pRef = ref + j;
    1124           0 :                     ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
    1125           0 :                     for (k = 0; k < block_height; k++) {
    1126           0 :                         ss0 = _mm256_loadu_si256((__m256i*)pRef);
    1127           0 :                         ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
    1128           0 :                         ss2 = _mm256_loadu_si256((__m256i *)pSrc);
    1129           0 :                         ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
    1130           0 :                         ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
    1131           0 :                         ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
    1132           0 :                         ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
    1133           0 :                         pSrc += src_stride;
    1134           0 :                         pRef += ref_stride;
    1135             :                     }
    1136           0 :                     ss7 = _mm256_adds_epu16(_mm256_adds_epu16(ss3, ss4), _mm256_adds_epu16(ss5, ss6));
    1137           0 :                     s3 = _mm256_castsi256_si128(ss7);
    1138           0 :                     s4 = _mm256_extracti128_si256(ss7, 1);
    1139           0 :                     s0 = _mm_adds_epu16(s3, s4);
    1140           0 :                     s0 = _mm_minpos_epu16(s0);
    1141           0 :                     temSum1 = _mm_extract_epi16(s0, 0);
    1142           0 :                     if (temSum1 < lowSum) {
    1143           0 :                         if (temSum1 != 0xFFFF) { // no overflow
    1144           0 :                             lowSum = temSum1;
    1145           0 :                             xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
    1146           0 :                             yBest = i;
    1147             :                         }
    1148             :                         else {
    1149           0 :                             ss0 = _mm256_unpacklo_epi16(ss3, _mm256_setzero_si256());
    1150           0 :                             ss3 = _mm256_unpackhi_epi16(ss3, _mm256_setzero_si256());
    1151           0 :                             ss1 = _mm256_unpacklo_epi16(ss4, _mm256_setzero_si256());
    1152           0 :                             ss4 = _mm256_unpackhi_epi16(ss4, _mm256_setzero_si256());
    1153           0 :                             ss2 = _mm256_unpacklo_epi16(ss5, _mm256_setzero_si256());
    1154           0 :                             ss5 = _mm256_unpackhi_epi16(ss5, _mm256_setzero_si256());
    1155           0 :                             ss7 = _mm256_unpacklo_epi16(ss6, _mm256_setzero_si256());
    1156           0 :                             ss6 = _mm256_unpackhi_epi16(ss6, _mm256_setzero_si256());
    1157           0 :                             ss0 = _mm256_add_epi32(_mm256_add_epi32(ss0, ss1), _mm256_add_epi32(ss2, ss7));
    1158           0 :                             ss3 = _mm256_add_epi32(_mm256_add_epi32(ss3, ss4), _mm256_add_epi32(ss5, ss6));
    1159           0 :                             s0 = _mm_add_epi32(_mm256_castsi256_si128(ss0), _mm256_extracti128_si256(ss0, 1));
    1160           0 :                             s3 = _mm_add_epi32(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
    1161           0 :                             k = leftover;
    1162           0 :                             while (k > 0) {
    1163           0 :                                 for (l = 0; l < 4 && k; l++, k--) {
    1164           0 :                                     temSum1 = _mm_extract_epi32(s0, 0);
    1165           0 :                                     s0 = _mm_srli_si128(s0, 4);
    1166           0 :                                     if (temSum1 < lowSum) {
    1167           0 :                                         lowSum = temSum1;
    1168           0 :                                         xBest = (int16_t)(j + leftover - k);
    1169           0 :                                         yBest = i;
    1170             :                                     }
    1171             :                                 }
    1172           0 :                                 s0 = s3;
    1173             :                             }
    1174             :                         }
    1175             :                     }
    1176             :                 }
    1177           0 :                 ref += src_stride_raw;
    1178             :             }
    1179             :         }
    1180           0 :         break;
    1181             : 
    1182           0 :     case 48:
    1183           0 :         if (block_height <= 32) {
    1184           0 :             for (i = 0; i < search_area_height; i++) {
    1185           0 :                 uint32_t startW = (i & 1) << 3;
    1186           0 :                 for (j = startW; j <= search_area_width - 8; j += 16) {
    1187           0 :                     pSrc = src;
    1188           0 :                     pRef = ref + j;
    1189           0 :                     s3 = s4 = s5 = s6 = _mm_setzero_si128();
    1190           0 :                     ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
    1191           0 :                     for (k = 0; k < block_height; k++) {
    1192           0 :                         ss0 = _mm256_loadu_si256((__m256i*)pRef);
    1193           0 :                         ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
    1194           0 :                         ss2 = _mm256_loadu_si256((__m256i *)pSrc);
    1195           0 :                         ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
    1196           0 :                         ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
    1197           0 :                         ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
    1198           0 :                         ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
    1199           0 :                         s0 = _mm_loadu_si128((__m128i*)(pRef + 32));
    1200           0 :                         s1 = _mm_loadu_si128((__m128i*)(pRef + 40));
    1201           0 :                         s2 = _mm_loadu_si128((__m128i*)(pSrc + 32));
    1202           0 :                         s3 = _mm_adds_epu16(s3, _mm_mpsadbw_epu8(s0, s2, 0));
    1203           0 :                         s4 = _mm_adds_epu16(s4, _mm_mpsadbw_epu8(s0, s2, 5));
    1204           0 :                         s5 = _mm_adds_epu16(s5, _mm_mpsadbw_epu8(s1, s2, 2));
    1205           0 :                         s6 = _mm_adds_epu16(s6, _mm_mpsadbw_epu8(s1, s2, 7));
    1206           0 :                         pSrc += src_stride;
    1207           0 :                         pRef += ref_stride;
    1208             :                     }
    1209           0 :                     s3 = _mm_adds_epu16(s3, s4);
    1210           0 :                     s5 = _mm_adds_epu16(s5, s6);
    1211           0 :                     s0 = _mm_adds_epu16(s3, s5);
    1212           0 :                     ss3 = _mm256_adds_epu16(ss3, ss4);
    1213           0 :                     ss5 = _mm256_adds_epu16(ss5, ss6);
    1214           0 :                     ss6 = _mm256_adds_epu16(ss3, ss5);
    1215           0 :                     s0 = _mm_adds_epu16(s0, _mm_adds_epu16(_mm256_castsi256_si128(ss6), _mm256_extracti128_si256(ss6, 1)));
    1216           0 :                     s0 = _mm_minpos_epu16(s0);
    1217           0 :                     temSum1 = _mm_extract_epi16(s0, 0);
    1218           0 :                     if (temSum1 < lowSum) {
    1219           0 :                         if (temSum1 != 0xFFFF) { // no overflow
    1220           0 :                             lowSum = temSum1;
    1221           0 :                             xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
    1222           0 :                             yBest = i;
    1223             :                         }
    1224             :                         else {
    1225           0 :                             ss4 = _mm256_unpacklo_epi16(ss3, _mm256_setzero_si256());
    1226           0 :                             ss3 = _mm256_unpackhi_epi16(ss3, _mm256_setzero_si256());
    1227           0 :                             ss6 = _mm256_unpacklo_epi16(ss5, _mm256_setzero_si256());
    1228           0 :                             ss5 = _mm256_unpackhi_epi16(ss5, _mm256_setzero_si256());
    1229           0 :                             ss4 = _mm256_add_epi32(ss4, ss6);
    1230           0 :                             ss3 = _mm256_add_epi32(ss3, ss5);
    1231           0 :                             s0 = _mm_add_epi32(_mm256_castsi256_si128(ss4), _mm256_extracti128_si256(ss4, 1));
    1232           0 :                             s1 = _mm_add_epi32(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
    1233           0 :                             s0 = _mm_add_epi32(s0, _mm_unpacklo_epi16(s3, _mm_setzero_si128()));
    1234           0 :                             s0 = _mm_add_epi32(s0, _mm_unpacklo_epi16(s5, _mm_setzero_si128()));
    1235           0 :                             s1 = _mm_add_epi32(s1, _mm_unpackhi_epi16(s3, _mm_setzero_si128()));
    1236           0 :                             s1 = _mm_add_epi32(s1, _mm_unpackhi_epi16(s5, _mm_setzero_si128()));
    1237           0 :                             UPDATE_BEST(s0, 0, 0);
    1238           0 :                             UPDATE_BEST(s0, 1, 0);
    1239           0 :                             UPDATE_BEST(s0, 2, 0);
    1240           0 :                             UPDATE_BEST(s0, 3, 0);
    1241           0 :                             UPDATE_BEST(s1, 0, 4);
    1242           0 :                             UPDATE_BEST(s1, 1, 4);
    1243           0 :                             UPDATE_BEST(s1, 2, 4);
    1244           0 :                             UPDATE_BEST(s1, 3, 4);
    1245             :                         }
    1246             :                     }
    1247             :                 }
    1248             : 
    1249           0 :                 if (leftover && j < search_area_width ) {
    1250           0 :                     pSrc = src;
    1251           0 :                     pRef = ref + j;
    1252           0 :                     s3 = s4 = s5 = s6 = _mm_setzero_si128();
    1253           0 :                     ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
    1254           0 :                     for (k = 0; k < block_height; k++) {
    1255           0 :                         ss0 = _mm256_loadu_si256((__m256i*)pRef);
    1256           0 :                         ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
    1257           0 :                         ss2 = _mm256_loadu_si256((__m256i *)pSrc);
    1258           0 :                         ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
    1259           0 :                         ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
    1260           0 :                         ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
    1261           0 :                         ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
    1262           0 :                         s0 = _mm_loadu_si128((__m128i*)(pRef + 32));
    1263           0 :                         s1 = _mm_loadu_si128((__m128i*)(pRef + 40));
    1264           0 :                         s2 = _mm_loadu_si128((__m128i*)(pSrc + 32));
    1265           0 :                         s3 = _mm_adds_epu16(s3, _mm_mpsadbw_epu8(s0, s2, 0));
    1266           0 :                         s4 = _mm_adds_epu16(s4, _mm_mpsadbw_epu8(s0, s2, 5));
    1267           0 :                         s5 = _mm_adds_epu16(s5, _mm_mpsadbw_epu8(s1, s2, 2));
    1268           0 :                         s6 = _mm_adds_epu16(s6, _mm_mpsadbw_epu8(s1, s2, 7));
    1269           0 :                         pSrc += src_stride;
    1270           0 :                         pRef += ref_stride;
    1271             :                     }
    1272           0 :                     s3 = _mm_adds_epu16(s3, s4);
    1273           0 :                     s5 = _mm_adds_epu16(s5, s6);
    1274           0 :                     s0 = _mm_adds_epu16(s3, s5);
    1275           0 :                     ss3 = _mm256_adds_epu16(ss3, ss4);
    1276           0 :                     ss5 = _mm256_adds_epu16(ss5, ss6);
    1277           0 :                     ss6 = _mm256_adds_epu16(ss3, ss5);
    1278           0 :                     s0 = _mm_adds_epu16(s0, _mm_adds_epu16(_mm256_castsi256_si128(ss6), _mm256_extracti128_si256(ss6, 1)));
    1279           0 :                     s0 = _mm_or_si128(s0, s8);
    1280           0 :                     s0 = _mm_minpos_epu16(s0);
    1281           0 :                     temSum1 = _mm_extract_epi16(s0, 0);
    1282           0 :                     if (temSum1 < lowSum) {
    1283           0 :                         if (temSum1 != 0xFFFF) { // no overflow
    1284           0 :                             lowSum = temSum1;
    1285           0 :                             xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
    1286           0 :                             yBest = i;
    1287             :                         }
    1288             :                         else {
    1289           0 :                             ss4 = _mm256_unpacklo_epi16(ss3, _mm256_setzero_si256());
    1290           0 :                             ss3 = _mm256_unpackhi_epi16(ss3, _mm256_setzero_si256());
    1291           0 :                             ss6 = _mm256_unpacklo_epi16(ss5, _mm256_setzero_si256());
    1292           0 :                             ss5 = _mm256_unpackhi_epi16(ss5, _mm256_setzero_si256());
    1293           0 :                             ss4 = _mm256_add_epi32(ss4, ss6);
    1294           0 :                             ss3 = _mm256_add_epi32(ss3, ss5);
    1295           0 :                             s0 = _mm_add_epi32(_mm256_castsi256_si128(ss4), _mm256_extracti128_si256(ss4, 1));
    1296           0 :                             s1 = _mm_add_epi32(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
    1297           0 :                             s0 = _mm_add_epi32(s0, _mm_unpacklo_epi16(s3, _mm_setzero_si128()));
    1298           0 :                             s0 = _mm_add_epi32(s0, _mm_unpacklo_epi16(s5, _mm_setzero_si128()));
    1299           0 :                             s1 = _mm_add_epi32(s1, _mm_unpackhi_epi16(s3, _mm_setzero_si128()));
    1300           0 :                             s1 = _mm_add_epi32(s1, _mm_unpackhi_epi16(s5, _mm_setzero_si128()));
    1301           0 :                             k = leftover;
    1302           0 :                             while (k > 0) {
    1303           0 :                                 for (l = 0; l < 4 && k; l++, k--) {
    1304           0 :                                     temSum1 = _mm_extract_epi32(s0, 0);
    1305           0 :                                     s0 = _mm_srli_si128(s0, 4);
    1306           0 :                                     if (temSum1 < lowSum) {
    1307           0 :                                         lowSum = temSum1;
    1308           0 :                                         xBest = (int16_t)(j + leftover - k);
    1309           0 :                                         yBest = i;
    1310             :                                     }
    1311             :                                 }
    1312           0 :                                 s0 = s1;
    1313             :                             }
    1314             :                         }
    1315             :                     }
    1316             :                 }
    1317           0 :                 ref += src_stride_raw;
    1318             :             }
    1319             :         }
    1320             :         else {
    1321           0 :             for (i = 0; i < search_area_height; i++) {
    1322           0 :                 uint32_t startW = (i & 1) << 3;
    1323           0 :                 for (j = startW; j <= search_area_width - 8; j += 16) {
    1324           0 :                     pSrc = src;
    1325           0 :                     pRef = ref + j;
    1326           0 :                     s3 = s4 = s5 = s6 = _mm_setzero_si128();
    1327           0 :                     ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
    1328           0 :                     for (k = 0; k < block_height; k++) {
    1329           0 :                         ss0 = _mm256_loadu_si256((__m256i*)pRef);
    1330           0 :                         ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
    1331           0 :                         ss2 = _mm256_loadu_si256((__m256i *)pSrc);
    1332           0 :                         ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
    1333           0 :                         ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
    1334           0 :                         ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
    1335           0 :                         ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
    1336           0 :                         s0 = _mm_loadu_si128((__m128i*)(pRef + 32));
    1337           0 :                         s1 = _mm_loadu_si128((__m128i*)(pRef + 40));
    1338           0 :                         s2 = _mm_loadu_si128((__m128i*)(pSrc + 32));
    1339           0 :                         s3 = _mm_adds_epu16(s3, _mm_mpsadbw_epu8(s0, s2, 0));
    1340           0 :                         s4 = _mm_adds_epu16(s4, _mm_mpsadbw_epu8(s0, s2, 5));
    1341           0 :                         s5 = _mm_adds_epu16(s5, _mm_mpsadbw_epu8(s1, s2, 2));
    1342           0 :                         s6 = _mm_adds_epu16(s6, _mm_mpsadbw_epu8(s1, s2, 7));
    1343           0 :                         pSrc += src_stride;
    1344           0 :                         pRef += ref_stride;
    1345             :                     }
    1346           0 :                     s0 = _mm_adds_epu16(_mm_adds_epu16(s3, s4), _mm_adds_epu16(s5, s6));
    1347           0 :                     ss7 = _mm256_adds_epu16(ss3, ss4);
    1348           0 :                     ss8 = _mm256_adds_epu16(ss5, ss6);
    1349           0 :                     ss7 = _mm256_adds_epu16(ss7, ss8);
    1350           0 :                     s0 = _mm_adds_epu16(s0, _mm_adds_epu16(_mm256_castsi256_si128(ss7), _mm256_extracti128_si256(ss7, 1)));
    1351           0 :                     s0 = _mm_minpos_epu16(s0);
    1352           0 :                     temSum1 = _mm_extract_epi16(s0, 0);
    1353           0 :                     if (temSum1 < lowSum) {
    1354           0 :                         if (temSum1 != 0xFFFF) { // no overflow
    1355           0 :                             lowSum = temSum1;
    1356           0 :                             xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
    1357           0 :                             yBest = i;
    1358             :                         }
    1359             :                         else {
    1360           0 :                             ss0 = _mm256_unpacklo_epi16(ss3, _mm256_setzero_si256());
    1361           0 :                             ss3 = _mm256_unpackhi_epi16(ss3, _mm256_setzero_si256());
    1362           0 :                             ss1 = _mm256_unpacklo_epi16(ss4, _mm256_setzero_si256());
    1363           0 :                             ss4 = _mm256_unpackhi_epi16(ss4, _mm256_setzero_si256());
    1364           0 :                             ss2 = _mm256_unpacklo_epi16(ss5, _mm256_setzero_si256());
    1365           0 :                             ss5 = _mm256_unpackhi_epi16(ss5, _mm256_setzero_si256());
    1366           0 :                             ss7 = _mm256_unpacklo_epi16(ss6, _mm256_setzero_si256());
    1367           0 :                             ss6 = _mm256_unpackhi_epi16(ss6, _mm256_setzero_si256());
    1368           0 :                             ss0 = _mm256_add_epi32(_mm256_add_epi32(ss0, ss1), _mm256_add_epi32(ss2, ss7));
    1369           0 :                             ss3 = _mm256_add_epi32(_mm256_add_epi32(ss3, ss4), _mm256_add_epi32(ss5, ss6));
    1370           0 :                             s0 = _mm_add_epi32(_mm256_castsi256_si128(ss0), _mm256_extracti128_si256(ss0, 1));
    1371           0 :                             s1 = _mm_add_epi32(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
    1372           0 :                             s0 = _mm_add_epi32(s0, _mm_unpacklo_epi16(s3, _mm_setzero_si128()));
    1373           0 :                             s0 = _mm_add_epi32(s0, _mm_unpacklo_epi16(s4, _mm_setzero_si128()));
    1374           0 :                             s0 = _mm_add_epi32(s0, _mm_unpacklo_epi16(s5, _mm_setzero_si128()));
    1375           0 :                             s0 = _mm_add_epi32(s0, _mm_unpacklo_epi16(s6, _mm_setzero_si128()));
    1376           0 :                             s1 = _mm_add_epi32(s1, _mm_unpackhi_epi16(s3, _mm_setzero_si128()));
    1377           0 :                             s1 = _mm_add_epi32(s1, _mm_unpackhi_epi16(s4, _mm_setzero_si128()));
    1378           0 :                             s1 = _mm_add_epi32(s1, _mm_unpackhi_epi16(s5, _mm_setzero_si128()));
    1379           0 :                             s1 = _mm_add_epi32(s1, _mm_unpackhi_epi16(s6, _mm_setzero_si128()));
    1380           0 :                             UPDATE_BEST(s0, 0, 0);
    1381           0 :                             UPDATE_BEST(s0, 1, 0);
    1382           0 :                             UPDATE_BEST(s0, 2, 0);
    1383           0 :                             UPDATE_BEST(s0, 3, 0);
    1384           0 :                             UPDATE_BEST(s1, 0, 4);
    1385           0 :                             UPDATE_BEST(s1, 1, 4);
    1386           0 :                             UPDATE_BEST(s1, 2, 4);
    1387           0 :                             UPDATE_BEST(s1, 3, 4);
    1388             :                         }
    1389             :                     }
    1390             :                 }
    1391             : 
    1392           0 :                 if (leftover && j < search_area_width ) {
    1393           0 :                     pSrc = src;
    1394           0 :                     pRef = ref + j;
    1395           0 :                     s3 = s4 = s5 = s6 = _mm_setzero_si128();
    1396           0 :                     ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
    1397           0 :                     for (k = 0; k < block_height; k++) {
    1398           0 :                         ss0 = _mm256_loadu_si256((__m256i*)pRef);
    1399           0 :                         ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
    1400           0 :                         ss2 = _mm256_loadu_si256((__m256i *)pSrc);
    1401           0 :                         ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
    1402           0 :                         ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
    1403           0 :                         ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
    1404           0 :                         ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
    1405           0 :                         s0 = _mm_loadu_si128((__m128i*)(pRef + 32));
    1406           0 :                         s1 = _mm_loadu_si128((__m128i*)(pRef + 40));
    1407           0 :                         s2 = _mm_loadu_si128((__m128i*)(pSrc + 32));
    1408           0 :                         s3 = _mm_adds_epu16(s3, _mm_mpsadbw_epu8(s0, s2, 0));
    1409           0 :                         s4 = _mm_adds_epu16(s4, _mm_mpsadbw_epu8(s0, s2, 5));
    1410           0 :                         s5 = _mm_adds_epu16(s5, _mm_mpsadbw_epu8(s1, s2, 2));
    1411           0 :                         s6 = _mm_adds_epu16(s6, _mm_mpsadbw_epu8(s1, s2, 7));
    1412           0 :                         pSrc += src_stride;
    1413           0 :                         pRef += ref_stride;
    1414             :                     }
    1415           0 :                     s0 = _mm_adds_epu16(_mm_adds_epu16(s3, s4), _mm_adds_epu16(s5, s6));
    1416           0 :                     ss7 = _mm256_adds_epu16(ss3, ss4);
    1417           0 :                     ss8 = _mm256_adds_epu16(ss5, ss6);
    1418           0 :                     ss7 = _mm256_adds_epu16(ss7, ss8);
    1419           0 :                     s0 = _mm_adds_epu16(s0, _mm_adds_epu16(_mm256_castsi256_si128(ss7), _mm256_extracti128_si256(ss7, 1)));
    1420           0 :                     s0 = _mm_or_si128(s0, s8);
    1421           0 :                     s0 = _mm_minpos_epu16(s0);
    1422           0 :                     temSum1 = _mm_extract_epi16(s0, 0);
    1423           0 :                     if (temSum1 < lowSum) {
    1424           0 :                         if (temSum1 != 0xFFFF) { // no overflow
    1425           0 :                             lowSum = temSum1;
    1426           0 :                             xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
    1427           0 :                             yBest = i;
    1428             :                         }
    1429             :                         else {
    1430           0 :                             ss0 = _mm256_unpacklo_epi16(ss3, _mm256_setzero_si256());
    1431           0 :                             ss3 = _mm256_unpackhi_epi16(ss3, _mm256_setzero_si256());
    1432           0 :                             ss1 = _mm256_unpacklo_epi16(ss4, _mm256_setzero_si256());
    1433           0 :                             ss4 = _mm256_unpackhi_epi16(ss4, _mm256_setzero_si256());
    1434           0 :                             ss2 = _mm256_unpacklo_epi16(ss5, _mm256_setzero_si256());
    1435           0 :                             ss5 = _mm256_unpackhi_epi16(ss5, _mm256_setzero_si256());
    1436           0 :                             ss7 = _mm256_unpacklo_epi16(ss6, _mm256_setzero_si256());
    1437           0 :                             ss6 = _mm256_unpackhi_epi16(ss6, _mm256_setzero_si256());
    1438           0 :                             ss0 = _mm256_add_epi32(_mm256_add_epi32(ss0, ss1), _mm256_add_epi32(ss2, ss7));
    1439           0 :                             ss3 = _mm256_add_epi32(_mm256_add_epi32(ss3, ss4), _mm256_add_epi32(ss5, ss6));
    1440           0 :                             s0 = _mm_add_epi32(_mm256_castsi256_si128(ss0), _mm256_extracti128_si256(ss0, 1));
    1441           0 :                             s1 = _mm_add_epi32(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
    1442           0 :                             s0 = _mm_add_epi32(s0, _mm_unpacklo_epi16(s3, _mm_setzero_si128()));
    1443           0 :                             s0 = _mm_add_epi32(s0, _mm_unpacklo_epi16(s4, _mm_setzero_si128()));
    1444           0 :                             s0 = _mm_add_epi32(s0, _mm_unpacklo_epi16(s5, _mm_setzero_si128()));
    1445           0 :                             s0 = _mm_add_epi32(s0, _mm_unpacklo_epi16(s6, _mm_setzero_si128()));
    1446           0 :                             s1 = _mm_add_epi32(s1, _mm_unpackhi_epi16(s3, _mm_setzero_si128()));
    1447           0 :                             s1 = _mm_add_epi32(s1, _mm_unpackhi_epi16(s4, _mm_setzero_si128()));
    1448           0 :                             s1 = _mm_add_epi32(s1, _mm_unpackhi_epi16(s5, _mm_setzero_si128()));
    1449           0 :                             s1 = _mm_add_epi32(s1, _mm_unpackhi_epi16(s6, _mm_setzero_si128()));
    1450           0 :                             k = leftover;
    1451           0 :                             while (k > 0) {
    1452           0 :                                 for (l = 0; l < 4 && k; l++, k--) {
    1453           0 :                                     temSum1 = _mm_extract_epi32(s0, 0);
    1454           0 :                                     s0 = _mm_srli_si128(s0, 4);
    1455           0 :                                     if (temSum1 < lowSum) {
    1456           0 :                                         lowSum = temSum1;
    1457           0 :                                         xBest = (int16_t)(j + leftover - k);
    1458           0 :                                         yBest = i;
    1459             :                                     }
    1460             :                                 }
    1461           0 :                                 s0 = s1;
    1462             :                             }
    1463             :                         }
    1464             :                     }
    1465             :                 }
    1466           0 :                 ref += src_stride_raw;
    1467             :             }
    1468             :         }
    1469           0 :         break;
    1470             : 
    1471           0 :     case 64:
    1472           0 :         if (block_height <= 32) {
    1473           0 :             for (i = 0; i < search_area_height; i++) {
    1474           0 :                 uint32_t startW = (i & 1) << 3;
    1475           0 :                 for (j = startW; j <= search_area_width - 8; j += 16) {
    1476           0 :                     pSrc = src;
    1477           0 :                     pRef = ref + j;
    1478           0 :                     ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
    1479           0 :                     for (k = 0; k < block_height; k++) {
    1480           0 :                         ss0 = _mm256_loadu_si256((__m256i*)pRef);
    1481           0 :                         ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
    1482           0 :                         ss2 = _mm256_loadu_si256((__m256i *)pSrc);
    1483           0 :                         ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
    1484           0 :                         ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
    1485           0 :                         ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
    1486           0 :                         ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
    1487           0 :                         ss0 = _mm256_loadu_si256((__m256i*)(pRef + 32));
    1488           0 :                         ss1 = _mm256_loadu_si256((__m256i*)(pRef + 40));
    1489           0 :                         ss2 = _mm256_loadu_si256((__m256i *)(pSrc + 32));
    1490           0 :                         ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
    1491           0 :                         ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
    1492           0 :                         ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
    1493           0 :                         ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
    1494           0 :                         pSrc += src_stride;
    1495           0 :                         pRef += ref_stride;
    1496             :                     }
    1497           0 :                     ss7 = _mm256_adds_epu16(_mm256_adds_epu16(ss3, ss4), _mm256_adds_epu16(ss5, ss6));
    1498           0 :                     s3 = _mm256_castsi256_si128(ss7);
    1499           0 :                     s4 = _mm256_extracti128_si256(ss7, 1);
    1500           0 :                     s0 = _mm_adds_epu16(s3, s4);
    1501           0 :                     s0 = _mm_minpos_epu16(s0);
    1502           0 :                     temSum1 = _mm_extract_epi16(s0, 0);
    1503           0 :                     if (temSum1 < lowSum) {
    1504           0 :                         if (temSum1 != 0xFFFF) { // no overflow
    1505           0 :                             lowSum = temSum1;
    1506           0 :                             xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
    1507           0 :                             yBest = i;
    1508             :                         }
    1509             :                         else {
    1510           0 :                             ss0 = _mm256_unpacklo_epi16(ss3, _mm256_setzero_si256());
    1511           0 :                             ss3 = _mm256_unpackhi_epi16(ss3, _mm256_setzero_si256());
    1512           0 :                             ss1 = _mm256_unpacklo_epi16(ss4, _mm256_setzero_si256());
    1513           0 :                             ss4 = _mm256_unpackhi_epi16(ss4, _mm256_setzero_si256());
    1514           0 :                             ss2 = _mm256_unpacklo_epi16(ss5, _mm256_setzero_si256());
    1515           0 :                             ss5 = _mm256_unpackhi_epi16(ss5, _mm256_setzero_si256());
    1516           0 :                             ss7 = _mm256_unpacklo_epi16(ss6, _mm256_setzero_si256());
    1517           0 :                             ss6 = _mm256_unpackhi_epi16(ss6, _mm256_setzero_si256());
    1518           0 :                             ss0 = _mm256_add_epi32(_mm256_add_epi32(ss0, ss1), _mm256_add_epi32(ss2, ss7));
    1519           0 :                             ss3 = _mm256_add_epi32(_mm256_add_epi32(ss3, ss4), _mm256_add_epi32(ss5, ss6));
    1520           0 :                             s0 = _mm_add_epi32(_mm256_castsi256_si128(ss0), _mm256_extracti128_si256(ss0, 1));
    1521           0 :                             s3 = _mm_add_epi32(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
    1522           0 :                             UPDATE_BEST(s0, 0, 0);
    1523           0 :                             UPDATE_BEST(s0, 1, 0);
    1524           0 :                             UPDATE_BEST(s0, 2, 0);
    1525           0 :                             UPDATE_BEST(s0, 3, 0);
    1526           0 :                             UPDATE_BEST(s3, 0, 4);
    1527           0 :                             UPDATE_BEST(s3, 1, 4);
    1528           0 :                             UPDATE_BEST(s3, 2, 4);
    1529           0 :                             UPDATE_BEST(s3, 3, 4);
    1530             :                         }
    1531             :                     }
    1532             :                 }
    1533             : 
    1534           0 :                 if (leftover && j < search_area_width ) {
    1535           0 :                     pSrc = src;
    1536           0 :                     pRef = ref + j;
    1537           0 :                     ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
    1538           0 :                     for (k = 0; k < block_height; k++) {
    1539           0 :                         ss0 = _mm256_loadu_si256((__m256i*)pRef);
    1540           0 :                         ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
    1541           0 :                         ss2 = _mm256_loadu_si256((__m256i *)pSrc);
    1542           0 :                         ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
    1543           0 :                         ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
    1544           0 :                         ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
    1545           0 :                         ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
    1546           0 :                         ss0 = _mm256_loadu_si256((__m256i*)(pRef + 32));
    1547           0 :                         ss1 = _mm256_loadu_si256((__m256i*)(pRef + 40));
    1548           0 :                         ss2 = _mm256_loadu_si256((__m256i *)(pSrc + 32));
    1549           0 :                         ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
    1550           0 :                         ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
    1551           0 :                         ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
    1552           0 :                         ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
    1553           0 :                         pSrc += src_stride;
    1554           0 :                         pRef += ref_stride;
    1555             :                     }
    1556           0 :                     ss7 = _mm256_adds_epu16(_mm256_adds_epu16(ss3, ss4), _mm256_adds_epu16(ss5, ss6));
    1557           0 :                     s3 = _mm256_castsi256_si128(ss7);
    1558           0 :                     s4 = _mm256_extracti128_si256(ss7, 1);
    1559           0 :                     s0 = _mm_adds_epu16(s3, s4);
    1560           0 :                     s0 = _mm_or_si128(s0, s8);
    1561           0 :                     s0 = _mm_minpos_epu16(s0);
    1562           0 :                     temSum1 = _mm_extract_epi16(s0, 0);
    1563           0 :                     if (temSum1 < lowSum) {
    1564           0 :                         if (temSum1 != 0xFFFF) { // no overflow
    1565           0 :                             lowSum = temSum1;
    1566           0 :                             xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
    1567           0 :                             yBest = i;
    1568             :                         }
    1569             :                         else {
    1570           0 :                             ss0 = _mm256_unpacklo_epi16(ss3, _mm256_setzero_si256());
    1571           0 :                             ss3 = _mm256_unpackhi_epi16(ss3, _mm256_setzero_si256());
    1572           0 :                             ss1 = _mm256_unpacklo_epi16(ss4, _mm256_setzero_si256());
    1573           0 :                             ss4 = _mm256_unpackhi_epi16(ss4, _mm256_setzero_si256());
    1574           0 :                             ss2 = _mm256_unpacklo_epi16(ss5, _mm256_setzero_si256());
    1575           0 :                             ss5 = _mm256_unpackhi_epi16(ss5, _mm256_setzero_si256());
    1576           0 :                             ss7 = _mm256_unpacklo_epi16(ss6, _mm256_setzero_si256());
    1577           0 :                             ss6 = _mm256_unpackhi_epi16(ss6, _mm256_setzero_si256());
    1578           0 :                             ss0 = _mm256_add_epi32(_mm256_add_epi32(ss0, ss1), _mm256_add_epi32(ss2, ss7));
    1579           0 :                             ss3 = _mm256_add_epi32(_mm256_add_epi32(ss3, ss4), _mm256_add_epi32(ss5, ss6));
    1580           0 :                             s0 = _mm_add_epi32(_mm256_castsi256_si128(ss0), _mm256_extracti128_si256(ss0, 1));
    1581           0 :                             s3 = _mm_add_epi32(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
    1582           0 :                             k = leftover;
    1583           0 :                             while (k > 0) {
    1584           0 :                                 for (l = 0; l < 4 && k; l++, k--) {
    1585           0 :                                     temSum1 = _mm_extract_epi32(s0, 0);
    1586           0 :                                     s0 = _mm_srli_si128(s0, 4);
    1587           0 :                                     if (temSum1 < lowSum) {
    1588           0 :                                         lowSum = temSum1;
    1589           0 :                                         xBest = (int16_t)(j + leftover - k);
    1590           0 :                                         yBest = i;
    1591             :                                     }
    1592             :                                 }
    1593           0 :                                 s0 = s3;
    1594             :                             }
    1595             :                         }
    1596             :                     }
    1597             :                 }
    1598           0 :                 ref += src_stride_raw;
    1599             :             }
    1600             :         }
    1601             :         else {
    1602             :             __m256i ss9, ss10;
    1603           0 :             for (i = 0; i < search_area_height; i++) {
    1604           0 :                 uint32_t startW = (i & 1) << 3;
    1605           0 :                 for (j = startW; j <= search_area_width - 8; j += 16) {
    1606           0 :                     pSrc = src;
    1607           0 :                     pRef = ref + j;
    1608           0 :                     ss3 = ss4 = ss5 = ss6 = ss7 = ss8 = ss9 = ss10 = _mm256_setzero_si256();
    1609           0 :                     for (k = 0; k < block_height; k++) {
    1610           0 :                         ss0 = _mm256_loadu_si256((__m256i*)pRef);
    1611           0 :                         ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
    1612           0 :                         ss2 = _mm256_loadu_si256((__m256i *)pSrc);
    1613           0 :                         ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
    1614           0 :                         ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
    1615           0 :                         ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
    1616           0 :                         ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
    1617           0 :                         ss0 = _mm256_loadu_si256((__m256i*)(pRef + 32));
    1618           0 :                         ss1 = _mm256_loadu_si256((__m256i*)(pRef + 40));
    1619           0 :                         ss2 = _mm256_loadu_si256((__m256i *)(pSrc + 32));
    1620           0 :                         ss7 = _mm256_adds_epu16(ss7, _mm256_mpsadbw_epu8(ss0, ss2, 0));
    1621           0 :                         ss8 = _mm256_adds_epu16(ss8, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
    1622           0 :                         ss9 = _mm256_adds_epu16(ss9, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
    1623           0 :                         ss10 = _mm256_adds_epu16(ss10, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
    1624           0 :                         pSrc += src_stride;
    1625           0 :                         pRef += ref_stride;
    1626             :                     }
    1627           0 :                     ss0 = _mm256_adds_epu16(_mm256_adds_epu16(ss3, ss4), _mm256_adds_epu16(ss5, ss6));
    1628           0 :                     ss0 = _mm256_adds_epu16(ss0, _mm256_adds_epu16(_mm256_adds_epu16(ss7, ss8), _mm256_adds_epu16(ss9, ss10)));
    1629           0 :                     s0 = _mm_adds_epu16(_mm256_castsi256_si128(ss0), _mm256_extracti128_si256(ss0, 1));
    1630           0 :                     s0 = _mm_minpos_epu16(s0);
    1631           0 :                     temSum1 = _mm_extract_epi16(s0, 0);
    1632           0 :                     if (temSum1 < lowSum) {
    1633           0 :                         if (temSum1 != 0xFFFF) { // no overflow
    1634           0 :                             lowSum = temSum1;
    1635           0 :                             xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
    1636           0 :                             yBest = i;
    1637             :                         }
    1638             :                         else {
    1639           0 :                             ss0 = _mm256_add_epi32(_mm256_add_epi32(_mm256_unpacklo_epi16(ss3, _mm256_setzero_si256()), _mm256_unpacklo_epi16(ss4, _mm256_setzero_si256())), _mm256_add_epi32(_mm256_unpacklo_epi16(ss5, _mm256_setzero_si256()), _mm256_unpacklo_epi16(ss6, _mm256_setzero_si256())));
    1640           0 :                             ss1 = _mm256_add_epi32(_mm256_add_epi32(_mm256_unpackhi_epi16(ss3, _mm256_setzero_si256()), _mm256_unpackhi_epi16(ss4, _mm256_setzero_si256())), _mm256_add_epi32(_mm256_unpackhi_epi16(ss5, _mm256_setzero_si256()), _mm256_unpackhi_epi16(ss6, _mm256_setzero_si256())));
    1641           0 :                             ss2 = _mm256_add_epi32(_mm256_add_epi32(_mm256_unpacklo_epi16(ss7, _mm256_setzero_si256()), _mm256_unpacklo_epi16(ss8, _mm256_setzero_si256())), _mm256_add_epi32(_mm256_unpacklo_epi16(ss9, _mm256_setzero_si256()), _mm256_unpacklo_epi16(ss10, _mm256_setzero_si256())));
    1642           0 :                             ss3 = _mm256_add_epi32(_mm256_add_epi32(_mm256_unpackhi_epi16(ss7, _mm256_setzero_si256()), _mm256_unpackhi_epi16(ss8, _mm256_setzero_si256())), _mm256_add_epi32(_mm256_unpackhi_epi16(ss9, _mm256_setzero_si256()), _mm256_unpackhi_epi16(ss10, _mm256_setzero_si256())));
    1643           0 :                             ss0 = _mm256_add_epi32(ss0, ss2);
    1644           0 :                             ss1 = _mm256_add_epi32(ss1, ss3);
    1645           0 :                             s0 = _mm_add_epi32(_mm256_castsi256_si128(ss0), _mm256_extracti128_si256(ss0, 1));
    1646           0 :                             s3 = _mm_add_epi32(_mm256_castsi256_si128(ss1), _mm256_extracti128_si256(ss1, 1));
    1647           0 :                             UPDATE_BEST(s0, 0, 0);
    1648           0 :                             UPDATE_BEST(s0, 1, 0);
    1649           0 :                             UPDATE_BEST(s0, 2, 0);
    1650           0 :                             UPDATE_BEST(s0, 3, 0);
    1651           0 :                             UPDATE_BEST(s3, 0, 4);
    1652           0 :                             UPDATE_BEST(s3, 1, 4);
    1653           0 :                             UPDATE_BEST(s3, 2, 4);
    1654           0 :                             UPDATE_BEST(s3, 3, 4);
    1655             :                         }
    1656             :                     }
    1657             :                 }
    1658             : 
    1659           0 :                 if (leftover && j < search_area_width ) {
    1660           0 :                     pSrc = src;
    1661           0 :                     pRef = ref + j;
    1662           0 :                     ss3 = ss4 = ss5 = ss6 = ss7 = ss8 = ss9 = ss10 = _mm256_setzero_si256();
    1663           0 :                     for (k = 0; k < block_height; k++) {
    1664           0 :                         ss0 = _mm256_loadu_si256((__m256i*)pRef);
    1665           0 :                         ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
    1666           0 :                         ss2 = _mm256_loadu_si256((__m256i *)pSrc);
    1667           0 :                         ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
    1668           0 :                         ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
    1669           0 :                         ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
    1670           0 :                         ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
    1671           0 :                         ss0 = _mm256_loadu_si256((__m256i*)(pRef + 32));
    1672           0 :                         ss1 = _mm256_loadu_si256((__m256i*)(pRef + 40));
    1673           0 :                         ss2 = _mm256_loadu_si256((__m256i *)(pSrc + 32));
    1674           0 :                         ss7 = _mm256_adds_epu16(ss7, _mm256_mpsadbw_epu8(ss0, ss2, 0));
    1675           0 :                         ss8 = _mm256_adds_epu16(ss8, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
    1676           0 :                         ss9 = _mm256_adds_epu16(ss9, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
    1677           0 :                         ss10 = _mm256_adds_epu16(ss10, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
    1678           0 :                         pSrc += src_stride;
    1679           0 :                         pRef += ref_stride;
    1680             :                     }
    1681           0 :                     ss0 = _mm256_adds_epu16(_mm256_adds_epu16(ss3, ss4), _mm256_adds_epu16(ss5, ss6));
    1682           0 :                     ss0 = _mm256_adds_epu16(ss0, _mm256_adds_epu16(_mm256_adds_epu16(ss7, ss8), _mm256_adds_epu16(ss9, ss10)));
    1683           0 :                     s0 = _mm_adds_epu16(_mm256_castsi256_si128(ss0), _mm256_extracti128_si256(ss0, 1));
    1684           0 :                     s0 = _mm_or_si128(s0, s8);
    1685           0 :                     s0 = _mm_minpos_epu16(s0);
    1686           0 :                     temSum1 = _mm_extract_epi16(s0, 0);
    1687           0 :                     if (temSum1 < lowSum) {
    1688           0 :                         if (temSum1 != 0xFFFF) { // no overflow
    1689           0 :                             lowSum = temSum1;
    1690           0 :                             xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
    1691           0 :                             yBest = i;
    1692             :                         }
    1693             :                         else {
    1694           0 :                             ss0 = _mm256_add_epi32(_mm256_add_epi32(_mm256_unpacklo_epi16(ss3, _mm256_setzero_si256()), _mm256_unpacklo_epi16(ss4, _mm256_setzero_si256())), _mm256_add_epi32(_mm256_unpacklo_epi16(ss5, _mm256_setzero_si256()), _mm256_unpacklo_epi16(ss6, _mm256_setzero_si256())));
    1695           0 :                             ss1 = _mm256_add_epi32(_mm256_add_epi32(_mm256_unpackhi_epi16(ss3, _mm256_setzero_si256()), _mm256_unpackhi_epi16(ss4, _mm256_setzero_si256())), _mm256_add_epi32(_mm256_unpackhi_epi16(ss5, _mm256_setzero_si256()), _mm256_unpackhi_epi16(ss6, _mm256_setzero_si256())));
    1696           0 :                             ss2 = _mm256_add_epi32(_mm256_add_epi32(_mm256_unpacklo_epi16(ss7, _mm256_setzero_si256()), _mm256_unpacklo_epi16(ss8, _mm256_setzero_si256())), _mm256_add_epi32(_mm256_unpacklo_epi16(ss9, _mm256_setzero_si256()), _mm256_unpacklo_epi16(ss10, _mm256_setzero_si256())));
    1697           0 :                             ss3 = _mm256_add_epi32(_mm256_add_epi32(_mm256_unpackhi_epi16(ss7, _mm256_setzero_si256()), _mm256_unpackhi_epi16(ss8, _mm256_setzero_si256())), _mm256_add_epi32(_mm256_unpackhi_epi16(ss9, _mm256_setzero_si256()), _mm256_unpackhi_epi16(ss10, _mm256_setzero_si256())));
    1698           0 :                             ss0 = _mm256_add_epi32(ss0, ss2);
    1699           0 :                             ss1 = _mm256_add_epi32(ss1, ss3);
    1700           0 :                             s0 = _mm_add_epi32(_mm256_castsi256_si128(ss0), _mm256_extracti128_si256(ss0, 1));
    1701           0 :                             s3 = _mm_add_epi32(_mm256_castsi256_si128(ss1), _mm256_extracti128_si256(ss1, 1));
    1702           0 :                             k = leftover;
    1703           0 :                             while (k > 0) {
    1704           0 :                                 for (l = 0; l < 4 && k; l++, k--) {
    1705           0 :                                     temSum1 = _mm_extract_epi32(s0, 0);
    1706           0 :                                     s0 = _mm_srli_si128(s0, 4);
    1707           0 :                                     if (temSum1 < lowSum) {
    1708           0 :                                         lowSum = temSum1;
    1709           0 :                                         xBest = (int16_t)(j + leftover - k);
    1710           0 :                                         yBest = i;
    1711             :                                     }
    1712             :                                 }
    1713           0 :                                 s0 = s3;
    1714             :                             }
    1715             :                         }
    1716             :                     }
    1717             :                 }
    1718           0 :                 ref += src_stride_raw;
    1719             :             }
    1720             :         }
    1721           0 :         break;
    1722             : 
    1723           0 :     default:
    1724             :         assert(0);
    1725           0 :         break;
    1726             :     }
    1727             : 
    1728           0 :     *best_sad = lowSum;
    1729           0 :     *x_search_center = xBest;
    1730           0 :     *y_search_center = yBest;
    1731           0 : }
    1732             : 
    1733             : /*******************************************************************************
    1734             :  * Requirement: width   = 4, 8, 16, 24, 32, 48 or 64
    1735             :  * Requirement: block_height <= 64
    1736             :  * Requirement: block_height % 2 = 0 when width = 4 or 8
    1737             : *******************************************************************************/
    1738       63181 : void sad_loop_kernel_avx2_intrin(
    1739             :     uint8_t  *src,                            // input parameter, source samples Ptr
    1740             :     uint32_t  src_stride,                      // input parameter, source stride
    1741             :     uint8_t  *ref,                            // input parameter, reference samples Ptr
    1742             :     uint32_t  ref_stride,                      // input parameter, reference stride
    1743             :     uint32_t  block_height,                   // input parameter, block height (M)
    1744             :     uint32_t  block_width,                    // input parameter, block width (N)
    1745             :     uint64_t *best_sad,
    1746             :     int16_t *x_search_center,
    1747             :     int16_t *y_search_center,
    1748             :     uint32_t  src_stride_raw,                   // input parameter, source stride (no line skipping)
    1749             :     int16_t search_area_width,
    1750             :     int16_t search_area_height)
    1751             : {
    1752       63181 :     int16_t xBest = *x_search_center, yBest = *y_search_center;
    1753       63181 :     uint32_t lowSum = 0xffffff;
    1754       63181 :     uint32_t temSum1 = 0;
    1755             :     int16_t i, j;
    1756             :     uint32_t k, l;
    1757       63181 :     uint32_t leftover = search_area_width & 7;
    1758             :     const uint8_t *pRef, *pSrc;
    1759       63181 :     __m128i s0, s1, s2, s3, s4, s5, s6, s8 = _mm_set1_epi32(-1);
    1760             :     __m256i ss0, ss1, ss2, ss3, ss4, ss5, ss6, ss7, ss8;
    1761             : 
    1762       63181 :     if (leftover) {
    1763         343 :         for (k = 0; k < leftover; k++)
    1764         294 :             s8 = _mm_slli_si128(s8, 2);
    1765             :     }
    1766             : 
    1767       63181 :     switch (block_width) {
    1768           0 :     case 4:
    1769             : 
    1770           0 :         if (!(block_height % 4)) {
    1771           0 :             uint32_t srcStrideT = 3 * src_stride;
    1772           0 :             uint32_t refStrideT = 3 * ref_stride;
    1773           0 :             for (i = 0; i < search_area_height; i++) {
    1774           0 :                 for (j = 0; j <= search_area_width - 8; j += 8) {
    1775           0 :                     pSrc = src;
    1776           0 :                     pRef = ref + j;
    1777           0 :                     ss3 = ss5 = _mm256_setzero_si256();
    1778           0 :                     for (k = 0; k < block_height; k += 4) {
    1779           0 :                         ss0 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pRef)), _mm_loadu_si128((__m128i*)(pRef + 2 * ref_stride)), 0x1);
    1780           0 :                         ss1 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)(pRef + ref_stride))), _mm_loadu_si128((__m128i*)(pRef + refStrideT)), 0x1);
    1781           0 :                         ss2 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_unpacklo_epi64(_mm_cvtsi32_si128(*(uint32_t *)pSrc), _mm_cvtsi32_si128(*(uint32_t *)(pSrc + src_stride)))), _mm_unpacklo_epi64(_mm_cvtsi32_si128(*(uint32_t *)(pSrc + 2 * src_stride)), _mm_cvtsi32_si128(*(uint32_t *)(pSrc + srcStrideT))), 0x1);
    1782           0 :                         ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
    1783           0 :                         ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
    1784           0 :                         pSrc += src_stride << 2;
    1785           0 :                         pRef += ref_stride << 2;
    1786             :                     }
    1787           0 :                     ss3 = _mm256_adds_epu16(ss3, ss5);
    1788           0 :                     s3 = _mm_adds_epu16(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
    1789           0 :                     s3 = _mm_minpos_epu16(s3);
    1790           0 :                     temSum1 = _mm_extract_epi16(s3, 0);
    1791           0 :                     if (temSum1 < lowSum) {
    1792           0 :                         lowSum = temSum1;
    1793           0 :                         xBest = (int16_t)(j + _mm_extract_epi16(s3, 1));
    1794           0 :                         yBest = i;
    1795             :                     }
    1796             :                 }
    1797             : 
    1798           0 :                 if (leftover) {
    1799           0 :                     pSrc = src;
    1800           0 :                     pRef = ref + j;
    1801           0 :                     ss3 = ss5 = _mm256_setzero_si256();
    1802           0 :                     for (k = 0; k < block_height; k += 4) {
    1803           0 :                         ss0 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pRef)), _mm_loadu_si128((__m128i*)(pRef + 2 * ref_stride)), 0x1);
    1804           0 :                         ss1 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)(pRef + ref_stride))), _mm_loadu_si128((__m128i*)(pRef + refStrideT)), 0x1);
    1805           0 :                         ss2 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_unpacklo_epi64(_mm_cvtsi32_si128(*(uint32_t *)pSrc), _mm_cvtsi32_si128(*(uint32_t *)(pSrc + src_stride)))), _mm_unpacklo_epi64(_mm_cvtsi32_si128(*(uint32_t *)(pSrc + 2 * src_stride)), _mm_cvtsi32_si128(*(uint32_t *)(pSrc + srcStrideT))), 0x1);
    1806           0 :                         ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
    1807           0 :                         ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
    1808           0 :                         pSrc += src_stride << 2;
    1809           0 :                         pRef += ref_stride << 2;
    1810             :                     }
    1811           0 :                     ss3 = _mm256_adds_epu16(ss3, ss5);
    1812           0 :                     s3 = _mm_adds_epu16(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
    1813           0 :                     s3 = _mm_or_si128(s3, s8);
    1814           0 :                     s3 = _mm_minpos_epu16(s3);
    1815           0 :                     temSum1 = _mm_extract_epi16(s3, 0);
    1816           0 :                     if (temSum1 < lowSum) {
    1817           0 :                         lowSum = temSum1;
    1818           0 :                         xBest = (int16_t)(j + _mm_extract_epi16(s3, 1));
    1819           0 :                         yBest = i;
    1820             :                     }
    1821             :                 }
    1822           0 :                 ref += src_stride_raw;
    1823             :             }
    1824             :         }
    1825             :         else {
    1826           0 :             for (i = 0; i < search_area_height; i++) {
    1827           0 :                 for (j = 0; j <= search_area_width - 8; j += 8) {
    1828           0 :                     pSrc = src;
    1829           0 :                     pRef = ref + j;
    1830           0 :                     s3 = _mm_setzero_si128();
    1831           0 :                     for (k = 0; k < block_height; k += 2) {
    1832           0 :                         s0 = _mm_loadu_si128((__m128i*)pRef);
    1833           0 :                         s1 = _mm_loadu_si128((__m128i*)(pRef + ref_stride));
    1834           0 :                         s2 = _mm_cvtsi32_si128(*(uint32_t *)pSrc);
    1835           0 :                         s5 = _mm_cvtsi32_si128(*(uint32_t *)(pSrc + src_stride));
    1836           0 :                         s3 = _mm_adds_epu16(s3, _mm_mpsadbw_epu8(s0, s2, 0));
    1837           0 :                         s3 = _mm_adds_epu16(s3, _mm_mpsadbw_epu8(s1, s5, 0));
    1838           0 :                         pSrc += src_stride << 1;
    1839           0 :                         pRef += ref_stride << 1;
    1840             :                     }
    1841           0 :                     s3 = _mm_minpos_epu16(s3);
    1842           0 :                     temSum1 = _mm_extract_epi16(s3, 0);
    1843           0 :                     if (temSum1 < lowSum) {
    1844           0 :                         lowSum = temSum1;
    1845           0 :                         xBest = (int16_t)(j + _mm_extract_epi16(s3, 1));
    1846           0 :                         yBest = i;
    1847             :                     }
    1848             :                 }
    1849             : 
    1850           0 :                 if (leftover) {
    1851           0 :                     pSrc = src;
    1852           0 :                     pRef = ref + j;
    1853           0 :                     s3 = _mm_setzero_si128();
    1854           0 :                     for (k = 0; k < block_height; k += 2) {
    1855           0 :                         s0 = _mm_loadu_si128((__m128i*)pRef);
    1856           0 :                         s1 = _mm_loadu_si128((__m128i*)(pRef + ref_stride));
    1857           0 :                         s2 = _mm_cvtsi32_si128(*(uint32_t *)pSrc);
    1858           0 :                         s5 = _mm_cvtsi32_si128(*(uint32_t *)(pSrc + src_stride));
    1859           0 :                         s3 = _mm_adds_epu16(s3, _mm_mpsadbw_epu8(s0, s2, 0));
    1860           0 :                         s3 = _mm_adds_epu16(s3, _mm_mpsadbw_epu8(s1, s5, 0));
    1861           0 :                         pSrc += src_stride << 1;
    1862           0 :                         pRef += ref_stride << 1;
    1863             :                     }
    1864           0 :                     s3 = _mm_or_si128(s3, s8);
    1865           0 :                     s3 = _mm_minpos_epu16(s3);
    1866           0 :                     temSum1 = _mm_extract_epi16(s3, 0);
    1867           0 :                     if (temSum1 < lowSum) {
    1868           0 :                         lowSum = temSum1;
    1869           0 :                         xBest = (int16_t)(j + _mm_extract_epi16(s3, 1));
    1870           0 :                         yBest = i;
    1871             :                     }
    1872             :                 }
    1873           0 :                 ref += src_stride_raw;
    1874             :             }
    1875             :         }
    1876             : 
    1877           0 :         break;
    1878             : 
    1879           0 :     case 8:
    1880           0 :         if (!(block_height % 4)) {
    1881           0 :             uint32_t srcStrideT = 3 * src_stride;
    1882           0 :             uint32_t refStrideT = 3 * ref_stride;
    1883           0 :             for (i = 0; i < search_area_height; i++) {
    1884           0 :                 for (j = 0; j <= search_area_width - 8; j += 8) {
    1885           0 :                     pSrc = src;
    1886           0 :                     pRef = ref + j;
    1887           0 :                     ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
    1888           0 :                     for (k = 0; k < block_height; k += 4) {
    1889           0 :                         ss0 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pRef)), _mm_loadu_si128((__m128i*)(pRef + 2 * ref_stride)), 0x1);
    1890           0 :                         ss1 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)(pRef + ref_stride))), _mm_loadu_si128((__m128i*)(pRef + refStrideT)), 0x1);
    1891           0 :                         ss2 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_unpacklo_epi64(_mm_loadl_epi64((__m128i*)pSrc), _mm_loadl_epi64((__m128i*)(pSrc + src_stride)))), _mm_unpacklo_epi64(_mm_loadl_epi64((__m128i*)(pSrc + 2 * src_stride)), _mm_loadl_epi64((__m128i*)(pSrc + srcStrideT))), 0x1);
    1892           0 :                         ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
    1893           0 :                         ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
    1894           0 :                         ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
    1895           0 :                         ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
    1896           0 :                         pSrc += src_stride << 2;
    1897           0 :                         pRef += ref_stride << 2;
    1898             :                     }
    1899           0 :                     ss3 = _mm256_adds_epu16(_mm256_adds_epu16(ss3, ss4), _mm256_adds_epu16(ss5, ss6));
    1900           0 :                     s3 = _mm_adds_epu16(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
    1901           0 :                     s3 = _mm_minpos_epu16(s3);
    1902           0 :                     temSum1 = _mm_extract_epi16(s3, 0);
    1903           0 :                     if (temSum1 < lowSum) {
    1904           0 :                         lowSum = temSum1;
    1905           0 :                         xBest = (int16_t)(j + _mm_extract_epi16(s3, 1));
    1906           0 :                         yBest = i;
    1907             :                     }
    1908             :                 }
    1909             : 
    1910           0 :                 if (leftover) {
    1911           0 :                     pSrc = src;
    1912           0 :                     pRef = ref + j;
    1913           0 :                     ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
    1914           0 :                     for (k = 0; k < block_height; k += 4) {
    1915           0 :                         ss0 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pRef)), _mm_loadu_si128((__m128i*)(pRef + 2 * ref_stride)), 0x1);
    1916           0 :                         ss1 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)(pRef + ref_stride))), _mm_loadu_si128((__m128i*)(pRef + refStrideT)), 0x1);
    1917           0 :                         ss2 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_unpacklo_epi64(_mm_loadl_epi64((__m128i*)pSrc), _mm_loadl_epi64((__m128i*)(pSrc + src_stride)))), _mm_unpacklo_epi64(_mm_loadl_epi64((__m128i*)(pSrc + 2 * src_stride)), _mm_loadl_epi64((__m128i*)(pSrc + srcStrideT))), 0x1);
    1918           0 :                         ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
    1919           0 :                         ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
    1920           0 :                         ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
    1921           0 :                         ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
    1922           0 :                         pSrc += src_stride << 2;
    1923           0 :                         pRef += ref_stride << 2;
    1924             :                     }
    1925           0 :                     ss3 = _mm256_adds_epu16(_mm256_adds_epu16(ss3, ss4), _mm256_adds_epu16(ss5, ss6));
    1926           0 :                     s3 = _mm_adds_epu16(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
    1927           0 :                     s3 = _mm_or_si128(s3, s8);
    1928           0 :                     s3 = _mm_minpos_epu16(s3);
    1929           0 :                     temSum1 = _mm_extract_epi16(s3, 0);
    1930           0 :                     if (temSum1 < lowSum) {
    1931           0 :                         lowSum = temSum1;
    1932           0 :                         xBest = (int16_t)(j + _mm_extract_epi16(s3, 1));
    1933           0 :                         yBest = i;
    1934             :                     }
    1935             :                 }
    1936           0 :                 ref += src_stride_raw;
    1937             :             }
    1938             :         }
    1939             :         else {
    1940           0 :             for (i = 0; i < search_area_height; i++) {
    1941           0 :                 for (j = 0; j <= search_area_width - 8; j += 8) {
    1942           0 :                     pSrc = src;
    1943           0 :                     pRef = ref + j;
    1944           0 :                     s3 = s4 = _mm_setzero_si128();
    1945           0 :                     for (k = 0; k < block_height; k += 2) {
    1946           0 :                         s0 = _mm_loadu_si128((__m128i*)pRef);
    1947           0 :                         s1 = _mm_loadu_si128((__m128i*)(pRef + ref_stride));
    1948           0 :                         s2 = _mm_loadl_epi64((__m128i*)pSrc);
    1949           0 :                         s5 = _mm_loadl_epi64((__m128i*)(pSrc + src_stride));
    1950           0 :                         s3 = _mm_adds_epu16(s3, _mm_mpsadbw_epu8(s0, s2, 0));
    1951           0 :                         s4 = _mm_adds_epu16(s4, _mm_mpsadbw_epu8(s0, s2, 5));
    1952           0 :                         s3 = _mm_adds_epu16(s3, _mm_mpsadbw_epu8(s1, s5, 0));
    1953           0 :                         s4 = _mm_adds_epu16(s4, _mm_mpsadbw_epu8(s1, s5, 5));
    1954           0 :                         pSrc += src_stride << 1;
    1955           0 :                         pRef += ref_stride << 1;
    1956             :                     }
    1957           0 :                     s3 = _mm_adds_epu16(s3, s4);
    1958           0 :                     s3 = _mm_minpos_epu16(s3);
    1959           0 :                     temSum1 = _mm_extract_epi16(s3, 0);
    1960           0 :                     if (temSum1 < lowSum) {
    1961           0 :                         lowSum = temSum1;
    1962           0 :                         xBest = (int16_t)(j + _mm_extract_epi16(s3, 1));
    1963           0 :                         yBest = i;
    1964             :                     }
    1965             :                 }
    1966             : 
    1967           0 :                 if (leftover) {
    1968           0 :                     pSrc = src;
    1969           0 :                     pRef = ref + j;
    1970           0 :                     s3 = s4 = _mm_setzero_si128();
    1971           0 :                     for (k = 0; k < block_height; k += 2) {
    1972           0 :                         s0 = _mm_loadu_si128((__m128i*)pRef);
    1973           0 :                         s1 = _mm_loadu_si128((__m128i*)(pRef + ref_stride));
    1974           0 :                         s2 = _mm_loadl_epi64((__m128i*)pSrc);
    1975           0 :                         s5 = _mm_loadl_epi64((__m128i*)(pSrc + src_stride));
    1976           0 :                         s3 = _mm_adds_epu16(s3, _mm_mpsadbw_epu8(s0, s2, 0));
    1977           0 :                         s4 = _mm_adds_epu16(s4, _mm_mpsadbw_epu8(s0, s2, 5));
    1978           0 :                         s3 = _mm_adds_epu16(s3, _mm_mpsadbw_epu8(s1, s5, 0));
    1979           0 :                         s4 = _mm_adds_epu16(s4, _mm_mpsadbw_epu8(s1, s5, 5));
    1980           0 :                         pSrc += src_stride << 1;
    1981           0 :                         pRef += ref_stride << 1;
    1982             :                     }
    1983           0 :                     s3 = _mm_adds_epu16(s3, s4);
    1984           0 :                     s3 = _mm_or_si128(s3, s8);
    1985           0 :                     s3 = _mm_minpos_epu16(s3);
    1986           0 :                     temSum1 = _mm_extract_epi16(s3, 0);
    1987           0 :                     if (temSum1 < lowSum) {
    1988           0 :                         lowSum = temSum1;
    1989           0 :                         xBest = (int16_t)(j + _mm_extract_epi16(s3, 1));
    1990           0 :                         yBest = i;
    1991             :                     }
    1992             :                 }
    1993           0 :                 ref += src_stride_raw;
    1994             :             }
    1995             :         }
    1996           0 :         break;
    1997             : 
    1998           0 :     case 16:
    1999           0 :         if (block_height <= 16) {
    2000           0 :             for (i = 0; i < search_area_height; i++) {
    2001           0 :                 for (j = 0; j <= search_area_width - 8; j += 8) {
    2002           0 :                     pSrc = src;
    2003           0 :                     pRef = ref + j;
    2004           0 :                     ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
    2005           0 :                     for (k = 0; k < block_height; k += 2) {
    2006           0 :                         ss0 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pRef)), _mm_loadu_si128((__m128i*)(pRef + ref_stride)), 0x1);
    2007           0 :                         ss1 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)(pRef + 8))), _mm_loadu_si128((__m128i*)(pRef + ref_stride + 8)), 0x1);
    2008           0 :                         ss2 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pSrc)), _mm_loadu_si128((__m128i*)(pSrc + src_stride)), 0x1);
    2009           0 :                         ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
    2010           0 :                         ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
    2011           0 :                         ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
    2012           0 :                         ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
    2013           0 :                         pSrc += 2 * src_stride;
    2014           0 :                         pRef += 2 * ref_stride;
    2015             :                     }
    2016           0 :                     ss3 = _mm256_adds_epu16(_mm256_adds_epu16(ss3, ss4), _mm256_adds_epu16(ss5, ss6));
    2017           0 :                     s3 = _mm_adds_epu16(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
    2018           0 :                     s3 = _mm_minpos_epu16(s3);
    2019           0 :                     temSum1 = _mm_extract_epi16(s3, 0);
    2020           0 :                     if (temSum1 < lowSum) {
    2021           0 :                         lowSum = temSum1;
    2022           0 :                         xBest = (int16_t)(j + _mm_extract_epi16(s3, 1));
    2023           0 :                         yBest = i;
    2024             :                     }
    2025             :                 }
    2026             : 
    2027           0 :                 if (leftover) {
    2028           0 :                     pSrc = src;
    2029           0 :                     pRef = ref + j;
    2030           0 :                     ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
    2031           0 :                     for (k = 0; k < block_height; k += 2) {
    2032           0 :                         ss0 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pRef)), _mm_loadu_si128((__m128i*)(pRef + ref_stride)), 0x1);
    2033           0 :                         ss1 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)(pRef + 8))), _mm_loadu_si128((__m128i*)(pRef + ref_stride + 8)), 0x1);
    2034           0 :                         ss2 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pSrc)), _mm_loadu_si128((__m128i*)(pSrc + src_stride)), 0x1);
    2035           0 :                         ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
    2036           0 :                         ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
    2037           0 :                         ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
    2038           0 :                         ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
    2039           0 :                         pSrc += 2 * src_stride;
    2040           0 :                         pRef += 2 * ref_stride;
    2041             :                     }
    2042           0 :                     ss3 = _mm256_adds_epu16(_mm256_adds_epu16(ss3, ss4), _mm256_adds_epu16(ss5, ss6));
    2043           0 :                     s3 = _mm_adds_epu16(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
    2044           0 :                     s3 = _mm_or_si128(s3, s8);
    2045           0 :                     s3 = _mm_minpos_epu16(s3);
    2046           0 :                     temSum1 = _mm_extract_epi16(s3, 0);
    2047           0 :                     if (temSum1 < lowSum) {
    2048           0 :                         lowSum = temSum1;
    2049           0 :                         xBest = (int16_t)(j + _mm_extract_epi16(s3, 1));
    2050           0 :                         yBest = i;
    2051             :                     }
    2052             :                 }
    2053           0 :                 ref += src_stride_raw;
    2054             :             }
    2055             :         }
    2056           0 :         else if (block_height <= 32) {
    2057           0 :             for (i = 0; i < search_area_height; i++) {
    2058           0 :                 for (j = 0; j <= search_area_width - 8; j += 8) {
    2059           0 :                     pSrc = src;
    2060           0 :                     pRef = ref + j;
    2061           0 :                     ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
    2062           0 :                     for (k = 0; k < block_height; k += 2) {
    2063           0 :                         ss0 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pRef)), _mm_loadu_si128((__m128i*)(pRef + ref_stride)), 0x1);
    2064           0 :                         ss1 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)(pRef + 8))), _mm_loadu_si128((__m128i*)(pRef + ref_stride + 8)), 0x1);
    2065           0 :                         ss2 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pSrc)), _mm_loadu_si128((__m128i*)(pSrc + src_stride)), 0x1);
    2066           0 :                         ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
    2067           0 :                         ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
    2068           0 :                         ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
    2069           0 :                         ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
    2070           0 :                         pSrc += 2 * src_stride;
    2071           0 :                         pRef += 2 * ref_stride;
    2072             :                     }
    2073           0 :                     ss3 = _mm256_adds_epu16(_mm256_adds_epu16(ss3, ss4), _mm256_adds_epu16(ss5, ss6));
    2074           0 :                     s3 = _mm256_castsi256_si128(ss3);
    2075           0 :                     s5 = _mm256_extracti128_si256(ss3, 1);
    2076           0 :                     s4 = _mm_minpos_epu16(s3);
    2077           0 :                     s6 = _mm_minpos_epu16(s5);
    2078           0 :                     s4 = _mm_unpacklo_epi16(s4, s4);
    2079           0 :                     s4 = _mm_unpacklo_epi32(s4, s4);
    2080           0 :                     s4 = _mm_unpacklo_epi64(s4, s4);
    2081           0 :                     s6 = _mm_unpacklo_epi16(s6, s6);
    2082           0 :                     s6 = _mm_unpacklo_epi32(s6, s6);
    2083           0 :                     s6 = _mm_unpacklo_epi64(s6, s6);
    2084           0 :                     s3 = _mm_sub_epi16(s3, s4);
    2085           0 :                     s5 = _mm_adds_epu16(s5, s3);
    2086           0 :                     s5 = _mm_sub_epi16(s5, s6);
    2087           0 :                     s5 = _mm_minpos_epu16(s5);
    2088           0 :                     temSum1 = _mm_extract_epi16(s5, 0);
    2089           0 :                     temSum1 += _mm_extract_epi16(s4, 0);
    2090           0 :                     temSum1 += _mm_extract_epi16(s6, 0);
    2091           0 :                     if (temSum1 < lowSum) {
    2092           0 :                         lowSum = temSum1;
    2093           0 :                         xBest = (int16_t)(j + _mm_extract_epi16(s5, 1));
    2094           0 :                         yBest = i;
    2095             :                     }
    2096             :                 }
    2097             : 
    2098           0 :                 if (leftover) {
    2099           0 :                     pSrc = src;
    2100           0 :                     pRef = ref + j;
    2101           0 :                     ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
    2102           0 :                     for (k = 0; k < block_height; k += 2) {
    2103           0 :                         ss0 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pRef)), _mm_loadu_si128((__m128i*)(pRef + ref_stride)), 0x1);
    2104           0 :                         ss1 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)(pRef + 8))), _mm_loadu_si128((__m128i*)(pRef + ref_stride + 8)), 0x1);
    2105           0 :                         ss2 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pSrc)), _mm_loadu_si128((__m128i*)(pSrc + src_stride)), 0x1);
    2106           0 :                         ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
    2107           0 :                         ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
    2108           0 :                         ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
    2109           0 :                         ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
    2110           0 :                         pSrc += 2 * src_stride;
    2111           0 :                         pRef += 2 * ref_stride;
    2112             :                     }
    2113           0 :                     ss3 = _mm256_adds_epu16(_mm256_adds_epu16(ss3, ss4), _mm256_adds_epu16(ss5, ss6));
    2114           0 :                     s3 = _mm256_castsi256_si128(ss3);
    2115           0 :                     s5 = _mm256_extracti128_si256(ss3, 1);
    2116           0 :                     s3 = _mm_or_si128(s3, s8);
    2117           0 :                     s5 = _mm_or_si128(s5, s8);
    2118           0 :                     s4 = _mm_minpos_epu16(s3);
    2119           0 :                     s6 = _mm_minpos_epu16(s5);
    2120           0 :                     s4 = _mm_unpacklo_epi16(s4, s4);
    2121           0 :                     s4 = _mm_unpacklo_epi32(s4, s4);
    2122           0 :                     s4 = _mm_unpacklo_epi64(s4, s4);
    2123           0 :                     s6 = _mm_unpacklo_epi16(s6, s6);
    2124           0 :                     s6 = _mm_unpacklo_epi32(s6, s6);
    2125           0 :                     s6 = _mm_unpacklo_epi64(s6, s6);
    2126           0 :                     s3 = _mm_sub_epi16(s3, s4);
    2127           0 :                     s5 = _mm_adds_epu16(s5, s3);
    2128           0 :                     s5 = _mm_sub_epi16(s5, s6);
    2129           0 :                     s5 = _mm_minpos_epu16(s5);
    2130           0 :                     temSum1 = _mm_extract_epi16(s5, 0);
    2131           0 :                     temSum1 += _mm_extract_epi16(s4, 0);
    2132           0 :                     temSum1 += _mm_extract_epi16(s6, 0);
    2133           0 :                     if (temSum1 < lowSum) {
    2134           0 :                         lowSum = temSum1;
    2135           0 :                         xBest = (int16_t)(j + _mm_extract_epi16(s5, 1));
    2136           0 :                         yBest = i;
    2137             :                     }
    2138             :                 }
    2139           0 :                 ref += src_stride_raw;
    2140             :             }
    2141             :         }
    2142             :         else {
    2143           0 :             for (i = 0; i < search_area_height; i++) {
    2144           0 :                 for (j = 0; j <= search_area_width - 8; j += 8) {
    2145           0 :                     pSrc = src;
    2146           0 :                     pRef = ref + j;
    2147           0 :                     ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
    2148           0 :                     for (k = 0; k < block_height; k += 2) {
    2149           0 :                         ss0 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pRef)), _mm_loadu_si128((__m128i*)(pRef + ref_stride)), 0x1);
    2150           0 :                         ss1 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)(pRef + 8))), _mm_loadu_si128((__m128i*)(pRef + ref_stride + 8)), 0x1);
    2151           0 :                         ss2 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pSrc)), _mm_loadu_si128((__m128i*)(pSrc + src_stride)), 0x1);
    2152           0 :                         ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
    2153           0 :                         ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
    2154           0 :                         ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
    2155           0 :                         ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
    2156           0 :                         pSrc += 2 * src_stride;
    2157           0 :                         pRef += 2 * ref_stride;
    2158             :                     }
    2159           0 :                     ss3 = _mm256_adds_epu16(ss3, ss4);
    2160           0 :                     ss5 = _mm256_adds_epu16(ss5, ss6);
    2161           0 :                     ss0 = _mm256_adds_epu16(ss3, ss5);
    2162           0 :                     s0 = _mm_adds_epu16(_mm256_castsi256_si128(ss0), _mm256_extracti128_si256(ss0, 1));
    2163           0 :                     s0 = _mm_minpos_epu16(s0);
    2164           0 :                     temSum1 = _mm_extract_epi16(s0, 0);
    2165           0 :                     if (temSum1 < lowSum) {
    2166           0 :                         if (temSum1 != 0xFFFF) { // no overflow
    2167           0 :                             lowSum = temSum1;
    2168           0 :                             xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
    2169           0 :                             yBest = i;
    2170             :                         }
    2171             :                         else {
    2172           0 :                             ss4 = _mm256_unpacklo_epi16(ss3, _mm256_setzero_si256());
    2173           0 :                             ss3 = _mm256_unpackhi_epi16(ss3, _mm256_setzero_si256());
    2174           0 :                             ss6 = _mm256_unpacklo_epi16(ss5, _mm256_setzero_si256());
    2175           0 :                             ss5 = _mm256_unpackhi_epi16(ss5, _mm256_setzero_si256());
    2176           0 :                             ss4 = _mm256_add_epi32(ss4, ss6);
    2177           0 :                             ss3 = _mm256_add_epi32(ss3, ss5);
    2178           0 :                             s0 = _mm_add_epi32(_mm256_castsi256_si128(ss4), _mm256_extracti128_si256(ss4, 1));
    2179           0 :                             s3 = _mm_add_epi32(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
    2180           0 :                             UPDATE_BEST(s0, 0, 0);
    2181           0 :                             UPDATE_BEST(s0, 1, 0);
    2182           0 :                             UPDATE_BEST(s0, 2, 0);
    2183           0 :                             UPDATE_BEST(s0, 3, 0);
    2184           0 :                             UPDATE_BEST(s3, 0, 4);
    2185           0 :                             UPDATE_BEST(s3, 1, 4);
    2186           0 :                             UPDATE_BEST(s3, 2, 4);
    2187           0 :                             UPDATE_BEST(s3, 3, 4);
    2188             :                         }
    2189             :                     }
    2190             :                 }
    2191             : 
    2192           0 :                 if (leftover) {
    2193           0 :                     pSrc = src;
    2194           0 :                     pRef = ref + j;
    2195           0 :                     ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
    2196           0 :                     for (k = 0; k < block_height; k += 2) {
    2197           0 :                         ss0 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pRef)), _mm_loadu_si128((__m128i*)(pRef + ref_stride)), 0x1);
    2198           0 :                         ss1 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)(pRef + 8))), _mm_loadu_si128((__m128i*)(pRef + ref_stride + 8)), 0x1);
    2199           0 :                         ss2 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pSrc)), _mm_loadu_si128((__m128i*)(pSrc + src_stride)), 0x1);
    2200           0 :                         ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
    2201           0 :                         ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
    2202           0 :                         ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
    2203           0 :                         ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
    2204           0 :                         pSrc += 2 * src_stride;
    2205           0 :                         pRef += 2 * ref_stride;
    2206             :                     }
    2207           0 :                     ss3 = _mm256_adds_epu16(ss3, ss4);
    2208           0 :                     ss5 = _mm256_adds_epu16(ss5, ss6);
    2209           0 :                     ss0 = _mm256_adds_epu16(ss3, ss5);
    2210           0 :                     s0 = _mm_adds_epu16(_mm256_castsi256_si128(ss0), _mm256_extracti128_si256(ss0, 1));
    2211           0 :                     s0 = _mm_or_si128(s0, s8);
    2212           0 :                     s0 = _mm_minpos_epu16(s0);
    2213           0 :                     temSum1 = _mm_extract_epi16(s0, 0);
    2214           0 :                     if (temSum1 < lowSum) {
    2215           0 :                         if (temSum1 != 0xFFFF) { // no overflow
    2216           0 :                             lowSum = temSum1;
    2217           0 :                             xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
    2218           0 :                             yBest = i;
    2219             :                         }
    2220             :                         else {
    2221           0 :                             ss4 = _mm256_unpacklo_epi16(ss3, _mm256_setzero_si256());
    2222           0 :                             ss3 = _mm256_unpackhi_epi16(ss3, _mm256_setzero_si256());
    2223           0 :                             ss6 = _mm256_unpacklo_epi16(ss5, _mm256_setzero_si256());
    2224           0 :                             ss5 = _mm256_unpackhi_epi16(ss5, _mm256_setzero_si256());
    2225           0 :                             ss4 = _mm256_add_epi32(ss4, ss6);
    2226           0 :                             ss3 = _mm256_add_epi32(ss3, ss5);
    2227           0 :                             s0 = _mm_add_epi32(_mm256_castsi256_si128(ss4), _mm256_extracti128_si256(ss4, 1));
    2228           0 :                             s3 = _mm_add_epi32(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
    2229           0 :                             k = leftover;
    2230           0 :                             while (k > 0) {
    2231           0 :                                 for (l = 0; l < 4 && k; l++, k--) {
    2232           0 :                                     temSum1 = _mm_extract_epi32(s0, 0);
    2233           0 :                                     s0 = _mm_srli_si128(s0, 4);
    2234           0 :                                     if (temSum1 < lowSum) {
    2235           0 :                                         lowSum = temSum1;
    2236           0 :                                         xBest = (int16_t)(j + leftover - k);
    2237           0 :                                         yBest = i;
    2238             :                                     }
    2239             :                                 }
    2240           0 :                                 s0 = s3;
    2241             :                             }
    2242             :                         }
    2243             :                     }
    2244             :                 }
    2245           0 :                 ref += src_stride_raw;
    2246             :             }
    2247             :         }
    2248           0 :         break;
    2249             : 
    2250           0 :     case 24:
    2251           0 :         if (block_height <= 16) {
    2252           0 :             for (i = 0; i < search_area_height; i++) {
    2253           0 :                 for (j = 0; j <= search_area_width - 8; j += 8) {
    2254           0 :                     pSrc = src;
    2255           0 :                     pRef = ref + j;
    2256           0 :                     ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
    2257           0 :                     for (k = 0; k < block_height; k++) {
    2258           0 :                         ss0 = _mm256_loadu_si256((__m256i*)pRef);
    2259           0 :                         ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
    2260           0 :                         ss2 = _mm256_loadu_si256((__m256i *)pSrc);
    2261           0 :                         ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
    2262           0 :                         ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
    2263           0 :                         ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
    2264           0 :                         ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
    2265           0 :                         pSrc += src_stride;
    2266           0 :                         pRef += ref_stride;
    2267             :                     }
    2268           0 :                     ss3 = _mm256_adds_epu16(ss3, ss4);
    2269           0 :                     ss5 = _mm256_adds_epu16(ss5, ss6);
    2270           0 :                     s3 = _mm_adds_epu16(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
    2271           0 :                     s5 = _mm256_castsi256_si128(ss5);
    2272           0 :                     s4 = _mm_minpos_epu16(s3);
    2273           0 :                     s6 = _mm_minpos_epu16(s5);
    2274           0 :                     s4 = _mm_unpacklo_epi16(s4, s4);
    2275           0 :                     s4 = _mm_unpacklo_epi32(s4, s4);
    2276           0 :                     s4 = _mm_unpacklo_epi64(s4, s4);
    2277           0 :                     s6 = _mm_unpacklo_epi16(s6, s6);
    2278           0 :                     s6 = _mm_unpacklo_epi32(s6, s6);
    2279           0 :                     s6 = _mm_unpacklo_epi64(s6, s6);
    2280           0 :                     s3 = _mm_sub_epi16(s3, s4);
    2281           0 :                     s5 = _mm_adds_epu16(s5, s3);
    2282           0 :                     s5 = _mm_sub_epi16(s5, s6);
    2283           0 :                     s5 = _mm_minpos_epu16(s5);
    2284           0 :                     temSum1 = _mm_extract_epi16(s5, 0);
    2285           0 :                     temSum1 += _mm_extract_epi16(s4, 0);
    2286           0 :                     temSum1 += _mm_extract_epi16(s6, 0);
    2287           0 :                     if (temSum1 < lowSum) {
    2288           0 :                         lowSum = temSum1;
    2289           0 :                         xBest = (int16_t)(j + _mm_extract_epi16(s5, 1));
    2290           0 :                         yBest = i;
    2291             :                     }
    2292             :                 }
    2293             : 
    2294           0 :                 if (leftover) {
    2295           0 :                     pSrc = src;
    2296           0 :                     pRef = ref + j;
    2297           0 :                     ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
    2298           0 :                     for (k = 0; k < block_height; k++) {
    2299           0 :                         ss0 = _mm256_loadu_si256((__m256i*)pRef);
    2300           0 :                         ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
    2301           0 :                         ss2 = _mm256_loadu_si256((__m256i *)pSrc);
    2302           0 :                         ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
    2303           0 :                         ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
    2304           0 :                         ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
    2305           0 :                         ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
    2306           0 :                         pSrc += src_stride;
    2307           0 :                         pRef += ref_stride;
    2308             :                     }
    2309           0 :                     ss3 = _mm256_adds_epu16(ss3, ss4);
    2310           0 :                     ss5 = _mm256_adds_epu16(ss5, ss6);
    2311           0 :                     s3 = _mm_adds_epu16(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
    2312           0 :                     s5 = _mm256_castsi256_si128(ss5);
    2313           0 :                     s3 = _mm_or_si128(s3, s8);
    2314           0 :                     s5 = _mm_or_si128(s5, s8);
    2315           0 :                     s4 = _mm_minpos_epu16(s3);
    2316           0 :                     s6 = _mm_minpos_epu16(s5);
    2317           0 :                     s4 = _mm_unpacklo_epi16(s4, s4);
    2318           0 :                     s4 = _mm_unpacklo_epi32(s4, s4);
    2319           0 :                     s4 = _mm_unpacklo_epi64(s4, s4);
    2320           0 :                     s6 = _mm_unpacklo_epi16(s6, s6);
    2321           0 :                     s6 = _mm_unpacklo_epi32(s6, s6);
    2322           0 :                     s6 = _mm_unpacklo_epi64(s6, s6);
    2323           0 :                     s3 = _mm_sub_epi16(s3, s4);
    2324           0 :                     s5 = _mm_adds_epu16(s5, s3);
    2325           0 :                     s5 = _mm_sub_epi16(s5, s6);
    2326           0 :                     s5 = _mm_minpos_epu16(s5);
    2327           0 :                     temSum1 = _mm_extract_epi16(s5, 0);
    2328           0 :                     temSum1 += _mm_extract_epi16(s4, 0);
    2329           0 :                     temSum1 += _mm_extract_epi16(s6, 0);
    2330           0 :                     if (temSum1 < lowSum) {
    2331           0 :                         lowSum = temSum1;
    2332           0 :                         xBest = (int16_t)(j + _mm_extract_epi16(s5, 1));
    2333           0 :                         yBest = i;
    2334             :                     }
    2335             :                 }
    2336           0 :                 ref += src_stride_raw;
    2337             :             }
    2338             :         }
    2339             :         else {
    2340           0 :             for (i = 0; i < search_area_height; i++) {
    2341           0 :                 for (j = 0; j <= search_area_width - 8; j += 8) {
    2342           0 :                     pSrc = src;
    2343           0 :                     pRef = ref + j;
    2344           0 :                     ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
    2345           0 :                     for (k = 0; k < block_height; k++) {
    2346           0 :                         ss0 = _mm256_loadu_si256((__m256i*)pRef);
    2347           0 :                         ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
    2348           0 :                         ss2 = _mm256_loadu_si256((__m256i *)pSrc);
    2349           0 :                         ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
    2350           0 :                         ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
    2351           0 :                         ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
    2352           0 :                         ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
    2353           0 :                         pSrc += src_stride;
    2354           0 :                         pRef += ref_stride;
    2355             :                     }
    2356           0 :                     ss3 = _mm256_adds_epu16(ss3, ss4);
    2357           0 :                     ss5 = _mm256_adds_epu16(ss5, ss6);
    2358           0 :                     s3 = _mm256_castsi256_si128(ss3);
    2359           0 :                     s4 = _mm256_extracti128_si256(ss3, 1);
    2360           0 :                     s5 = _mm256_castsi256_si128(ss5);
    2361           0 :                     s0 = _mm_adds_epu16(_mm_adds_epu16(s3, s4), s5);
    2362           0 :                     s0 = _mm_minpos_epu16(s0);
    2363           0 :                     temSum1 = _mm_extract_epi16(s0, 0);
    2364           0 :                     if (temSum1 < lowSum) {
    2365           0 :                         if (temSum1 != 0xFFFF) { // no overflow
    2366           0 :                             lowSum = temSum1;
    2367           0 :                             xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
    2368           0 :                             yBest = i;
    2369             :                         }
    2370             :                         else {
    2371           0 :                             s0 = _mm_unpacklo_epi16(s3, _mm_setzero_si128());
    2372           0 :                             s3 = _mm_unpackhi_epi16(s3, _mm_setzero_si128());
    2373           0 :                             s1 = _mm_unpacklo_epi16(s4, _mm_setzero_si128());
    2374           0 :                             s4 = _mm_unpackhi_epi16(s4, _mm_setzero_si128());
    2375           0 :                             s2 = _mm_unpacklo_epi16(s5, _mm_setzero_si128());
    2376           0 :                             s5 = _mm_unpackhi_epi16(s5, _mm_setzero_si128());
    2377           0 :                             s0 = _mm_add_epi32(_mm_add_epi32(s0, s1), s2);
    2378           0 :                             s3 = _mm_add_epi32(_mm_add_epi32(s3, s4), s5);
    2379           0 :                             UPDATE_BEST(s0, 0, 0);
    2380           0 :                             UPDATE_BEST(s0, 1, 0);
    2381           0 :                             UPDATE_BEST(s0, 2, 0);
    2382           0 :                             UPDATE_BEST(s0, 3, 0);
    2383           0 :                             UPDATE_BEST(s3, 0, 4);
    2384           0 :                             UPDATE_BEST(s3, 1, 4);
    2385           0 :                             UPDATE_BEST(s3, 2, 4);
    2386           0 :                             UPDATE_BEST(s3, 3, 4);
    2387             :                         }
    2388             :                     }
    2389             :                 }
    2390             : 
    2391           0 :                 if (leftover) {
    2392           0 :                     pSrc = src;
    2393           0 :                     pRef = ref + j;
    2394           0 :                     ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
    2395           0 :                     for (k = 0; k < block_height; k++) {
    2396           0 :                         ss0 = _mm256_loadu_si256((__m256i*)pRef);
    2397           0 :                         ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
    2398           0 :                         ss2 = _mm256_loadu_si256((__m256i *)pSrc);
    2399           0 :                         ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
    2400           0 :                         ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
    2401           0 :                         ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
    2402           0 :                         ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
    2403           0 :                         pSrc += src_stride;
    2404           0 :                         pRef += ref_stride;
    2405             :                     }
    2406           0 :                     ss3 = _mm256_adds_epu16(ss3, ss4);
    2407           0 :                     ss5 = _mm256_adds_epu16(ss5, ss6);
    2408           0 :                     s3 = _mm256_castsi256_si128(ss3);
    2409           0 :                     s4 = _mm256_extracti128_si256(ss3, 1);
    2410           0 :                     s5 = _mm256_castsi256_si128(ss5);
    2411           0 :                     s0 = _mm_adds_epu16(_mm_adds_epu16(s3, s4), s5);
    2412           0 :                     s0 = _mm_or_si128(s0, s8);
    2413           0 :                     s0 = _mm_minpos_epu16(s0);
    2414           0 :                     temSum1 = _mm_extract_epi16(s0, 0);
    2415           0 :                     if (temSum1 < lowSum) {
    2416           0 :                         if (temSum1 != 0xFFFF) { // no overflow
    2417           0 :                             lowSum = temSum1;
    2418           0 :                             xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
    2419           0 :                             yBest = i;
    2420             :                         }
    2421             :                         else {
    2422           0 :                             s0 = _mm_unpacklo_epi16(s3, _mm_setzero_si128());
    2423           0 :                             s3 = _mm_unpackhi_epi16(s3, _mm_setzero_si128());
    2424           0 :                             s1 = _mm_unpacklo_epi16(s4, _mm_setzero_si128());
    2425           0 :                             s4 = _mm_unpackhi_epi16(s4, _mm_setzero_si128());
    2426           0 :                             s2 = _mm_unpacklo_epi16(s5, _mm_setzero_si128());
    2427           0 :                             s5 = _mm_unpackhi_epi16(s5, _mm_setzero_si128());
    2428           0 :                             s0 = _mm_add_epi32(_mm_add_epi32(s0, s1), s2);
    2429           0 :                             s3 = _mm_add_epi32(_mm_add_epi32(s3, s4), s5);
    2430           0 :                             k = leftover;
    2431           0 :                             while (k > 0) {
    2432           0 :                                 for (l = 0; l < 4 && k; l++, k--) {
    2433           0 :                                     temSum1 = _mm_extract_epi32(s0, 0);
    2434           0 :                                     s0 = _mm_srli_si128(s0, 4);
    2435           0 :                                     if (temSum1 < lowSum) {
    2436           0 :                                         lowSum = temSum1;
    2437           0 :                                         xBest = (int16_t)(j + leftover - k);
    2438           0 :                                         yBest = i;
    2439             :                                     }
    2440             :                                 }
    2441           0 :                                 s0 = s3;
    2442             :                             }
    2443             :                         }
    2444             :                     }
    2445             :                 }
    2446           0 :                 ref += src_stride_raw;
    2447             :             }
    2448             :         }
    2449           0 :         break;
    2450             : 
    2451       31596 :     case 32:
    2452       31596 :         if (block_height <= 16) {
    2453           0 :             for (i = 0; i < search_area_height; i++) {
    2454           0 :                 for (j = 0; j <= search_area_width - 8; j += 8) {
    2455           0 :                     pSrc = src;
    2456           0 :                     pRef = ref + j;
    2457           0 :                     ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
    2458           0 :                     for (k = 0; k < block_height; k++) {
    2459           0 :                         ss0 = _mm256_loadu_si256((__m256i*)pRef);
    2460           0 :                         ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
    2461           0 :                         ss2 = _mm256_loadu_si256((__m256i *)pSrc);
    2462           0 :                         ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
    2463           0 :                         ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
    2464           0 :                         ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
    2465           0 :                         ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
    2466           0 :                         pSrc += src_stride;
    2467           0 :                         pRef += ref_stride;
    2468             :                     }
    2469           0 :                     ss3 = _mm256_adds_epu16(_mm256_adds_epu16(ss3, ss4), _mm256_adds_epu16(ss5, ss6));
    2470           0 :                     s3 = _mm256_castsi256_si128(ss3);
    2471           0 :                     s5 = _mm256_extracti128_si256(ss3, 1);
    2472           0 :                     s4 = _mm_minpos_epu16(s3);
    2473           0 :                     s6 = _mm_minpos_epu16(s5);
    2474           0 :                     s4 = _mm_unpacklo_epi16(s4, s4);
    2475           0 :                     s4 = _mm_unpacklo_epi32(s4, s4);
    2476           0 :                     s4 = _mm_unpacklo_epi64(s4, s4);
    2477           0 :                     s6 = _mm_unpacklo_epi16(s6, s6);
    2478           0 :                     s6 = _mm_unpacklo_epi32(s6, s6);
    2479           0 :                     s6 = _mm_unpacklo_epi64(s6, s6);
    2480           0 :                     s3 = _mm_sub_epi16(s3, s4);
    2481           0 :                     s5 = _mm_adds_epu16(s5, s3);
    2482           0 :                     s5 = _mm_sub_epi16(s5, s6);
    2483           0 :                     s5 = _mm_minpos_epu16(s5);
    2484           0 :                     temSum1 = _mm_extract_epi16(s5, 0);
    2485           0 :                     temSum1 += _mm_extract_epi16(s4, 0);
    2486           0 :                     temSum1 += _mm_extract_epi16(s6, 0);
    2487           0 :                     if (temSum1 < lowSum) {
    2488           0 :                         lowSum = temSum1;
    2489           0 :                         xBest = (int16_t)(j + _mm_extract_epi16(s5, 1));
    2490           0 :                         yBest = i;
    2491             :                     }
    2492             :                 }
    2493             : 
    2494           0 :                 if (leftover) {
    2495           0 :                     pSrc = src;
    2496           0 :                     pRef = ref + j;
    2497           0 :                     ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
    2498           0 :                     for (k = 0; k < block_height; k++) {
    2499           0 :                         ss0 = _mm256_loadu_si256((__m256i*)pRef);
    2500           0 :                         ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
    2501           0 :                         ss2 = _mm256_loadu_si256((__m256i *)pSrc);
    2502           0 :                         ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
    2503           0 :                         ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
    2504           0 :                         ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
    2505           0 :                         ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
    2506           0 :                         pSrc += src_stride;
    2507           0 :                         pRef += ref_stride;
    2508             :                     }
    2509           0 :                     ss3 = _mm256_adds_epu16(_mm256_adds_epu16(ss3, ss4), _mm256_adds_epu16(ss5, ss6));
    2510           0 :                     s3 = _mm256_castsi256_si128(ss3);
    2511           0 :                     s5 = _mm256_extracti128_si256(ss3, 1);
    2512           0 :                     s3 = _mm_or_si128(s3, s8);
    2513           0 :                     s5 = _mm_or_si128(s5, s8);
    2514           0 :                     s4 = _mm_minpos_epu16(s3);
    2515           0 :                     s6 = _mm_minpos_epu16(s5);
    2516           0 :                     s4 = _mm_unpacklo_epi16(s4, s4);
    2517           0 :                     s4 = _mm_unpacklo_epi32(s4, s4);
    2518           0 :                     s4 = _mm_unpacklo_epi64(s4, s4);
    2519           0 :                     s6 = _mm_unpacklo_epi16(s6, s6);
    2520           0 :                     s6 = _mm_unpacklo_epi32(s6, s6);
    2521           0 :                     s6 = _mm_unpacklo_epi64(s6, s6);
    2522           0 :                     s3 = _mm_sub_epi16(s3, s4);
    2523           0 :                     s5 = _mm_adds_epu16(s5, s3);
    2524           0 :                     s5 = _mm_sub_epi16(s5, s6);
    2525           0 :                     s5 = _mm_minpos_epu16(s5);
    2526           0 :                     temSum1 = _mm_extract_epi16(s5, 0);
    2527           0 :                     temSum1 += _mm_extract_epi16(s4, 0);
    2528           0 :                     temSum1 += _mm_extract_epi16(s6, 0);
    2529           0 :                     if (temSum1 < lowSum) {
    2530           0 :                         lowSum = temSum1;
    2531           0 :                         xBest = (int16_t)(j + _mm_extract_epi16(s5, 1));
    2532           0 :                         yBest = i;
    2533             :                     }
    2534             :                 }
    2535           0 :                 ref += src_stride_raw;
    2536             :             }
    2537             :         }
    2538       31596 :         else if (block_height <= 32) {
    2539      322460 :             for (i = 0; i < search_area_height; i++) {
    2540      658039 :                 for (j = 0; j <= search_area_width - 8; j += 8) {
    2541      367175 :                     pSrc = src;
    2542      367175 :                     pRef = ref + j;
    2543      367175 :                     ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
    2544    12045500 :                     for (k = 0; k < block_height; k++) {
    2545    11678300 :                         ss0 = _mm256_loadu_si256((__m256i*)pRef);
    2546    23356600 :                         ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
    2547    11678300 :                         ss2 = _mm256_loadu_si256((__m256i *)pSrc);
    2548    11678300 :                         ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
    2549    11678300 :                         ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
    2550    11678300 :                         ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
    2551    11678300 :                         ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
    2552    11678300 :                         pSrc += src_stride;
    2553    11678300 :                         pRef += ref_stride;
    2554             :                     }
    2555      367175 :                     ss3 = _mm256_adds_epu16(ss3, ss4);
    2556      367175 :                     ss5 = _mm256_adds_epu16(ss5, ss6);
    2557      367175 :                     ss6 = _mm256_adds_epu16(ss3, ss5);
    2558      367175 :                     s3 = _mm256_castsi256_si128(ss6);
    2559      367175 :                     s4 = _mm256_extracti128_si256(ss6, 1);
    2560      367175 :                     s0 = _mm_adds_epu16(s3, s4);
    2561      367175 :                     s0 = _mm_minpos_epu16(s0);
    2562      367175 :                     temSum1 = _mm_extract_epi16(s0, 0);
    2563      367175 :                     if (temSum1 < lowSum) {
    2564      168486 :                         if (temSum1 != 0xFFFF) { // no overflow
    2565      168475 :                             lowSum = temSum1;
    2566      168475 :                             xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
    2567      168475 :                             yBest = i;
    2568             :                         }
    2569             :                         else {
    2570          22 :                             ss4 = _mm256_unpacklo_epi16(ss3, _mm256_setzero_si256());
    2571          22 :                             ss3 = _mm256_unpackhi_epi16(ss3, _mm256_setzero_si256());
    2572          22 :                             ss6 = _mm256_unpacklo_epi16(ss5, _mm256_setzero_si256());
    2573          22 :                             ss5 = _mm256_unpackhi_epi16(ss5, _mm256_setzero_si256());
    2574          11 :                             ss4 = _mm256_add_epi32(ss4, ss6);
    2575          11 :                             ss3 = _mm256_add_epi32(ss3, ss5);
    2576          22 :                             s0 = _mm_add_epi32(_mm256_castsi256_si128(ss4), _mm256_extracti128_si256(ss4, 1));
    2577          22 :                             s3 = _mm_add_epi32(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
    2578          11 :                             UPDATE_BEST(s0, 0, 0);
    2579          11 :                             UPDATE_BEST(s0, 1, 0);
    2580          11 :                             UPDATE_BEST(s0, 2, 0);
    2581          11 :                             UPDATE_BEST(s0, 3, 0);
    2582          11 :                             UPDATE_BEST(s3, 0, 4);
    2583          11 :                             UPDATE_BEST(s3, 1, 4);
    2584          11 :                             UPDATE_BEST(s3, 2, 4);
    2585          11 :                             UPDATE_BEST(s3, 3, 4);
    2586             :                         }
    2587             :                     }
    2588             :                 }
    2589             : 
    2590      290864 :                 if (leftover) {
    2591         256 :                     pSrc = src;
    2592         256 :                     pRef = ref + j;
    2593         256 :                     ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
    2594        8448 :                     for (k = 0; k < block_height; k++) {
    2595        8192 :                         ss0 = _mm256_loadu_si256((__m256i*)pRef);
    2596       16384 :                         ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
    2597        8192 :                         ss2 = _mm256_loadu_si256((__m256i *)pSrc);
    2598        8192 :                         ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
    2599        8192 :                         ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
    2600        8192 :                         ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
    2601        8192 :                         ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
    2602        8192 :                         pSrc += src_stride;
    2603        8192 :                         pRef += ref_stride;
    2604             :                     }
    2605         256 :                     ss3 = _mm256_adds_epu16(ss3, ss4);
    2606         256 :                     ss5 = _mm256_adds_epu16(ss5, ss6);
    2607         256 :                     ss6 = _mm256_adds_epu16(ss3, ss5);
    2608         256 :                     s3 = _mm256_castsi256_si128(ss6);
    2609         256 :                     s4 = _mm256_extracti128_si256(ss6, 1);
    2610         256 :                     s0 = _mm_adds_epu16(s3, s4);
    2611             :                     //s0 = _mm_adds_epu16(_mm_adds_epu16(s3, s4), _mm_adds_epu16(s5, s6));
    2612         256 :                     s0 = _mm_or_si128(s0, s8);
    2613         256 :                     s0 = _mm_minpos_epu16(s0);
    2614         256 :                     temSum1 = _mm_extract_epi16(s0, 0);
    2615         256 :                     if (temSum1 < lowSum) {
    2616         137 :                         if (temSum1 != 0xFFFF) { // no overflow
    2617         129 :                             lowSum = temSum1;
    2618         129 :                             xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
    2619         129 :                             yBest = i;
    2620             :                         }
    2621             :                         else {
    2622          16 :                             ss4 = _mm256_unpacklo_epi16(ss3, _mm256_setzero_si256());
    2623          16 :                             ss3 = _mm256_unpackhi_epi16(ss3, _mm256_setzero_si256());
    2624          16 :                             ss6 = _mm256_unpacklo_epi16(ss5, _mm256_setzero_si256());
    2625          16 :                             ss5 = _mm256_unpackhi_epi16(ss5, _mm256_setzero_si256());
    2626           8 :                             ss4 = _mm256_add_epi32(ss4, ss6);
    2627           8 :                             ss3 = _mm256_add_epi32(ss3, ss5);
    2628          16 :                             s0 = _mm_add_epi32(_mm256_castsi256_si128(ss4), _mm256_extracti128_si256(ss4, 1));
    2629          16 :                             s3 = _mm_add_epi32(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
    2630           8 :                             k = leftover;
    2631          24 :                             while (k > 0) {
    2632          64 :                                 for (l = 0; l < 4 && k; l++, k--) {
    2633          48 :                                     temSum1 = _mm_extract_epi32(s0, 0);
    2634          48 :                                     s0 = _mm_srli_si128(s0, 4);
    2635          48 :                                     if (temSum1 < lowSum) {
    2636          16 :                                         lowSum = temSum1;
    2637          16 :                                         xBest = (int16_t)(j + leftover - k);
    2638          16 :                                         yBest = i;
    2639             :                                     }
    2640             :                                 }
    2641          16 :                                 s0 = s3;
    2642             :                             }
    2643             :                         }
    2644             :                     }
    2645             :                 }
    2646      290864 :                 ref += src_stride_raw;
    2647             :             }
    2648             :         }
    2649             :         else {
    2650           0 :             for (i = 0; i < search_area_height; i++) {
    2651           0 :                 for (j = 0; j <= search_area_width - 8; j += 8) {
    2652           0 :                     pSrc = src;
    2653           0 :                     pRef = ref + j;
    2654           0 :                     ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
    2655           0 :                     for (k = 0; k < block_height; k++) {
    2656           0 :                         ss0 = _mm256_loadu_si256((__m256i*)pRef);
    2657           0 :                         ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
    2658           0 :                         ss2 = _mm256_loadu_si256((__m256i *)pSrc);
    2659           0 :                         ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
    2660           0 :                         ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
    2661           0 :                         ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
    2662           0 :                         ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
    2663           0 :                         pSrc += src_stride;
    2664           0 :                         pRef += ref_stride;
    2665             :                     }
    2666           0 :                     ss7 = _mm256_adds_epu16(_mm256_adds_epu16(ss3, ss4), _mm256_adds_epu16(ss5, ss6));
    2667           0 :                     s3 = _mm256_castsi256_si128(ss7);
    2668           0 :                     s4 = _mm256_extracti128_si256(ss7, 1);
    2669           0 :                     s0 = _mm_adds_epu16(s3, s4);
    2670           0 :                     s0 = _mm_minpos_epu16(s0);
    2671           0 :                     temSum1 = _mm_extract_epi16(s0, 0);
    2672           0 :                     if (temSum1 < lowSum) {
    2673           0 :                         if (temSum1 != 0xFFFF) { // no overflow
    2674           0 :                             lowSum = temSum1;
    2675           0 :                             xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
    2676           0 :                             yBest = i;
    2677             :                         }
    2678             :                         else {
    2679           0 :                             ss0 = _mm256_unpacklo_epi16(ss3, _mm256_setzero_si256());
    2680           0 :                             ss3 = _mm256_unpackhi_epi16(ss3, _mm256_setzero_si256());
    2681           0 :                             ss1 = _mm256_unpacklo_epi16(ss4, _mm256_setzero_si256());
    2682           0 :                             ss4 = _mm256_unpackhi_epi16(ss4, _mm256_setzero_si256());
    2683           0 :                             ss2 = _mm256_unpacklo_epi16(ss5, _mm256_setzero_si256());
    2684           0 :                             ss5 = _mm256_unpackhi_epi16(ss5, _mm256_setzero_si256());
    2685           0 :                             ss7 = _mm256_unpacklo_epi16(ss6, _mm256_setzero_si256());
    2686           0 :                             ss6 = _mm256_unpackhi_epi16(ss6, _mm256_setzero_si256());
    2687           0 :                             ss0 = _mm256_add_epi32(_mm256_add_epi32(ss0, ss1), _mm256_add_epi32(ss2, ss7));
    2688           0 :                             ss3 = _mm256_add_epi32(_mm256_add_epi32(ss3, ss4), _mm256_add_epi32(ss5, ss6));
    2689           0 :                             s0 = _mm_add_epi32(_mm256_castsi256_si128(ss0), _mm256_extracti128_si256(ss0, 1));
    2690           0 :                             s3 = _mm_add_epi32(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
    2691           0 :                             UPDATE_BEST(s0, 0, 0);
    2692           0 :                             UPDATE_BEST(s0, 1, 0);
    2693           0 :                             UPDATE_BEST(s0, 2, 0);
    2694           0 :                             UPDATE_BEST(s0, 3, 0);
    2695           0 :                             UPDATE_BEST(s3, 0, 4);
    2696           0 :                             UPDATE_BEST(s3, 1, 4);
    2697           0 :                             UPDATE_BEST(s3, 2, 4);
    2698           0 :                             UPDATE_BEST(s3, 3, 4);
    2699             :                         }
    2700             :                     }
    2701             :                 }
    2702             : 
    2703           0 :                 if (leftover) {
    2704           0 :                     pSrc = src;
    2705           0 :                     pRef = ref + j;
    2706           0 :                     ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
    2707           0 :                     for (k = 0; k < block_height; k++) {
    2708           0 :                         ss0 = _mm256_loadu_si256((__m256i*)pRef);
    2709           0 :                         ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
    2710           0 :                         ss2 = _mm256_loadu_si256((__m256i *)pSrc);
    2711           0 :                         ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
    2712           0 :                         ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
    2713           0 :                         ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
    2714           0 :                         ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
    2715           0 :                         pSrc += src_stride;
    2716           0 :                         pRef += ref_stride;
    2717             :                     }
    2718           0 :                     ss7 = _mm256_adds_epu16(_mm256_adds_epu16(ss3, ss4), _mm256_adds_epu16(ss5, ss6));
    2719           0 :                     s3 = _mm256_castsi256_si128(ss7);
    2720           0 :                     s4 = _mm256_extracti128_si256(ss7, 1);
    2721           0 :                     s0 = _mm_adds_epu16(s3, s4);
    2722           0 :                     s0 = _mm_minpos_epu16(s0);
    2723           0 :                     temSum1 = _mm_extract_epi16(s0, 0);
    2724           0 :                     if (temSum1 < lowSum) {
    2725           0 :                         if (temSum1 != 0xFFFF) { // no overflow
    2726           0 :                             lowSum = temSum1;
    2727           0 :                             xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
    2728           0 :                             yBest = i;
    2729             :                         }
    2730             :                         else {
    2731           0 :                             ss0 = _mm256_unpacklo_epi16(ss3, _mm256_setzero_si256());
    2732           0 :                             ss3 = _mm256_unpackhi_epi16(ss3, _mm256_setzero_si256());
    2733           0 :                             ss1 = _mm256_unpacklo_epi16(ss4, _mm256_setzero_si256());
    2734           0 :                             ss4 = _mm256_unpackhi_epi16(ss4, _mm256_setzero_si256());
    2735           0 :                             ss2 = _mm256_unpacklo_epi16(ss5, _mm256_setzero_si256());
    2736           0 :                             ss5 = _mm256_unpackhi_epi16(ss5, _mm256_setzero_si256());
    2737           0 :                             ss7 = _mm256_unpacklo_epi16(ss6, _mm256_setzero_si256());
    2738           0 :                             ss6 = _mm256_unpackhi_epi16(ss6, _mm256_setzero_si256());
    2739           0 :                             ss0 = _mm256_add_epi32(_mm256_add_epi32(ss0, ss1), _mm256_add_epi32(ss2, ss7));
    2740           0 :                             ss3 = _mm256_add_epi32(_mm256_add_epi32(ss3, ss4), _mm256_add_epi32(ss5, ss6));
    2741           0 :                             s0 = _mm_add_epi32(_mm256_castsi256_si128(ss0), _mm256_extracti128_si256(ss0, 1));
    2742           0 :                             s3 = _mm_add_epi32(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
    2743           0 :                             k = leftover;
    2744           0 :                             while (k > 0) {
    2745           0 :                                 for (l = 0; l < 4 && k; l++, k--) {
    2746           0 :                                     temSum1 = _mm_extract_epi32(s0, 0);
    2747           0 :                                     s0 = _mm_srli_si128(s0, 4);
    2748           0 :                                     if (temSum1 < lowSum) {
    2749           0 :                                         lowSum = temSum1;
    2750           0 :                                         xBest = (int16_t)(j + leftover - k);
    2751           0 :                                         yBest = i;
    2752             :                                     }
    2753             :                                 }
    2754           0 :                                 s0 = s3;
    2755             :                             }
    2756             :                         }
    2757             :                     }
    2758             :                 }
    2759           0 :                 ref += src_stride_raw;
    2760             :             }
    2761             :         }
    2762       31596 :         break;
    2763             : 
    2764           0 :     case 48:
    2765           0 :         if (block_height <= 32) {
    2766           0 :             for (i = 0; i < search_area_height; i++) {
    2767           0 :                 for (j = 0; j <= search_area_width - 8; j += 8) {
    2768           0 :                     pSrc = src;
    2769           0 :                     pRef = ref + j;
    2770           0 :                     s3 = s4 = s5 = s6 = _mm_setzero_si128();
    2771           0 :                     ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
    2772           0 :                     for (k = 0; k < block_height; k++) {
    2773           0 :                         ss0 = _mm256_loadu_si256((__m256i*)pRef);
    2774           0 :                         ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
    2775           0 :                         ss2 = _mm256_loadu_si256((__m256i *)pSrc);
    2776           0 :                         ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
    2777           0 :                         ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
    2778           0 :                         ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
    2779           0 :                         ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
    2780           0 :                         s0 = _mm_loadu_si128((__m128i*)(pRef + 32));
    2781           0 :                         s1 = _mm_loadu_si128((__m128i*)(pRef + 40));
    2782           0 :                         s2 = _mm_loadu_si128((__m128i*)(pSrc + 32));
    2783           0 :                         s3 = _mm_adds_epu16(s3, _mm_mpsadbw_epu8(s0, s2, 0));
    2784           0 :                         s4 = _mm_adds_epu16(s4, _mm_mpsadbw_epu8(s0, s2, 5));
    2785           0 :                         s5 = _mm_adds_epu16(s5, _mm_mpsadbw_epu8(s1, s2, 2));
    2786           0 :                         s6 = _mm_adds_epu16(s6, _mm_mpsadbw_epu8(s1, s2, 7));
    2787           0 :                         pSrc += src_stride;
    2788           0 :                         pRef += ref_stride;
    2789             :                     }
    2790           0 :                     s3 = _mm_adds_epu16(s3, s4);
    2791           0 :                     s5 = _mm_adds_epu16(s5, s6);
    2792           0 :                     s0 = _mm_adds_epu16(s3, s5);
    2793           0 :                     ss3 = _mm256_adds_epu16(ss3, ss4);
    2794           0 :                     ss5 = _mm256_adds_epu16(ss5, ss6);
    2795           0 :                     ss6 = _mm256_adds_epu16(ss3, ss5);
    2796           0 :                     s0 = _mm_adds_epu16(s0, _mm_adds_epu16(_mm256_castsi256_si128(ss6), _mm256_extracti128_si256(ss6, 1)));
    2797           0 :                     s0 = _mm_minpos_epu16(s0);
    2798           0 :                     temSum1 = _mm_extract_epi16(s0, 0);
    2799           0 :                     if (temSum1 < lowSum) {
    2800           0 :                         if (temSum1 != 0xFFFF) { // no overflow
    2801           0 :                             lowSum = temSum1;
    2802           0 :                             xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
    2803           0 :                             yBest = i;
    2804             :                         }
    2805             :                         else {
    2806           0 :                             ss4 = _mm256_unpacklo_epi16(ss3, _mm256_setzero_si256());
    2807           0 :                             ss3 = _mm256_unpackhi_epi16(ss3, _mm256_setzero_si256());
    2808           0 :                             ss6 = _mm256_unpacklo_epi16(ss5, _mm256_setzero_si256());
    2809           0 :                             ss5 = _mm256_unpackhi_epi16(ss5, _mm256_setzero_si256());
    2810           0 :                             ss4 = _mm256_add_epi32(ss4, ss6);
    2811           0 :                             ss3 = _mm256_add_epi32(ss3, ss5);
    2812           0 :                             s0 = _mm_add_epi32(_mm256_castsi256_si128(ss4), _mm256_extracti128_si256(ss4, 1));
    2813           0 :                             s1 = _mm_add_epi32(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
    2814           0 :                             s0 = _mm_add_epi32(s0, _mm_unpacklo_epi16(s3, _mm_setzero_si128()));
    2815           0 :                             s0 = _mm_add_epi32(s0, _mm_unpacklo_epi16(s5, _mm_setzero_si128()));
    2816           0 :                             s1 = _mm_add_epi32(s1, _mm_unpackhi_epi16(s3, _mm_setzero_si128()));
    2817           0 :                             s1 = _mm_add_epi32(s1, _mm_unpackhi_epi16(s5, _mm_setzero_si128()));
    2818           0 :                             UPDATE_BEST(s0, 0, 0);
    2819           0 :                             UPDATE_BEST(s0, 1, 0);
    2820           0 :                             UPDATE_BEST(s0, 2, 0);
    2821           0 :                             UPDATE_BEST(s0, 3, 0);
    2822           0 :                             UPDATE_BEST(s1, 0, 4);
    2823           0 :                             UPDATE_BEST(s1, 1, 4);
    2824           0 :                             UPDATE_BEST(s1, 2, 4);
    2825           0 :                             UPDATE_BEST(s1, 3, 4);
    2826             :                         }
    2827             :                     }
    2828             :                 }
    2829             : 
    2830           0 :                 if (leftover) {
    2831           0 :                     pSrc = src;
    2832           0 :                     pRef = ref + j;
    2833           0 :                     s3 = s4 = s5 = s6 = _mm_setzero_si128();
    2834           0 :                     ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
    2835           0 :                     for (k = 0; k < block_height; k++) {
    2836           0 :                         ss0 = _mm256_loadu_si256((__m256i*)pRef);
    2837           0 :                         ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
    2838           0 :                         ss2 = _mm256_loadu_si256((__m256i *)pSrc);
    2839           0 :                         ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
    2840           0 :                         ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
    2841           0 :                         ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
    2842           0 :                         ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
    2843           0 :                         s0 = _mm_loadu_si128((__m128i*)(pRef + 32));
    2844           0 :                         s1 = _mm_loadu_si128((__m128i*)(pRef + 40));
    2845           0 :                         s2 = _mm_loadu_si128((__m128i*)(pSrc + 32));
    2846           0 :                         s3 = _mm_adds_epu16(s3, _mm_mpsadbw_epu8(s0, s2, 0));
    2847           0 :                         s4 = _mm_adds_epu16(s4, _mm_mpsadbw_epu8(s0, s2, 5));
    2848           0 :                         s5 = _mm_adds_epu16(s5, _mm_mpsadbw_epu8(s1, s2, 2));
    2849           0 :                         s6 = _mm_adds_epu16(s6, _mm_mpsadbw_epu8(s1, s2, 7));
    2850           0 :                         pSrc += src_stride;
    2851           0 :                         pRef += ref_stride;
    2852             :                     }
    2853           0 :                     s3 = _mm_adds_epu16(s3, s4);
    2854           0 :                     s5 = _mm_adds_epu16(s5, s6);
    2855           0 :                     s0 = _mm_adds_epu16(s3, s5);
    2856           0 :                     ss3 = _mm256_adds_epu16(ss3, ss4);
    2857           0 :                     ss5 = _mm256_adds_epu16(ss5, ss6);
    2858           0 :                     ss6 = _mm256_adds_epu16(ss3, ss5);
    2859           0 :                     s0 = _mm_adds_epu16(s0, _mm_adds_epu16(_mm256_castsi256_si128(ss6), _mm256_extracti128_si256(ss6, 1)));
    2860           0 :                     s0 = _mm_or_si128(s0, s8);
    2861           0 :                     s0 = _mm_minpos_epu16(s0);
    2862           0 :                     temSum1 = _mm_extract_epi16(s0, 0);
    2863           0 :                     if (temSum1 < lowSum) {
    2864           0 :                         if (temSum1 != 0xFFFF) { // no overflow
    2865           0 :                             lowSum = temSum1;
    2866           0 :                             xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
    2867           0 :                             yBest = i;
    2868             :                         }
    2869             :                         else {
    2870           0 :                             ss4 = _mm256_unpacklo_epi16(ss3, _mm256_setzero_si256());
    2871           0 :                             ss3 = _mm256_unpackhi_epi16(ss3, _mm256_setzero_si256());
    2872           0 :                             ss6 = _mm256_unpacklo_epi16(ss5, _mm256_setzero_si256());
    2873           0 :                             ss5 = _mm256_unpackhi_epi16(ss5, _mm256_setzero_si256());
    2874           0 :                             ss4 = _mm256_add_epi32(ss4, ss6);
    2875           0 :                             ss3 = _mm256_add_epi32(ss3, ss5);
    2876           0 :                             s0 = _mm_add_epi32(_mm256_castsi256_si128(ss4), _mm256_extracti128_si256(ss4, 1));
    2877           0 :                             s1 = _mm_add_epi32(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
    2878           0 :                             s0 = _mm_add_epi32(s0, _mm_unpacklo_epi16(s3, _mm_setzero_si128()));
    2879           0 :                             s0 = _mm_add_epi32(s0, _mm_unpacklo_epi16(s5, _mm_setzero_si128()));
    2880           0 :                             s1 = _mm_add_epi32(s1, _mm_unpackhi_epi16(s3, _mm_setzero_si128()));
    2881           0 :                             s1 = _mm_add_epi32(s1, _mm_unpackhi_epi16(s5, _mm_setzero_si128()));
    2882           0 :                             k = leftover;
    2883           0 :                             while (k > 0) {
    2884           0 :                                 for (l = 0; l < 4 && k; l++, k--) {
    2885           0 :                                     temSum1 = _mm_extract_epi32(s0, 0);
    2886           0 :                                     s0 = _mm_srli_si128(s0, 4);
    2887           0 :                                     if (temSum1 < lowSum) {
    2888           0 :                                         lowSum = temSum1;
    2889           0 :                                         xBest = (int16_t)(j + leftover - k);
    2890           0 :                                         yBest = i;
    2891             :                                     }
    2892             :                                 }
    2893           0 :                                 s0 = s1;
    2894             :                             }
    2895             :                         }
    2896             :                     }
    2897             :                 }
    2898           0 :                 ref += src_stride_raw;
    2899             :             }
    2900             :         }
    2901             :         else {
    2902           0 :             for (i = 0; i < search_area_height; i++) {
    2903           0 :                 for (j = 0; j <= search_area_width - 8; j += 8) {
    2904           0 :                     pSrc = src;
    2905           0 :                     pRef = ref + j;
    2906           0 :                     s3 = s4 = s5 = s6 = _mm_setzero_si128();
    2907           0 :                     ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
    2908           0 :                     for (k = 0; k < block_height; k++) {
    2909           0 :                         ss0 = _mm256_loadu_si256((__m256i*)pRef);
    2910           0 :                         ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
    2911           0 :                         ss2 = _mm256_loadu_si256((__m256i *)pSrc);
    2912           0 :                         ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
    2913           0 :                         ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
    2914           0 :                         ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
    2915           0 :                         ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
    2916           0 :                         s0 = _mm_loadu_si128((__m128i*)(pRef + 32));
    2917           0 :                         s1 = _mm_loadu_si128((__m128i*)(pRef + 40));
    2918           0 :                         s2 = _mm_loadu_si128((__m128i*)(pSrc + 32));
    2919           0 :                         s3 = _mm_adds_epu16(s3, _mm_mpsadbw_epu8(s0, s2, 0));
    2920           0 :                         s4 = _mm_adds_epu16(s4, _mm_mpsadbw_epu8(s0, s2, 5));
    2921           0 :                         s5 = _mm_adds_epu16(s5, _mm_mpsadbw_epu8(s1, s2, 2));
    2922           0 :                         s6 = _mm_adds_epu16(s6, _mm_mpsadbw_epu8(s1, s2, 7));
    2923           0 :                         pSrc += src_stride;
    2924           0 :                         pRef += ref_stride;
    2925             :                     }
    2926           0 :                     s0 = _mm_adds_epu16(_mm_adds_epu16(s3, s4), _mm_adds_epu16(s5, s6));
    2927           0 :                     ss7 = _mm256_adds_epu16(ss3, ss4);
    2928           0 :                     ss8 = _mm256_adds_epu16(ss5, ss6);
    2929           0 :                     ss7 = _mm256_adds_epu16(ss7, ss8);
    2930           0 :                     s0 = _mm_adds_epu16(s0, _mm_adds_epu16(_mm256_castsi256_si128(ss7), _mm256_extracti128_si256(ss7, 1)));
    2931           0 :                     s0 = _mm_minpos_epu16(s0);
    2932           0 :                     temSum1 = _mm_extract_epi16(s0, 0);
    2933           0 :                     if (temSum1 < lowSum) {
    2934           0 :                         if (temSum1 != 0xFFFF) { // no overflow
    2935           0 :                             lowSum = temSum1;
    2936           0 :                             xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
    2937           0 :                             yBest = i;
    2938             :                         }
    2939             :                         else {
    2940           0 :                             ss0 = _mm256_unpacklo_epi16(ss3, _mm256_setzero_si256());
    2941           0 :                             ss3 = _mm256_unpackhi_epi16(ss3, _mm256_setzero_si256());
    2942           0 :                             ss1 = _mm256_unpacklo_epi16(ss4, _mm256_setzero_si256());
    2943           0 :                             ss4 = _mm256_unpackhi_epi16(ss4, _mm256_setzero_si256());
    2944           0 :                             ss2 = _mm256_unpacklo_epi16(ss5, _mm256_setzero_si256());
    2945           0 :                             ss5 = _mm256_unpackhi_epi16(ss5, _mm256_setzero_si256());
    2946           0 :                             ss7 = _mm256_unpacklo_epi16(ss6, _mm256_setzero_si256());
    2947           0 :                             ss6 = _mm256_unpackhi_epi16(ss6, _mm256_setzero_si256());
    2948           0 :                             ss0 = _mm256_add_epi32(_mm256_add_epi32(ss0, ss1), _mm256_add_epi32(ss2, ss7));
    2949           0 :                             ss3 = _mm256_add_epi32(_mm256_add_epi32(ss3, ss4), _mm256_add_epi32(ss5, ss6));
    2950           0 :                             s0 = _mm_add_epi32(_mm256_castsi256_si128(ss0), _mm256_extracti128_si256(ss0, 1));
    2951           0 :                             s1 = _mm_add_epi32(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
    2952           0 :                             s0 = _mm_add_epi32(s0, _mm_unpacklo_epi16(s3, _mm_setzero_si128()));
    2953           0 :                             s0 = _mm_add_epi32(s0, _mm_unpacklo_epi16(s4, _mm_setzero_si128()));
    2954           0 :                             s0 = _mm_add_epi32(s0, _mm_unpacklo_epi16(s5, _mm_setzero_si128()));
    2955           0 :                             s0 = _mm_add_epi32(s0, _mm_unpacklo_epi16(s6, _mm_setzero_si128()));
    2956           0 :                             s1 = _mm_add_epi32(s1, _mm_unpackhi_epi16(s3, _mm_setzero_si128()));
    2957           0 :                             s1 = _mm_add_epi32(s1, _mm_unpackhi_epi16(s4, _mm_setzero_si128()));
    2958           0 :                             s1 = _mm_add_epi32(s1, _mm_unpackhi_epi16(s5, _mm_setzero_si128()));
    2959           0 :                             s1 = _mm_add_epi32(s1, _mm_unpackhi_epi16(s6, _mm_setzero_si128()));
    2960           0 :                             UPDATE_BEST(s0, 0, 0);
    2961           0 :                             UPDATE_BEST(s0, 1, 0);
    2962           0 :                             UPDATE_BEST(s0, 2, 0);
    2963           0 :                             UPDATE_BEST(s0, 3, 0);
    2964           0 :                             UPDATE_BEST(s1, 0, 4);
    2965           0 :                             UPDATE_BEST(s1, 1, 4);
    2966           0 :                             UPDATE_BEST(s1, 2, 4);
    2967           0 :                             UPDATE_BEST(s1, 3, 4);
    2968             :                         }
    2969             :                     }
    2970             :                 }
    2971             : 
    2972           0 :                 if (leftover) {
    2973           0 :                     pSrc = src;
    2974           0 :                     pRef = ref + j;
    2975           0 :                     s3 = s4 = s5 = s6 = _mm_setzero_si128();
    2976           0 :                     ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
    2977           0 :                     for (k = 0; k < block_height; k++) {
    2978           0 :                         ss0 = _mm256_loadu_si256((__m256i*)pRef);
    2979           0 :                         ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
    2980           0 :                         ss2 = _mm256_loadu_si256((__m256i *)pSrc);
    2981           0 :                         ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
    2982           0 :                         ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
    2983           0 :                         ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
    2984           0 :                         ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
    2985           0 :                         s0 = _mm_loadu_si128((__m128i*)(pRef + 32));
    2986           0 :                         s1 = _mm_loadu_si128((__m128i*)(pRef + 40));
    2987           0 :                         s2 = _mm_loadu_si128((__m128i*)(pSrc + 32));
    2988           0 :                         s3 = _mm_adds_epu16(s3, _mm_mpsadbw_epu8(s0, s2, 0));
    2989           0 :                         s4 = _mm_adds_epu16(s4, _mm_mpsadbw_epu8(s0, s2, 5));
    2990           0 :                         s5 = _mm_adds_epu16(s5, _mm_mpsadbw_epu8(s1, s2, 2));
    2991           0 :                         s6 = _mm_adds_epu16(s6, _mm_mpsadbw_epu8(s1, s2, 7));
    2992           0 :                         pSrc += src_stride;
    2993           0 :                         pRef += ref_stride;
    2994             :                     }
    2995           0 :                     s0 = _mm_adds_epu16(_mm_adds_epu16(s3, s4), _mm_adds_epu16(s5, s6));
    2996           0 :                     ss7 = _mm256_adds_epu16(ss3, ss4);
    2997           0 :                     ss8 = _mm256_adds_epu16(ss5, ss6);
    2998           0 :                     ss7 = _mm256_adds_epu16(ss7, ss8);
    2999           0 :                     s0 = _mm_adds_epu16(s0, _mm_adds_epu16(_mm256_castsi256_si128(ss7), _mm256_extracti128_si256(ss7, 1)));
    3000           0 :                     s0 = _mm_or_si128(s0, s8);
    3001           0 :                     s0 = _mm_minpos_epu16(s0);
    3002           0 :                     temSum1 = _mm_extract_epi16(s0, 0);
    3003           0 :                     if (temSum1 < lowSum) {
    3004           0 :                         if (temSum1 != 0xFFFF) { // no overflow
    3005           0 :                             lowSum = temSum1;
    3006           0 :                             xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
    3007           0 :                             yBest = i;
    3008             :                         }
    3009             :                         else {
    3010           0 :                             ss0 = _mm256_unpacklo_epi16(ss3, _mm256_setzero_si256());
    3011           0 :                             ss3 = _mm256_unpackhi_epi16(ss3, _mm256_setzero_si256());
    3012           0 :                             ss1 = _mm256_unpacklo_epi16(ss4, _mm256_setzero_si256());
    3013           0 :                             ss4 = _mm256_unpackhi_epi16(ss4, _mm256_setzero_si256());
    3014           0 :                             ss2 = _mm256_unpacklo_epi16(ss5, _mm256_setzero_si256());
    3015           0 :                             ss5 = _mm256_unpackhi_epi16(ss5, _mm256_setzero_si256());
    3016           0 :                             ss7 = _mm256_unpacklo_epi16(ss6, _mm256_setzero_si256());
    3017           0 :                             ss6 = _mm256_unpackhi_epi16(ss6, _mm256_setzero_si256());
    3018           0 :                             ss0 = _mm256_add_epi32(_mm256_add_epi32(ss0, ss1), _mm256_add_epi32(ss2, ss7));
    3019           0 :                             ss3 = _mm256_add_epi32(_mm256_add_epi32(ss3, ss4), _mm256_add_epi32(ss5, ss6));
    3020           0 :                             s0 = _mm_add_epi32(_mm256_castsi256_si128(ss0), _mm256_extracti128_si256(ss0, 1));
    3021           0 :                             s1 = _mm_add_epi32(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
    3022           0 :                             s0 = _mm_add_epi32(s0, _mm_unpacklo_epi16(s3, _mm_setzero_si128()));
    3023           0 :                             s0 = _mm_add_epi32(s0, _mm_unpacklo_epi16(s4, _mm_setzero_si128()));
    3024           0 :                             s0 = _mm_add_epi32(s0, _mm_unpacklo_epi16(s5, _mm_setzero_si128()));
    3025           0 :                             s0 = _mm_add_epi32(s0, _mm_unpacklo_epi16(s6, _mm_setzero_si128()));
    3026           0 :                             s1 = _mm_add_epi32(s1, _mm_unpackhi_epi16(s3, _mm_setzero_si128()));
    3027           0 :                             s1 = _mm_add_epi32(s1, _mm_unpackhi_epi16(s4, _mm_setzero_si128()));
    3028           0 :                             s1 = _mm_add_epi32(s1, _mm_unpackhi_epi16(s5, _mm_setzero_si128()));
    3029           0 :                             s1 = _mm_add_epi32(s1, _mm_unpackhi_epi16(s6, _mm_setzero_si128()));
    3030           0 :                             k = leftover;
    3031           0 :                             while (k > 0) {
    3032           0 :                                 for (l = 0; l < 4 && k; l++, k--) {
    3033           0 :                                     temSum1 = _mm_extract_epi32(s0, 0);
    3034           0 :                                     s0 = _mm_srli_si128(s0, 4);
    3035           0 :                                     if (temSum1 < lowSum) {
    3036           0 :                                         lowSum = temSum1;
    3037           0 :                                         xBest = (int16_t)(j + leftover - k);
    3038           0 :                                         yBest = i;
    3039             :                                     }
    3040             :                                 }
    3041           0 :                                 s0 = s1;
    3042             :                             }
    3043             :                         }
    3044             :                     }
    3045             :                 }
    3046           0 :                 ref += src_stride_raw;
    3047             :             }
    3048             :         }
    3049           0 :         break;
    3050             : 
    3051       31598 :     case 64:
    3052       31598 :         if (block_height <= 32) {
    3053           0 :             for (i = 0; i < search_area_height; i++) {
    3054           0 :                 for (j = 0; j <= search_area_width - 8; j += 8) {
    3055           0 :                     pSrc = src;
    3056           0 :                     pRef = ref + j;
    3057           0 :                     ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
    3058           0 :                     for (k = 0; k < block_height; k++) {
    3059           0 :                         ss0 = _mm256_loadu_si256((__m256i*)pRef);
    3060           0 :                         ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
    3061           0 :                         ss2 = _mm256_loadu_si256((__m256i *)pSrc);
    3062           0 :                         ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
    3063           0 :                         ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
    3064           0 :                         ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
    3065           0 :                         ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
    3066           0 :                         ss0 = _mm256_loadu_si256((__m256i*)(pRef + 32));
    3067           0 :                         ss1 = _mm256_loadu_si256((__m256i*)(pRef + 40));
    3068           0 :                         ss2 = _mm256_loadu_si256((__m256i *)(pSrc + 32));
    3069           0 :                         ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
    3070           0 :                         ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
    3071           0 :                         ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
    3072           0 :                         ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
    3073           0 :                         pSrc += src_stride;
    3074           0 :                         pRef += ref_stride;
    3075             :                     }
    3076           0 :                     ss7 = _mm256_adds_epu16(_mm256_adds_epu16(ss3, ss4), _mm256_adds_epu16(ss5, ss6));
    3077           0 :                     s3 = _mm256_castsi256_si128(ss7);
    3078           0 :                     s4 = _mm256_extracti128_si256(ss7, 1);
    3079           0 :                     s0 = _mm_adds_epu16(s3, s4);
    3080           0 :                     s0 = _mm_minpos_epu16(s0);
    3081           0 :                     temSum1 = _mm_extract_epi16(s0, 0);
    3082           0 :                     if (temSum1 < lowSum) {
    3083           0 :                         if (temSum1 != 0xFFFF) { // no overflow
    3084           0 :                             lowSum = temSum1;
    3085           0 :                             xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
    3086           0 :                             yBest = i;
    3087             :                         }
    3088             :                         else {
    3089           0 :                             ss0 = _mm256_unpacklo_epi16(ss3, _mm256_setzero_si256());
    3090           0 :                             ss3 = _mm256_unpackhi_epi16(ss3, _mm256_setzero_si256());
    3091           0 :                             ss1 = _mm256_unpacklo_epi16(ss4, _mm256_setzero_si256());
    3092           0 :                             ss4 = _mm256_unpackhi_epi16(ss4, _mm256_setzero_si256());
    3093           0 :                             ss2 = _mm256_unpacklo_epi16(ss5, _mm256_setzero_si256());
    3094           0 :                             ss5 = _mm256_unpackhi_epi16(ss5, _mm256_setzero_si256());
    3095           0 :                             ss7 = _mm256_unpacklo_epi16(ss6, _mm256_setzero_si256());
    3096           0 :                             ss6 = _mm256_unpackhi_epi16(ss6, _mm256_setzero_si256());
    3097           0 :                             ss0 = _mm256_add_epi32(_mm256_add_epi32(ss0, ss1), _mm256_add_epi32(ss2, ss7));
    3098           0 :                             ss3 = _mm256_add_epi32(_mm256_add_epi32(ss3, ss4), _mm256_add_epi32(ss5, ss6));
    3099           0 :                             s0 = _mm_add_epi32(_mm256_castsi256_si128(ss0), _mm256_extracti128_si256(ss0, 1));
    3100           0 :                             s3 = _mm_add_epi32(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
    3101           0 :                             UPDATE_BEST(s0, 0, 0);
    3102           0 :                             UPDATE_BEST(s0, 1, 0);
    3103           0 :                             UPDATE_BEST(s0, 2, 0);
    3104           0 :                             UPDATE_BEST(s0, 3, 0);
    3105           0 :                             UPDATE_BEST(s3, 0, 4);
    3106           0 :                             UPDATE_BEST(s3, 1, 4);
    3107           0 :                             UPDATE_BEST(s3, 2, 4);
    3108           0 :                             UPDATE_BEST(s3, 3, 4);
    3109             :                         }
    3110             :                     }
    3111             :                 }
    3112             : 
    3113           0 :                 if (leftover) {
    3114           0 :                     pSrc = src;
    3115           0 :                     pRef = ref + j;
    3116           0 :                     ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
    3117           0 :                     for (k = 0; k < block_height; k++) {
    3118           0 :                         ss0 = _mm256_loadu_si256((__m256i*)pRef);
    3119           0 :                         ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
    3120           0 :                         ss2 = _mm256_loadu_si256((__m256i *)pSrc);
    3121           0 :                         ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
    3122           0 :                         ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
    3123           0 :                         ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
    3124           0 :                         ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
    3125           0 :                         ss0 = _mm256_loadu_si256((__m256i*)(pRef + 32));
    3126           0 :                         ss1 = _mm256_loadu_si256((__m256i*)(pRef + 40));
    3127           0 :                         ss2 = _mm256_loadu_si256((__m256i *)(pSrc + 32));
    3128           0 :                         ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
    3129           0 :                         ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
    3130           0 :                         ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
    3131           0 :                         ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
    3132           0 :                         pSrc += src_stride;
    3133           0 :                         pRef += ref_stride;
    3134             :                     }
    3135           0 :                     ss7 = _mm256_adds_epu16(_mm256_adds_epu16(ss3, ss4), _mm256_adds_epu16(ss5, ss6));
    3136           0 :                     s3 = _mm256_castsi256_si128(ss7);
    3137           0 :                     s4 = _mm256_extracti128_si256(ss7, 1);
    3138           0 :                     s0 = _mm_adds_epu16(s3, s4);
    3139           0 :                     s0 = _mm_or_si128(s0, s8);
    3140           0 :                     s0 = _mm_minpos_epu16(s0);
    3141           0 :                     temSum1 = _mm_extract_epi16(s0, 0);
    3142           0 :                     if (temSum1 < lowSum) {
    3143           0 :                         if (temSum1 != 0xFFFF) { // no overflow
    3144           0 :                             lowSum = temSum1;
    3145           0 :                             xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
    3146           0 :                             yBest = i;
    3147             :                         }
    3148             :                         else {
    3149           0 :                             ss0 = _mm256_unpacklo_epi16(ss3, _mm256_setzero_si256());
    3150           0 :                             ss3 = _mm256_unpackhi_epi16(ss3, _mm256_setzero_si256());
    3151           0 :                             ss1 = _mm256_unpacklo_epi16(ss4, _mm256_setzero_si256());
    3152           0 :                             ss4 = _mm256_unpackhi_epi16(ss4, _mm256_setzero_si256());
    3153           0 :                             ss2 = _mm256_unpacklo_epi16(ss5, _mm256_setzero_si256());
    3154           0 :                             ss5 = _mm256_unpackhi_epi16(ss5, _mm256_setzero_si256());
    3155           0 :                             ss7 = _mm256_unpacklo_epi16(ss6, _mm256_setzero_si256());
    3156           0 :                             ss6 = _mm256_unpackhi_epi16(ss6, _mm256_setzero_si256());
    3157           0 :                             ss0 = _mm256_add_epi32(_mm256_add_epi32(ss0, ss1), _mm256_add_epi32(ss2, ss7));
    3158           0 :                             ss3 = _mm256_add_epi32(_mm256_add_epi32(ss3, ss4), _mm256_add_epi32(ss5, ss6));
    3159           0 :                             s0 = _mm_add_epi32(_mm256_castsi256_si128(ss0), _mm256_extracti128_si256(ss0, 1));
    3160           0 :                             s3 = _mm_add_epi32(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
    3161           0 :                             k = leftover;
    3162           0 :                             while (k > 0) {
    3163           0 :                                 for (l = 0; l < 4 && k; l++, k--) {
    3164           0 :                                     temSum1 = _mm_extract_epi32(s0, 0);
    3165           0 :                                     s0 = _mm_srli_si128(s0, 4);
    3166           0 :                                     if (temSum1 < lowSum) {
    3167           0 :                                         lowSum = temSum1;
    3168           0 :                                         xBest = (int16_t)(j + leftover - k);
    3169           0 :                                         yBest = i;
    3170             :                                     }
    3171             :                                 }
    3172           0 :                                 s0 = s3;
    3173             :                             }
    3174             :                         }
    3175             :                     }
    3176             :                 }
    3177           0 :                 ref += src_stride_raw;
    3178             :             }
    3179             :         }
    3180             :         else {
    3181             :             __m256i ss9, ss10;
    3182      177124 :             for (i = 0; i < search_area_height; i++) {
    3183      290987 :                 for (j = 0; j <= search_area_width - 8; j += 8) {
    3184      145461 :                     pSrc = src;
    3185      145461 :                     pRef = ref + j;
    3186      145461 :                     ss3 = ss4 = ss5 = ss6 = ss7 = ss8 = ss9 = ss10 = _mm256_setzero_si256();
    3187     9362210 :                     for (k = 0; k < block_height; k++) {
    3188     9216750 :                         ss0 = _mm256_loadu_si256((__m256i*)pRef);
    3189    18433500 :                         ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
    3190     9216750 :                         ss2 = _mm256_loadu_si256((__m256i *)pSrc);
    3191     9216750 :                         ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
    3192     9216750 :                         ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
    3193     9216750 :                         ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
    3194     9216750 :                         ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
    3195     9216750 :                         ss0 = _mm256_loadu_si256((__m256i*)(pRef + 32));
    3196     9216750 :                         ss1 = _mm256_loadu_si256((__m256i*)(pRef + 40));
    3197     9216750 :                         ss2 = _mm256_loadu_si256((__m256i *)(pSrc + 32));
    3198     9216750 :                         ss7 = _mm256_adds_epu16(ss7, _mm256_mpsadbw_epu8(ss0, ss2, 0));
    3199     9216750 :                         ss8 = _mm256_adds_epu16(ss8, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
    3200     9216750 :                         ss9 = _mm256_adds_epu16(ss9, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
    3201     9216750 :                         ss10 = _mm256_adds_epu16(ss10, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
    3202     9216750 :                         pSrc += src_stride;
    3203     9216750 :                         pRef += ref_stride;
    3204             :                     }
    3205      436383 :                     ss0 = _mm256_adds_epu16(_mm256_adds_epu16(ss3, ss4), _mm256_adds_epu16(ss5, ss6));
    3206      436383 :                     ss0 = _mm256_adds_epu16(ss0, _mm256_adds_epu16(_mm256_adds_epu16(ss7, ss8), _mm256_adds_epu16(ss9, ss10)));
    3207      436383 :                     s0 = _mm_adds_epu16(_mm256_castsi256_si128(ss0), _mm256_extracti128_si256(ss0, 1));
    3208      145461 :                     s0 = _mm_minpos_epu16(s0);
    3209      145461 :                     temSum1 = _mm_extract_epi16(s0, 0);
    3210      145461 :                     if (temSum1 < lowSum) {
    3211      101377 :                         if (temSum1 != 0xFFFF) { // no overflow
    3212       72451 :                             lowSum = temSum1;
    3213       72451 :                             xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
    3214       72451 :                             yBest = i;
    3215             :                         }
    3216             :                         else {
    3217      318186 :                             ss0 = _mm256_add_epi32(_mm256_add_epi32(_mm256_unpacklo_epi16(ss3, _mm256_setzero_si256()), _mm256_unpacklo_epi16(ss4, _mm256_setzero_si256())), _mm256_add_epi32(_mm256_unpacklo_epi16(ss5, _mm256_setzero_si256()), _mm256_unpacklo_epi16(ss6, _mm256_setzero_si256())));
    3218      318186 :                             ss1 = _mm256_add_epi32(_mm256_add_epi32(_mm256_unpackhi_epi16(ss3, _mm256_setzero_si256()), _mm256_unpackhi_epi16(ss4, _mm256_setzero_si256())), _mm256_add_epi32(_mm256_unpackhi_epi16(ss5, _mm256_setzero_si256()), _mm256_unpackhi_epi16(ss6, _mm256_setzero_si256())));
    3219      318186 :                             ss2 = _mm256_add_epi32(_mm256_add_epi32(_mm256_unpacklo_epi16(ss7, _mm256_setzero_si256()), _mm256_unpacklo_epi16(ss8, _mm256_setzero_si256())), _mm256_add_epi32(_mm256_unpacklo_epi16(ss9, _mm256_setzero_si256()), _mm256_unpacklo_epi16(ss10, _mm256_setzero_si256())));
    3220      318186 :                             ss3 = _mm256_add_epi32(_mm256_add_epi32(_mm256_unpackhi_epi16(ss7, _mm256_setzero_si256()), _mm256_unpackhi_epi16(ss8, _mm256_setzero_si256())), _mm256_add_epi32(_mm256_unpackhi_epi16(ss9, _mm256_setzero_si256()), _mm256_unpackhi_epi16(ss10, _mm256_setzero_si256())));
    3221       28926 :                             ss0 = _mm256_add_epi32(ss0, ss2);
    3222       28926 :                             ss1 = _mm256_add_epi32(ss1, ss3);
    3223       57852 :                             s0 = _mm_add_epi32(_mm256_castsi256_si128(ss0), _mm256_extracti128_si256(ss0, 1));
    3224       57852 :                             s3 = _mm_add_epi32(_mm256_castsi256_si128(ss1), _mm256_extracti128_si256(ss1, 1));
    3225       28926 :                             UPDATE_BEST(s0, 0, 0);
    3226       28926 :                             UPDATE_BEST(s0, 1, 0);
    3227       28926 :                             UPDATE_BEST(s0, 2, 0);
    3228       28926 :                             UPDATE_BEST(s0, 3, 0);
    3229       28926 :                             UPDATE_BEST(s3, 0, 4);
    3230       28926 :                             UPDATE_BEST(s3, 1, 4);
    3231       28926 :                             UPDATE_BEST(s3, 2, 4);
    3232       28926 :                             UPDATE_BEST(s3, 3, 4);
    3233             :                         }
    3234             :                     }
    3235             :                 }
    3236             : 
    3237      145526 :                 if (leftover) {
    3238          68 :                     pSrc = src;
    3239          68 :                     pRef = ref + j;
    3240          68 :                     ss3 = ss4 = ss5 = ss6 = ss7 = ss8 = ss9 = ss10 = _mm256_setzero_si256();
    3241        4420 :                     for (k = 0; k < block_height; k++) {
    3242        4352 :                         ss0 = _mm256_loadu_si256((__m256i*)pRef);
    3243        8704 :                         ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
    3244        4352 :                         ss2 = _mm256_loadu_si256((__m256i *)pSrc);
    3245        4352 :                         ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
    3246        4352 :                         ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
    3247        4352 :                         ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
    3248        4352 :                         ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
    3249        4352 :                         ss0 = _mm256_loadu_si256((__m256i*)(pRef + 32));
    3250        4352 :                         ss1 = _mm256_loadu_si256((__m256i*)(pRef + 40));
    3251        4352 :                         ss2 = _mm256_loadu_si256((__m256i *)(pSrc + 32));
    3252        4352 :                         ss7 = _mm256_adds_epu16(ss7, _mm256_mpsadbw_epu8(ss0, ss2, 0));
    3253        4352 :                         ss8 = _mm256_adds_epu16(ss8, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
    3254        4352 :                         ss9 = _mm256_adds_epu16(ss9, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
    3255        4352 :                         ss10 = _mm256_adds_epu16(ss10, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
    3256        4352 :                         pSrc += src_stride;
    3257        4352 :                         pRef += ref_stride;
    3258             :                     }
    3259         204 :                     ss0 = _mm256_adds_epu16(_mm256_adds_epu16(ss3, ss4), _mm256_adds_epu16(ss5, ss6));
    3260         204 :                     ss0 = _mm256_adds_epu16(ss0, _mm256_adds_epu16(_mm256_adds_epu16(ss7, ss8), _mm256_adds_epu16(ss9, ss10)));
    3261         204 :                     s0 = _mm_adds_epu16(_mm256_castsi256_si128(ss0), _mm256_extracti128_si256(ss0, 1));
    3262          68 :                     s0 = _mm_or_si128(s0, s8);
    3263          68 :                     s0 = _mm_minpos_epu16(s0);
    3264          68 :                     temSum1 = _mm_extract_epi16(s0, 0);
    3265          68 :                     if (temSum1 < lowSum) {
    3266          68 :                         if (temSum1 != 0xFFFF) { // no overflow
    3267           0 :                             lowSum = temSum1;
    3268           0 :                             xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
    3269           0 :                             yBest = i;
    3270             :                         }
    3271             :                         else {
    3272         748 :                             ss0 = _mm256_add_epi32(_mm256_add_epi32(_mm256_unpacklo_epi16(ss3, _mm256_setzero_si256()), _mm256_unpacklo_epi16(ss4, _mm256_setzero_si256())), _mm256_add_epi32(_mm256_unpacklo_epi16(ss5, _mm256_setzero_si256()), _mm256_unpacklo_epi16(ss6, _mm256_setzero_si256())));
    3273         748 :                             ss1 = _mm256_add_epi32(_mm256_add_epi32(_mm256_unpackhi_epi16(ss3, _mm256_setzero_si256()), _mm256_unpackhi_epi16(ss4, _mm256_setzero_si256())), _mm256_add_epi32(_mm256_unpackhi_epi16(ss5, _mm256_setzero_si256()), _mm256_unpackhi_epi16(ss6, _mm256_setzero_si256())));
    3274         748 :                             ss2 = _mm256_add_epi32(_mm256_add_epi32(_mm256_unpacklo_epi16(ss7, _mm256_setzero_si256()), _mm256_unpacklo_epi16(ss8, _mm256_setzero_si256())), _mm256_add_epi32(_mm256_unpacklo_epi16(ss9, _mm256_setzero_si256()), _mm256_unpacklo_epi16(ss10, _mm256_setzero_si256())));
    3275         748 :                             ss3 = _mm256_add_epi32(_mm256_add_epi32(_mm256_unpackhi_epi16(ss7, _mm256_setzero_si256()), _mm256_unpackhi_epi16(ss8, _mm256_setzero_si256())), _mm256_add_epi32(_mm256_unpackhi_epi16(ss9, _mm256_setzero_si256()), _mm256_unpackhi_epi16(ss10, _mm256_setzero_si256())));
    3276          68 :                             ss0 = _mm256_add_epi32(ss0, ss2);
    3277          68 :                             ss1 = _mm256_add_epi32(ss1, ss3);
    3278         136 :                             s0 = _mm_add_epi32(_mm256_castsi256_si128(ss0), _mm256_extracti128_si256(ss0, 1));
    3279         136 :                             s3 = _mm_add_epi32(_mm256_castsi256_si128(ss1), _mm256_extracti128_si256(ss1, 1));
    3280          68 :                             k = leftover;
    3281         204 :                             while (k > 0) {
    3282         544 :                                 for (l = 0; l < 4 && k; l++, k--) {
    3283         408 :                                     temSum1 = _mm_extract_epi32(s0, 0);
    3284         408 :                                     s0 = _mm_srli_si128(s0, 4);
    3285         408 :                                     if (temSum1 < lowSum) {
    3286          99 :                                         lowSum = temSum1;
    3287          99 :                                         xBest = (int16_t)(j + leftover - k);
    3288          99 :                                         yBest = i;
    3289             :                                     }
    3290             :                                 }
    3291         136 :                                 s0 = s3;
    3292             :                             }
    3293             :                         }
    3294             :                     }
    3295             :                 }
    3296      145526 :                 ref += src_stride_raw;
    3297             :             }
    3298             :         }
    3299       31598 :         break;
    3300             : 
    3301           0 :     default:
    3302             :         assert(0);
    3303           0 :         break;
    3304             :     }
    3305             : 
    3306       63181 :     *best_sad = lowSum;
    3307       63181 :     *x_search_center = xBest;
    3308       63181 :     *y_search_center = yBest;
    3309       63181 : }
    3310             : 
    3311             : /*******************************************************************************
    3312             : * Requirement: height % 4 = 0
    3313             : *******************************************************************************/
    3314             : SIMD_INLINE uint32_t compute4x_m_sad_avx2(
    3315             :     const uint8_t  *src,   // input parameter, source samples Ptr
    3316             :     uint32_t  src_stride,  // input parameter, source stride
    3317             :     const uint8_t  *ref,   // input parameter, reference samples Ptr
    3318             :     uint32_t  ref_stride,  // input parameter, reference stride
    3319             :     uint32_t  height)      // input parameter, block height (M)
    3320             : {
    3321    10956100 :     uint32_t y = height;
    3322             :     __m128i xmm0;
    3323    10956100 :     __m256i ymm = _mm256_setzero_si256();
    3324             : 
    3325             :     do {
    3326    21261100 :         const __m256i src0123 = load_u8_4x4_avx2(src, src_stride);
    3327    21261200 :         const __m256i ref0123 = load_u8_4x4_avx2(ref, ref_stride);
    3328    21261500 :         ymm = _mm256_add_epi32(ymm, _mm256_sad_epu8(src0123, ref0123));
    3329    21261500 :         src += src_stride << 2;
    3330    21261500 :         ref += ref_stride << 2;
    3331    21261500 :         y -= 4;
    3332    21261500 :     } while (y);
    3333             : 
    3334    21913000 :     xmm0 = _mm_add_epi32(_mm256_castsi256_si128(ymm),
    3335    10956500 :         _mm256_extracti128_si256(ymm, 1));
    3336             : 
    3337    10956500 :     return (uint32_t)_mm_cvtsi128_si32(xmm0);
    3338             : }
    3339             : 
    3340    10956100 : uint32_t eb_compute4x_m_sad_avx2_intrin(
    3341             :     const uint8_t  *src,   // input parameter, source samples Ptr
    3342             :     uint32_t  src_stride,  // input parameter, source stride
    3343             :     const uint8_t  *ref,   // input parameter, reference samples Ptr
    3344             :     uint32_t  ref_stride,  // input parameter, reference stride
    3345             :     uint32_t  height,     // input parameter, block height (M)
    3346             :     uint32_t  width)      // input parameter, block width (N)
    3347             : {
    3348             :     (void)width;
    3349    10956500 :     return compute4x_m_sad_avx2(src, src_stride, ref, ref_stride, height);
    3350             : }
    3351             : 
    3352   137181000 : static INLINE uint32_t sad_final_avx2(const __m256i sad) {
    3353   137181000 :     const __m128i sad_lo = _mm256_castsi256_si128(sad);
    3354   137181000 :     const __m128i sad_hi = _mm256_extracti128_si256(sad, 1);
    3355   137181000 :     const __m128i sum = _mm_add_epi32(sad_lo, sad_hi);
    3356   137181000 :     const __m128i sum_hi = _mm_srli_si128(sum, 8);
    3357   137181000 :     const __m128i d = _mm_add_epi32(sum, sum_hi);
    3358   137181000 :     return (uint32_t)_mm_cvtsi128_si32(d);
    3359             : }
    3360             : 
    3361             : /*******************************************************************************
    3362             : * Requirement: height % 4 = 0
    3363             : *******************************************************************************/
    3364             : SIMD_INLINE uint32_t compute8x_m_sad_avx2(
    3365             :     const uint8_t  *src,   // input parameter, source samples Ptr
    3366             :     uint32_t  src_stride,  // input parameter, source stride
    3367             :     const uint8_t  *ref,   // input parameter, reference samples Ptr
    3368             :     uint32_t  ref_stride,  // input parameter, reference stride
    3369             :     uint32_t  height)      // input parameter, block height (M)
    3370             : {
    3371    64160600 :     uint32_t y = height;
    3372    64160600 :     __m256i sad = _mm256_setzero_si256();
    3373             : 
    3374             :     do {
    3375   210800000 :         const __m256i src0123 = load_u8_8x4_avx2(src, src_stride);
    3376   210824000 :         const __m256i ref0123 = load_u8_8x4_avx2(ref, ref_stride);
    3377   210800000 :         sad = _mm256_add_epi32(sad, _mm256_sad_epu8(src0123, ref0123));
    3378   210800000 :         src += src_stride << 2;
    3379   210800000 :         ref += ref_stride << 2;
    3380   210800000 :         y -= 4;
    3381   210800000 :     } while (y);
    3382             : 
    3383    64159900 :     return sad_final_avx2(sad);
    3384             : }
    3385             : 
    3386    64160600 : uint32_t eb_compute8x_m_sad_avx2_intrin(
    3387             :     const uint8_t  *src,   // input parameter, source samples Ptr
    3388             :     uint32_t  src_stride,  // input parameter, source stride
    3389             :     const uint8_t  *ref,   // input parameter, reference samples Ptr
    3390             :     uint32_t  ref_stride,  // input parameter, reference stride
    3391             :     uint32_t  height,     // input parameter, block height (M)
    3392             :     uint32_t  width)      // input parameter, block width (N)
    3393             : {
    3394             :     (void)width;
    3395    64181900 :     return compute8x_m_sad_avx2(src, src_stride, ref, ref_stride, height);
    3396             : }
    3397             : 
    3398   398655000 : static INLINE void compute16_sad_avx2(const uint8_t *const src,
    3399             :     const uint32_t src_stride, const uint8_t *const ref,
    3400             :     const uint32_t ref_stride, __m256i *const sum)
    3401             : {
    3402   398655000 :     const __m256i s = loadu_u8_16x2_avx2(src, src_stride);
    3403   398691000 :     const __m256i r = loadu_u8_16x2_avx2(ref, ref_stride);
    3404   398626000 :     const __m256i sad = _mm256_sad_epu8(s, r);
    3405   398626000 :     *sum = _mm256_add_epi32(*sum, sad);
    3406   398626000 : }
    3407             : 
    3408   869164000 : static INLINE void compute32_sad_avx2(const uint8_t *const src,
    3409             :     const uint8_t *const ref, __m256i *const sum)
    3410             : {
    3411   869164000 :     const __m256i s = _mm256_loadu_si256((__m256i *)src);
    3412   869164000 :     const __m256i r = _mm256_loadu_si256((__m256i *)ref);
    3413   869164000 :     const __m256i sad = _mm256_sad_epu8(s, r);
    3414   869164000 :     *sum = _mm256_add_epi32(*sum, sad);
    3415   869164000 : }
    3416             : 
    3417             : /*******************************************************************************
    3418             : * Requirement: height % 4 = 0
    3419             : *******************************************************************************/
    3420             : SIMD_INLINE uint32_t compute16x_m_sad_avx2(
    3421             :     const uint8_t  *src,        // input parameter, source samples Ptr
    3422             :     uint32_t  src_stride,  // input parameter, source stride
    3423             :     const uint8_t  *ref,        // input parameter, reference samples Ptr
    3424             :     uint32_t  ref_stride,  // input parameter, reference stride
    3425             :     uint32_t  height)      // input parameter, block height (M)
    3426             : {
    3427    45180700 :     uint32_t y = height;
    3428    45180700 :     __m256i sad = _mm256_setzero_si256();
    3429             : 
    3430             :     do {
    3431   199715000 :         compute16_sad_avx2(src + 0 * src_stride, src_stride,
    3432             :             ref + 0 * ref_stride, ref_stride, &sad);
    3433   199785000 :         compute16_sad_avx2(src + 2 * src_stride, src_stride,
    3434   199785000 :             ref + 2 * ref_stride, ref_stride, &sad);
    3435   199718000 :         src += src_stride << 2;
    3436   199718000 :         ref += ref_stride << 2;
    3437   199718000 :         y -= 4;
    3438   199718000 :     } while (y);
    3439             : 
    3440    45183100 :     return sad_final_avx2(sad);
    3441             : }
    3442             : 
    3443    45180700 : uint32_t eb_compute16x_m_sad_avx2_intrin(
    3444             :     const uint8_t  *src,        // input parameter, source samples Ptr
    3445             :     uint32_t  src_stride,  // input parameter, source stride
    3446             :     const uint8_t  *ref,        // input parameter, reference samples Ptr
    3447             :     uint32_t  ref_stride,  // input parameter, reference stride
    3448             :     uint32_t  height,     // input parameter, block height (M)
    3449             :     uint32_t  width)      // input parameter, block width (N)
    3450             : {
    3451             :     (void)width;
    3452    45191800 :     return compute16x_m_sad_avx2(src, src_stride, ref, ref_stride, height);
    3453             : }
    3454             : 
    3455             : /*******************************************************************************
    3456             : * Requirement: height % 2 = 0
    3457             : *******************************************************************************/
    3458           0 : uint32_t eb_compute24x_m_sad_avx2_intrin(
    3459             :     const uint8_t  *src,        // input parameter, source samples Ptr
    3460             :     uint32_t  src_stride,  // input parameter, source stride
    3461             :     const uint8_t  *ref,        // input parameter, reference samples Ptr
    3462             :     uint32_t  ref_stride,  // input parameter, reference stride
    3463             :     uint32_t  height,     // input parameter, block height (M)
    3464             :     uint32_t  width)     // input parameter, block width (N)
    3465             : {
    3466           0 :     uint32_t y = height;
    3467           0 :     __m256i sad = _mm256_setzero_si256();
    3468             : 
    3469             :     (void)width;
    3470             : 
    3471             :     do {
    3472           0 :         compute32_sad_avx2(src + 0 * src_stride, ref + 0 * ref_stride, &sad);
    3473           0 :         compute32_sad_avx2(src + 1 * src_stride, ref + 1 * ref_stride, &sad);
    3474           0 :         src += src_stride << 1;
    3475           0 :         ref += ref_stride << 1;
    3476           0 :         y -= 2;
    3477           0 :     } while (y);
    3478             : 
    3479           0 :     const __m128i sad_lo = _mm256_castsi256_si128(sad);
    3480           0 :     const __m128i sad_hi = _mm256_extracti128_si256(sad, 1);
    3481           0 :     const __m128i sum_lo = _mm_add_epi32(sad_lo, _mm_srli_si128(sad_lo, 8));
    3482           0 :     const __m128i sum = _mm_add_epi32(sum_lo, sad_hi);
    3483             : 
    3484           0 :     return (uint32_t)_mm_cvtsi128_si32(sum);
    3485             : }
    3486             : 
    3487             : /*******************************************************************************
    3488             : * Requirement: height % 2 = 0
    3489             : *******************************************************************************/
    3490    22134600 : static INLINE uint32_t compute32x_m_sad_avx2(
    3491             :     const uint8_t  *src,   // input parameter, source samples Ptr
    3492             :     uint32_t  src_stride,  // input parameter, source stride
    3493             :     const uint8_t  *ref,   // input parameter, reference samples Ptr
    3494             :     uint32_t  ref_stride,  // input parameter, reference stride
    3495             :     uint32_t  height)     // input parameter, block height (M)
    3496             : {
    3497    22134600 :     uint32_t y = height;
    3498    22134600 :     __m256i sad = _mm256_setzero_si256();
    3499             : 
    3500             :     do {
    3501   242598000 :         compute32_sad_avx2(src + 0 * src_stride, ref + 0 * ref_stride, &sad);
    3502   242640000 :         compute32_sad_avx2(src + 1 * src_stride, ref + 1 * ref_stride, &sad);
    3503   242600000 :         src += src_stride << 1;
    3504   242600000 :         ref += ref_stride << 1;
    3505   242600000 :         y -= 2;
    3506   242600000 :     } while (y);
    3507             : 
    3508    22135800 :     return sad_final_avx2(sad);
    3509             : }
    3510             : 
    3511    22135400 : uint32_t eb_compute32x_m_sad_avx2_intrin(
    3512             :     const uint8_t  *src,   // input parameter, source samples Ptr
    3513             :     uint32_t  src_stride,  // input parameter, source stride
    3514             :     const uint8_t  *ref,   // input parameter, reference samples Ptr
    3515             :     uint32_t  ref_stride,  // input parameter, reference stride
    3516             :     uint32_t  height,      // input parameter, block height (M)
    3517             :     uint32_t  width)       // input parameter, block width (N)
    3518             : {
    3519             :     (void)width;
    3520    22135400 :     return compute32x_m_sad_avx2(src, src_stride, ref, ref_stride, height);
    3521             : }
    3522             : 
    3523             : /*******************************************************************************
    3524             : * Requirement: height % 2 = 0
    3525             : *******************************************************************************/
    3526           0 : uint32_t eb_compute48x_m_sad_avx2_intrin(
    3527             :     const uint8_t  *src,   // input parameter, source samples Ptr
    3528             :     uint32_t  src_stride,  // input parameter, source stride
    3529             :     const uint8_t  *ref,   // input parameter, reference samples Ptr
    3530             :     uint32_t  ref_stride,  // input parameter, reference stride
    3531             :     uint32_t  height,     // input parameter, block height (M)
    3532             :     uint32_t  width)     // input parameter, block width (N)
    3533             : {
    3534           0 :     uint32_t y = height;
    3535           0 :     __m256i sad = _mm256_setzero_si256();
    3536             : 
    3537             :     (void)width;
    3538             : 
    3539             :     do {
    3540           0 :         compute32_sad_avx2(src + 0 * src_stride, ref + 0 * ref_stride, &sad);
    3541           0 :         compute32_sad_avx2(src + 1 * src_stride, ref + 1 * ref_stride, &sad);
    3542           0 :         compute16_sad_avx2(src + 32, src_stride, ref + 32, ref_stride, &sad);
    3543           0 :         src += src_stride << 1;
    3544           0 :         ref += ref_stride << 1;
    3545           0 :         y -= 2;
    3546           0 :     } while (y);
    3547             : 
    3548           0 :     return sad_final_avx2(sad);
    3549             : }
    3550             : 
    3551             : /*******************************************************************************
    3552             : * Requirement: height % 2 = 0
    3553             : *******************************************************************************/
    3554             : SIMD_INLINE uint32_t compute64x_m_sad_avx2(
    3555             :     const uint8_t  *src,   // input parameter, source samples Ptr
    3556             :     uint32_t  src_stride,  // input parameter, source stride
    3557             :     const uint8_t  *ref,   // input parameter, reference samples Ptr
    3558             :     uint32_t  ref_stride,  // input parameter, reference stride
    3559             :     uint32_t  height)      // input parameter, block height (M)
    3560             : {
    3561     5935820 :     uint32_t y = height;
    3562     5935820 :     __m256i sad = _mm256_setzero_si256();
    3563             : 
    3564             :     do {
    3565    96917400 :         compute32_sad_avx2(src, ref, &sad);
    3566    96967000 :         compute32_sad_avx2(src + 32, ref + 32, &sad);
    3567    96932200 :         compute32_sad_avx2(src + src_stride, ref + ref_stride, &sad);
    3568    96930600 :         compute32_sad_avx2(src + src_stride + 32, ref + ref_stride + 32, &sad);
    3569    96917500 :         src += src_stride << 1;
    3570    96917500 :         ref += ref_stride << 1;
    3571    96917500 :         y -= 2;
    3572    96917500 :     } while (y);
    3573             : 
    3574     5935940 :     return sad_final_avx2(sad);
    3575             : }
    3576             : 
    3577             : SIMD_INLINE uint32_t compute128x_m_sad_avx2(
    3578             :     const uint8_t  *src,   // input parameter, source samples Ptr
    3579             :     uint32_t  src_stride,  // input parameter, source stride
    3580             :     const uint8_t  *ref,   // input parameter, reference samples Ptr
    3581             :     uint32_t  ref_stride,  // input parameter, reference stride
    3582             :     uint32_t  height)      // input parameter, block height (M)
    3583             : {
    3584           0 :     uint32_t y = height;
    3585           0 :     __m256i sad = _mm256_setzero_si256();
    3586             : 
    3587             :     do {
    3588           0 :         compute32_sad_avx2(src + 0 * 32, ref + 0 * 32, &sad);
    3589           0 :         compute32_sad_avx2(src + 1 * 32, ref + 1 * 32, &sad);
    3590           0 :         compute32_sad_avx2(src + 2 * 32, ref + 2 * 32, &sad);
    3591           0 :         compute32_sad_avx2(src + 3 * 32, ref + 3 * 32, &sad);
    3592           0 :         src += src_stride;
    3593           0 :         ref += ref_stride;
    3594           0 :     } while (--y);
    3595             : 
    3596           0 :     return sad_final_avx2(sad);
    3597             : }
    3598             : 
    3599     5935820 : uint32_t eb_compute64x_m_sad_avx2_intrin(
    3600             :     const uint8_t  *src,   // input parameter, source samples Ptr
    3601             :     uint32_t  src_stride,  // input parameter, source stride
    3602             :     const uint8_t  *ref,   // input parameter, reference samples Ptr
    3603             :     uint32_t  ref_stride,  // input parameter, reference stride
    3604             :     uint32_t  height,      // input parameter, block height (M)
    3605             :     uint32_t  width)       // input parameter, block width (N)
    3606             : {
    3607             :     (void)width;
    3608     5935980 :     return compute64x_m_sad_avx2(src, src_stride, ref, ref_stride, height);
    3609             : }
    3610             : 
    3611    27775300 : static INLINE void sad_eight_8x2x2_avx2(const uint8_t *src,
    3612             :     const uint32_t src_stride, const uint8_t *ref, const uint32_t ref_stride,
    3613             :     __m256i d[2])
    3614             : {
    3615    27775300 :     const __m256i s = loadu_u8_16x2_avx2(src, src_stride);
    3616    25982200 :     const __m256i r0 = loadu_u8_16x2_avx2(ref + 0, ref_stride);
    3617    25043400 :     const __m256i r1 = loadu_u8_16x2_avx2(ref + 8, ref_stride);
    3618    23762700 :     d[0] = _mm256_adds_epu16(d[0], _mm256_mpsadbw_epu8(r0, s, 0x00));
    3619    23762700 :     d[0] = _mm256_adds_epu16(d[0], _mm256_mpsadbw_epu8(r0, s, 0x2D)); // 101 101
    3620    23762700 :     d[1] = _mm256_adds_epu16(d[1], _mm256_mpsadbw_epu8(r1, s, 0x12)); // 010 010
    3621    23762700 :     d[1] = _mm256_adds_epu16(d[1], _mm256_mpsadbw_epu8(r1, s, 0x3F)); // 111 111
    3622    23762700 : }
    3623             : 
    3624             : /*
    3625             : NOTE: Slower than avx2. Abandoned.
    3626             : static INLINE void sad_eight_8x2x2_avx512(const uint8_t *const src,
    3627             :     const uint32_t src_stride, const uint8_t *const ref,
    3628             :     const uint32_t ref_stride, __m512i *const d)
    3629             : {
    3630             :     const __m512i c0 =
    3631             :         _mm512_setr_epi32(0, 0, 0, 0, 2, 2, 2, 2, 4, 4, 4, 4, 6, 6, 6, 6);
    3632             :     const __m512i c1 =
    3633             :         _mm512_setr_epi32(1, 1, 1, 1, 3, 3, 3, 3, 5, 5, 5, 5, 7, 7, 7, 7);
    3634             :     const __m512i c2 = _mm512_setr_epi64(0, 1, 1, 2, 4, 5, 5, 6);
    3635             : 
    3636             :     const __m256i s01 = loadu_u8_16x2_avx2(src, src_stride);
    3637             :     const __m512i s = _mm512_castsi256_si512(s01);
    3638             :     const __m512i ss0 = _mm512_permutexvar_epi32(c0, s);
    3639             :     const __m512i ss1 = _mm512_permutexvar_epi32(c1, s);
    3640             : 
    3641             :     const __m256i r0 = _mm256_loadu_si256((__m256i*)ref);
    3642             :     const __m256i r1 = _mm256_loadu_si256((__m256i*)(ref + ref_stride));
    3643             :     const __m512i r = _mm512_inserti64x4(_mm512_castsi256_si512(r0), r1, 1);
    3644             :     const __m512i rr0 = _mm512_permutexvar_epi64(c2, r);
    3645             : 
    3646             :     *d = _mm512_adds_epu16(*d, _mm512_dbsad_epu8(ss0, rr0, 0x94)); //10 01 01 00
    3647             :     *d = _mm512_adds_epu16(*d, _mm512_dbsad_epu8(ss1, rr0, 0xE9)); //11 10 10 01
    3648             : }
    3649             : 
    3650             : Usage:
    3651             : s_512 = _mm512_setzero_si512();
    3652             : sad_eight_8x2x2_avx512(src + 0 * src_stride, 8 * src_stride,
    3653             :     ref + 0 * ref_stride, 8 * ref_stride, &s_512);
    3654             : sad_eight_8x2x2_avx512(src + 2 * src_stride, 8 * src_stride,
    3655             :      ref + 2 * ref_stride, 8 * ref_stride, &s_512);
    3656             : sad_eight_8x2x2_avx512(src + 4 * src_stride, 8 * src_stride,
    3657             :      ref + 4 * ref_stride, 8 * ref_stride, &s_512);
    3658             : sad_eight_8x2x2_avx512(src + 6 * src_stride, 8 * src_stride,
    3659             :      ref + 6 * ref_stride, 8 * ref_stride, &s_512);
    3660             : sad_eight_8x2x2_avx512(src + 1 * src_stride, 8 * src_stride,
    3661             :      ref + 1 * ref_stride, 8 * ref_stride, &s_512);
    3662             : sad_eight_8x2x2_avx512(src + 3 * src_stride, 8 * src_stride,
    3663             :      ref + 3 * ref_stride, 8 * ref_stride, &s_512);
    3664             : sad_eight_8x2x2_avx512(src + 5 * src_stride, 8 * src_stride,
    3665             :      ref + 5 * ref_stride, 8 * ref_stride, &s_512);
    3666             : sad_eight_8x2x2_avx512(src + 7 * src_stride, 8 * src_stride,
    3667             :      ref + 7 * ref_stride, 8 * ref_stride, &s_512);
    3668             : s_256[0] = _mm512_castsi512_si256(s_512);
    3669             : s_256[1] = _mm512_extracti64x4_epi64(s_512, 1);
    3670             : */
    3671             : 
    3672             : /*******************************************************************************
    3673             : * Requirement: p_best_sad8x8[i] must be less than 0x7FFFFFFF because signed comparison is used.
    3674             : *******************************************************************************/
    3675    12104600 : void get_eight_horizontal_search_point_results_8x8_16x16_pu_avx2_intrin(
    3676             :     uint8_t   *src,
    3677             :     uint32_t   src_stride,
    3678             :     uint8_t   *ref,
    3679             :     uint32_t   ref_stride,
    3680             :     uint32_t  *p_best_sad8x8,
    3681             :     uint32_t  *p_best_mv8x8,
    3682             :     uint32_t  *p_best_sad16x16,
    3683             :     uint32_t  *p_best_mv16x16,
    3684             :     uint32_t   mv,
    3685             :     uint16_t  *p_sad16x16,
    3686             :     EbBool     sub_sad)
    3687             : {
    3688             :     __m128i s_128[4], s16_128, best_sad_128, best_mv_128, mv_128;
    3689             :     __m256i s_256[2];
    3690             : 
    3691             :     /*
    3692             :     -------------------------------------   -----------------------------------
    3693             :     | 8x8_00 | 8x8_01 | 8x8_04 | 8x8_05 |   8x8_16 | 8x8_17 | 8x8_20 | 8x8_21 |
    3694             :     -------------------------------------   -----------------------------------
    3695             :     | 8x8_02 | 8x8_03 | 8x8_06 | 8x8_07 |   8x8_18 | 8x8_19 | 8x8_22 | 8x8_23 |
    3696             :     -----------------------   -----------   ----------------------   ----------
    3697             :     | 8x8_08 | 8x8_09 | 8x8_12 | 8x8_13 |   8x8_24 | 8x8_25 | 8x8_29 | 8x8_29 |
    3698             :     ----------------------    -----------   ---------------------    ----------
    3699             :     | 8x8_10 | 8x8_11 | 8x8_14 | 8x8_15 |   8x8_26 | 8x8_27 | 8x8_30 | 8x8_31 |
    3700             :     -------------------------------------   -----------------------------------
    3701             : 
    3702             :     -------------------------------------   -----------------------------------
    3703             :     | 8x8_32 | 8x8_33 | 8x8_36 | 8x8_37 |   8x8_48 | 8x8_49 | 8x8_52 | 8x8_53 |
    3704             :     -------------------------------------   -----------------------------------
    3705             :     | 8x8_34 | 8x8_35 | 8x8_38 | 8x8_39 |   8x8_50 | 8x8_51 | 8x8_54 | 8x8_55 |
    3706             :     -----------------------   -----------   ----------------------   ----------
    3707             :     | 8x8_40 | 8x8_41 | 8x8_44 | 8x8_45 |   8x8_56 | 8x8_57 | 8x8_60 | 8x8_61 |
    3708             :     ----------------------    -----------   ---------------------    ----------
    3709             :     | 8x8_42 | 8x8_43 | 8x8_46 | 8x8_48 |   8x8_58 | 8x8_59 | 8x8_62 | 8x8_63 |
    3710             :     -------------------------------------   -----------------------------------
    3711             :     */
    3712             : 
    3713             :     /*
    3714             :     ----------------------    ----------------------
    3715             :     |  16x16_0  |  16x16_1  |  16x16_4  |  16x16_5  |
    3716             :     ----------------------    ----------------------
    3717             :     |  16x16_2  |  16x16_3  |  16x16_6  |  16x16_7  |
    3718             :     -----------------------   -----------------------
    3719             :     |  16x16_8  |  16x16_9  |  16x16_12 |  16x16_13 |
    3720             :     ----------------------    ----------------------
    3721             :     |  16x16_10 |  16x16_11 |  16x16_14 |  16x16_15 |
    3722             :     -----------------------   -----------------------
    3723             :     */
    3724             : 
    3725             :     // 8x8_0, 8x8_1, 8x8_2 & 8x8_3
    3726    12104600 :     s_256[0] = s_256[1] = _mm256_setzero_si256();
    3727    12104600 :     sad_eight_8x2x2_avx2(src + 0 * src_stride, 8 * src_stride, ref + 0 * ref_stride, 8 * ref_stride, s_256);
    3728    10196500 :     sad_eight_8x2x2_avx2(src + 2 * src_stride, 8 * src_stride, ref + 2 * ref_stride, 8 * ref_stride, s_256);
    3729     9905510 :     sad_eight_8x2x2_avx2(src + 4 * src_stride, 8 * src_stride, ref + 4 * ref_stride, 8 * ref_stride, s_256);
    3730     9851360 :     sad_eight_8x2x2_avx2(src + 6 * src_stride, 8 * src_stride, ref + 6 * ref_stride, 8 * ref_stride, s_256);
    3731             : 
    3732             :     //16x16
    3733     9961550 :     if (sub_sad) {
    3734     9961550 :         s_256[0] = _mm256_slli_epi16(s_256[0], 1);
    3735    19923100 :         s_256[1] = _mm256_slli_epi16(s_256[1], 1);
    3736             :     }
    3737             :     else {
    3738             :         // 8x8_0, 8x8_1, 8x8_2 & 8x8_3
    3739           0 :         sad_eight_8x2x2_avx2(src + 1 * src_stride, 8 * src_stride, ref + 1 * ref_stride, 8 * ref_stride, s_256);
    3740           0 :         sad_eight_8x2x2_avx2(src + 3 * src_stride, 8 * src_stride, ref + 3 * ref_stride, 8 * ref_stride, s_256);
    3741           0 :         sad_eight_8x2x2_avx2(src + 5 * src_stride, 8 * src_stride, ref + 5 * ref_stride, 8 * ref_stride, s_256);
    3742           0 :         sad_eight_8x2x2_avx2(src + 7 * src_stride, 8 * src_stride, ref + 7 * ref_stride, 8 * ref_stride, s_256);
    3743             :     }
    3744             : 
    3745    10018000 :     s_128[0] = _mm256_castsi256_si128(s_256[0]);
    3746    10018000 :     s_128[1] = _mm256_castsi256_si128(s_256[1]);
    3747    10018000 :     s_128[2] = _mm256_extracti128_si256(s_256[0], 1);
    3748    10018000 :     s_128[3] = _mm256_extracti128_si256(s_256[1], 1);
    3749    10018000 :     s16_128 = _mm_adds_epu16(s_128[0], s_128[1]);
    3750    10018000 :     s16_128 = _mm_adds_epu16(s16_128, s_128[2]);
    3751    20035900 :     s16_128 = _mm_adds_epu16(s16_128, s_128[3]);
    3752             : 
    3753             :     //sotore the 8 SADs(16x16 SADs)
    3754             :     _mm_store_si128((__m128i*)p_sad16x16, s16_128);
    3755             : 
    3756             :     //find the best for 16x16
    3757    10018000 :     const __m128i minpos16 = _mm_minpos_epu16(s16_128);
    3758    10018000 :     const uint32_t sad = _mm_extract_epi16(minpos16, 0);
    3759             : 
    3760    10018000 :     if (sad < p_best_sad16x16[0]) {
    3761      970301 :         const int32_t best_mv = 4 * _mm_extract_epi16(minpos16, 1);
    3762      970301 :         const int16_t xMv = _MVXT(mv) + (int16_t)best_mv;
    3763      970301 :         const int16_t yMv = _MVYT(mv);
    3764      970301 :         p_best_sad16x16[0] = sad;
    3765      970301 :         *p_best_mv16x16 = ((uint16_t)yMv << 16) | ((uint16_t)xMv);
    3766             :     }
    3767             : 
    3768             :     //find the best for 8x8_0, 8x8_1, 8x8_2 & 8x8_3
    3769    10018000 :     s_128[0] = _mm_minpos_epu16(s_128[0]);
    3770    10018000 :     s_128[1] = _mm_minpos_epu16(s_128[1]);
    3771    10018000 :     s_128[2] = _mm_minpos_epu16(s_128[2]);
    3772    10018000 :     s_128[3] = _mm_minpos_epu16(s_128[3]);
    3773    10018000 :     s_128[0] = _mm_unpacklo_epi16(s_128[0], s_128[1]);
    3774    10018000 :     s_128[2] = _mm_unpacklo_epi16(s_128[2], s_128[3]);
    3775    20035900 :     s_128[0] = _mm_unpacklo_epi32(s_128[0], s_128[2]);
    3776    20035900 :     s_128[1] = _mm_unpackhi_epi16(s_128[0], _mm_setzero_si128());
    3777    10018000 :     const __m128i sad_128 = _mm_unpacklo_epi16(s_128[0], _mm_setzero_si128());
    3778    20035900 :     const __m128i offset_128 = _mm_slli_epi16(s_128[1], 2);
    3779             : 
    3780    10018000 :     best_sad_128 = _mm_loadu_si128((__m128i*)p_best_sad8x8);
    3781    10018000 :     const __m128i mask = _mm_cmpgt_epi32(best_sad_128, sad_128);
    3782    10018000 :     best_sad_128 = _mm_min_epu32(sad_128, best_sad_128);
    3783             :     _mm_storeu_si128((__m128i*)p_best_sad8x8, best_sad_128);
    3784             : 
    3785    20035900 :     mv_128 = _mm_set1_epi32(mv);
    3786    10018000 :     mv_128 = _mm_add_epi16(mv_128, offset_128);
    3787    10018000 :     mv_128 = _mm_and_si128(mv_128, mask);
    3788    10018000 :     best_mv_128 = _mm_loadu_si128((__m128i*)p_best_mv8x8);
    3789    10018000 :     best_mv_128 = _mm_andnot_si128(mask, best_mv_128);
    3790    10018000 :     best_mv_128 = _mm_or_si128(best_mv_128, mv_128);
    3791             :     _mm_storeu_si128((__m128i*)p_best_mv8x8, best_mv_128);
    3792    10018000 : }
    3793             : 
    3794     3140520 : static INLINE __m256i add_4_sad_avx2(
    3795             :     const uint16_t *const p_sad16x16)
    3796             : {
    3797     3140520 :     const __m128i s0 = _mm_loadu_si128((__m128i*)(p_sad16x16 + 0 * 8));
    3798     3140520 :     const __m128i s1 = _mm_loadu_si128((__m128i*)(p_sad16x16 + 1 * 8));
    3799     3140520 :     const __m128i s2 = _mm_loadu_si128((__m128i*)(p_sad16x16 + 2 * 8));
    3800     6281050 :     const __m128i s3 = _mm_loadu_si128((__m128i*)(p_sad16x16 + 3 * 8));
    3801             :     __m256i s_256[4];
    3802             : 
    3803     3140520 :     s_256[0] = _mm256_cvtepu16_epi32(s0);
    3804     3140520 :     s_256[1] = _mm256_cvtepu16_epi32(s1);
    3805     3140520 :     s_256[2] = _mm256_cvtepu16_epi32(s2);
    3806     3140520 :     s_256[3] = _mm256_cvtepu16_epi32(s3);
    3807             : 
    3808     3140520 :     s_256[0] = _mm256_add_epi32(s_256[0], s_256[1]);
    3809     3140520 :     s_256[2] = _mm256_add_epi32(s_256[2], s_256[3]);
    3810     6281050 :     return _mm256_add_epi32(s_256[0], s_256[2]);
    3811             : }
    3812             : 
    3813     1766440 : static INLINE void update_best_sse2(const __m128i sad, const uint32_t mv,
    3814             :     uint32_t *const p_best_sad32x32, uint32_t *const p_best_mv32x32)
    3815             : {
    3816     1766440 :     const __m128i minpos = _mm_minpos_epu16(sad);
    3817     1766440 :     const uint32_t min_sad = (uint16_t)_mm_extract_epi16(minpos, 0);
    3818             : 
    3819     1766440 :     if (min_sad < *p_best_sad32x32) {
    3820      185317 :         const int32_t best_mv = 4 * _mm_extract_epi16(minpos, 1);
    3821      185317 :         const int16_t xMv = _MVXT(mv) + (int16_t)best_mv;
    3822      185317 :         const int16_t yMv = _MVYT(mv);
    3823      185317 :         *p_best_sad32x32 = min_sad;
    3824      185317 :         *p_best_mv32x32 = ((uint16_t)yMv << 16) | ((uint16_t)xMv);
    3825             :     }
    3826     1766440 : }
    3827             : 
    3828             : /*******************************************
    3829             : Calcualte SAD for 32x32,64x64 from 16x16
    3830             : and check if there is improvement, if yes keep
    3831             : the best SAD+MV
    3832             : *******************************************/
    3833      787935 : void get_eight_horizontal_search_point_results_32x32_64x64_pu_avx2_intrin(
    3834             :     uint16_t  *p_sad16x16,
    3835             :     uint32_t  *p_best_sad32x32,
    3836             :     uint32_t  *p_best_sad64x64,
    3837             :     uint32_t  *p_best_mv32x32,
    3838             :     uint32_t  *p_best_mv64x64,
    3839             :     uint32_t   mv)
    3840             : {
    3841             :     __m256i s_256[4], sum[2];
    3842             : 
    3843             :     /*--------------------
    3844             :     |  32x32_0  |  32x32_1
    3845             :     ----------------------
    3846             :     |  32x32_2  |  32x32_3
    3847             :     ----------------------*/
    3848             : 
    3849             :     /*  data ordering in p_sad16x16 buffer
    3850             : 
    3851             :     Search    Search            Search
    3852             :     Point 0   Point 1           Point 7
    3853             :     ---------------------------------------
    3854             :     16x16_0    |    x    |    x    | ...... |    x    |
    3855             :     ---------------------------------------
    3856             :     16x16_1    |    x    |    x    | ...... |    x    |
    3857             : 
    3858             :     16x16_n    |    x    |    x    | ...... |    x    |
    3859             : 
    3860             :     ---------------------------------------
    3861             :     16x16_15   |    x    |    x    | ...... |    x    |
    3862             :     ---------------------------------------
    3863             :     */
    3864             : 
    3865      787935 :     s_256[0] = add_4_sad_avx2(p_sad16x16 + 0 * 8);
    3866      787661 :     s_256[1] = add_4_sad_avx2(p_sad16x16 + 4 * 8);
    3867      787401 :     s_256[2] = add_4_sad_avx2(p_sad16x16 + 8 * 8);
    3868      787347 :     s_256[3] = add_4_sad_avx2(p_sad16x16 + 12 * 8);
    3869             : 
    3870      787607 :     sum[0] = _mm256_add_epi32(s_256[0], s_256[1]);
    3871      787607 :     sum[1] = _mm256_add_epi32(s_256[2], s_256[3]);
    3872      787607 :     sum[0] = _mm256_add_epi32(sum[0], sum[1]);
    3873      787607 :     const __m128i sad_0 = _mm256_castsi256_si128(sum[0]);
    3874      787607 :     const __m128i sad_1 = _mm256_extracti128_si256(sum[0], 1);
    3875             : 
    3876      787607 :     const __m128i ss = _mm_packus_epi32(sad_0, sad_1);
    3877      787607 :     const __m128i minpos = _mm_minpos_epu16(ss);
    3878      787607 :     const uint32_t min_sad = (uint16_t)_mm_extract_epi16(minpos, 0);
    3879             : 
    3880      787607 :     if (min_sad != 0xFFFF) {
    3881      442030 :         if (min_sad < *p_best_sad64x64) {
    3882       57351 :             const uint32_t bestMV64x64 = 4 * _mm_extract_epi16(minpos, 1);
    3883       57351 :             const int16_t xMv = _MVXT(mv) + (int16_t)bestMV64x64;
    3884       57351 :             const int16_t yMv = _MVYT(mv);
    3885       57351 :             *p_best_sad64x64 = min_sad;
    3886       57351 :             *p_best_mv64x64 = ((uint16_t)yMv << 16) | ((uint16_t)xMv);
    3887             :         }
    3888             : 
    3889      442030 :         s_256[0] = _mm256_packus_epi32(s_256[0], s_256[1]);
    3890      442030 :         s_256[2] = _mm256_packus_epi32(s_256[2], s_256[3]);
    3891      442030 :         s_256[0] = _mm256_permute4x64_epi64(s_256[0], 0xD8);
    3892      442030 :         s_256[2] = _mm256_permute4x64_epi64(s_256[2], 0xD8);
    3893             : 
    3894      442030 :         const __m128i s0_128 = _mm256_castsi256_si128(s_256[0]);
    3895      442030 :         const __m128i s1_128 = _mm256_extracti128_si256(s_256[0], 1);
    3896      442030 :         const __m128i s2_128 = _mm256_castsi256_si128(s_256[2]);
    3897      442030 :         const __m128i s3_128 = _mm256_extracti128_si256(s_256[2], 1);
    3898             : 
    3899      442030 :         update_best_sse2(s0_128, mv, &p_best_sad32x32[0], &p_best_mv32x32[0]);
    3900      441977 :         update_best_sse2(s1_128, mv, &p_best_sad32x32[1], &p_best_mv32x32[1]);
    3901      441965 :         update_best_sse2(s2_128, mv, &p_best_sad32x32[2], &p_best_mv32x32[2]);
    3902      442005 :         update_best_sse2(s3_128, mv, &p_best_sad32x32[3], &p_best_mv32x32[3]);
    3903             :     }
    3904             :     else {
    3905             :         __m128i s0, s1, s2, s3, s4, s5;
    3906             :         __m256i ss0, ss1, ss2, ss3, ss4, ss5, ss6, ss7;
    3907      345577 :         const __m128i min_val0 = _mm_min_epu32(sad_0, sad_1);
    3908      345577 :         const __m128i min_val0_hi = _mm_srli_si128(min_val0, 8);
    3909      345577 :         const __m128i min_val1 = _mm_min_epu32(min_val0, min_val0_hi);
    3910      345577 :         const __m128i min_val1_hi = _mm_srli_si128(min_val1, 4);
    3911      345577 :         const __m128i min_val2 = _mm_min_epu32(min_val1, min_val1_hi);
    3912      345577 :         const uint32_t min_val = _mm_cvtsi128_si32(min_val2);
    3913             : 
    3914      345577 :         if (min_val < *p_best_sad64x64) {
    3915       38715 :             const __m128i mask0 = _mm_cmpgt_epi32(sad_0, sad_1);
    3916       38715 :             const __m128i mask1 = _mm_cmpgt_epi32(min_val0, min_val0_hi);
    3917       38715 :             const __m128i mask2 = _mm_cmpgt_epi32(min_val1, min_val1_hi);
    3918             :             __m128i offset0, offset1;
    3919             : 
    3920       38715 :             offset0 = _mm_setr_epi32(0 * 4, 1 * 4, 2 * 4, 3 * 4);
    3921       38715 :             offset1 = _mm_setr_epi32(4 * 4, 5 * 4, 6 * 4, 7 * 4);
    3922       38715 :             offset0 = _mm_andnot_si128(mask0, offset0);
    3923       38715 :             offset1 = _mm_and_si128(mask0, offset1);
    3924       38715 :             offset0 = _mm_or_si128(offset0, offset1);
    3925             : 
    3926       38715 :             offset1 = _mm_srli_si128(offset0, 8);
    3927       38715 :             offset0 = _mm_andnot_si128(mask1, offset0);
    3928       38715 :             offset1 = _mm_and_si128(mask1, offset1);
    3929       38715 :             offset0 = _mm_or_si128(offset0, offset1);
    3930             : 
    3931       38715 :             offset1 = _mm_srli_si128(offset0, 4);
    3932       38715 :             offset0 = _mm_andnot_si128(mask2, offset0);
    3933       38715 :             offset1 = _mm_and_si128(mask2, offset1);
    3934       38715 :             offset0 = _mm_or_si128(offset0, offset1);
    3935             : 
    3936       38715 :             const uint32_t bestMV64x64 = _mm_cvtsi128_si32(offset0);
    3937       38715 :             const int16_t xMv = _MVXT(mv) + (int16_t)bestMV64x64;
    3938       38715 :             const int16_t yMv = _MVYT(mv);
    3939       38715 :             *p_best_sad64x64 = min_val;
    3940       38715 :             *p_best_mv64x64 = ((uint16_t)yMv << 16) | ((uint16_t)xMv);
    3941             :         }
    3942             : 
    3943             :         // XY
    3944             :         // X: 32x32 block [0..3]
    3945             :         // Y: Search position [0..7]
    3946      345577 :         ss0 = s_256[0];                         // 07 06 05 04  03 02 01 00
    3947      345577 :         ss1 = s_256[1];                         // 17 16 15 14  13 12 11 10
    3948      345577 :         ss2 = s_256[2];                         // 27 26 25 24  23 22 21 20
    3949      345577 :         ss3 = s_256[3];                         // 37 36 35 34  33 32 31 30
    3950      345577 :         ss4 = _mm256_unpacklo_epi32(ss0, ss1);  // 15 05 14 04  11 01 10 00
    3951      345577 :         ss5 = _mm256_unpacklo_epi32(ss2, ss3);  // 35 25 34 24  31 21 30 20
    3952      345577 :         ss6 = _mm256_unpackhi_epi32(ss0, ss1);  // 17 07 16 06  13 03 12 02
    3953      345577 :         ss7 = _mm256_unpackhi_epi32(ss2, ss3);  // 37 27 36 26  33 23 32 22
    3954      345577 :         ss0 = _mm256_unpacklo_epi64(ss4, ss5);  // 34 24 14 04  30 20 10 00
    3955      345577 :         ss1 = _mm256_unpackhi_epi64(ss4, ss5);  // 35 25 15 05  31 21 11 01
    3956      345577 :         ss2 = _mm256_unpacklo_epi64(ss6, ss7);  // 36 26 16 06  32 22 12 02
    3957      345577 :         ss3 = _mm256_unpackhi_epi64(ss6, ss7);  // 37 27 17 07  33 23 13 03
    3958             : 
    3959             :         //   ss4   |  ss5-2  |                ss6        |
    3960             :         // a0 : a1 | a2 : a3 | min(a0, a1) : min(a2, a3) |    | (ss4 & !ss6) | ((ss5-2) & ss6) | ((ss4 & !ss6) | ((ss5-2) & ss6)) |
    3961             :         // > (-1)  | >  (-3) |         >     (-1)        | a3 |       0      |       -3        |              -3                  |
    3962             :         // > (-1)  | >  (-3) |         <=     (0)        | a1 |      -1      |        0        |              -1                  |
    3963             :         // > (-1)  | <= (-2) |         >     (-1)        | a2 |       0      |       -2        |              -2                  |
    3964             :         // > (-1)  | <= (-2) |         <=     (0)        | a1 |      -1      |        0        |              -1                  |
    3965             :         // <= (0)  | >  (-3) |         >     (-1)        | a3 |       0      |       -3        |              -3                  |
    3966             :         // <= (0)  | >  (-3) |         <=     (0)        | a0 |       0      |        0        |               0                  |
    3967             :         // <= (0)  | <= (-2) |         >     (-1)        | a2 |       0      |       -2        |              -2                  |
    3968             :         // <= (0)  | <= (-2) |         <=     (0)        | a0 |       0      |        0        |               0                  |
    3969             : 
    3970             :         // *** 8 search points per position ***
    3971             : 
    3972             :         // ss0: Search Pos 0,4 for blocks 0,1,2,3
    3973             :         // ss1: Search Pos 1,5 for blocks 0,1,2,3
    3974             :         // ss2: Search Pos 2,6 for blocks 0,1,2,3
    3975             :         // ss3: Search Pos 3,7 for blocks 0,1,2,3
    3976             : 
    3977      345577 :         ss4 = _mm256_cmpgt_epi32(ss0, ss1);
    3978      345577 :         ss0 = _mm256_min_epi32(ss0, ss1);
    3979      345577 :         ss5 = _mm256_cmpgt_epi32(ss2, ss3);
    3980      345577 :         ss2 = _mm256_min_epi32(ss2, ss3);
    3981      691154 :         ss5 = _mm256_sub_epi32(ss5, _mm256_set1_epi32(2)); // ss5-2
    3982             : 
    3983             :         // *** 4 search points per position ***
    3984      345577 :         ss6 = _mm256_cmpgt_epi32(ss0, ss2);
    3985      345577 :         ss0 = _mm256_min_epi32(ss0, ss2);
    3986      345577 :         ss5 = _mm256_and_si256(ss5, ss6); // (ss5-2) & ss6
    3987      345577 :         ss4 = _mm256_andnot_si256(ss6, ss4); // ss4 & !ss6
    3988      345577 :         ss4 = _mm256_or_si256(ss4, ss5); // (ss4 & !ss6) | ((ss5-2) & ss6)
    3989             : 
    3990             :         // *** 2 search points per position ***
    3991             : 
    3992             :         // ss0 = 8 SADs, two search points for each 32x32
    3993             :         // ss4 = 8 MVs, two search points for each 32x32
    3994             :         //
    3995             :         // XY
    3996             :         // X: 32x32 block [0..3]
    3997             :         // Y: search position [0..1]
    3998             :         // Format: 00 10 20 30  01 11 21 31
    3999             : 
    4000             :         // Each 128 bits contains 4 32x32 32bit block results
    4001             :         // SAD
    4002      345577 :         s0 = _mm256_castsi256_si128(ss0);
    4003      345577 :         s1 = _mm256_extracti128_si256(ss0, 1);
    4004             :         // MV
    4005      345577 :         s2 = _mm256_castsi256_si128(ss4);
    4006      345577 :         s3 = _mm256_extracti128_si256(ss4, 1);
    4007             : 
    4008             :         // Choose the best MV out of the two, use s4 to hold results of min
    4009      345577 :         s4 = _mm_cmpgt_epi32(s0, s1);
    4010      345577 :         s0 = _mm_min_epi32(s0, s1);
    4011             : 
    4012             :         // Extract MV's based on the blocks to s2
    4013      691154 :         s3 = _mm_sub_epi32(s3, _mm_set1_epi32(4)); // s3-4
    4014             :         // Remove the MV's are not used from s2
    4015      345577 :         s2 = _mm_andnot_si128(s4, s2);
    4016             :         // Remove the MV's that are not used from s3 (inverse from s2 above operation)
    4017      345577 :         s3 = _mm_and_si128(s4, s3);
    4018             :         // Combine the remaining candidates into s2
    4019      345577 :         s2 = _mm_or_si128(s2, s3);
    4020             :         // Convert MV's into encoders format
    4021      345577 :         s2 = _mm_slli_epi32(s2, 2); // mv info (negative)
    4022             : 
    4023             :         // ***SAD***
    4024             :         // s0: current SAD candidates for each 32x32
    4025             :         // s1: best SAD's for 32x32
    4026             : 
    4027             :         // Load best SAD's
    4028      345577 :         s1 = _mm_loadu_si128((__m128i*)p_best_sad32x32);
    4029             : 
    4030             :         // Determine which candidates are better than the current best SAD's.
    4031             :         // s4 is used to determine the MV's of the new best SAD's
    4032      345577 :         s4 = _mm_cmpgt_epi32(s1, s0);
    4033             :         // Combine old and new min SAD's
    4034      345577 :         s0 = _mm_min_epu32(s0, s1);
    4035             :         // Store new best SAD's back to memory
    4036             :         _mm_storeu_si128((__m128i*)p_best_sad32x32, s0);
    4037             : 
    4038             :         // ***Motion Vectors***
    4039             :         // Load best MV's
    4040             :         // s3: candidate MV's
    4041             :         // s4: results of comparing SAD's
    4042             :         // s5: previous best MV's
    4043             : 
    4044             :         // Load previous best MV's
    4045      345577 :         s5 = _mm_loadu_si128((__m128i*)p_best_mv32x32);
    4046             :         // Remove the MV's that are being replaced
    4047      345577 :         s5 = _mm_andnot_si128(s4, s5);
    4048             : 
    4049             :         //Set mvx to s0 and mvy to s1
    4050      345577 :         s0 = _mm_set1_epi32(mv & 0xFFFF);
    4051      691154 :         s1 = _mm_set1_epi32(mv & 0xFFFF0000);
    4052             : 
    4053             :         // Add candidate MV's to base MV
    4054      345577 :         s3 = _mm_sub_epi32(s0, s2);
    4055             :         // Limit to int16_t
    4056      691154 :         s3 = _mm_and_si128(s3, _mm_set1_epi32(0xFFFF));
    4057             :         //mvy | mvx
    4058      345577 :         s3 = _mm_or_si128(s3, s1);
    4059             : 
    4060             :         // Remove non-candidate's
    4061      345577 :         s3 = _mm_and_si128(s3, s4);
    4062             :         // Combine remaining candidates with remaining best MVs
    4063      345577 :         s3 = _mm_or_si128(s3, s5);
    4064             :         // Store back to memory
    4065             :         _mm_storeu_si128((__m128i*)p_best_mv32x32, s3);
    4066             :     }
    4067      787610 : }
    4068             : 
    4069             : /*******************************************************************************
    4070             : * Requirement: width   = 4, 8, 16, 24, 32, 48 or 64
    4071             : * Requirement: block_height <= 64
    4072             : * Requirement: block_height % 2 = 0 when width = 4 or 8
    4073             : *******************************************************************************/
    4074       31594 : void sad_loop_kernel_avx2_hme_l0_intrin(
    4075             :     uint8_t  *src,                            // input parameter, source samples Ptr
    4076             :     uint32_t  src_stride,                      // input parameter, source stride
    4077             :     uint8_t  *ref,                            // input parameter, reference samples Ptr
    4078             :     uint32_t  ref_stride,                      // input parameter, reference stride
    4079             :     uint32_t  block_height,                   // input parameter, block height (M)
    4080             :     uint32_t  block_width,                    // input parameter, block width (N)
    4081             :     uint64_t *best_sad,
    4082             :     int16_t *x_search_center,
    4083             :     int16_t *y_search_center,
    4084             :     uint32_t  src_stride_raw,                   // input parameter, source stride (no line skipping)
    4085             :     int16_t search_area_width,
    4086             :     int16_t search_area_height)
    4087             : {
    4088       31594 :     int16_t xBest = *x_search_center, yBest = *y_search_center;
    4089       31594 :     uint32_t lowSum = 0xffffff;
    4090       31594 :     uint32_t temSum1 = 0;
    4091             :     int16_t i, j;
    4092             :     uint32_t k;
    4093             :     const uint8_t *pRef, *pSrc;
    4094       31594 :     __m128i s0, s1, s2, s3, s4, s5, s6, s7 = _mm_set1_epi32(-1);
    4095             :     __m256i ss0, ss1, ss2, ss3, ss4, ss5, ss6, ss7, ss8, ss9, ss10, ss11;
    4096             : 
    4097       31594 :     switch (block_width) {
    4098           0 :     case 4:
    4099             : 
    4100           0 :         if (!(block_height % 4)) {
    4101           0 :             uint32_t srcStrideT = 3 * src_stride;
    4102           0 :             uint32_t refStrideT = 3 * ref_stride;
    4103           0 :             for (i = 0; i < search_area_height; i++) {
    4104           0 :                 for (j = 0; j <= search_area_width - 8; j += 8) {
    4105           0 :                     pSrc = src;
    4106           0 :                     pRef = ref + j;
    4107           0 :                     ss3 = ss5 = _mm256_setzero_si256();
    4108           0 :                     for (k = 0; k < block_height; k += 4) {
    4109           0 :                         ss0 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pRef)), _mm_loadu_si128((__m128i*)(pRef + 2 * ref_stride)), 0x1);
    4110           0 :                         ss1 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)(pRef + ref_stride))), _mm_loadu_si128((__m128i*)(pRef + refStrideT)), 0x1);
    4111           0 :                         ss2 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_unpacklo_epi64(_mm_cvtsi32_si128(*(uint32_t *)pSrc), _mm_cvtsi32_si128(*(uint32_t *)(pSrc + src_stride)))), _mm_unpacklo_epi64(_mm_cvtsi32_si128(*(uint32_t *)(pSrc + 2 * src_stride)), _mm_cvtsi32_si128(*(uint32_t *)(pSrc + srcStrideT))), 0x1);
    4112           0 :                         ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
    4113           0 :                         ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
    4114           0 :                         pSrc += src_stride << 2;
    4115           0 :                         pRef += ref_stride << 2;
    4116             :                     }
    4117           0 :                     ss3 = _mm256_adds_epu16(ss3, ss5);
    4118           0 :                     s3 = _mm_adds_epu16(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
    4119           0 :                     s3 = _mm_minpos_epu16(s3);
    4120           0 :                     temSum1 = _mm_extract_epi16(s3, 0);
    4121           0 :                     if (temSum1 < lowSum) {
    4122           0 :                         lowSum = temSum1;
    4123           0 :                         xBest = (int16_t)(j + _mm_extract_epi16(s3, 1));
    4124           0 :                         yBest = i;
    4125             :                     }
    4126             :                 }
    4127           0 :                 ref += src_stride_raw;
    4128             :             }
    4129             :         }
    4130             :         else {
    4131           0 :             for (i = 0; i < search_area_height; i++) {
    4132           0 :                 for (j = 0; j <= search_area_width - 8; j += 8) {
    4133           0 :                     pSrc = src;
    4134           0 :                     pRef = ref + j;
    4135           0 :                     s3 = _mm_setzero_si128();
    4136           0 :                     for (k = 0; k < block_height; k += 2) {
    4137           0 :                         s0 = _mm_loadu_si128((__m128i*)pRef);
    4138           0 :                         s1 = _mm_loadu_si128((__m128i*)(pRef + ref_stride));
    4139           0 :                         s2 = _mm_cvtsi32_si128(*(uint32_t *)pSrc);
    4140           0 :                         s5 = _mm_cvtsi32_si128(*(uint32_t *)(pSrc + src_stride));
    4141           0 :                         s3 = _mm_adds_epu16(s3, _mm_mpsadbw_epu8(s0, s2, 0));
    4142           0 :                         s3 = _mm_adds_epu16(s3, _mm_mpsadbw_epu8(s1, s5, 0));
    4143           0 :                         pSrc += src_stride << 1;
    4144           0 :                         pRef += ref_stride << 1;
    4145             :                     }
    4146           0 :                     s3 = _mm_minpos_epu16(s3);
    4147           0 :                     temSum1 = _mm_extract_epi16(s3, 0);
    4148           0 :                     if (temSum1 < lowSum) {
    4149           0 :                         lowSum = temSum1;
    4150           0 :                         xBest = (int16_t)(j + _mm_extract_epi16(s3, 1));
    4151           0 :                         yBest = i;
    4152             :                     }
    4153             :                 }
    4154           0 :                 ref += src_stride_raw;
    4155             :             }
    4156             :         }
    4157             : 
    4158           0 :         break;
    4159             : 
    4160           0 :     case 8:
    4161           0 :         if (!(block_height % 4)) {
    4162           0 :             uint32_t srcStrideT = 3 * src_stride;
    4163           0 :             uint32_t refStrideT = 3 * ref_stride;
    4164           0 :             for (i = 0; i < search_area_height; i++) {
    4165           0 :                 for (j = 0; j <= search_area_width - 8; j += 8) {
    4166           0 :                     pSrc = src;
    4167           0 :                     pRef = ref + j;
    4168           0 :                     ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
    4169           0 :                     for (k = 0; k < block_height; k += 4) {
    4170           0 :                         ss0 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pRef)), _mm_loadu_si128((__m128i*)(pRef + 2 * ref_stride)), 0x1);
    4171           0 :                         ss1 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)(pRef + ref_stride))), _mm_loadu_si128((__m128i*)(pRef + refStrideT)), 0x1);
    4172           0 :                         ss2 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_unpacklo_epi64(_mm_loadl_epi64((__m128i*)pSrc), _mm_loadl_epi64((__m128i*)(pSrc + src_stride)))), _mm_unpacklo_epi64(_mm_loadl_epi64((__m128i*)(pSrc + 2 * src_stride)), _mm_loadl_epi64((__m128i*)(pSrc + srcStrideT))), 0x1);
    4173           0 :                         ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
    4174           0 :                         ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
    4175           0 :                         ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
    4176           0 :                         ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
    4177           0 :                         pSrc += src_stride << 2;
    4178           0 :                         pRef += ref_stride << 2;
    4179             :                     }
    4180           0 :                     ss3 = _mm256_adds_epu16(_mm256_adds_epu16(ss3, ss4), _mm256_adds_epu16(ss5, ss6));
    4181           0 :                     s3 = _mm_adds_epu16(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
    4182           0 :                     s3 = _mm_minpos_epu16(s3);
    4183           0 :                     temSum1 = _mm_extract_epi16(s3, 0);
    4184           0 :                     if (temSum1 < lowSum) {
    4185           0 :                         lowSum = temSum1;
    4186           0 :                         xBest = (int16_t)(j + _mm_extract_epi16(s3, 1));
    4187           0 :                         yBest = i;
    4188             :                     }
    4189             :                 }
    4190           0 :                 ref += src_stride_raw;
    4191             :             }
    4192             :         }
    4193             :         else {
    4194           0 :             for (i = 0; i < search_area_height; i++) {
    4195           0 :                 for (j = 0; j <= search_area_width - 8; j += 8) {
    4196           0 :                     pSrc = src;
    4197           0 :                     pRef = ref + j;
    4198           0 :                     s3 = s4 = _mm_setzero_si128();
    4199           0 :                     for (k = 0; k < block_height; k += 2) {
    4200           0 :                         s0 = _mm_loadu_si128((__m128i*)pRef);
    4201           0 :                         s1 = _mm_loadu_si128((__m128i*)(pRef + ref_stride));
    4202           0 :                         s2 = _mm_loadl_epi64((__m128i*)pSrc);
    4203           0 :                         s5 = _mm_loadl_epi64((__m128i*)(pSrc + src_stride));
    4204           0 :                         s3 = _mm_adds_epu16(s3, _mm_mpsadbw_epu8(s0, s2, 0));
    4205           0 :                         s4 = _mm_adds_epu16(s4, _mm_mpsadbw_epu8(s0, s2, 5));
    4206           0 :                         s3 = _mm_adds_epu16(s3, _mm_mpsadbw_epu8(s1, s5, 0));
    4207           0 :                         s4 = _mm_adds_epu16(s4, _mm_mpsadbw_epu8(s1, s5, 5));
    4208           0 :                         pSrc += src_stride << 1;
    4209           0 :                         pRef += ref_stride << 1;
    4210             :                     }
    4211           0 :                     s3 = _mm_adds_epu16(s3, s4);
    4212           0 :                     s3 = _mm_minpos_epu16(s3);
    4213           0 :                     temSum1 = _mm_extract_epi16(s3, 0);
    4214           0 :                     if (temSum1 < lowSum) {
    4215           0 :                         lowSum = temSum1;
    4216           0 :                         xBest = (int16_t)(j + _mm_extract_epi16(s3, 1));
    4217           0 :                         yBest = i;
    4218             :                     }
    4219             :                 }
    4220           0 :                 ref += src_stride_raw;
    4221             :             }
    4222             :         }
    4223           0 :         break;
    4224             : 
    4225       31597 :     case 16:
    4226       31597 :         if (block_height <= 16) {
    4227      758605 :             for (i = 0; i < search_area_height; i++) {
    4228     3474890 :                 for (j = 0; j <= search_area_width - 16; j += 16) {
    4229     2747880 :                     pSrc = src;
    4230     2747880 :                     pRef = ref + j;
    4231     2747880 :                     ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
    4232     2747880 :                     ss7 = ss9 = ss10 = ss11 = _mm256_setzero_si256();
    4233    24145200 :                     for (k = 0; k < block_height; k += 2) {
    4234    64192100 :                         ss0 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pRef)), _mm_loadu_si128((__m128i*)(pRef + ref_stride)), 0x1);
    4235    64192100 :                         ss1 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)(pRef + 8))), _mm_loadu_si128((__m128i*)(pRef + ref_stride + 8)), 0x1);
    4236    64192100 :                         ss2 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pSrc)), _mm_loadu_si128((__m128i*)(pSrc + src_stride)), 0x1);
    4237    21397400 :                         ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
    4238    21397400 :                         ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
    4239    21397400 :                         ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
    4240    21397400 :                         ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
    4241             : 
    4242    64192100 :                         ss0 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)(pRef + 16))), _mm_loadu_si128((__m128i*)(pRef + ref_stride + 16)), 0x1);
    4243    21397400 :                         ss7 = _mm256_adds_epu16(ss7, _mm256_mpsadbw_epu8(ss1, ss2, 0));
    4244    21397400 :                         ss11 = _mm256_adds_epu16(ss11, _mm256_mpsadbw_epu8(ss1, ss2, 45));
    4245    21397400 :                         ss9 = _mm256_adds_epu16(ss9, _mm256_mpsadbw_epu8(ss0, ss2, 18));
    4246    21397400 :                         ss10 = _mm256_adds_epu16(ss10, _mm256_mpsadbw_epu8(ss0, ss2, 63));
    4247             : 
    4248    21397400 :                         pSrc += 2 * src_stride;
    4249    21397400 :                         pRef += 2 * ref_stride;
    4250             :                     }
    4251     5495770 :                     ss3 = _mm256_adds_epu16(_mm256_adds_epu16(ss3, ss4), _mm256_adds_epu16(ss5, ss6));
    4252     8243660 :                     s3 = _mm_adds_epu16(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
    4253     2747880 :                     s3 = _mm_minpos_epu16(s3);
    4254     2747880 :                     temSum1 = _mm_extract_epi16(s3, 0);
    4255     2747880 :                     if (temSum1 < lowSum) {
    4256      194478 :                         lowSum = temSum1;
    4257      194478 :                         xBest = (int16_t)(j + _mm_extract_epi16(s3, 1));
    4258      194478 :                         yBest = i;
    4259             :                     }
    4260             : 
    4261     5495770 :                     ss7 = _mm256_adds_epu16(_mm256_adds_epu16(ss7, ss11), _mm256_adds_epu16(ss9, ss10));
    4262     8243660 :                     s7 = _mm_adds_epu16(_mm256_castsi256_si128(ss7), _mm256_extracti128_si256(ss7, 1));
    4263     2747880 :                     s7 = _mm_minpos_epu16(s7);
    4264     2747880 :                     temSum1 = _mm_extract_epi16(s7, 0);
    4265     2747880 :                     if (temSum1 < lowSum) {
    4266       60971 :                         lowSum = temSum1;
    4267       60971 :                         xBest = (int16_t)(j + 8 + _mm_extract_epi16(s7, 1));
    4268       60971 :                         yBest = i;
    4269             :                     }
    4270             :                 }
    4271      727007 :                 ref += src_stride_raw;
    4272             :             }
    4273             :         }
    4274           0 :         else if (block_height <= 32) {
    4275           0 :             for (i = 0; i < search_area_height; i++) {
    4276           0 :                 for (j = 0; j <= search_area_width - 8; j += 8) {
    4277           0 :                     pSrc = src;
    4278           0 :                     pRef = ref + j;
    4279           0 :                     ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
    4280           0 :                     for (k = 0; k < block_height; k += 2) {
    4281           0 :                         ss0 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pRef)), _mm_loadu_si128((__m128i*)(pRef + ref_stride)), 0x1);
    4282           0 :                         ss1 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)(pRef + 8))), _mm_loadu_si128((__m128i*)(pRef + ref_stride + 8)), 0x1);
    4283           0 :                         ss2 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pSrc)), _mm_loadu_si128((__m128i*)(pSrc + src_stride)), 0x1);
    4284           0 :                         ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
    4285           0 :                         ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
    4286           0 :                         ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
    4287           0 :                         ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
    4288           0 :                         pSrc += 2 * src_stride;
    4289           0 :                         pRef += 2 * ref_stride;
    4290             :                     }
    4291           0 :                     ss3 = _mm256_adds_epu16(_mm256_adds_epu16(ss3, ss4), _mm256_adds_epu16(ss5, ss6));
    4292           0 :                     s3 = _mm256_castsi256_si128(ss3);
    4293           0 :                     s5 = _mm256_extracti128_si256(ss3, 1);
    4294           0 :                     s4 = _mm_minpos_epu16(s3);
    4295           0 :                     s6 = _mm_minpos_epu16(s5);
    4296           0 :                     s4 = _mm_unpacklo_epi16(s4, s4);
    4297           0 :                     s4 = _mm_unpacklo_epi32(s4, s4);
    4298           0 :                     s4 = _mm_unpacklo_epi64(s4, s4);
    4299           0 :                     s6 = _mm_unpacklo_epi16(s6, s6);
    4300           0 :                     s6 = _mm_unpacklo_epi32(s6, s6);
    4301           0 :                     s6 = _mm_unpacklo_epi64(s6, s6);
    4302           0 :                     s3 = _mm_sub_epi16(s3, s4);
    4303           0 :                     s5 = _mm_adds_epu16(s5, s3);
    4304           0 :                     s5 = _mm_sub_epi16(s5, s6);
    4305           0 :                     s5 = _mm_minpos_epu16(s5);
    4306           0 :                     temSum1 = _mm_extract_epi16(s5, 0);
    4307           0 :                     temSum1 += _mm_extract_epi16(s4, 0);
    4308           0 :                     temSum1 += _mm_extract_epi16(s6, 0);
    4309           0 :                     if (temSum1 < lowSum) {
    4310           0 :                         lowSum = temSum1;
    4311           0 :                         xBest = (int16_t)(j + _mm_extract_epi16(s5, 1));
    4312           0 :                         yBest = i;
    4313             :                     }
    4314             :                 }
    4315           0 :                 ref += src_stride_raw;
    4316             :             }
    4317             :         }
    4318             :         else {
    4319           0 :             for (i = 0; i < search_area_height; i++) {
    4320           0 :                 for (j = 0; j <= search_area_width - 8; j += 8) {
    4321           0 :                     pSrc = src;
    4322           0 :                     pRef = ref + j;
    4323           0 :                     ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
    4324           0 :                     for (k = 0; k < block_height; k += 2) {
    4325           0 :                         ss0 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pRef)), _mm_loadu_si128((__m128i*)(pRef + ref_stride)), 0x1);
    4326           0 :                         ss1 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)(pRef + 8))), _mm_loadu_si128((__m128i*)(pRef + ref_stride + 8)), 0x1);
    4327           0 :                         ss2 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pSrc)), _mm_loadu_si128((__m128i*)(pSrc + src_stride)), 0x1);
    4328           0 :                         ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
    4329           0 :                         ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
    4330           0 :                         ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
    4331           0 :                         ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
    4332           0 :                         pSrc += 2 * src_stride;
    4333           0 :                         pRef += 2 * ref_stride;
    4334             :                     }
    4335           0 :                     ss3 = _mm256_adds_epu16(ss3, ss4);
    4336           0 :                     ss5 = _mm256_adds_epu16(ss5, ss6);
    4337           0 :                     ss0 = _mm256_adds_epu16(ss3, ss5);
    4338           0 :                     s0 = _mm_adds_epu16(_mm256_castsi256_si128(ss0), _mm256_extracti128_si256(ss0, 1));
    4339           0 :                     s0 = _mm_minpos_epu16(s0);
    4340           0 :                     temSum1 = _mm_extract_epi16(s0, 0);
    4341           0 :                     if (temSum1 < lowSum) {
    4342           0 :                         if (temSum1 != 0xFFFF) { // no overflow
    4343           0 :                             lowSum = temSum1;
    4344           0 :                             xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
    4345           0 :                             yBest = i;
    4346             :                         }
    4347             :                         else {
    4348           0 :                             ss4 = _mm256_unpacklo_epi16(ss3, _mm256_setzero_si256());
    4349           0 :                             ss3 = _mm256_unpackhi_epi16(ss3, _mm256_setzero_si256());
    4350           0 :                             ss6 = _mm256_unpacklo_epi16(ss5, _mm256_setzero_si256());
    4351           0 :                             ss5 = _mm256_unpackhi_epi16(ss5, _mm256_setzero_si256());
    4352           0 :                             ss4 = _mm256_add_epi32(ss4, ss6);
    4353           0 :                             ss3 = _mm256_add_epi32(ss3, ss5);
    4354           0 :                             s0 = _mm_add_epi32(_mm256_castsi256_si128(ss4), _mm256_extracti128_si256(ss4, 1));
    4355           0 :                             s3 = _mm_add_epi32(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
    4356           0 :                             UPDATE_BEST(s0, 0, 0);
    4357           0 :                             UPDATE_BEST(s0, 1, 0);
    4358           0 :                             UPDATE_BEST(s0, 2, 0);
    4359           0 :                             UPDATE_BEST(s0, 3, 0);
    4360           0 :                             UPDATE_BEST(s3, 0, 4);
    4361           0 :                             UPDATE_BEST(s3, 1, 4);
    4362           0 :                             UPDATE_BEST(s3, 2, 4);
    4363           0 :                             UPDATE_BEST(s3, 3, 4);
    4364             :                         }
    4365             :                     }
    4366             :                 }
    4367           0 :                 ref += src_stride_raw;
    4368             :             }
    4369             :         }
    4370       31597 :         break;
    4371             : 
    4372           0 :     case 24:
    4373           0 :         if (block_height <= 16) {
    4374           0 :             for (i = 0; i < search_area_height; i++) {
    4375           0 :                 for (j = 0; j <= search_area_width - 8; j += 8) {
    4376           0 :                     pSrc = src;
    4377           0 :                     pRef = ref + j;
    4378           0 :                     ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
    4379           0 :                     for (k = 0; k < block_height; k++) {
    4380           0 :                         ss0 = _mm256_loadu_si256((__m256i*)pRef);
    4381           0 :                         ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
    4382           0 :                         ss2 = _mm256_loadu_si256((__m256i *)pSrc);
    4383           0 :                         ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
    4384           0 :                         ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
    4385           0 :                         ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
    4386           0 :                         ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
    4387           0 :                         pSrc += src_stride;
    4388           0 :                         pRef += ref_stride;
    4389             :                     }
    4390           0 :                     ss3 = _mm256_adds_epu16(ss3, ss4);
    4391           0 :                     ss5 = _mm256_adds_epu16(ss5, ss6);
    4392           0 :                     s3 = _mm_adds_epu16(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
    4393           0 :                     s5 = _mm256_castsi256_si128(ss5);
    4394           0 :                     s4 = _mm_minpos_epu16(s3);
    4395           0 :                     s6 = _mm_minpos_epu16(s5);
    4396           0 :                     s4 = _mm_unpacklo_epi16(s4, s4);
    4397           0 :                     s4 = _mm_unpacklo_epi32(s4, s4);
    4398           0 :                     s4 = _mm_unpacklo_epi64(s4, s4);
    4399           0 :                     s6 = _mm_unpacklo_epi16(s6, s6);
    4400           0 :                     s6 = _mm_unpacklo_epi32(s6, s6);
    4401           0 :                     s6 = _mm_unpacklo_epi64(s6, s6);
    4402           0 :                     s3 = _mm_sub_epi16(s3, s4);
    4403           0 :                     s5 = _mm_adds_epu16(s5, s3);
    4404           0 :                     s5 = _mm_sub_epi16(s5, s6);
    4405           0 :                     s5 = _mm_minpos_epu16(s5);
    4406           0 :                     temSum1 = _mm_extract_epi16(s5, 0);
    4407           0 :                     temSum1 += _mm_extract_epi16(s4, 0);
    4408           0 :                     temSum1 += _mm_extract_epi16(s6, 0);
    4409           0 :                     if (temSum1 < lowSum) {
    4410           0 :                         lowSum = temSum1;
    4411           0 :                         xBest = (int16_t)(j + _mm_extract_epi16(s5, 1));
    4412           0 :                         yBest = i;
    4413             :                     }
    4414             :                 }
    4415           0 :                 ref += src_stride_raw;
    4416             :             }
    4417             :         }
    4418             :         else {
    4419           0 :             for (i = 0; i < search_area_height; i++) {
    4420           0 :                 for (j = 0; j <= search_area_width - 8; j += 8) {
    4421           0 :                     pSrc = src;
    4422           0 :                     pRef = ref + j;
    4423           0 :                     ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
    4424           0 :                     for (k = 0; k < block_height; k++) {
    4425           0 :                         ss0 = _mm256_loadu_si256((__m256i*)pRef);
    4426           0 :                         ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
    4427           0 :                         ss2 = _mm256_loadu_si256((__m256i *)pSrc);
    4428           0 :                         ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
    4429           0 :                         ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
    4430           0 :                         ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
    4431           0 :                         ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
    4432           0 :                         pSrc += src_stride;
    4433           0 :                         pRef += ref_stride;
    4434             :                     }
    4435           0 :                     ss3 = _mm256_adds_epu16(ss3, ss4);
    4436           0 :                     ss5 = _mm256_adds_epu16(ss5, ss6);
    4437           0 :                     s3 = _mm256_castsi256_si128(ss3);
    4438           0 :                     s4 = _mm256_extracti128_si256(ss3, 1);
    4439           0 :                     s5 = _mm256_castsi256_si128(ss5);
    4440           0 :                     s0 = _mm_adds_epu16(_mm_adds_epu16(s3, s4), s5);
    4441           0 :                     s0 = _mm_minpos_epu16(s0);
    4442           0 :                     temSum1 = _mm_extract_epi16(s0, 0);
    4443           0 :                     if (temSum1 < lowSum) {
    4444           0 :                         if (temSum1 != 0xFFFF) { // no overflow
    4445           0 :                             lowSum = temSum1;
    4446           0 :                             xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
    4447           0 :                             yBest = i;
    4448             :                         }
    4449             :                         else {
    4450           0 :                             s0 = _mm_unpacklo_epi16(s3, _mm_setzero_si128());
    4451           0 :                             s3 = _mm_unpackhi_epi16(s3, _mm_setzero_si128());
    4452           0 :                             s1 = _mm_unpacklo_epi16(s4, _mm_setzero_si128());
    4453           0 :                             s4 = _mm_unpackhi_epi16(s4, _mm_setzero_si128());
    4454           0 :                             s2 = _mm_unpacklo_epi16(s5, _mm_setzero_si128());
    4455           0 :                             s5 = _mm_unpackhi_epi16(s5, _mm_setzero_si128());
    4456           0 :                             s0 = _mm_add_epi32(_mm_add_epi32(s0, s1), s2);
    4457           0 :                             s3 = _mm_add_epi32(_mm_add_epi32(s3, s4), s5);
    4458           0 :                             UPDATE_BEST(s0, 0, 0);
    4459           0 :                             UPDATE_BEST(s0, 1, 0);
    4460           0 :                             UPDATE_BEST(s0, 2, 0);
    4461           0 :                             UPDATE_BEST(s0, 3, 0);
    4462           0 :                             UPDATE_BEST(s3, 0, 4);
    4463           0 :                             UPDATE_BEST(s3, 1, 4);
    4464           0 :                             UPDATE_BEST(s3, 2, 4);
    4465           0 :                             UPDATE_BEST(s3, 3, 4);
    4466             :                         }
    4467             :                     }
    4468             :                 }
    4469           0 :                 ref += src_stride_raw;
    4470             :             }
    4471             :         }
    4472           0 :         break;
    4473             : 
    4474           0 :     case 32:
    4475           0 :         if (block_height <= 16) {
    4476           0 :             for (i = 0; i < search_area_height; i++) {
    4477           0 :                 for (j = 0; j <= search_area_width - 8; j += 8) {
    4478           0 :                     pSrc = src;
    4479           0 :                     pRef = ref + j;
    4480           0 :                     ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
    4481           0 :                     for (k = 0; k < block_height; k++) {
    4482           0 :                         ss0 = _mm256_loadu_si256((__m256i*)pRef);
    4483           0 :                         ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
    4484           0 :                         ss2 = _mm256_loadu_si256((__m256i *)pSrc);
    4485           0 :                         ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
    4486           0 :                         ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
    4487           0 :                         ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
    4488           0 :                         ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
    4489           0 :                         pSrc += src_stride;
    4490           0 :                         pRef += ref_stride;
    4491             :                     }
    4492           0 :                     ss3 = _mm256_adds_epu16(_mm256_adds_epu16(ss3, ss4), _mm256_adds_epu16(ss5, ss6));
    4493           0 :                     s3 = _mm256_castsi256_si128(ss3);
    4494           0 :                     s5 = _mm256_extracti128_si256(ss3, 1);
    4495           0 :                     s4 = _mm_minpos_epu16(s3);
    4496           0 :                     s6 = _mm_minpos_epu16(s5);
    4497           0 :                     s4 = _mm_unpacklo_epi16(s4, s4);
    4498           0 :                     s4 = _mm_unpacklo_epi32(s4, s4);
    4499           0 :                     s4 = _mm_unpacklo_epi64(s4, s4);
    4500           0 :                     s6 = _mm_unpacklo_epi16(s6, s6);
    4501           0 :                     s6 = _mm_unpacklo_epi32(s6, s6);
    4502           0 :                     s6 = _mm_unpacklo_epi64(s6, s6);
    4503           0 :                     s3 = _mm_sub_epi16(s3, s4);
    4504           0 :                     s5 = _mm_adds_epu16(s5, s3);
    4505           0 :                     s5 = _mm_sub_epi16(s5, s6);
    4506           0 :                     s5 = _mm_minpos_epu16(s5);
    4507           0 :                     temSum1 = _mm_extract_epi16(s5, 0);
    4508           0 :                     temSum1 += _mm_extract_epi16(s4, 0);
    4509           0 :                     temSum1 += _mm_extract_epi16(s6, 0);
    4510           0 :                     if (temSum1 < lowSum) {
    4511           0 :                         lowSum = temSum1;
    4512           0 :                         xBest = (int16_t)(j + _mm_extract_epi16(s5, 1));
    4513           0 :                         yBest = i;
    4514             :                     }
    4515             :                 }
    4516           0 :                 ref += src_stride_raw;
    4517             :             }
    4518             :         }
    4519           0 :         else if (block_height <= 32) {
    4520           0 :             for (i = 0; i < search_area_height; i++) {
    4521           0 :                 for (j = 0; j <= search_area_width - 8; j += 8) {
    4522           0 :                     pSrc = src;
    4523           0 :                     pRef = ref + j;
    4524           0 :                     ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
    4525           0 :                     for (k = 0; k < block_height; k++) {
    4526           0 :                         ss0 = _mm256_loadu_si256((__m256i*)pRef);
    4527           0 :                         ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
    4528           0 :                         ss2 = _mm256_loadu_si256((__m256i *)pSrc);
    4529           0 :                         ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
    4530           0 :                         ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
    4531           0 :                         ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
    4532           0 :                         ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
    4533           0 :                         pSrc += src_stride;
    4534           0 :                         pRef += ref_stride;
    4535             :                     }
    4536           0 :                     ss3 = _mm256_adds_epu16(ss3, ss4);
    4537           0 :                     ss5 = _mm256_adds_epu16(ss5, ss6);
    4538           0 :                     ss6 = _mm256_adds_epu16(ss3, ss5);
    4539           0 :                     s3 = _mm256_castsi256_si128(ss6);
    4540           0 :                     s4 = _mm256_extracti128_si256(ss6, 1);
    4541           0 :                     s0 = _mm_adds_epu16(s3, s4);
    4542           0 :                     s0 = _mm_minpos_epu16(s0);
    4543           0 :                     temSum1 = _mm_extract_epi16(s0, 0);
    4544           0 :                     if (temSum1 < lowSum) {
    4545           0 :                         if (temSum1 != 0xFFFF) { // no overflow
    4546           0 :                             lowSum = temSum1;
    4547           0 :                             xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
    4548           0 :                             yBest = i;
    4549             :                         }
    4550             :                         else {
    4551           0 :                             ss4 = _mm256_unpacklo_epi16(ss3, _mm256_setzero_si256());
    4552           0 :                             ss3 = _mm256_unpackhi_epi16(ss3, _mm256_setzero_si256());
    4553           0 :                             ss6 = _mm256_unpacklo_epi16(ss5, _mm256_setzero_si256());
    4554           0 :                             ss5 = _mm256_unpackhi_epi16(ss5, _mm256_setzero_si256());
    4555           0 :                             ss4 = _mm256_add_epi32(ss4, ss6);
    4556           0 :                             ss3 = _mm256_add_epi32(ss3, ss5);
    4557           0 :                             s0 = _mm_add_epi32(_mm256_castsi256_si128(ss4), _mm256_extracti128_si256(ss4, 1));
    4558           0 :                             s3 = _mm_add_epi32(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
    4559           0 :                             UPDATE_BEST(s0, 0, 0);
    4560           0 :                             UPDATE_BEST(s0, 1, 0);
    4561           0 :                             UPDATE_BEST(s0, 2, 0);
    4562           0 :                             UPDATE_BEST(s0, 3, 0);
    4563           0 :                             UPDATE_BEST(s3, 0, 4);
    4564           0 :                             UPDATE_BEST(s3, 1, 4);
    4565           0 :                             UPDATE_BEST(s3, 2, 4);
    4566           0 :                             UPDATE_BEST(s3, 3, 4);
    4567             :                         }
    4568             :                     }
    4569             :                 }
    4570           0 :                 ref += src_stride_raw;
    4571             :             }
    4572             :         }
    4573             :         else {
    4574           0 :             for (i = 0; i < search_area_height; i++) {
    4575           0 :                 for (j = 0; j <= search_area_width - 8; j += 8) {
    4576           0 :                     pSrc = src;
    4577           0 :                     pRef = ref + j;
    4578           0 :                     ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
    4579           0 :                     for (k = 0; k < block_height; k++) {
    4580           0 :                         ss0 = _mm256_loadu_si256((__m256i*)pRef);
    4581           0 :                         ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
    4582           0 :                         ss2 = _mm256_loadu_si256((__m256i *)pSrc);
    4583           0 :                         ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
    4584           0 :                         ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
    4585           0 :                         ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
    4586           0 :                         ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
    4587           0 :                         pSrc += src_stride;
    4588           0 :                         pRef += ref_stride;
    4589             :                     }
    4590           0 :                     ss7 = _mm256_adds_epu16(_mm256_adds_epu16(ss3, ss4), _mm256_adds_epu16(ss5, ss6));
    4591           0 :                     s3 = _mm256_castsi256_si128(ss7);
    4592           0 :                     s4 = _mm256_extracti128_si256(ss7, 1);
    4593           0 :                     s0 = _mm_adds_epu16(s3, s4);
    4594           0 :                     s0 = _mm_minpos_epu16(s0);
    4595           0 :                     temSum1 = _mm_extract_epi16(s0, 0);
    4596           0 :                     if (temSum1 < lowSum) {
    4597           0 :                         if (temSum1 != 0xFFFF) { // no overflow
    4598           0 :                             lowSum = temSum1;
    4599           0 :                             xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
    4600           0 :                             yBest = i;
    4601             :                         }
    4602             :                         else {
    4603           0 :                             ss0 = _mm256_unpacklo_epi16(ss3, _mm256_setzero_si256());
    4604           0 :                             ss3 = _mm256_unpackhi_epi16(ss3, _mm256_setzero_si256());
    4605           0 :                             ss1 = _mm256_unpacklo_epi16(ss4, _mm256_setzero_si256());
    4606           0 :                             ss4 = _mm256_unpackhi_epi16(ss4, _mm256_setzero_si256());
    4607           0 :                             ss2 = _mm256_unpacklo_epi16(ss5, _mm256_setzero_si256());
    4608           0 :                             ss5 = _mm256_unpackhi_epi16(ss5, _mm256_setzero_si256());
    4609           0 :                             ss7 = _mm256_unpacklo_epi16(ss6, _mm256_setzero_si256());
    4610           0 :                             ss6 = _mm256_unpackhi_epi16(ss6, _mm256_setzero_si256());
    4611           0 :                             ss0 = _mm256_add_epi32(_mm256_add_epi32(ss0, ss1), _mm256_add_epi32(ss2, ss7));
    4612           0 :                             ss3 = _mm256_add_epi32(_mm256_add_epi32(ss3, ss4), _mm256_add_epi32(ss5, ss6));
    4613           0 :                             s0 = _mm_add_epi32(_mm256_castsi256_si128(ss0), _mm256_extracti128_si256(ss0, 1));
    4614           0 :                             s3 = _mm_add_epi32(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
    4615           0 :                             UPDATE_BEST(s0, 0, 0);
    4616           0 :                             UPDATE_BEST(s0, 1, 0);
    4617           0 :                             UPDATE_BEST(s0, 2, 0);
    4618           0 :                             UPDATE_BEST(s0, 3, 0);
    4619           0 :                             UPDATE_BEST(s3, 0, 4);
    4620           0 :                             UPDATE_BEST(s3, 1, 4);
    4621           0 :                             UPDATE_BEST(s3, 2, 4);
    4622           0 :                             UPDATE_BEST(s3, 3, 4);
    4623             :                         }
    4624             :                     }
    4625             :                 }
    4626           0 :                 ref += src_stride_raw;
    4627             :             }
    4628             :         }
    4629           0 :         break;
    4630             : 
    4631           0 :     case 48:
    4632           0 :         if (block_height <= 32) {
    4633           0 :             for (i = 0; i < search_area_height; i++) {
    4634           0 :                 for (j = 0; j <= search_area_width - 8; j += 8) {
    4635           0 :                     pSrc = src;
    4636           0 :                     pRef = ref + j;
    4637           0 :                     s3 = s4 = s5 = s6 = _mm_setzero_si128();
    4638           0 :                     ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
    4639           0 :                     for (k = 0; k < block_height; k++) {
    4640           0 :                         ss0 = _mm256_loadu_si256((__m256i*)pRef);
    4641           0 :                         ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
    4642           0 :                         ss2 = _mm256_loadu_si256((__m256i *)pSrc);
    4643           0 :                         ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
    4644           0 :                         ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
    4645           0 :                         ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
    4646           0 :                         ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
    4647           0 :                         s0 = _mm_loadu_si128((__m128i*)(pRef + 32));
    4648           0 :                         s1 = _mm_loadu_si128((__m128i*)(pRef + 40));
    4649           0 :                         s2 = _mm_loadu_si128((__m128i*)(pSrc + 32));
    4650           0 :                         s3 = _mm_adds_epu16(s3, _mm_mpsadbw_epu8(s0, s2, 0));
    4651           0 :                         s4 = _mm_adds_epu16(s4, _mm_mpsadbw_epu8(s0, s2, 5));
    4652           0 :                         s5 = _mm_adds_epu16(s5, _mm_mpsadbw_epu8(s1, s2, 2));
    4653           0 :                         s6 = _mm_adds_epu16(s6, _mm_mpsadbw_epu8(s1, s2, 7));
    4654           0 :                         pSrc += src_stride;
    4655           0 :                         pRef += ref_stride;
    4656             :                     }
    4657           0 :                     s3 = _mm_adds_epu16(s3, s4);
    4658           0 :                     s5 = _mm_adds_epu16(s5, s6);
    4659           0 :                     s0 = _mm_adds_epu16(s3, s5);
    4660           0 :                     ss3 = _mm256_adds_epu16(ss3, ss4);
    4661           0 :                     ss5 = _mm256_adds_epu16(ss5, ss6);
    4662           0 :                     ss6 = _mm256_adds_epu16(ss3, ss5);
    4663           0 :                     s0 = _mm_adds_epu16(s0, _mm_adds_epu16(_mm256_castsi256_si128(ss6), _mm256_extracti128_si256(ss6, 1)));
    4664           0 :                     s0 = _mm_minpos_epu16(s0);
    4665           0 :                     temSum1 = _mm_extract_epi16(s0, 0);
    4666           0 :                     if (temSum1 < lowSum) {
    4667           0 :                         if (temSum1 != 0xFFFF) { // no overflow
    4668           0 :                             lowSum = temSum1;
    4669           0 :                             xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
    4670           0 :                             yBest = i;
    4671             :                         }
    4672             :                         else {
    4673           0 :                             ss4 = _mm256_unpacklo_epi16(ss3, _mm256_setzero_si256());
    4674           0 :                             ss3 = _mm256_unpackhi_epi16(ss3, _mm256_setzero_si256());
    4675           0 :                             ss6 = _mm256_unpacklo_epi16(ss5, _mm256_setzero_si256());
    4676           0 :                             ss5 = _mm256_unpackhi_epi16(ss5, _mm256_setzero_si256());
    4677           0 :                             ss4 = _mm256_add_epi32(ss4, ss6);
    4678           0 :                             ss3 = _mm256_add_epi32(ss3, ss5);
    4679           0 :                             s0 = _mm_add_epi32(_mm256_castsi256_si128(ss4), _mm256_extracti128_si256(ss4, 1));
    4680           0 :                             s1 = _mm_add_epi32(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
    4681           0 :                             s0 = _mm_add_epi32(s0, _mm_unpacklo_epi16(s3, _mm_setzero_si128()));
    4682           0 :                             s0 = _mm_add_epi32(s0, _mm_unpacklo_epi16(s5, _mm_setzero_si128()));
    4683           0 :                             s1 = _mm_add_epi32(s1, _mm_unpackhi_epi16(s3, _mm_setzero_si128()));
    4684           0 :                             s1 = _mm_add_epi32(s1, _mm_unpackhi_epi16(s5, _mm_setzero_si128()));
    4685           0 :                             UPDATE_BEST(s0, 0, 0);
    4686           0 :                             UPDATE_BEST(s0, 1, 0);
    4687           0 :                             UPDATE_BEST(s0, 2, 0);
    4688           0 :                             UPDATE_BEST(s0, 3, 0);
    4689           0 :                             UPDATE_BEST(s1, 0, 4);
    4690           0 :                             UPDATE_BEST(s1, 1, 4);
    4691           0 :                             UPDATE_BEST(s1, 2, 4);
    4692           0 :                             UPDATE_BEST(s1, 3, 4);
    4693             :                         }
    4694             :                     }
    4695             :                 }
    4696           0 :                 ref += src_stride_raw;
    4697             :             }
    4698             :         }
    4699             :         else {
    4700           0 :             for (i = 0; i < search_area_height; i++) {
    4701           0 :                 for (j = 0; j <= search_area_width - 8; j += 8) {
    4702           0 :                     pSrc = src;
    4703           0 :                     pRef = ref + j;
    4704           0 :                     s3 = s4 = s5 = s6 = _mm_setzero_si128();
    4705           0 :                     ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
    4706           0 :                     for (k = 0; k < block_height; k++) {
    4707           0 :                         ss0 = _mm256_loadu_si256((__m256i*)pRef);
    4708           0 :                         ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
    4709           0 :                         ss2 = _mm256_loadu_si256((__m256i *)pSrc);
    4710           0 :                         ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
    4711           0 :                         ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
    4712           0 :                         ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
    4713           0 :                         ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
    4714           0 :                         s0 = _mm_loadu_si128((__m128i*)(pRef + 32));
    4715           0 :                         s1 = _mm_loadu_si128((__m128i*)(pRef + 40));
    4716           0 :                         s2 = _mm_loadu_si128((__m128i*)(pSrc + 32));
    4717           0 :                         s3 = _mm_adds_epu16(s3, _mm_mpsadbw_epu8(s0, s2, 0));
    4718           0 :                         s4 = _mm_adds_epu16(s4, _mm_mpsadbw_epu8(s0, s2, 5));
    4719           0 :                         s5 = _mm_adds_epu16(s5, _mm_mpsadbw_epu8(s1, s2, 2));
    4720           0 :                         s6 = _mm_adds_epu16(s6, _mm_mpsadbw_epu8(s1, s2, 7));
    4721           0 :                         pSrc += src_stride;
    4722           0 :                         pRef += ref_stride;
    4723             :                     }
    4724           0 :                     s0 = _mm_adds_epu16(_mm_adds_epu16(s3, s4), _mm_adds_epu16(s5, s6));
    4725           0 :                     ss7 = _mm256_adds_epu16(ss3, ss4);
    4726           0 :                     ss8 = _mm256_adds_epu16(ss5, ss6);
    4727           0 :                     ss7 = _mm256_adds_epu16(ss7, ss8);
    4728           0 :                     s0 = _mm_adds_epu16(s0, _mm_adds_epu16(_mm256_castsi256_si128(ss7), _mm256_extracti128_si256(ss7, 1)));
    4729           0 :                     s0 = _mm_minpos_epu16(s0);
    4730           0 :                     temSum1 = _mm_extract_epi16(s0, 0);
    4731           0 :                     if (temSum1 < lowSum) {
    4732           0 :                         if (temSum1 != 0xFFFF) { // no overflow
    4733           0 :                             lowSum = temSum1;
    4734           0 :                             xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
    4735           0 :                             yBest = i;
    4736             :                         }
    4737             :                         else {
    4738           0 :                             ss0 = _mm256_unpacklo_epi16(ss3, _mm256_setzero_si256());
    4739           0 :                             ss3 = _mm256_unpackhi_epi16(ss3, _mm256_setzero_si256());
    4740           0 :                             ss1 = _mm256_unpacklo_epi16(ss4, _mm256_setzero_si256());
    4741           0 :                             ss4 = _mm256_unpackhi_epi16(ss4, _mm256_setzero_si256());
    4742           0 :                             ss2 = _mm256_unpacklo_epi16(ss5, _mm256_setzero_si256());
    4743           0 :                             ss5 = _mm256_unpackhi_epi16(ss5, _mm256_setzero_si256());
    4744           0 :                             ss7 = _mm256_unpacklo_epi16(ss6, _mm256_setzero_si256());
    4745           0 :                             ss6 = _mm256_unpackhi_epi16(ss6, _mm256_setzero_si256());
    4746           0 :                             ss0 = _mm256_add_epi32(_mm256_add_epi32(ss0, ss1), _mm256_add_epi32(ss2, ss7));
    4747           0 :                             ss3 = _mm256_add_epi32(_mm256_add_epi32(ss3, ss4), _mm256_add_epi32(ss5, ss6));
    4748           0 :                             s0 = _mm_add_epi32(_mm256_castsi256_si128(ss0), _mm256_extracti128_si256(ss0, 1));
    4749           0 :                             s1 = _mm_add_epi32(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
    4750           0 :                             s0 = _mm_add_epi32(s0, _mm_unpacklo_epi16(s3, _mm_setzero_si128()));
    4751           0 :                             s0 = _mm_add_epi32(s0, _mm_unpacklo_epi16(s4, _mm_setzero_si128()));
    4752           0 :                             s0 = _mm_add_epi32(s0, _mm_unpacklo_epi16(s5, _mm_setzero_si128()));
    4753           0 :                             s0 = _mm_add_epi32(s0, _mm_unpacklo_epi16(s6, _mm_setzero_si128()));
    4754           0 :                             s1 = _mm_add_epi32(s1, _mm_unpackhi_epi16(s3, _mm_setzero_si128()));
    4755           0 :                             s1 = _mm_add_epi32(s1, _mm_unpackhi_epi16(s4, _mm_setzero_si128()));
    4756           0 :                             s1 = _mm_add_epi32(s1, _mm_unpackhi_epi16(s5, _mm_setzero_si128()));
    4757           0 :                             s1 = _mm_add_epi32(s1, _mm_unpackhi_epi16(s6, _mm_setzero_si128()));
    4758           0 :                             UPDATE_BEST(s0, 0, 0);
    4759           0 :                             UPDATE_BEST(s0, 1, 0);
    4760           0 :                             UPDATE_BEST(s0, 2, 0);
    4761           0 :                             UPDATE_BEST(s0, 3, 0);
    4762           0 :                             UPDATE_BEST(s1, 0, 4);
    4763           0 :                             UPDATE_BEST(s1, 1, 4);
    4764           0 :                             UPDATE_BEST(s1, 2, 4);
    4765           0 :                             UPDATE_BEST(s1, 3, 4);
    4766             :                         }
    4767             :                     }
    4768             :                 }
    4769           0 :                 ref += src_stride_raw;
    4770             :             }
    4771             :         }
    4772           0 :         break;
    4773             : 
    4774           0 :     case 64:
    4775           0 :         if (block_height <= 32) {
    4776           0 :             for (i = 0; i < search_area_height; i++) {
    4777           0 :                 for (j = 0; j <= search_area_width - 8; j += 8) {
    4778           0 :                     pSrc = src;
    4779           0 :                     pRef = ref + j;
    4780           0 :                     ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
    4781           0 :                     for (k = 0; k < block_height; k++) {
    4782           0 :                         ss0 = _mm256_loadu_si256((__m256i*)pRef);
    4783           0 :                         ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
    4784           0 :                         ss2 = _mm256_loadu_si256((__m256i *)pSrc);
    4785           0 :                         ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
    4786           0 :                         ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
    4787           0 :                         ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
    4788           0 :                         ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
    4789           0 :                         ss0 = _mm256_loadu_si256((__m256i*)(pRef + 32));
    4790           0 :                         ss1 = _mm256_loadu_si256((__m256i*)(pRef + 40));
    4791           0 :                         ss2 = _mm256_loadu_si256((__m256i *)(pSrc + 32));
    4792           0 :                         ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
    4793           0 :                         ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
    4794           0 :                         ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
    4795           0 :                         ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
    4796           0 :                         pSrc += src_stride;
    4797           0 :                         pRef += ref_stride;
    4798             :                     }
    4799           0 :                     ss7 = _mm256_adds_epu16(_mm256_adds_epu16(ss3, ss4), _mm256_adds_epu16(ss5, ss6));
    4800           0 :                     s3 = _mm256_castsi256_si128(ss7);
    4801           0 :                     s4 = _mm256_extracti128_si256(ss7, 1);
    4802           0 :                     s0 = _mm_adds_epu16(s3, s4);
    4803           0 :                     s0 = _mm_minpos_epu16(s0);
    4804           0 :                     temSum1 = _mm_extract_epi16(s0, 0);
    4805           0 :                     if (temSum1 < lowSum) {
    4806           0 :                         if (temSum1 != 0xFFFF) { // no overflow
    4807           0 :                             lowSum = temSum1;
    4808           0 :                             xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
    4809           0 :                             yBest = i;
    4810             :                         }
    4811             :                         else {
    4812           0 :                             ss0 = _mm256_unpacklo_epi16(ss3, _mm256_setzero_si256());
    4813           0 :                             ss3 = _mm256_unpackhi_epi16(ss3, _mm256_setzero_si256());
    4814           0 :                             ss1 = _mm256_unpacklo_epi16(ss4, _mm256_setzero_si256());
    4815           0 :                             ss4 = _mm256_unpackhi_epi16(ss4, _mm256_setzero_si256());
    4816           0 :                             ss2 = _mm256_unpacklo_epi16(ss5, _mm256_setzero_si256());
    4817           0 :                             ss5 = _mm256_unpackhi_epi16(ss5, _mm256_setzero_si256());
    4818           0 :                             ss7 = _mm256_unpacklo_epi16(ss6, _mm256_setzero_si256());
    4819           0 :                             ss6 = _mm256_unpackhi_epi16(ss6, _mm256_setzero_si256());
    4820           0 :                             ss0 = _mm256_add_epi32(_mm256_add_epi32(ss0, ss1), _mm256_add_epi32(ss2, ss7));
    4821           0 :                             ss3 = _mm256_add_epi32(_mm256_add_epi32(ss3, ss4), _mm256_add_epi32(ss5, ss6));
    4822           0 :                             s0 = _mm_add_epi32(_mm256_castsi256_si128(ss0), _mm256_extracti128_si256(ss0, 1));
    4823           0 :                             s3 = _mm_add_epi32(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
    4824           0 :                             UPDATE_BEST(s0, 0, 0);
    4825           0 :                             UPDATE_BEST(s0, 1, 0);
    4826           0 :                             UPDATE_BEST(s0, 2, 0);
    4827           0 :                             UPDATE_BEST(s0, 3, 0);
    4828           0 :                             UPDATE_BEST(s3, 0, 4);
    4829           0 :                             UPDATE_BEST(s3, 1, 4);
    4830           0 :                             UPDATE_BEST(s3, 2, 4);
    4831           0 :                             UPDATE_BEST(s3, 3, 4);
    4832             :                         }
    4833             :                     }
    4834             :                 }
    4835           0 :                 ref += src_stride_raw;
    4836             :             }
    4837             :         }
    4838             :         else {
    4839             :             __m256i ss9, ss10;
    4840           0 :             for (i = 0; i < search_area_height; i++) {
    4841           0 :                 for (j = 0; j <= search_area_width - 8; j += 8) {
    4842           0 :                     pSrc = src;
    4843           0 :                     pRef = ref + j;
    4844           0 :                     ss3 = ss4 = ss5 = ss6 = ss7 = ss8 = ss9 = ss10 = _mm256_setzero_si256();
    4845           0 :                     for (k = 0; k < block_height; k++) {
    4846           0 :                         ss0 = _mm256_loadu_si256((__m256i*)pRef);
    4847           0 :                         ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
    4848           0 :                         ss2 = _mm256_loadu_si256((__m256i *)pSrc);
    4849           0 :                         ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
    4850           0 :                         ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
    4851           0 :                         ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
    4852           0 :                         ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
    4853           0 :                         ss0 = _mm256_loadu_si256((__m256i*)(pRef + 32));
    4854           0 :                         ss1 = _mm256_loadu_si256((__m256i*)(pRef + 40));
    4855           0 :                         ss2 = _mm256_loadu_si256((__m256i *)(pSrc + 32));
    4856           0 :                         ss7 = _mm256_adds_epu16(ss7, _mm256_mpsadbw_epu8(ss0, ss2, 0));
    4857           0 :                         ss8 = _mm256_adds_epu16(ss8, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
    4858           0 :                         ss9 = _mm256_adds_epu16(ss9, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
    4859           0 :                         ss10 = _mm256_adds_epu16(ss10, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
    4860           0 :                         pSrc += src_stride;
    4861           0 :                         pRef += ref_stride;
    4862             :                     }
    4863           0 :                     ss0 = _mm256_adds_epu16(_mm256_adds_epu16(ss3, ss4), _mm256_adds_epu16(ss5, ss6));
    4864           0 :                     ss0 = _mm256_adds_epu16(ss0, _mm256_adds_epu16(_mm256_adds_epu16(ss7, ss8), _mm256_adds_epu16(ss9, ss10)));
    4865           0 :                     s0 = _mm_adds_epu16(_mm256_castsi256_si128(ss0), _mm256_extracti128_si256(ss0, 1));
    4866           0 :                     s0 = _mm_minpos_epu16(s0);
    4867           0 :                     temSum1 = _mm_extract_epi16(s0, 0);
    4868           0 :                     if (temSum1 < lowSum) {
    4869           0 :                         if (temSum1 != 0xFFFF) { // no overflow
    4870           0 :                             lowSum = temSum1;
    4871           0 :                             xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
    4872           0 :                             yBest = i;
    4873             :                         }
    4874             :                         else {
    4875           0 :                             ss0 = _mm256_add_epi32(_mm256_add_epi32(_mm256_unpacklo_epi16(ss3, _mm256_setzero_si256()), _mm256_unpacklo_epi16(ss4, _mm256_setzero_si256())), _mm256_add_epi32(_mm256_unpacklo_epi16(ss5, _mm256_setzero_si256()), _mm256_unpacklo_epi16(ss6, _mm256_setzero_si256())));
    4876           0 :                             ss1 = _mm256_add_epi32(_mm256_add_epi32(_mm256_unpackhi_epi16(ss3, _mm256_setzero_si256()), _mm256_unpackhi_epi16(ss4, _mm256_setzero_si256())), _mm256_add_epi32(_mm256_unpackhi_epi16(ss5, _mm256_setzero_si256()), _mm256_unpackhi_epi16(ss6, _mm256_setzero_si256())));
    4877           0 :                             ss2 = _mm256_add_epi32(_mm256_add_epi32(_mm256_unpacklo_epi16(ss7, _mm256_setzero_si256()), _mm256_unpacklo_epi16(ss8, _mm256_setzero_si256())), _mm256_add_epi32(_mm256_unpacklo_epi16(ss9, _mm256_setzero_si256()), _mm256_unpacklo_epi16(ss10, _mm256_setzero_si256())));
    4878           0 :                             ss3 = _mm256_add_epi32(_mm256_add_epi32(_mm256_unpackhi_epi16(ss7, _mm256_setzero_si256()), _mm256_unpackhi_epi16(ss8, _mm256_setzero_si256())), _mm256_add_epi32(_mm256_unpackhi_epi16(ss9, _mm256_setzero_si256()), _mm256_unpackhi_epi16(ss10, _mm256_setzero_si256())));
    4879           0 :                             ss0 = _mm256_add_epi32(ss0, ss2);
    4880           0 :                             ss1 = _mm256_add_epi32(ss1, ss3);
    4881           0 :                             s0 = _mm_add_epi32(_mm256_castsi256_si128(ss0), _mm256_extracti128_si256(ss0, 1));
    4882           0 :                             s3 = _mm_add_epi32(_mm256_castsi256_si128(ss1), _mm256_extracti128_si256(ss1, 1));
    4883           0 :                             UPDATE_BEST(s0, 0, 0);
    4884           0 :                             UPDATE_BEST(s0, 1, 0);
    4885           0 :                             UPDATE_BEST(s0, 2, 0);
    4886           0 :                             UPDATE_BEST(s0, 3, 0);
    4887           0 :                             UPDATE_BEST(s3, 0, 4);
    4888           0 :                             UPDATE_BEST(s3, 1, 4);
    4889           0 :                             UPDATE_BEST(s3, 2, 4);
    4890           0 :                             UPDATE_BEST(s3, 3, 4);
    4891             :                         }
    4892             :                     }
    4893             :                 }
    4894           0 :                 ref += src_stride_raw;
    4895             :             }
    4896             :         }
    4897           0 :         break;
    4898             : 
    4899           0 :     default:
    4900             :         assert(0);
    4901           0 :         break;
    4902             :     }
    4903             : 
    4904       31594 :     *best_sad = lowSum;
    4905       31594 :     *x_search_center = xBest;
    4906       31594 :     *y_search_center = yBest;
    4907       31594 : }
    4908             : 
    4909           0 : uint32_t eb_aom_sad4x4_avx2(const uint8_t *src_ptr, int src_stride,
    4910             :     const uint8_t *ref_ptr, int ref_stride) {
    4911           0 :     return compute4x_m_sad_avx2(src_ptr, src_stride, ref_ptr, ref_stride, 4);
    4912             : }
    4913             : 
    4914           0 : uint32_t eb_aom_sad4x8_avx2(const uint8_t *src_ptr, int src_stride,
    4915             :     const uint8_t *ref_ptr, int ref_stride) {
    4916           0 :     return compute4x_m_sad_avx2(src_ptr, src_stride, ref_ptr, ref_stride, 8);
    4917             : }
    4918             : 
    4919           0 : uint32_t eb_aom_sad4x16_avx2(const uint8_t *src_ptr, int src_stride,
    4920             :     const uint8_t *ref_ptr, int ref_stride) {
    4921           0 :     return compute4x_m_sad_avx2(src_ptr, src_stride, ref_ptr, ref_stride, 16);
    4922             : }
    4923             : 
    4924           0 : uint32_t eb_aom_sad8x4_avx2(const uint8_t *src_ptr, int src_stride,
    4925             :     const uint8_t *ref_ptr, int ref_stride) {
    4926           0 :     return compute8x_m_sad_avx2(src_ptr, src_stride, ref_ptr, ref_stride, 4);
    4927             : }
    4928             : 
    4929           0 : uint32_t eb_aom_sad8x8_avx2(const uint8_t *src_ptr, int src_stride,
    4930             :     const uint8_t *ref_ptr, int ref_stride) {
    4931           0 :     return compute8x_m_sad_avx2(src_ptr, src_stride, ref_ptr, ref_stride, 8);
    4932             : }
    4933             : 
    4934           0 : uint32_t eb_aom_sad8x16_avx2(const uint8_t *src_ptr, int src_stride,
    4935             :     const uint8_t *ref_ptr, int ref_stride) {
    4936           0 :     return compute8x_m_sad_avx2(src_ptr, src_stride, ref_ptr, ref_stride, 16);
    4937             : }
    4938             : 
    4939           0 : uint32_t eb_aom_sad8x32_avx2(const uint8_t *src_ptr, int src_stride,
    4940             :     const uint8_t *ref_ptr, int ref_stride) {
    4941           0 :     return compute8x_m_sad_avx2(src_ptr, src_stride, ref_ptr, ref_stride, 32);
    4942             : }
    4943             : 
    4944           0 : uint32_t eb_aom_sad16x4_avx2(const uint8_t *src_ptr, int src_stride,
    4945             :     const uint8_t *ref_ptr, int ref_stride) {
    4946           0 :     return compute16x_m_sad_avx2(src_ptr, src_stride, ref_ptr, ref_stride, 4);
    4947             : }
    4948             : 
    4949           0 : uint32_t eb_aom_sad16x8_avx2(const uint8_t *src_ptr, int src_stride,
    4950             :     const uint8_t *ref_ptr, int ref_stride) {
    4951           0 :     return compute16x_m_sad_avx2(src_ptr, src_stride, ref_ptr, ref_stride, 8);
    4952             : }
    4953             : 
    4954           0 : uint32_t eb_aom_sad16x16_avx2(const uint8_t *src_ptr, int src_stride,
    4955             :     const uint8_t *ref_ptr, int ref_stride) {
    4956           0 :     return compute16x_m_sad_avx2(src_ptr, src_stride, ref_ptr, ref_stride, 16);
    4957             : }
    4958             : 
    4959           0 : uint32_t eb_aom_sad16x32_avx2(const uint8_t *src_ptr, int src_stride,
    4960             :     const uint8_t *ref_ptr, int ref_stride) {
    4961           0 :     return compute16x_m_sad_avx2(src_ptr, src_stride, ref_ptr, ref_stride, 32);
    4962             : }
    4963             : 
    4964           0 : uint32_t eb_aom_sad16x64_avx2(const uint8_t *src_ptr, int src_stride,
    4965             :     const uint8_t *ref_ptr, int ref_stride) {
    4966           0 :     return compute16x_m_sad_avx2(src_ptr, src_stride, ref_ptr, ref_stride, 64);
    4967             : }
    4968             : 
    4969           0 : uint32_t eb_aom_sad32x8_avx2(const uint8_t *src_ptr, int src_stride,
    4970             :     const uint8_t *ref_ptr, int ref_stride) {
    4971           0 :     return compute32x_m_sad_avx2(src_ptr, src_stride, ref_ptr, ref_stride, 8);
    4972             : }
    4973             : 
    4974           0 : uint32_t eb_aom_sad32x16_avx2(const uint8_t *src_ptr, int src_stride,
    4975             :     const uint8_t *ref_ptr, int ref_stride) {
    4976           0 :     return compute32x_m_sad_avx2(src_ptr, src_stride, ref_ptr, ref_stride, 16);
    4977             : }
    4978             : 
    4979           0 : uint32_t eb_aom_sad32x32_avx2(const uint8_t *src_ptr, int src_stride,
    4980             :     const uint8_t *ref_ptr, int ref_stride) {
    4981           0 :     return compute32x_m_sad_avx2(src_ptr, src_stride, ref_ptr, ref_stride, 32);
    4982             : }
    4983             : 
    4984           0 : uint32_t eb_aom_sad32x64_avx2(const uint8_t *src_ptr, int src_stride,
    4985             :     const uint8_t *ref_ptr, int ref_stride) {
    4986           0 :     return compute32x_m_sad_avx2(src_ptr, src_stride, ref_ptr, ref_stride, 64);
    4987             : }
    4988             : 
    4989           0 : uint32_t eb_aom_sad64x16_avx2(const uint8_t *src_ptr, int src_stride,
    4990             :     const uint8_t *ref_ptr, int ref_stride) {
    4991           0 :     return compute64x_m_sad_avx2(src_ptr, src_stride, ref_ptr, ref_stride, 16);
    4992             : }
    4993             : 
    4994           0 : uint32_t eb_aom_sad64x32_avx2(const uint8_t *src_ptr, int src_stride,
    4995             :     const uint8_t *ref_ptr, int ref_stride) {
    4996           0 :     return compute64x_m_sad_avx2(src_ptr, src_stride, ref_ptr, ref_stride, 32);
    4997             : }
    4998             : 
    4999           0 : uint32_t eb_aom_sad64x64_avx2(const uint8_t *src_ptr, int src_stride,
    5000             :     const uint8_t *ref_ptr, int ref_stride) {
    5001           0 :     return compute64x_m_sad_avx2(src_ptr, src_stride, ref_ptr, ref_stride, 64);
    5002             : }
    5003             : 
    5004           0 : uint32_t eb_aom_sad128x64_avx2(const uint8_t *src_ptr, int src_stride,
    5005             :     const uint8_t *ref_ptr, int ref_stride) {
    5006           0 :     return compute128x_m_sad_avx2(src_ptr, src_stride, ref_ptr, ref_stride, 64);
    5007             : }
    5008             : 
    5009           0 : uint32_t eb_aom_sad128x128_avx2(const uint8_t *src_ptr, int src_stride,
    5010             :     const uint8_t *ref_ptr, int ref_stride) {
    5011           0 :     return compute128x_m_sad_avx2(src_ptr, src_stride, ref_ptr, ref_stride,
    5012             :         128);
    5013             : }
    5014             : 
    5015             : SIMD_INLINE void eb_aom_sad4xhx4d_calc_avx2(
    5016             :     const uint8_t *src, int src_stride,
    5017             :     const uint8_t *const ref[4], int ref_stride,
    5018             :     uint32_t res[4], uint32_t height) {
    5019             :     uint32_t y;
    5020           0 :     uint32_t hsteps = height >> 2;
    5021             :     const uint8_t *ref0, *ref1, *ref2, *ref3;
    5022             :     assert(!(height % 4));
    5023             : 
    5024           0 :     ref0 = ref[0];
    5025           0 :     ref1 = ref[1];
    5026           0 :     ref2 = ref[2];
    5027           0 :     ref3 = ref[3];
    5028             : 
    5029           0 :     __m256i mm256_sad0 = _mm256_setzero_si256();
    5030           0 :     __m256i mm256_sad1 = _mm256_setzero_si256();
    5031           0 :     __m256i mm256_sad2 = _mm256_setzero_si256();
    5032           0 :     __m256i mm256_sad3 = _mm256_setzero_si256();
    5033             :     __m256i mm256_src;
    5034             :     __m256i mm256_ref0;
    5035             :     __m256i mm256_ref1;
    5036             :     __m256i mm256_ref2;
    5037             :     __m256i mm256_ref3;
    5038             : 
    5039           0 :     for (y = 0; y < hsteps; y++) {
    5040           0 :         mm256_src = _mm256_setr_epi32(*(uint32_t*)src,
    5041           0 :             *(uint32_t*)(src + 1 * src_stride),
    5042           0 :             *(uint32_t*)(src + 2 * src_stride),
    5043           0 :             *(uint32_t*)(src + 3 * src_stride),
    5044             :             0, 0, 0, 0);
    5045             : 
    5046           0 :         mm256_ref0 = _mm256_setr_epi32(*(uint32_t*)ref0,
    5047           0 :             *(uint32_t*)(ref0 + 1 * ref_stride),
    5048           0 :             *(uint32_t*)(ref0 + 2 * ref_stride),
    5049           0 :             *(uint32_t*)(ref0 + 3 * ref_stride),
    5050             :             0, 0, 0, 0);
    5051             : 
    5052           0 :         mm256_ref1 = _mm256_setr_epi32(*(uint32_t*)ref1,
    5053           0 :             *(uint32_t*)(ref1 + 1 * ref_stride),
    5054           0 :             *(uint32_t*)(ref1 + 2 * ref_stride),
    5055           0 :             *(uint32_t*)(ref1 + 3 * ref_stride),
    5056             :             0, 0, 0, 0);
    5057             : 
    5058           0 :         mm256_ref2 = _mm256_setr_epi32(*(uint32_t*)ref2,
    5059           0 :             *(uint32_t*)(ref2 + 1 * ref_stride),
    5060           0 :             *(uint32_t*)(ref2 + 2 * ref_stride),
    5061           0 :             *(uint32_t*)(ref2 + 3 * ref_stride),
    5062             :             0, 0, 0, 0);
    5063             : 
    5064           0 :         mm256_ref3 = _mm256_setr_epi32(*(uint32_t*)ref3,
    5065           0 :             *(uint32_t*)(ref3 + 1 * ref_stride),
    5066           0 :             *(uint32_t*)(ref3 + 2 * ref_stride),
    5067           0 :             *(uint32_t*)(ref3 + 3 * ref_stride),
    5068             :             0, 0, 0, 0);
    5069             : 
    5070           0 :         mm256_sad0 = _mm256_add_epi16(mm256_sad0,
    5071             :             _mm256_sad_epu8(mm256_src, mm256_ref0));
    5072             : 
    5073           0 :         mm256_sad1 = _mm256_add_epi16(mm256_sad1,
    5074             :             _mm256_sad_epu8(mm256_src, mm256_ref1));
    5075             : 
    5076           0 :         mm256_sad2 = _mm256_add_epi16(mm256_sad2,
    5077             :             _mm256_sad_epu8(mm256_src, mm256_ref2));
    5078             : 
    5079           0 :         mm256_sad3 = _mm256_add_epi16(mm256_sad3,
    5080             :             _mm256_sad_epu8(mm256_src, mm256_ref3));
    5081             : 
    5082           0 :         src += src_stride << 2;
    5083           0 :         ref0 += ref_stride << 2;
    5084           0 :         ref1 += ref_stride << 2;
    5085           0 :         ref2 += ref_stride << 2;
    5086           0 :         ref3 += ref_stride << 2;
    5087             :     }
    5088             : 
    5089           0 :     res[0] = _mm256_extract_epi32(mm256_sad0, 0) + _mm256_extract_epi32(
    5090             :         mm256_sad0, 2);
    5091           0 :     res[1] = _mm256_extract_epi32(mm256_sad1, 0) + _mm256_extract_epi32(
    5092             :         mm256_sad1, 2);
    5093           0 :     res[2] = _mm256_extract_epi32(mm256_sad2, 0) + _mm256_extract_epi32(
    5094             :         mm256_sad2, 2);
    5095           0 :     res[3] = _mm256_extract_epi32(mm256_sad3, 0) + _mm256_extract_epi32(
    5096             :         mm256_sad3, 2);
    5097           0 : }
    5098             : 
    5099           0 : void eb_aom_sad4x4x4d_avx2(
    5100             :     const uint8_t *src, int src_stride,
    5101             :     const uint8_t *const ref[4], int ref_stride,
    5102             :     uint32_t res[4]) {
    5103             :     eb_aom_sad4xhx4d_calc_avx2(src, src_stride,
    5104             :         ref, ref_stride, res, 4);
    5105           0 : }
    5106             : 
    5107           0 : void eb_aom_sad4x8x4d_avx2(
    5108             :     const uint8_t *src, int src_stride,
    5109             :     const uint8_t *const ref[4], int ref_stride,
    5110             :     uint32_t res[4]) {
    5111             :     eb_aom_sad4xhx4d_calc_avx2(src, src_stride,
    5112             :         ref, ref_stride, res, 8);
    5113           0 : }
    5114             : 
    5115           0 : void eb_aom_sad4x16x4d_avx2(
    5116             :     const uint8_t *src, int src_stride,
    5117             :     const uint8_t *const ref[4], int ref_stride,
    5118             :     uint32_t res[4]) {
    5119             :     eb_aom_sad4xhx4d_calc_avx2(src, src_stride,
    5120             :         ref, ref_stride, res, 16);
    5121           0 : }
    5122             : 
    5123             : SIMD_INLINE void eb_aom_sad8xhx4d_calc_avx2(
    5124             :     const uint8_t *src, int src_stride,
    5125             :     const uint8_t *const ref[4], int ref_stride,
    5126             :     uint32_t res[4], uint32_t  height) {
    5127             :     __m128i xmm0;
    5128           0 :     __m256i ymm0 = _mm256_setzero_si256();
    5129           0 :     __m256i ymm1 = _mm256_setzero_si256();
    5130           0 :     __m256i ymm2 = _mm256_setzero_si256();
    5131           0 :     __m256i ymm3 = _mm256_setzero_si256();
    5132             :     uint32_t y;
    5133             : 
    5134             :     const uint8_t *ref0, *ref1, *ref2, *ref3;
    5135             : 
    5136           0 :     ref0 = ref[0];
    5137           0 :     ref1 = ref[1];
    5138           0 :     ref2 = ref[2];
    5139           0 :     ref3 = ref[3];
    5140             : 
    5141           0 :     for (y = 0; y < height; y += 4) {
    5142             :         __m128i src01, src23;
    5143           0 :         src01 = _mm_loadl_epi64((__m128i *)(src + 0 * src_stride));
    5144           0 :         src01 = _mm_castpd_si128(_mm_loadh_pd(_mm_castsi128_pd(src01),
    5145           0 :             (double *)(src + 1 * src_stride)));
    5146           0 :         src23 = _mm_loadl_epi64((__m128i *)(src + 2 * src_stride));
    5147           0 :         src23 = _mm_castpd_si128(_mm_loadh_pd(_mm_castsi128_pd(src23),
    5148           0 :             (double *)(src + 3 * src_stride)));
    5149           0 :         const __m256i src0123 = _mm256_setr_m128i(src01, src23);
    5150             : 
    5151           0 :         src01 = _mm_loadl_epi64((__m128i *)(ref0 + 0 * ref_stride));
    5152           0 :         src01 = _mm_castpd_si128(_mm_loadh_pd(_mm_castsi128_pd(src01),
    5153           0 :             (double *)(ref0 + 1 * ref_stride)));
    5154           0 :         src23 = _mm_loadl_epi64((__m128i *)(ref0 + 2 * ref_stride));
    5155           0 :         src23 = _mm_castpd_si128(_mm_loadh_pd(_mm_castsi128_pd(src23),
    5156           0 :             (double *)(ref0 + 3 * ref_stride)));
    5157           0 :         const __m256i ref0123_0 =  _mm256_setr_m128i(src01, src23);
    5158             : 
    5159           0 :         src01 = _mm_loadl_epi64((__m128i *)(ref1 + 0 * ref_stride));
    5160           0 :         src01 = _mm_castpd_si128(_mm_loadh_pd(_mm_castsi128_pd(src01),
    5161           0 :             (double *)(ref1 + 1 * ref_stride)));
    5162           0 :         src23 = _mm_loadl_epi64((__m128i *)(ref1 + 2 * ref_stride));
    5163           0 :         src23 = _mm_castpd_si128(_mm_loadh_pd(_mm_castsi128_pd(src23),
    5164           0 :             (double *)(ref1 + 3 * ref_stride)));
    5165           0 :         const __m256i ref0123_1 = _mm256_setr_m128i(src01, src23);
    5166             : 
    5167           0 :         src01 = _mm_loadl_epi64((__m128i *)(ref2 + 0 * ref_stride));
    5168           0 :         src01 = _mm_castpd_si128(_mm_loadh_pd(_mm_castsi128_pd(src01),
    5169           0 :             (double *)(ref2 + 1 * ref_stride)));
    5170           0 :         src23 = _mm_loadl_epi64((__m128i *)(ref2 + 2 * ref_stride));
    5171           0 :         src23 = _mm_castpd_si128(_mm_loadh_pd(_mm_castsi128_pd(src23),
    5172           0 :             (double *)(ref2 + 3 * ref_stride)));
    5173           0 :         const __m256i ref0123_2 = _mm256_setr_m128i(src01, src23);
    5174             : 
    5175           0 :         src01 = _mm_loadl_epi64((__m128i *)(ref3 + 0 * ref_stride));
    5176           0 :         src01 = _mm_castpd_si128(_mm_loadh_pd(_mm_castsi128_pd(src01),
    5177           0 :             (double *)(ref3 + 1 * ref_stride)));
    5178           0 :         src23 = _mm_loadl_epi64((__m128i *)(ref3 + 2 * ref_stride));
    5179           0 :         src23 = _mm_castpd_si128(_mm_loadh_pd(_mm_castsi128_pd(src23),
    5180           0 :             (double *)(ref3 + 3 * ref_stride)));
    5181           0 :         const __m256i ref0123_3 = _mm256_setr_m128i(src01, src23);
    5182             : 
    5183           0 :         ymm0 = _mm256_add_epi32(ymm0, _mm256_sad_epu8(src0123, ref0123_0));
    5184           0 :         ymm1 = _mm256_add_epi32(ymm1, _mm256_sad_epu8(src0123, ref0123_1));
    5185           0 :         ymm2 = _mm256_add_epi32(ymm2, _mm256_sad_epu8(src0123, ref0123_2));
    5186           0 :         ymm3 = _mm256_add_epi32(ymm3, _mm256_sad_epu8(src0123, ref0123_3));
    5187           0 :         src += src_stride << 2;
    5188           0 :         ref0 += ref_stride << 2;
    5189           0 :         ref1 += ref_stride << 2;
    5190           0 :         ref2 += ref_stride << 2;
    5191           0 :         ref3 += ref_stride << 2;
    5192             :     }
    5193             : 
    5194           0 :     xmm0 = _mm_add_epi32(_mm256_castsi256_si128(ymm0),
    5195           0 :         _mm256_extracti128_si256(ymm0, 1));
    5196           0 :     xmm0 = _mm_add_epi32(xmm0, _mm_srli_si128(xmm0, 8));
    5197           0 :     res[0] = (uint32_t)_mm_cvtsi128_si32(xmm0);
    5198             : 
    5199           0 :     xmm0 = _mm_add_epi32(_mm256_castsi256_si128(ymm1),
    5200           0 :         _mm256_extracti128_si256(ymm1, 1));
    5201           0 :     xmm0 = _mm_add_epi32(xmm0, _mm_srli_si128(xmm0, 8));
    5202           0 :     res[1] = (uint32_t)_mm_cvtsi128_si32(xmm0);
    5203             : 
    5204           0 :     xmm0 = _mm_add_epi32(_mm256_castsi256_si128(ymm2),
    5205           0 :         _mm256_extracti128_si256(ymm2, 1));
    5206           0 :     xmm0 = _mm_add_epi32(xmm0, _mm_srli_si128(xmm0, 8));
    5207           0 :     res[2] = (uint32_t)_mm_cvtsi128_si32(xmm0);
    5208             : 
    5209           0 :     xmm0 = _mm_add_epi32(_mm256_castsi256_si128(ymm3),
    5210           0 :         _mm256_extracti128_si256(ymm3, 1));
    5211           0 :     xmm0 = _mm_add_epi32(xmm0, _mm_srli_si128(xmm0, 8));
    5212           0 :     res[3] = (uint32_t)_mm_cvtsi128_si32(xmm0);
    5213           0 : }
    5214             : 
    5215           0 : void eb_aom_sad8x4x4d_avx2(
    5216             :     const uint8_t *src, int src_stride,
    5217             :     const uint8_t *const ref[4], int ref_stride,
    5218             :     uint32_t res[4]) {
    5219             :     eb_aom_sad8xhx4d_calc_avx2(src, src_stride,
    5220             :         ref, ref_stride, res, 4);
    5221           0 : }
    5222             : 
    5223           0 : void eb_aom_sad8x8x4d_avx2(
    5224             :     const uint8_t *src, int src_stride,
    5225             :     const uint8_t *const ref[4], int ref_stride,
    5226             :     uint32_t res[4]) {
    5227             :     eb_aom_sad8xhx4d_calc_avx2(src, src_stride,
    5228             :         ref, ref_stride, res, 8);
    5229           0 : }
    5230             : 
    5231           0 : void eb_aom_sad8x16x4d_avx2(
    5232             :     const uint8_t *src, int src_stride,
    5233             :     const uint8_t *const ref[4], int ref_stride,
    5234             :     uint32_t res[4]) {
    5235             :     eb_aom_sad8xhx4d_calc_avx2(src, src_stride,
    5236             :         ref, ref_stride, res, 16);
    5237           0 : }
    5238             : 
    5239           0 : void eb_aom_sad8x32x4d_avx2(
    5240             :     const uint8_t *src, int src_stride,
    5241             :     const uint8_t *const ref[4], int ref_stride,
    5242             :     uint32_t res[4]) {
    5243             :     eb_aom_sad8xhx4d_calc_avx2(src, src_stride,
    5244             :         ref, ref_stride, res, 32);
    5245           0 : }
    5246             : 
    5247             : SIMD_INLINE void eb_aom_sad16xhx4d_calc_avx2(
    5248             :     const uint8_t *src, int src_stride,
    5249             :     const uint8_t *const ref[4], int ref_stride,
    5250             :     uint32_t res[4], uint32_t  height) {
    5251             :     __m128i xmm0;
    5252           0 :     __m256i ymm0 = _mm256_setzero_si256();
    5253           0 :     __m256i ymm1 = _mm256_setzero_si256();
    5254           0 :     __m256i ymm2 = _mm256_setzero_si256();
    5255           0 :     __m256i ymm3 = _mm256_setzero_si256();
    5256             :     uint32_t y;
    5257             : 
    5258             :     const uint8_t *ref0, *ref1, *ref2, *ref3;
    5259             : 
    5260           0 :     ref0 = ref[0];
    5261           0 :     ref1 = ref[1];
    5262           0 :     ref2 = ref[2];
    5263           0 :     ref3 = ref[3];
    5264             : 
    5265           0 :     for (y = 0; y < height; y += 2) {
    5266           0 :         __m256i src0 = _mm256_setr_m128i(
    5267             :             _mm_loadu_si128((__m128i *)(src + 0 * src_stride)),
    5268             :             _mm_loadu_si128((__m128i *)(src + 1 * src_stride)));
    5269             : 
    5270           0 :         __m256i r0 = _mm256_setr_m128i(
    5271             :             _mm_loadu_si128((__m128i *)(ref0 + 0 * ref_stride)),
    5272             :             _mm_loadu_si128((__m128i *)(ref0 + 1 * ref_stride)));
    5273             : 
    5274           0 :         __m256i r1 = _mm256_setr_m128i(
    5275             :             _mm_loadu_si128((__m128i *)(ref1 + 0 * ref_stride)),
    5276             :             _mm_loadu_si128((__m128i *)(ref1 + 1 * ref_stride)));
    5277             : 
    5278           0 :         __m256i r2 = _mm256_setr_m128i(
    5279             :             _mm_loadu_si128((__m128i *)(ref2 + 0 * ref_stride)),
    5280             :             _mm_loadu_si128((__m128i *)(ref2 + 1 * ref_stride)));
    5281             : 
    5282           0 :         __m256i r3 = _mm256_setr_m128i(
    5283             :             _mm_loadu_si128((__m128i *)(ref3 + 0 * ref_stride)),
    5284             :             _mm_loadu_si128((__m128i *)(ref3 + 1 * ref_stride)));
    5285             : 
    5286           0 :         ymm0 = _mm256_add_epi32(ymm0, _mm256_sad_epu8(src0, r0));
    5287           0 :         ymm1 = _mm256_add_epi32(ymm1, _mm256_sad_epu8(src0, r1));
    5288           0 :         ymm2 = _mm256_add_epi32(ymm2, _mm256_sad_epu8(src0, r2));
    5289           0 :         ymm3 = _mm256_add_epi32(ymm3, _mm256_sad_epu8(src0, r3));
    5290             : 
    5291           0 :         src += src_stride << 1;
    5292           0 :         ref0 += ref_stride << 1;
    5293           0 :         ref1 += ref_stride << 1;
    5294           0 :         ref2 += ref_stride << 1;
    5295           0 :         ref3 += ref_stride << 1;
    5296             :     }
    5297             : 
    5298           0 :     xmm0 = _mm_add_epi32(_mm256_castsi256_si128(ymm0),
    5299           0 :         _mm256_extracti128_si256(ymm0, 1));
    5300           0 :     xmm0 = _mm_add_epi32(xmm0, _mm_srli_si128(xmm0, 8));
    5301           0 :     res[0] = (uint32_t)_mm_cvtsi128_si32(xmm0);
    5302             : 
    5303           0 :     xmm0 = _mm_add_epi32(_mm256_castsi256_si128(ymm1),
    5304           0 :         _mm256_extracti128_si256(ymm1, 1));
    5305           0 :     xmm0 = _mm_add_epi32(xmm0, _mm_srli_si128(xmm0, 8));
    5306           0 :     res[1] = (uint32_t)_mm_cvtsi128_si32(xmm0);
    5307             : 
    5308           0 :     xmm0 = _mm_add_epi32(_mm256_castsi256_si128(ymm2),
    5309           0 :         _mm256_extracti128_si256(ymm2, 1));
    5310           0 :     xmm0 = _mm_add_epi32(xmm0, _mm_srli_si128(xmm0, 8));
    5311           0 :     res[2] = (uint32_t)_mm_cvtsi128_si32(xmm0);
    5312             : 
    5313           0 :     xmm0 = _mm_add_epi32(_mm256_castsi256_si128(ymm3),
    5314           0 :         _mm256_extracti128_si256(ymm3, 1));
    5315           0 :     xmm0 = _mm_add_epi32(xmm0, _mm_srli_si128(xmm0, 8));
    5316           0 :     res[3] = (uint32_t)_mm_cvtsi128_si32(xmm0);
    5317           0 : }
    5318             : 
    5319           0 : void eb_aom_sad16x4x4d_avx2(
    5320             :     const uint8_t *src, int src_stride,
    5321             :     const uint8_t *const ref[4], int ref_stride,
    5322             :     uint32_t res[4]) {
    5323             :     eb_aom_sad16xhx4d_calc_avx2(src, src_stride,
    5324             :         ref, ref_stride, res, 4);
    5325           0 : }
    5326             : 
    5327           0 : void eb_aom_sad16x8x4d_avx2(
    5328             :     const uint8_t *src, int src_stride,
    5329             :     const uint8_t *const ref[4], int ref_stride,
    5330             :     uint32_t res[4]) {
    5331             :     eb_aom_sad16xhx4d_calc_avx2(src, src_stride,
    5332             :         ref, ref_stride, res, 8);
    5333           0 : }
    5334             : 
    5335           0 : void eb_aom_sad16x16x4d_avx2(
    5336             :     const uint8_t *src, int src_stride,
    5337             :     const uint8_t *const ref[4], int ref_stride,
    5338             :     uint32_t res[4]) {
    5339             :     eb_aom_sad16xhx4d_calc_avx2(src, src_stride,
    5340             :         ref, ref_stride, res, 16);
    5341           0 : }
    5342             : 
    5343           0 : void eb_aom_sad16x32x4d_avx2(
    5344             :     const uint8_t *src, int src_stride,
    5345             :     const uint8_t *const ref[4], int ref_stride,
    5346             :     uint32_t res[4]) {
    5347             :     eb_aom_sad16xhx4d_calc_avx2(src, src_stride,
    5348             :         ref, ref_stride, res, 32);
    5349           0 : }
    5350             : 
    5351           0 : void eb_aom_sad16x64x4d_avx2(
    5352             :     const uint8_t *src, int src_stride,
    5353             :     const uint8_t *const ref[4], int ref_stride,
    5354             :     uint32_t res[4]) {
    5355             :     eb_aom_sad16xhx4d_calc_avx2(src, src_stride,
    5356             :         ref, ref_stride, res, 64);
    5357           0 : }
    5358             : 
    5359           0 : void eb_aom_sad32x8x4d_avx2(const uint8_t *src, int src_stride,
    5360             :     const uint8_t *const ref[4], int ref_stride,
    5361             :     uint32_t res[4]) {
    5362             :     __m256i src_reg, ref0_reg, ref1_reg, ref2_reg, ref3_reg;
    5363             :     __m256i sum_ref0, sum_ref1, sum_ref2, sum_ref3;
    5364             :     __m256i sum_mlow, sum_mhigh;
    5365             :     int i;
    5366             :     const uint8_t *ref0, *ref1, *ref2, *ref3;
    5367             : 
    5368           0 :     ref0 = ref[0];
    5369           0 :     ref1 = ref[1];
    5370           0 :     ref2 = ref[2];
    5371           0 :     ref3 = ref[3];
    5372           0 :     sum_ref0 = _mm256_set1_epi16(0);
    5373           0 :     sum_ref1 = _mm256_set1_epi16(0);
    5374           0 :     sum_ref2 = _mm256_set1_epi16(0);
    5375           0 :     sum_ref3 = _mm256_set1_epi16(0);
    5376           0 :     for (i = 0; i < 8; i++) {
    5377             :         // load src and all refs
    5378           0 :         src_reg = _mm256_loadu_si256((const __m256i *)src);
    5379           0 :         ref0_reg = _mm256_loadu_si256((const __m256i *)ref0);
    5380           0 :         ref1_reg = _mm256_loadu_si256((const __m256i *)ref1);
    5381           0 :         ref2_reg = _mm256_loadu_si256((const __m256i *)ref2);
    5382           0 :         ref3_reg = _mm256_loadu_si256((const __m256i *)ref3);
    5383             :         // sum of the absolute differences between every ref-i to src
    5384           0 :         ref0_reg = _mm256_sad_epu8(ref0_reg, src_reg);
    5385           0 :         ref1_reg = _mm256_sad_epu8(ref1_reg, src_reg);
    5386           0 :         ref2_reg = _mm256_sad_epu8(ref2_reg, src_reg);
    5387           0 :         ref3_reg = _mm256_sad_epu8(ref3_reg, src_reg);
    5388             :         // sum every ref-i
    5389           0 :         sum_ref0 = _mm256_add_epi32(sum_ref0, ref0_reg);
    5390           0 :         sum_ref1 = _mm256_add_epi32(sum_ref1, ref1_reg);
    5391           0 :         sum_ref2 = _mm256_add_epi32(sum_ref2, ref2_reg);
    5392           0 :         sum_ref3 = _mm256_add_epi32(sum_ref3, ref3_reg);
    5393             : 
    5394           0 :         src += src_stride;
    5395           0 :         ref0 += ref_stride;
    5396           0 :         ref1 += ref_stride;
    5397           0 :         ref2 += ref_stride;
    5398           0 :         ref3 += ref_stride;
    5399             :     }
    5400             :     {
    5401             :         __m128i sum;
    5402             :         // in sum_ref-i the result is saved in the first 4 bytes
    5403             :         // the other 4 bytes are zeroed.
    5404             :         // sum_ref1 and sum_ref3 are shifted left by 4 bytes
    5405           0 :         sum_ref1 = _mm256_slli_si256(sum_ref1, 4);
    5406           0 :         sum_ref3 = _mm256_slli_si256(sum_ref3, 4);
    5407             : 
    5408             :         // merge sum_ref0 and sum_ref1 also sum_ref2 and sum_ref3
    5409           0 :         sum_ref0 = _mm256_or_si256(sum_ref0, sum_ref1);
    5410           0 :         sum_ref2 = _mm256_or_si256(sum_ref2, sum_ref3);
    5411             : 
    5412             :         // merge every 64 bit from each sum_ref-i
    5413           0 :         sum_mlow = _mm256_unpacklo_epi64(sum_ref0, sum_ref2);
    5414           0 :         sum_mhigh = _mm256_unpackhi_epi64(sum_ref0, sum_ref2);
    5415             : 
    5416             :         // add the low 64 bit to the high 64 bit
    5417           0 :         sum_mlow = _mm256_add_epi32(sum_mlow, sum_mhigh);
    5418             : 
    5419             :         // add the low 128 bit to the high 128 bit
    5420           0 :         sum = _mm_add_epi32(_mm256_castsi256_si128(sum_mlow),
    5421           0 :             _mm256_extractf128_si256(sum_mlow, 1));
    5422             : 
    5423             :         _mm_storeu_si128((__m128i *)(res), sum);
    5424             :     }
    5425             :     _mm256_zeroupper();
    5426           0 : }
    5427             : 
    5428           0 : void eb_aom_sad32x16x4d_avx2(const uint8_t *src, int src_stride,
    5429             :     const uint8_t *const ref[4], int ref_stride,
    5430             :     uint32_t res[4]) {
    5431             :     __m256i src_reg, ref0_reg, ref1_reg, ref2_reg, ref3_reg;
    5432             :     __m256i sum_ref0, sum_ref1, sum_ref2, sum_ref3;
    5433             :     __m256i sum_mlow, sum_mhigh;
    5434             :     int i;
    5435             :     const uint8_t *ref0, *ref1, *ref2, *ref3;
    5436             : 
    5437           0 :     ref0 = ref[0];
    5438           0 :     ref1 = ref[1];
    5439           0 :     ref2 = ref[2];
    5440           0 :     ref3 = ref[3];
    5441           0 :     sum_ref0 = _mm256_set1_epi16(0);
    5442           0 :     sum_ref1 = _mm256_set1_epi16(0);
    5443           0 :     sum_ref2 = _mm256_set1_epi16(0);
    5444           0 :     sum_ref3 = _mm256_set1_epi16(0);
    5445           0 :     for (i = 0; i < 16; i++) {
    5446             :         // load src and all refs
    5447           0 :         src_reg = _mm256_loadu_si256((const __m256i *)src);
    5448           0 :         ref0_reg = _mm256_loadu_si256((const __m256i *)ref0);
    5449           0 :         ref1_reg = _mm256_loadu_si256((const __m256i *)ref1);
    5450           0 :         ref2_reg = _mm256_loadu_si256((const __m256i *)ref2);
    5451           0 :         ref3_reg = _mm256_loadu_si256((const __m256i *)ref3);
    5452             :         // sum of the absolute differences between every ref-i to src
    5453           0 :         ref0_reg = _mm256_sad_epu8(ref0_reg, src_reg);
    5454           0 :         ref1_reg = _mm256_sad_epu8(ref1_reg, src_reg);
    5455           0 :         ref2_reg = _mm256_sad_epu8(ref2_reg, src_reg);
    5456           0 :         ref3_reg = _mm256_sad_epu8(ref3_reg, src_reg);
    5457             :         // sum every ref-i
    5458           0 :         sum_ref0 = _mm256_add_epi32(sum_ref0, ref0_reg);
    5459           0 :         sum_ref1 = _mm256_add_epi32(sum_ref1, ref1_reg);
    5460           0 :         sum_ref2 = _mm256_add_epi32(sum_ref2, ref2_reg);
    5461           0 :         sum_ref3 = _mm256_add_epi32(sum_ref3, ref3_reg);
    5462             : 
    5463           0 :         src += src_stride;
    5464           0 :         ref0 += ref_stride;
    5465           0 :         ref1 += ref_stride;
    5466           0 :         ref2 += ref_stride;
    5467           0 :         ref3 += ref_stride;
    5468             :     }
    5469             :     {
    5470             :         __m128i sum;
    5471             :         // in sum_ref-i the result is saved in the first 4 bytes
    5472             :         // the other 4 bytes are zeroed.
    5473             :         // sum_ref1 and sum_ref3 are shifted left by 4 bytes
    5474           0 :         sum_ref1 = _mm256_slli_si256(sum_ref1, 4);
    5475           0 :         sum_ref3 = _mm256_slli_si256(sum_ref3, 4);
    5476             : 
    5477             :         // merge sum_ref0 and sum_ref1 also sum_ref2 and sum_ref3
    5478           0 :         sum_ref0 = _mm256_or_si256(sum_ref0, sum_ref1);
    5479           0 :         sum_ref2 = _mm256_or_si256(sum_ref2, sum_ref3);
    5480             : 
    5481             :         // merge every 64 bit from each sum_ref-i
    5482           0 :         sum_mlow = _mm256_unpacklo_epi64(sum_ref0, sum_ref2);
    5483           0 :         sum_mhigh = _mm256_unpackhi_epi64(sum_ref0, sum_ref2);
    5484             : 
    5485             :         // add the low 64 bit to the high 64 bit
    5486           0 :         sum_mlow = _mm256_add_epi32(sum_mlow, sum_mhigh);
    5487             : 
    5488             :         // add the low 128 bit to the high 128 bit
    5489           0 :         sum = _mm_add_epi32(_mm256_castsi256_si128(sum_mlow),
    5490           0 :             _mm256_extractf128_si256(sum_mlow, 1));
    5491             : 
    5492             :         _mm_storeu_si128((__m128i *)(res), sum);
    5493             :     }
    5494             :     _mm256_zeroupper();
    5495           0 : }
    5496             : 
    5497           0 : static INLINE void sad32x32x4d_avx2(const uint8_t *src, int src_stride,
    5498             :     const uint8_t *const ref[4], int ref_stride,
    5499             :     uint32_t res[4]) {
    5500             :     __m256i src_reg, ref0_reg, ref1_reg, ref2_reg, ref3_reg;
    5501             :     __m256i sum_ref0, sum_ref1, sum_ref2, sum_ref3;
    5502             :     __m256i sum_mlow, sum_mhigh;
    5503             :     int i;
    5504             :     const uint8_t *ref0, *ref1, *ref2, *ref3;
    5505             : 
    5506           0 :     ref0 = ref[0];
    5507           0 :     ref1 = ref[1];
    5508           0 :     ref2 = ref[2];
    5509           0 :     ref3 = ref[3];
    5510           0 :     sum_ref0 = _mm256_set1_epi16(0);
    5511           0 :     sum_ref1 = _mm256_set1_epi16(0);
    5512           0 :     sum_ref2 = _mm256_set1_epi16(0);
    5513           0 :     sum_ref3 = _mm256_set1_epi16(0);
    5514           0 :     for (i = 0; i < 32; i++) {
    5515             :         // load src and all refs
    5516           0 :         src_reg = _mm256_loadu_si256((const __m256i *)src);
    5517           0 :         ref0_reg = _mm256_loadu_si256((const __m256i *)ref0);
    5518           0 :         ref1_reg = _mm256_loadu_si256((const __m256i *)ref1);
    5519           0 :         ref2_reg = _mm256_loadu_si256((const __m256i *)ref2);
    5520           0 :         ref3_reg = _mm256_loadu_si256((const __m256i *)ref3);
    5521             :         // sum of the absolute differences between every ref-i to src
    5522           0 :         ref0_reg = _mm256_sad_epu8(ref0_reg, src_reg);
    5523           0 :         ref1_reg = _mm256_sad_epu8(ref1_reg, src_reg);
    5524           0 :         ref2_reg = _mm256_sad_epu8(ref2_reg, src_reg);
    5525           0 :         ref3_reg = _mm256_sad_epu8(ref3_reg, src_reg);
    5526             :         // sum every ref-i
    5527           0 :         sum_ref0 = _mm256_add_epi32(sum_ref0, ref0_reg);
    5528           0 :         sum_ref1 = _mm256_add_epi32(sum_ref1, ref1_reg);
    5529           0 :         sum_ref2 = _mm256_add_epi32(sum_ref2, ref2_reg);
    5530           0 :         sum_ref3 = _mm256_add_epi32(sum_ref3, ref3_reg);
    5531             : 
    5532           0 :         src += src_stride;
    5533           0 :         ref0 += ref_stride;
    5534           0 :         ref1 += ref_stride;
    5535           0 :         ref2 += ref_stride;
    5536           0 :         ref3 += ref_stride;
    5537             :     }
    5538             :     {
    5539             :         __m128i sum;
    5540             :         // in sum_ref-i the result is saved in the first 4 bytes
    5541             :         // the other 4 bytes are zeroed.
    5542             :         // sum_ref1 and sum_ref3 are shifted left by 4 bytes
    5543           0 :         sum_ref1 = _mm256_slli_si256(sum_ref1, 4);
    5544           0 :         sum_ref3 = _mm256_slli_si256(sum_ref3, 4);
    5545             : 
    5546             :         // merge sum_ref0 and sum_ref1 also sum_ref2 and sum_ref3
    5547           0 :         sum_ref0 = _mm256_or_si256(sum_ref0, sum_ref1);
    5548           0 :         sum_ref2 = _mm256_or_si256(sum_ref2, sum_ref3);
    5549             : 
    5550             :         // merge every 64 bit from each sum_ref-i
    5551           0 :         sum_mlow = _mm256_unpacklo_epi64(sum_ref0, sum_ref2);
    5552           0 :         sum_mhigh = _mm256_unpackhi_epi64(sum_ref0, sum_ref2);
    5553             : 
    5554             :         // add the low 64 bit to the high 64 bit
    5555           0 :         sum_mlow = _mm256_add_epi32(sum_mlow, sum_mhigh);
    5556             : 
    5557             :         // add the low 128 bit to the high 128 bit
    5558           0 :         sum = _mm_add_epi32(_mm256_castsi256_si128(sum_mlow),
    5559           0 :             _mm256_extractf128_si256(sum_mlow, 1));
    5560             : 
    5561             :         _mm_storeu_si128((__m128i *)(res), sum);
    5562             :     }
    5563             :     _mm256_zeroupper();
    5564           0 : }
    5565             : 
    5566           0 : void eb_aom_sad32x32x4d_avx2(const uint8_t *src, int src_stride,
    5567             :     const uint8_t *const ref[4], int ref_stride,
    5568             :     uint32_t res[4]) {
    5569           0 :     sad32x32x4d_avx2(src, src_stride, ref, ref_stride, res);
    5570           0 : }
    5571             : 
    5572           0 : void eb_aom_sad64x16x4d_avx2(const uint8_t *src, int src_stride,
    5573             :     const uint8_t *const ref[4], int ref_stride,
    5574             :     uint32_t res[4]) {
    5575             :     __m256i src_reg, srcnext_reg, ref0_reg, ref0next_reg;
    5576             :     __m256i ref1_reg, ref1next_reg, ref2_reg, ref2next_reg;
    5577             :     __m256i ref3_reg, ref3next_reg;
    5578             :     __m256i sum_ref0, sum_ref1, sum_ref2, sum_ref3;
    5579             :     __m256i sum_mlow, sum_mhigh;
    5580             :     int i;
    5581             :     const uint8_t *ref0, *ref1, *ref2, *ref3;
    5582             : 
    5583           0 :     ref0 = ref[0];
    5584           0 :     ref1 = ref[1];
    5585           0 :     ref2 = ref[2];
    5586           0 :     ref3 = ref[3];
    5587           0 :     sum_ref0 = _mm256_set1_epi16(0);
    5588           0 :     sum_ref1 = _mm256_set1_epi16(0);
    5589           0 :     sum_ref2 = _mm256_set1_epi16(0);
    5590           0 :     sum_ref3 = _mm256_set1_epi16(0);
    5591           0 :     for (i = 0; i < 16; i++) {
    5592             :         // load 64 bytes from src and all refs
    5593           0 :         src_reg = _mm256_loadu_si256((const __m256i *)src);
    5594           0 :         srcnext_reg = _mm256_loadu_si256((const __m256i *)(src + 32));
    5595           0 :         ref0_reg = _mm256_loadu_si256((const __m256i *)ref0);
    5596           0 :         ref0next_reg = _mm256_loadu_si256((const __m256i *)(ref0 + 32));
    5597           0 :         ref1_reg = _mm256_loadu_si256((const __m256i *)ref1);
    5598           0 :         ref1next_reg = _mm256_loadu_si256((const __m256i *)(ref1 + 32));
    5599           0 :         ref2_reg = _mm256_loadu_si256((const __m256i *)ref2);
    5600           0 :         ref2next_reg = _mm256_loadu_si256((const __m256i *)(ref2 + 32));
    5601           0 :         ref3_reg = _mm256_loadu_si256((const __m256i *)ref3);
    5602           0 :         ref3next_reg = _mm256_loadu_si256((const __m256i *)(ref3 + 32));
    5603             :         // sum of the absolute differences between every ref-i to src
    5604           0 :         ref0_reg = _mm256_sad_epu8(ref0_reg, src_reg);
    5605           0 :         ref1_reg = _mm256_sad_epu8(ref1_reg, src_reg);
    5606           0 :         ref2_reg = _mm256_sad_epu8(ref2_reg, src_reg);
    5607           0 :         ref3_reg = _mm256_sad_epu8(ref3_reg, src_reg);
    5608           0 :         ref0next_reg = _mm256_sad_epu8(ref0next_reg, srcnext_reg);
    5609           0 :         ref1next_reg = _mm256_sad_epu8(ref1next_reg, srcnext_reg);
    5610           0 :         ref2next_reg = _mm256_sad_epu8(ref2next_reg, srcnext_reg);
    5611           0 :         ref3next_reg = _mm256_sad_epu8(ref3next_reg, srcnext_reg);
    5612             : 
    5613             :         // sum every ref-i
    5614           0 :         sum_ref0 = _mm256_add_epi32(sum_ref0, ref0_reg);
    5615           0 :         sum_ref1 = _mm256_add_epi32(sum_ref1, ref1_reg);
    5616           0 :         sum_ref2 = _mm256_add_epi32(sum_ref2, ref2_reg);
    5617           0 :         sum_ref3 = _mm256_add_epi32(sum_ref3, ref3_reg);
    5618           0 :         sum_ref0 = _mm256_add_epi32(sum_ref0, ref0next_reg);
    5619           0 :         sum_ref1 = _mm256_add_epi32(sum_ref1, ref1next_reg);
    5620           0 :         sum_ref2 = _mm256_add_epi32(sum_ref2, ref2next_reg);
    5621           0 :         sum_ref3 = _mm256_add_epi32(sum_ref3, ref3next_reg);
    5622           0 :         src += src_stride;
    5623           0 :         ref0 += ref_stride;
    5624           0 :         ref1 += ref_stride;
    5625           0 :         ref2 += ref_stride;
    5626           0 :         ref3 += ref_stride;
    5627             :     }
    5628             :     {
    5629             :         __m128i sum;
    5630             : 
    5631             :         // in sum_ref-i the result is saved in the first 4 bytes
    5632             :         // the other 4 bytes are zeroed.
    5633             :         // sum_ref1 and sum_ref3 are shifted left by 4 bytes
    5634           0 :         sum_ref1 = _mm256_slli_si256(sum_ref1, 4);
    5635           0 :         sum_ref3 = _mm256_slli_si256(sum_ref3, 4);
    5636             : 
    5637             :         // merge sum_ref0 and sum_ref1 also sum_ref2 and sum_ref3
    5638           0 :         sum_ref0 = _mm256_or_si256(sum_ref0, sum_ref1);
    5639           0 :         sum_ref2 = _mm256_or_si256(sum_ref2, sum_ref3);
    5640             : 
    5641             :         // merge every 64 bit from each sum_ref-i
    5642           0 :         sum_mlow = _mm256_unpacklo_epi64(sum_ref0, sum_ref2);
    5643           0 :         sum_mhigh = _mm256_unpackhi_epi64(sum_ref0, sum_ref2);
    5644             : 
    5645             :         // add the low 64 bit to the high 64 bit
    5646           0 :         sum_mlow = _mm256_add_epi32(sum_mlow, sum_mhigh);
    5647             : 
    5648             :         // add the low 128 bit to the high 128 bit
    5649           0 :         sum = _mm_add_epi32(_mm256_castsi256_si128(sum_mlow),
    5650           0 :             _mm256_extractf128_si256(sum_mlow, 1));
    5651             : 
    5652             :         _mm_storeu_si128((__m128i *)(res), sum);
    5653             :     }
    5654             :     _mm256_zeroupper();
    5655           0 : }
    5656             : 
    5657             : SIMD_INLINE void sad64x64x4d_avx2(const uint8_t *src, int src_stride,
    5658             :     const uint8_t *const ref[4], int ref_stride,
    5659             :     uint32_t res[4]) {
    5660             :     __m256i src_reg, srcnext_reg, ref0_reg, ref0next_reg;
    5661             :     __m256i ref1_reg, ref1next_reg, ref2_reg, ref2next_reg;
    5662             :     __m256i ref3_reg, ref3next_reg;
    5663             :     __m256i sum_ref0, sum_ref1, sum_ref2, sum_ref3;
    5664             :     __m256i sum_mlow, sum_mhigh;
    5665             :     int i;
    5666             :     const uint8_t *ref0, *ref1, *ref2, *ref3;
    5667             : 
    5668           0 :     ref0 = ref[0];
    5669           0 :     ref1 = ref[1];
    5670           0 :     ref2 = ref[2];
    5671           0 :     ref3 = ref[3];
    5672           0 :     sum_ref0 = _mm256_set1_epi16(0);
    5673           0 :     sum_ref1 = _mm256_set1_epi16(0);
    5674           0 :     sum_ref2 = _mm256_set1_epi16(0);
    5675           0 :     sum_ref3 = _mm256_set1_epi16(0);
    5676           0 :     for (i = 0; i < 64; i++) {
    5677             :         // load 64 bytes from src and all refs
    5678           0 :         src_reg = _mm256_loadu_si256((const __m256i *)src);
    5679           0 :         srcnext_reg = _mm256_loadu_si256((const __m256i *)(src + 32));
    5680           0 :         ref0_reg = _mm256_loadu_si256((const __m256i *)ref0);
    5681           0 :         ref0next_reg = _mm256_loadu_si256((const __m256i *)(ref0 + 32));
    5682           0 :         ref1_reg = _mm256_loadu_si256((const __m256i *)ref1);
    5683           0 :         ref1next_reg = _mm256_loadu_si256((const __m256i *)(ref1 + 32));
    5684           0 :         ref2_reg = _mm256_loadu_si256((const __m256i *)ref2);
    5685           0 :         ref2next_reg = _mm256_loadu_si256((const __m256i *)(ref2 + 32));
    5686           0 :         ref3_reg = _mm256_loadu_si256((const __m256i *)ref3);
    5687           0 :         ref3next_reg = _mm256_loadu_si256((const __m256i *)(ref3 + 32));
    5688             :         // sum of the absolute differences between every ref-i to src
    5689           0 :         ref0_reg = _mm256_sad_epu8(ref0_reg, src_reg);
    5690           0 :         ref1_reg = _mm256_sad_epu8(ref1_reg, src_reg);
    5691           0 :         ref2_reg = _mm256_sad_epu8(ref2_reg, src_reg);
    5692           0 :         ref3_reg = _mm256_sad_epu8(ref3_reg, src_reg);
    5693           0 :         ref0next_reg = _mm256_sad_epu8(ref0next_reg, srcnext_reg);
    5694           0 :         ref1next_reg = _mm256_sad_epu8(ref1next_reg, srcnext_reg);
    5695           0 :         ref2next_reg = _mm256_sad_epu8(ref2next_reg, srcnext_reg);
    5696           0 :         ref3next_reg = _mm256_sad_epu8(ref3next_reg, srcnext_reg);
    5697             : 
    5698             :         // sum every ref-i
    5699           0 :         sum_ref0 = _mm256_add_epi32(sum_ref0, ref0_reg);
    5700           0 :         sum_ref1 = _mm256_add_epi32(sum_ref1, ref1_reg);
    5701           0 :         sum_ref2 = _mm256_add_epi32(sum_ref2, ref2_reg);
    5702           0 :         sum_ref3 = _mm256_add_epi32(sum_ref3, ref3_reg);
    5703           0 :         sum_ref0 = _mm256_add_epi32(sum_ref0, ref0next_reg);
    5704           0 :         sum_ref1 = _mm256_add_epi32(sum_ref1, ref1next_reg);
    5705           0 :         sum_ref2 = _mm256_add_epi32(sum_ref2, ref2next_reg);
    5706           0 :         sum_ref3 = _mm256_add_epi32(sum_ref3, ref3next_reg);
    5707           0 :         src += src_stride;
    5708           0 :         ref0 += ref_stride;
    5709           0 :         ref1 += ref_stride;
    5710           0 :         ref2 += ref_stride;
    5711           0 :         ref3 += ref_stride;
    5712             :     }
    5713             :     {
    5714             :         __m128i sum;
    5715             : 
    5716             :         // in sum_ref-i the result is saved in the first 4 bytes
    5717             :         // the other 4 bytes are zeroed.
    5718             :         // sum_ref1 and sum_ref3 are shifted left by 4 bytes
    5719           0 :         sum_ref1 = _mm256_slli_si256(sum_ref1, 4);
    5720           0 :         sum_ref3 = _mm256_slli_si256(sum_ref3, 4);
    5721             : 
    5722             :         // merge sum_ref0 and sum_ref1 also sum_ref2 and sum_ref3
    5723           0 :         sum_ref0 = _mm256_or_si256(sum_ref0, sum_ref1);
    5724           0 :         sum_ref2 = _mm256_or_si256(sum_ref2, sum_ref3);
    5725             : 
    5726             :         // merge every 64 bit from each sum_ref-i
    5727           0 :         sum_mlow = _mm256_unpacklo_epi64(sum_ref0, sum_ref2);
    5728           0 :         sum_mhigh = _mm256_unpackhi_epi64(sum_ref0, sum_ref2);
    5729             : 
    5730             :         // add the low 64 bit to the high 64 bit
    5731           0 :         sum_mlow = _mm256_add_epi32(sum_mlow, sum_mhigh);
    5732             : 
    5733             :         // add the low 128 bit to the high 128 bit
    5734           0 :         sum = _mm_add_epi32(_mm256_castsi256_si128(sum_mlow),
    5735           0 :             _mm256_extractf128_si256(sum_mlow, 1));
    5736             : 
    5737             :         _mm_storeu_si128((__m128i *)(res), sum);
    5738             :     }
    5739             :     _mm256_zeroupper();
    5740           0 : }
    5741             : 
    5742           0 : void eb_aom_sad64x64x4d_avx2(const uint8_t *src, int src_stride,
    5743             :     const uint8_t *const ref[4], int ref_stride,
    5744             :     uint32_t res[4]) {
    5745             :     sad64x64x4d_avx2(src, src_stride, ref, ref_stride, res);
    5746           0 : }
    5747             : 
    5748           0 : void eb_aom_sad32x64x4d_avx2(const uint8_t *src, int src_stride,
    5749             :     const uint8_t *const ref[4], int ref_stride,
    5750             :     uint32_t res[4]) {
    5751             :     const uint8_t *rf[4];
    5752             :     uint32_t sum0[4];
    5753             :     uint32_t sum1[4];
    5754             : 
    5755           0 :     rf[0] = ref[0];
    5756           0 :     rf[1] = ref[1];
    5757           0 :     rf[2] = ref[2];
    5758           0 :     rf[3] = ref[3];
    5759           0 :     sad32x32x4d_avx2(src, src_stride, rf, ref_stride, sum0);
    5760           0 :     src += src_stride << 5;
    5761           0 :     rf[0] += ref_stride << 5;
    5762           0 :     rf[1] += ref_stride << 5;
    5763           0 :     rf[2] += ref_stride << 5;
    5764           0 :     rf[3] += ref_stride << 5;
    5765           0 :     sad32x32x4d_avx2(src, src_stride, rf, ref_stride, sum1);
    5766           0 :     res[0] = sum0[0] + sum1[0];
    5767           0 :     res[1] = sum0[1] + sum1[1];
    5768           0 :     res[2] = sum0[2] + sum1[2];
    5769           0 :     res[3] = sum0[3] + sum1[3];
    5770           0 : }
    5771             : 
    5772           0 : void eb_aom_sad64x32x4d_avx2(const uint8_t *src, int src_stride,
    5773             :     const uint8_t *const ref[4], int ref_stride,
    5774             :     uint32_t res[4]) {
    5775             :     const uint8_t *rf[4];
    5776             :     uint32_t sum0[4];
    5777             :     uint32_t sum1[4];
    5778           0 :     unsigned int half_width = 32;
    5779             : 
    5780           0 :     rf[0] = ref[0];
    5781           0 :     rf[1] = ref[1];
    5782           0 :     rf[2] = ref[2];
    5783           0 :     rf[3] = ref[3];
    5784           0 :     sad32x32x4d_avx2(src, src_stride, rf, ref_stride, sum0);
    5785           0 :     src += half_width;
    5786           0 :     rf[0] += half_width;
    5787           0 :     rf[1] += half_width;
    5788           0 :     rf[2] += half_width;
    5789           0 :     rf[3] += half_width;
    5790           0 :     sad32x32x4d_avx2(src, src_stride, rf, ref_stride, sum1);
    5791           0 :     res[0] = sum0[0] + sum1[0];
    5792           0 :     res[1] = sum0[1] + sum1[1];
    5793           0 :     res[2] = sum0[2] + sum1[2];
    5794           0 :     res[3] = sum0[3] + sum1[3];
    5795           0 : }
    5796             : 
    5797           0 : static INLINE unsigned int sad32x32(const uint8_t *src_ptr, int src_stride,
    5798             :     const uint8_t *ref_ptr, int ref_stride) {
    5799             :     __m256i s1, s2, r1, r2;
    5800           0 :     __m256i sum = _mm256_setzero_si256();
    5801             :     __m128i sum_i128;
    5802             :     int i;
    5803             : 
    5804           0 :     for (i = 0; i < 16; ++i) {
    5805           0 :         r1 = _mm256_loadu_si256((__m256i const *)ref_ptr);
    5806           0 :         r2 = _mm256_loadu_si256((__m256i const *)(ref_ptr + ref_stride));
    5807           0 :         s1 = _mm256_sad_epu8(r1, _mm256_loadu_si256((__m256i const *)src_ptr));
    5808           0 :         s2 = _mm256_sad_epu8(
    5809           0 :             r2, _mm256_loadu_si256((__m256i const *)(src_ptr + src_stride)));
    5810           0 :         sum = _mm256_add_epi32(sum, _mm256_add_epi32(s1, s2));
    5811           0 :         ref_ptr += ref_stride << 1;
    5812           0 :         src_ptr += src_stride << 1;
    5813             :     }
    5814             : 
    5815           0 :     sum = _mm256_add_epi32(sum, _mm256_srli_si256(sum, 8));
    5816           0 :     sum_i128 = _mm_add_epi32(_mm256_extracti128_si256(sum, 1),
    5817             :         _mm256_castsi256_si128(sum));
    5818           0 :     return _mm_cvtsi128_si32(sum_i128);
    5819             : }
    5820             : 
    5821             : SIMD_INLINE unsigned int sad64x32(const uint8_t *src_ptr, int src_stride,
    5822             :     const uint8_t *ref_ptr, int ref_stride) {
    5823           0 :     unsigned int half_width = 32;
    5824           0 :     uint32_t sum = sad32x32(src_ptr, src_stride, ref_ptr, ref_stride);
    5825           0 :     src_ptr += half_width;
    5826           0 :     ref_ptr += half_width;
    5827           0 :     sum += sad32x32(src_ptr, src_stride, ref_ptr, ref_stride);
    5828           0 :     return sum;
    5829             : }
    5830             : 
    5831             : SIMD_INLINE unsigned int sad64x64(const uint8_t *src_ptr, int src_stride,
    5832             :     const uint8_t *ref_ptr, int ref_stride) {
    5833           0 :     uint32_t sum = sad64x32(src_ptr, src_stride, ref_ptr, ref_stride);
    5834           0 :     src_ptr += src_stride << 5;
    5835           0 :     ref_ptr += ref_stride << 5;
    5836           0 :     sum += sad64x32(src_ptr, src_stride, ref_ptr, ref_stride);
    5837           0 :     return sum;
    5838             : }
    5839             : 
    5840           0 : unsigned int eb_aom_sad64x128_avx2(const uint8_t *src_ptr, int src_stride,
    5841             :     const uint8_t *ref_ptr, int ref_stride) {
    5842           0 :     uint32_t sum = sad64x64(src_ptr, src_stride, ref_ptr, ref_stride);
    5843           0 :     src_ptr += src_stride << 6;
    5844           0 :     ref_ptr += ref_stride << 6;
    5845           0 :     sum += sad64x64(src_ptr, src_stride, ref_ptr, ref_stride);
    5846           0 :     return sum;
    5847             : }
    5848             : 
    5849             : SIMD_INLINE void sad64x64x4d(const uint8_t *src, int src_stride,
    5850             :     const uint8_t *const ref[4], int ref_stride,
    5851             :     __m128i *res) {
    5852             :     uint32_t sum[4];
    5853             :     sad64x64x4d_avx2(src, src_stride, ref, ref_stride, sum);
    5854           0 :     *res = _mm_loadu_si128((const __m128i *)sum);
    5855           0 : }
    5856             : 
    5857           0 : void eb_aom_sad64x128x4d_avx2(const uint8_t *src, int src_stride,
    5858             :     const uint8_t *const ref[4], int ref_stride,
    5859             :     uint32_t res[4]) {
    5860             :     __m128i sum0, sum1;
    5861             :     const uint8_t *rf[4];
    5862             : 
    5863           0 :     rf[0] = ref[0];
    5864           0 :     rf[1] = ref[1];
    5865           0 :     rf[2] = ref[2];
    5866           0 :     rf[3] = ref[3];
    5867             :     sad64x64x4d(src, src_stride, rf, ref_stride, &sum0);
    5868           0 :     src += src_stride << 6;
    5869           0 :     rf[0] += ref_stride << 6;
    5870           0 :     rf[1] += ref_stride << 6;
    5871           0 :     rf[2] += ref_stride << 6;
    5872           0 :     rf[3] += ref_stride << 6;
    5873             :     sad64x64x4d(src, src_stride, rf, ref_stride, &sum1);
    5874           0 :     sum0 = _mm_add_epi32(sum0, sum1);
    5875           0 :     _mm_storeu_si128((__m128i *)res, sum0);
    5876           0 : }
    5877             : 
    5878             : SIMD_INLINE void sad128x64x4d_avx2(const uint8_t *src, int src_stride,
    5879             :     const uint8_t *const ref[4], int ref_stride,
    5880             :     uint32_t res[4]) {
    5881             :     __m128i sum0, sum1;
    5882           0 :     unsigned int half_width = 64;
    5883             :     const uint8_t *rf[4];
    5884             : 
    5885           0 :     rf[0] = ref[0];
    5886           0 :     rf[1] = ref[1];
    5887           0 :     rf[2] = ref[2];
    5888           0 :     rf[3] = ref[3];
    5889             :     sad64x64x4d(src, src_stride, rf, ref_stride, &sum0);
    5890           0 :     src += half_width;
    5891           0 :     rf[0] += half_width;
    5892           0 :     rf[1] += half_width;
    5893           0 :     rf[2] += half_width;
    5894           0 :     rf[3] += half_width;
    5895             :     sad64x64x4d(src, src_stride, rf, ref_stride, &sum1);
    5896           0 :     sum0 = _mm_add_epi32(sum0, sum1);
    5897           0 :     _mm_storeu_si128((__m128i *)res, sum0);
    5898           0 : }
    5899             : 
    5900           0 : void eb_aom_sad128x64x4d_avx2(const uint8_t *src, int src_stride,
    5901             :     const uint8_t *const ref[4], int ref_stride,
    5902             :     uint32_t res[4]) {
    5903             :     sad128x64x4d_avx2(src, src_stride, ref, ref_stride, res);
    5904           0 : }
    5905             : 
    5906           0 : void eb_aom_sad128x128x4d_avx2(const uint8_t *src, int src_stride,
    5907             :     const uint8_t *const ref[4], int ref_stride,
    5908             :     uint32_t res[4]) {
    5909             :     const uint8_t *rf[4];
    5910             :     uint32_t sum0[4];
    5911             :     uint32_t sum1[4];
    5912             : 
    5913           0 :     rf[0] = ref[0];
    5914           0 :     rf[1] = ref[1];
    5915           0 :     rf[2] = ref[2];
    5916           0 :     rf[3] = ref[3];
    5917             :     sad128x64x4d_avx2(src, src_stride, rf, ref_stride, sum0);
    5918           0 :     src += src_stride << 6;
    5919           0 :     rf[0] += ref_stride << 6;
    5920           0 :     rf[1] += ref_stride << 6;
    5921           0 :     rf[2] += ref_stride << 6;
    5922           0 :     rf[3] += ref_stride << 6;
    5923             :     sad128x64x4d_avx2(src, src_stride, rf, ref_stride, sum1);
    5924           0 :     res[0] = sum0[0] + sum1[0];
    5925           0 :     res[1] = sum0[1] + sum1[1];
    5926           0 :     res[2] = sum0[2] + sum1[2];
    5927           0 :     res[3] = sum0[3] + sum1[3];
    5928           0 : }
    5929             : 
    5930    34282600 : void ext_all_sad_calculation_8x8_16x16_avx2(
    5931             :     uint8_t   *src,
    5932             :     uint32_t   src_stride,
    5933             :     uint8_t   *ref,
    5934             :     uint32_t   ref_stride,
    5935             :     uint32_t   mv,
    5936             :     uint32_t  *p_best_sad8x8,
    5937             :     uint32_t  *p_best_sad16x16,
    5938             :     uint32_t  *p_best_mv8x8,
    5939             :     uint32_t  *p_best_mv16x16,
    5940             :     uint32_t   p_eight_sad16x16[16][8],
    5941             :     uint32_t   p_eight_sad8x8[64][8])
    5942             : {
    5943             :     static const char offsets[16] = {
    5944             :         0, 1, 4, 5, 2, 3, 6, 7, 8, 9, 12, 13, 10, 11, 14, 15
    5945             :     };
    5946             : 
    5947             :     //---- 16x16 : 0, 1, 4, 5, 2, 3, 6, 7, 8, 9, 12, 13, 10, 11, 14, 15
    5948   171158000 :     for (int y = 0; y < 4; y++) {
    5949   681580000 :         for (int x = 0; x < 4; x++) {
    5950   544705000 :             const uint32_t start_16x16_pos = offsets[4 * y + x];
    5951   544705000 :             const uint32_t start_8x8_pos = 4 * start_16x16_pos;
    5952   544705000 :             const uint8_t *s = src + 16 * y * src_stride + 16 * x;
    5953   544705000 :             const uint8_t *r = ref + 16 * y * ref_stride + 16 * x;
    5954   544705000 :             __m256i sad02 = _mm256_setzero_si256();
    5955   544705000 :             __m256i sad13 = _mm256_setzero_si256();
    5956             : 
    5957  2689560000 :             for (int i = 0; i < 4; i++)
    5958             :             {
    5959  2144860000 :                 const __m128i src01 = _mm_loadu_si128((__m128i *)(s + 0 * src_stride));
    5960  4289720000 :                 const __m128i src23 = _mm_loadu_si128((__m128i *)(s + 8 * src_stride));
    5961  2144860000 :                 const __m128i ref0 = _mm_loadu_si128((__m128i *)(r + 0 * ref_stride + 0));
    5962  2144860000 :                 const __m128i ref1 = _mm_loadu_si128((__m128i *)(r + 0 * ref_stride + 8));
    5963  2144860000 :                 const __m128i ref2 = _mm_loadu_si128((__m128i *)(r + 8 * ref_stride + 0));
    5964  2144860000 :                 const __m128i ref3 = _mm_loadu_si128((__m128i *)(r + 8 * ref_stride + 8));
    5965  2144860000 :                 const __m256i src0123 = _mm256_insertf128_si256(_mm256_castsi128_si256(src01), src23, 1);
    5966  2144860000 :                 const __m256i ref02 = _mm256_insertf128_si256(_mm256_castsi128_si256(ref0), ref2, 1);
    5967  2144860000 :                 const __m256i ref13 = _mm256_insertf128_si256(_mm256_castsi128_si256(ref1), ref3, 1);
    5968  2144860000 :                 sad02 = _mm256_adds_epu16(sad02, _mm256_mpsadbw_epu8(ref02, src0123, 0));  // 000 000
    5969  2144860000 :                 sad02 = _mm256_adds_epu16(sad02, _mm256_mpsadbw_epu8(ref02, src0123, 45)); // 101 101
    5970  2144860000 :                 sad13 = _mm256_adds_epu16(sad13, _mm256_mpsadbw_epu8(ref13, src0123, 18)); // 010 010
    5971  2144860000 :                 sad13 = _mm256_adds_epu16(sad13, _mm256_mpsadbw_epu8(ref13, src0123, 63)); // 111 111
    5972  2144860000 :                 s += 2 * src_stride;
    5973  2144860000 :                 r += 2 * ref_stride;
    5974             :             }
    5975             : 
    5976   544705000 :             sad02 = _mm256_slli_epi16(sad02, 1);
    5977   544705000 :             sad13 = _mm256_slli_epi16(sad13, 1);
    5978             : 
    5979   544705000 :             const __m256i sad0202 = _mm256_permute4x64_epi64(sad02, 0xD8);
    5980   544705000 :             const __m256i sad1313 = _mm256_permute4x64_epi64(sad13, 0xD8);
    5981  1089410000 :             const __m256i sad00 = _mm256_unpacklo_epi16(sad0202, _mm256_setzero_si256());
    5982  1089410000 :             const __m256i sad11 = _mm256_unpacklo_epi16(sad1313, _mm256_setzero_si256());
    5983  1089410000 :             const __m256i sad22 = _mm256_unpackhi_epi16(sad0202, _mm256_setzero_si256());
    5984   544705000 :             const __m256i sad33 = _mm256_unpackhi_epi16(sad1313, _mm256_setzero_si256());
    5985             : 
    5986   544705000 :             _mm256_storeu_si256((__m256i*)(p_eight_sad8x8[0 + start_8x8_pos]), sad00);
    5987   544705000 :             _mm256_storeu_si256((__m256i*)(p_eight_sad8x8[1 + start_8x8_pos]), sad11);
    5988   544705000 :             _mm256_storeu_si256((__m256i*)(p_eight_sad8x8[2 + start_8x8_pos]), sad22);
    5989   544705000 :             _mm256_storeu_si256((__m256i*)(p_eight_sad8x8[3 + start_8x8_pos]), sad33);
    5990             : 
    5991   544705000 :             const __m128i sad0 = _mm256_castsi256_si128(sad02);
    5992   544705000 :             const __m128i sad1 = _mm256_castsi256_si128(sad13);
    5993   544705000 :             const __m128i sad2 = _mm256_extracti128_si256(sad02, 1);
    5994   544705000 :             const __m128i sad3 = _mm256_extracti128_si256(sad13, 1);
    5995             : 
    5996   544705000 :             const __m128i minpos0 = _mm_minpos_epu16(sad0);
    5997   544705000 :             const __m128i minpos1 = _mm_minpos_epu16(sad1);
    5998   544705000 :             const __m128i minpos2 = _mm_minpos_epu16(sad2);
    5999   544705000 :             const __m128i minpos3 = _mm_minpos_epu16(sad3);
    6000             : 
    6001   544705000 :             const __m128i minpos01 = _mm_unpacklo_epi16(minpos0, minpos1);
    6002   544705000 :             const __m128i minpos23 = _mm_unpacklo_epi16(minpos2, minpos3);
    6003   544705000 :             const __m128i minpos0123 = _mm_unpacklo_epi32(minpos01, minpos23);
    6004  1089410000 :             const __m128i sad8x8 = _mm_unpacklo_epi16(minpos0123, _mm_setzero_si128());
    6005  1089410000 :             const __m128i pos0123 = _mm_unpackhi_epi16(minpos0123, _mm_setzero_si128());
    6006   544705000 :             const __m128i pos8x8 = _mm_slli_epi32(pos0123, 2);
    6007             : 
    6008  1089410000 :             __m128i best_sad8x8 = _mm_loadu_si128((__m128i *)(p_best_sad8x8 + start_8x8_pos));
    6009   544705000 :             const __m128i mask = _mm_cmplt_epi32(sad8x8, best_sad8x8);
    6010   544705000 :             best_sad8x8 = _mm_min_epi32(best_sad8x8, sad8x8);
    6011   544705000 :             _mm_storeu_si128((__m128i *)(p_best_sad8x8 + start_8x8_pos), best_sad8x8);
    6012             : 
    6013   544705000 :             __m128i best_mv8x8 = _mm_loadu_si128((__m128i *)(p_best_mv8x8 + start_8x8_pos));
    6014  1089410000 :             const __m128i mvs = _mm_set1_epi32(mv);
    6015   544705000 :             const __m128i mv8x8 = _mm_add_epi16(mvs, pos8x8);
    6016   544705000 :             best_mv8x8 = _mm_blendv_epi8(best_mv8x8, mv8x8, mask);
    6017   544705000 :             _mm_storeu_si128((__m128i *)(p_best_mv8x8 + start_8x8_pos), best_mv8x8);
    6018             : 
    6019   544705000 :             const __m128i sum01 = _mm_add_epi16(sad0, sad1);
    6020   544705000 :             const __m128i sum23 = _mm_add_epi16(sad2, sad3);
    6021   544705000 :             const __m128i sad16x16_16 = _mm_add_epi16(sum01, sum23);
    6022   544705000 :             const __m256i sad16x16_32 = _mm256_cvtepu16_epi32(sad16x16_16);
    6023   544705000 :             _mm256_storeu_si256((__m256i*)(p_eight_sad16x16[start_16x16_pos]), sad16x16_32);
    6024             : 
    6025   544705000 :             const __m128i minpos16x16 = _mm_minpos_epu16(sad16x16_16);
    6026   544705000 :             const uint32_t min16x16 = _mm_extract_epi16(minpos16x16, 0);
    6027             : 
    6028   544705000 :             if (min16x16 < p_best_sad16x16[start_16x16_pos]) {
    6029     4025300 :                 p_best_sad16x16[start_16x16_pos] = min16x16;
    6030             : 
    6031     4025300 :                 const __m128i pos = _mm_srli_si128(minpos16x16, 2);
    6032     4025300 :                 const __m128i pos16x16 = _mm_slli_epi32(pos, 2);
    6033     4025300 :                 const __m128i mv16x16 = _mm_add_epi16(mvs, pos16x16);
    6034     4025300 :                 p_best_mv16x16[start_16x16_pos] = _mm_extract_epi32(mv16x16, 0);
    6035             :             }
    6036             :         }
    6037             :     }
    6038    34282600 : }
    6039             : 
    6040             : #define avx2_find_min_pos_init() \
    6041             :     const __m256i idx_min_pos_prv = _mm256_setr_epi32(0, 1, 2, 3, 4, 5, 6, 7)
    6042             : 
    6043             : /* Horizontally search the minimum value in vector.
    6044             :    Store the minimum index in best_id.
    6045             :    To fast calculations, reduce available max value to 27 bits.
    6046             :    First call avx2_find_min_pos_init in function
    6047             :    */
    6048             : #define avx2_find_min_pos(in, best_id) {                                      \
    6049             :     __m256i x = _mm256_slli_epi32(in, 3);                 /* x = x<<3 | idx */\
    6050             :     x = _mm256_add_epi32(x, idx_min_pos_prv);             /*x = [12345678]*/  \
    6051             :     const __m256i y = _mm256_permute2f128_si256(x, x, 1); /*y = [56781234]*/  \
    6052             :     const __m256i m1 = _mm256_min_epu32(x, y);            /*m1 = [12341234]*/ \
    6053             :     const __m256i m2 = _mm256_permute4x64_epi64(m1, 5);   /*m2 = [34123412]*/ \
    6054             :     const __m256i m3 = _mm256_min_epu32(m1, m2);          /*m3 = [12121212]*/ \
    6055             :     const __m256i m4 = _mm256_shuffle_epi32(m3, 5);       /*m4 = [21212121]*/ \
    6056             :     const __m256i m = _mm256_min_epu32(m3, m4);           /*m5 = [11111111]*/ \
    6057             :     /* (x<<3 | idx) & (0b000111) = idx */  \
    6058             :     best_id = _mm256_extract_epi16(m, 0) & 0x07; }
    6059             : 
    6060    34284600 : void ext_eigth_sad_calculation_nsq_avx2(
    6061             :     uint32_t   p_sad8x8[64][8],
    6062             :     uint32_t   p_sad16x16[16][8],
    6063             :     uint32_t   p_sad32x32[4][8],
    6064             :     uint32_t  *p_best_sad64x32,
    6065             :     uint32_t  *p_best_mv64x32,
    6066             :     uint32_t  *p_best_sad32x16,
    6067             :     uint32_t  *p_best_mv32x16,
    6068             :     uint32_t  *p_best_sad16x8,
    6069             :     uint32_t  *p_best_mv16x8,
    6070             :     uint32_t  *p_best_sad32x64,
    6071             :     uint32_t  *p_best_mv32x64,
    6072             :     uint32_t  *p_best_sad16x32,
    6073             :     uint32_t  *p_best_mv16x32,
    6074             :     uint32_t  *p_best_sad8x16,
    6075             :     uint32_t  *p_best_mv8x16,
    6076             :     uint32_t  *p_best_sad32x8,
    6077             :     uint32_t  *p_best_mv32x8,
    6078             :     uint32_t  *p_best_sad8x32,
    6079             :     uint32_t  *p_best_mv8x32,
    6080             :     uint32_t  *p_best_sad64x16,
    6081             :     uint32_t  *p_best_mv64x16,
    6082             :     uint32_t  *p_best_sad16x64,
    6083             :     uint32_t  *p_best_mv16x64,
    6084             :     uint32_t   mv) {
    6085    34284600 :     avx2_find_min_pos_init();
    6086             :     uint8_t search_index;
    6087             :     DECLARE_ALIGNED(32, uint32_t, sad[8]);
    6088             :     DECLARE_ALIGNED(32, uint32_t, sad_16x8[32][8]);
    6089             :     DECLARE_ALIGNED(32, uint32_t, sad_8x16[32][8]);
    6090             :     DECLARE_ALIGNED(32, uint32_t, sad_32x16[8][8]);
    6091             :     DECLARE_ALIGNED(32, uint32_t, sad_16x32[8][8]);
    6092             :     DECLARE_ALIGNED(32, uint32_t, computed_idx[8]);
    6093             : 
    6094    34284600 :     __m256i search_idx_avx2 = _mm256_setr_epi32(0, 4, 8, 12, 16, 20, 24, 28);
    6095    68569300 :     __m256i mv_avx2 = _mm256_set1_epi32(mv);
    6096    34284600 :     __m256i new_mv_avx2 = _mm256_add_epi32(search_idx_avx2, mv_avx2);
    6097    68569300 :     new_mv_avx2 = _mm256_and_si256(new_mv_avx2, _mm256_set1_epi32(0xffff));
    6098    68569300 :     *(__m256i *)computed_idx = _mm256_or_si256(new_mv_avx2,
    6099             :         _mm256_and_si256(mv_avx2, _mm256_set1_epi32(0xffff0000)));
    6100             : 
    6101             : #define ADD_VECS(dst, a, b)                           \
    6102             :     *(__m256i *) dst = _mm256_add_epi32(              \
    6103             :         _mm256_loadu_si256((__m256i const *) a),      \
    6104             :         _mm256_loadu_si256((__m256i const *) b));
    6105             : 
    6106             : #define SEARCH_BEST(serch, best, best_mv)              \
    6107             :     avx2_find_min_pos(*(__m256i*)serch, search_index); \
    6108             :     if (serch[search_index] < best) {                  \
    6109             :         best = serch[search_index];                    \
    6110             :         best_mv = computed_idx[search_index];          \
    6111             :     }
    6112             : 
    6113             : #define SEARCH_CALC_BEST(a, b, best, best_mv)          \
    6114             :     ADD_VECS(sad, a, b);\
    6115             :     SEARCH_BEST(sad, best, best_mv)
    6116             : 
    6117             :     // 32x16
    6118   102854000 :     ADD_VECS(sad_32x16[0], p_sad16x16[0], p_sad16x16[1]);
    6119   102854000 :     ADD_VECS(sad_32x16[1], p_sad16x16[2], p_sad16x16[3]);
    6120   102854000 :     ADD_VECS(sad_32x16[2], p_sad16x16[4], p_sad16x16[5]);
    6121   102854000 :     ADD_VECS(sad_32x16[3], p_sad16x16[6], p_sad16x16[7]);
    6122   102854000 :     ADD_VECS(sad_32x16[4], p_sad16x16[8], p_sad16x16[9]);
    6123   102854000 :     ADD_VECS(sad_32x16[5], p_sad16x16[10], p_sad16x16[11]);
    6124   102854000 :     ADD_VECS(sad_32x16[6], p_sad16x16[12], p_sad16x16[13]);
    6125   102854000 :     ADD_VECS(sad_32x16[7], p_sad16x16[14], p_sad16x16[15]);
    6126             : 
    6127             :     // 16x8
    6128   102854000 :     ADD_VECS(sad_16x8[0], p_sad8x8[0], p_sad8x8[1]);
    6129   102854000 :     ADD_VECS(sad_16x8[1], p_sad8x8[2], p_sad8x8[3]);
    6130   102854000 :     ADD_VECS(sad_16x8[2], p_sad8x8[4], p_sad8x8[5]);
    6131   102854000 :     ADD_VECS(sad_16x8[3], p_sad8x8[6], p_sad8x8[7]);
    6132   102854000 :     ADD_VECS(sad_16x8[4], p_sad8x8[8], p_sad8x8[9]);
    6133   102854000 :     ADD_VECS(sad_16x8[5], p_sad8x8[10], p_sad8x8[11]);
    6134   102854000 :     ADD_VECS(sad_16x8[6], p_sad8x8[12], p_sad8x8[13]);
    6135   102854000 :     ADD_VECS(sad_16x8[7], p_sad8x8[14], p_sad8x8[15]);
    6136   102854000 :     ADD_VECS(sad_16x8[8], p_sad8x8[16], p_sad8x8[17]);
    6137   102854000 :     ADD_VECS(sad_16x8[9], p_sad8x8[18], p_sad8x8[19]);
    6138   102854000 :     ADD_VECS(sad_16x8[10], p_sad8x8[20], p_sad8x8[21]);
    6139   102854000 :     ADD_VECS(sad_16x8[11], p_sad8x8[22], p_sad8x8[23]);
    6140   102854000 :     ADD_VECS(sad_16x8[12], p_sad8x8[24], p_sad8x8[25]);
    6141   102854000 :     ADD_VECS(sad_16x8[13], p_sad8x8[26], p_sad8x8[27]);
    6142   102854000 :     ADD_VECS(sad_16x8[14], p_sad8x8[28], p_sad8x8[29]);
    6143   102854000 :     ADD_VECS(sad_16x8[15], p_sad8x8[30], p_sad8x8[31]);
    6144   102854000 :     ADD_VECS(sad_16x8[16], p_sad8x8[32], p_sad8x8[33]);
    6145   102854000 :     ADD_VECS(sad_16x8[17], p_sad8x8[34], p_sad8x8[35]);
    6146   102854000 :     ADD_VECS(sad_16x8[18], p_sad8x8[36], p_sad8x8[37]);
    6147   102854000 :     ADD_VECS(sad_16x8[19], p_sad8x8[38], p_sad8x8[39]);
    6148   102854000 :     ADD_VECS(sad_16x8[20], p_sad8x8[40], p_sad8x8[41]);
    6149   102854000 :     ADD_VECS(sad_16x8[21], p_sad8x8[42], p_sad8x8[43]);
    6150   102854000 :     ADD_VECS(sad_16x8[22], p_sad8x8[44], p_sad8x8[45]);
    6151   102854000 :     ADD_VECS(sad_16x8[23], p_sad8x8[46], p_sad8x8[47]);
    6152   102854000 :     ADD_VECS(sad_16x8[24], p_sad8x8[48], p_sad8x8[49]);
    6153   102854000 :     ADD_VECS(sad_16x8[25], p_sad8x8[50], p_sad8x8[51]);
    6154   102854000 :     ADD_VECS(sad_16x8[26], p_sad8x8[52], p_sad8x8[53]);
    6155   102854000 :     ADD_VECS(sad_16x8[27], p_sad8x8[54], p_sad8x8[55]);
    6156   102854000 :     ADD_VECS(sad_16x8[28], p_sad8x8[56], p_sad8x8[57]);
    6157   102854000 :     ADD_VECS(sad_16x8[29], p_sad8x8[58], p_sad8x8[59]);
    6158   102854000 :     ADD_VECS(sad_16x8[30], p_sad8x8[60], p_sad8x8[61]);
    6159   102854000 :     ADD_VECS(sad_16x8[31], p_sad8x8[62], p_sad8x8[63]);
    6160             :     // 16x32
    6161   102854000 :     ADD_VECS(sad_16x32[0], p_sad16x16[0], p_sad16x16[2]);
    6162   102854000 :     ADD_VECS(sad_16x32[1], p_sad16x16[1], p_sad16x16[3]);
    6163   102854000 :     ADD_VECS(sad_16x32[2], p_sad16x16[4], p_sad16x16[6]);
    6164   102854000 :     ADD_VECS(sad_16x32[3], p_sad16x16[5], p_sad16x16[7]);
    6165   102854000 :     ADD_VECS(sad_16x32[4], p_sad16x16[8], p_sad16x16[10]);
    6166   102854000 :     ADD_VECS(sad_16x32[5], p_sad16x16[9], p_sad16x16[11]);
    6167   102854000 :     ADD_VECS(sad_16x32[6], p_sad16x16[12], p_sad16x16[14]);
    6168   102854000 :     ADD_VECS(sad_16x32[7], p_sad16x16[13], p_sad16x16[15]);
    6169             :     // 8x16
    6170   102854000 :     ADD_VECS(sad_8x16[0], p_sad8x8[0], p_sad8x8[2]);
    6171   102854000 :     ADD_VECS(sad_8x16[1], p_sad8x8[1], p_sad8x8[3]);
    6172   102854000 :     ADD_VECS(sad_8x16[2], p_sad8x8[4], p_sad8x8[6]);
    6173   102854000 :     ADD_VECS(sad_8x16[3], p_sad8x8[5], p_sad8x8[7]);
    6174   102854000 :     ADD_VECS(sad_8x16[4], p_sad8x8[8], p_sad8x8[10]);
    6175   102854000 :     ADD_VECS(sad_8x16[5], p_sad8x8[9], p_sad8x8[11]);
    6176   102854000 :     ADD_VECS(sad_8x16[6], p_sad8x8[12], p_sad8x8[14]);
    6177   102854000 :     ADD_VECS(sad_8x16[7], p_sad8x8[13], p_sad8x8[15]);
    6178   102854000 :     ADD_VECS(sad_8x16[8], p_sad8x8[16], p_sad8x8[18]);
    6179   102854000 :     ADD_VECS(sad_8x16[9], p_sad8x8[17], p_sad8x8[19]);
    6180   102854000 :     ADD_VECS(sad_8x16[10], p_sad8x8[20], p_sad8x8[22]);
    6181   102854000 :     ADD_VECS(sad_8x16[11], p_sad8x8[21], p_sad8x8[23]);
    6182   102854000 :     ADD_VECS(sad_8x16[12], p_sad8x8[24], p_sad8x8[26]);
    6183   102854000 :     ADD_VECS(sad_8x16[13], p_sad8x8[25], p_sad8x8[27]);
    6184   102854000 :     ADD_VECS(sad_8x16[14], p_sad8x8[28], p_sad8x8[30]);
    6185   102854000 :     ADD_VECS(sad_8x16[15], p_sad8x8[29], p_sad8x8[31]);
    6186   102854000 :     ADD_VECS(sad_8x16[16], p_sad8x8[32], p_sad8x8[34]);
    6187   102854000 :     ADD_VECS(sad_8x16[17], p_sad8x8[33], p_sad8x8[35]);
    6188   102854000 :     ADD_VECS(sad_8x16[18], p_sad8x8[36], p_sad8x8[38]);
    6189   102854000 :     ADD_VECS(sad_8x16[19], p_sad8x8[37], p_sad8x8[39]);
    6190   102854000 :     ADD_VECS(sad_8x16[20], p_sad8x8[40], p_sad8x8[42]);
    6191   102854000 :     ADD_VECS(sad_8x16[21], p_sad8x8[41], p_sad8x8[43]);
    6192   102854000 :     ADD_VECS(sad_8x16[22], p_sad8x8[44], p_sad8x8[46]);
    6193   102854000 :     ADD_VECS(sad_8x16[23], p_sad8x8[45], p_sad8x8[47]);
    6194   102854000 :     ADD_VECS(sad_8x16[24], p_sad8x8[48], p_sad8x8[50]);
    6195   102854000 :     ADD_VECS(sad_8x16[25], p_sad8x8[49], p_sad8x8[51]);
    6196   102854000 :     ADD_VECS(sad_8x16[26], p_sad8x8[52], p_sad8x8[54]);
    6197   102854000 :     ADD_VECS(sad_8x16[27], p_sad8x8[53], p_sad8x8[55]);
    6198   102854000 :     ADD_VECS(sad_8x16[28], p_sad8x8[56], p_sad8x8[58]);
    6199   102854000 :     ADD_VECS(sad_8x16[29], p_sad8x8[57], p_sad8x8[59]);
    6200   102854000 :     ADD_VECS(sad_8x16[30], p_sad8x8[60], p_sad8x8[62]);
    6201   102854000 :     ADD_VECS(sad_8x16[31], p_sad8x8[61], p_sad8x8[63]);
    6202             : 
    6203             :     // 32x16
    6204   205708000 :     SEARCH_BEST(sad_32x16[0], p_best_sad32x16[0], p_best_mv32x16[0]);
    6205   205708000 :     SEARCH_BEST(sad_32x16[1], p_best_sad32x16[1], p_best_mv32x16[1]);
    6206   205708000 :     SEARCH_BEST(sad_32x16[2], p_best_sad32x16[2], p_best_mv32x16[2]);
    6207   205708000 :     SEARCH_BEST(sad_32x16[3], p_best_sad32x16[3], p_best_mv32x16[3]);
    6208   205708000 :     SEARCH_BEST(sad_32x16[4], p_best_sad32x16[4], p_best_mv32x16[4]);
    6209   205708000 :     SEARCH_BEST(sad_32x16[5], p_best_sad32x16[5], p_best_mv32x16[5]);
    6210   205708000 :     SEARCH_BEST(sad_32x16[6], p_best_sad32x16[6], p_best_mv32x16[6]);
    6211   205708000 :     SEARCH_BEST(sad_32x16[7], p_best_sad32x16[7], p_best_mv32x16[7]);
    6212             :     // 16x8
    6213   205708000 :     SEARCH_BEST(sad_16x8[0], p_best_sad16x8[0], p_best_mv16x8[0]);
    6214   205708000 :     SEARCH_BEST(sad_16x8[1], p_best_sad16x8[1], p_best_mv16x8[1]);
    6215   205708000 :     SEARCH_BEST(sad_16x8[2], p_best_sad16x8[2], p_best_mv16x8[2]);
    6216   205708000 :     SEARCH_BEST(sad_16x8[3], p_best_sad16x8[3], p_best_mv16x8[3]);
    6217   205708000 :     SEARCH_BEST(sad_16x8[4], p_best_sad16x8[4], p_best_mv16x8[4]);
    6218   205708000 :     SEARCH_BEST(sad_16x8[5], p_best_sad16x8[5], p_best_mv16x8[5]);
    6219   205708000 :     SEARCH_BEST(sad_16x8[6], p_best_sad16x8[6], p_best_mv16x8[6]);
    6220   205708000 :     SEARCH_BEST(sad_16x8[7], p_best_sad16x8[7], p_best_mv16x8[7]);
    6221   205708000 :     SEARCH_BEST(sad_16x8[8], p_best_sad16x8[8], p_best_mv16x8[8]);
    6222   205708000 :     SEARCH_BEST(sad_16x8[9], p_best_sad16x8[9], p_best_mv16x8[9]);
    6223   205708000 :     SEARCH_BEST(sad_16x8[10], p_best_sad16x8[10], p_best_mv16x8[10]);
    6224   205708000 :     SEARCH_BEST(sad_16x8[11], p_best_sad16x8[11], p_best_mv16x8[11]);
    6225   205708000 :     SEARCH_BEST(sad_16x8[12], p_best_sad16x8[12], p_best_mv16x8[12]);
    6226   205708000 :     SEARCH_BEST(sad_16x8[13], p_best_sad16x8[13], p_best_mv16x8[13]);
    6227   205708000 :     SEARCH_BEST(sad_16x8[14], p_best_sad16x8[14], p_best_mv16x8[14]);
    6228   205708000 :     SEARCH_BEST(sad_16x8[15], p_best_sad16x8[15], p_best_mv16x8[15]);
    6229   205708000 :     SEARCH_BEST(sad_16x8[16], p_best_sad16x8[16], p_best_mv16x8[16]);
    6230   205708000 :     SEARCH_BEST(sad_16x8[17], p_best_sad16x8[17], p_best_mv16x8[17]);
    6231   205708000 :     SEARCH_BEST(sad_16x8[18], p_best_sad16x8[18], p_best_mv16x8[18]);
    6232   205708000 :     SEARCH_BEST(sad_16x8[19], p_best_sad16x8[19], p_best_mv16x8[19]);
    6233   205708000 :     SEARCH_BEST(sad_16x8[20], p_best_sad16x8[20], p_best_mv16x8[20]);
    6234   205708000 :     SEARCH_BEST(sad_16x8[21], p_best_sad16x8[21], p_best_mv16x8[21]);
    6235   205708000 :     SEARCH_BEST(sad_16x8[22], p_best_sad16x8[22], p_best_mv16x8[22]);
    6236   205708000 :     SEARCH_BEST(sad_16x8[23], p_best_sad16x8[23], p_best_mv16x8[23]);
    6237   205708000 :     SEARCH_BEST(sad_16x8[24], p_best_sad16x8[24], p_best_mv16x8[24]);
    6238   205708000 :     SEARCH_BEST(sad_16x8[25], p_best_sad16x8[25], p_best_mv16x8[25]);
    6239   205708000 :     SEARCH_BEST(sad_16x8[26], p_best_sad16x8[26], p_best_mv16x8[26]);
    6240   205708000 :     SEARCH_BEST(sad_16x8[27], p_best_sad16x8[27], p_best_mv16x8[27]);
    6241   205708000 :     SEARCH_BEST(sad_16x8[28], p_best_sad16x8[28], p_best_mv16x8[28]);
    6242   205708000 :     SEARCH_BEST(sad_16x8[29], p_best_sad16x8[29], p_best_mv16x8[29]);
    6243   205708000 :     SEARCH_BEST(sad_16x8[30], p_best_sad16x8[30], p_best_mv16x8[30]);
    6244   205708000 :     SEARCH_BEST(sad_16x8[31], p_best_sad16x8[31], p_best_mv16x8[31]);
    6245             :     // 16x32
    6246   205708000 :     SEARCH_BEST(sad_16x32[0], p_best_sad16x32[0], p_best_mv16x32[0]);
    6247   205708000 :     SEARCH_BEST(sad_16x32[1], p_best_sad16x32[1], p_best_mv16x32[1]);
    6248   205708000 :     SEARCH_BEST(sad_16x32[2], p_best_sad16x32[2], p_best_mv16x32[2]);
    6249   205708000 :     SEARCH_BEST(sad_16x32[3], p_best_sad16x32[3], p_best_mv16x32[3]);
    6250   205708000 :     SEARCH_BEST(sad_16x32[4], p_best_sad16x32[4], p_best_mv16x32[4]);
    6251   205708000 :     SEARCH_BEST(sad_16x32[5], p_best_sad16x32[5], p_best_mv16x32[5]);
    6252   205708000 :     SEARCH_BEST(sad_16x32[6], p_best_sad16x32[6], p_best_mv16x32[6]);
    6253   205708000 :     SEARCH_BEST(sad_16x32[7], p_best_sad16x32[7], p_best_mv16x32[7]);
    6254             :     // 8x16
    6255   205708000 :     SEARCH_BEST(sad_8x16[0], p_best_sad8x16[0], p_best_mv8x16[0]);
    6256   205708000 :     SEARCH_BEST(sad_8x16[1], p_best_sad8x16[1], p_best_mv8x16[1]);
    6257   205708000 :     SEARCH_BEST(sad_8x16[2], p_best_sad8x16[2], p_best_mv8x16[2]);
    6258   205708000 :     SEARCH_BEST(sad_8x16[3], p_best_sad8x16[3], p_best_mv8x16[3]);
    6259   205708000 :     SEARCH_BEST(sad_8x16[4], p_best_sad8x16[4], p_best_mv8x16[4]);
    6260   205708000 :     SEARCH_BEST(sad_8x16[5], p_best_sad8x16[5], p_best_mv8x16[5]);
    6261   205708000 :     SEARCH_BEST(sad_8x16[6], p_best_sad8x16[6], p_best_mv8x16[6]);
    6262   205708000 :     SEARCH_BEST(sad_8x16[7], p_best_sad8x16[7], p_best_mv8x16[7]);
    6263   205708000 :     SEARCH_BEST(sad_8x16[8], p_best_sad8x16[8], p_best_mv8x16[8]);
    6264   205708000 :     SEARCH_BEST(sad_8x16[9], p_best_sad8x16[9], p_best_mv8x16[9]);
    6265   205708000 :     SEARCH_BEST(sad_8x16[10], p_best_sad8x16[10], p_best_mv8x16[10]);
    6266   205708000 :     SEARCH_BEST(sad_8x16[11], p_best_sad8x16[11], p_best_mv8x16[11]);
    6267   205708000 :     SEARCH_BEST(sad_8x16[12], p_best_sad8x16[12], p_best_mv8x16[12]);
    6268   205708000 :     SEARCH_BEST(sad_8x16[13], p_best_sad8x16[13], p_best_mv8x16[13]);
    6269   205708000 :     SEARCH_BEST(sad_8x16[14], p_best_sad8x16[14], p_best_mv8x16[14]);
    6270   205708000 :     SEARCH_BEST(sad_8x16[15], p_best_sad8x16[15], p_best_mv8x16[15]);
    6271   205708000 :     SEARCH_BEST(sad_8x16[16], p_best_sad8x16[16], p_best_mv8x16[16]);
    6272   205708000 :     SEARCH_BEST(sad_8x16[17], p_best_sad8x16[17], p_best_mv8x16[17]);
    6273   205708000 :     SEARCH_BEST(sad_8x16[18], p_best_sad8x16[18], p_best_mv8x16[18]);
    6274   205708000 :     SEARCH_BEST(sad_8x16[19], p_best_sad8x16[19], p_best_mv8x16[19]);
    6275   205708000 :     SEARCH_BEST(sad_8x16[20], p_best_sad8x16[20], p_best_mv8x16[20]);
    6276   205708000 :     SEARCH_BEST(sad_8x16[21], p_best_sad8x16[21], p_best_mv8x16[21]);
    6277   205708000 :     SEARCH_BEST(sad_8x16[22], p_best_sad8x16[22], p_best_mv8x16[22]);
    6278   205708000 :     SEARCH_BEST(sad_8x16[23], p_best_sad8x16[23], p_best_mv8x16[23]);
    6279   205708000 :     SEARCH_BEST(sad_8x16[24], p_best_sad8x16[24], p_best_mv8x16[24]);
    6280   205708000 :     SEARCH_BEST(sad_8x16[25], p_best_sad8x16[25], p_best_mv8x16[25]);
    6281   205708000 :     SEARCH_BEST(sad_8x16[26], p_best_sad8x16[26], p_best_mv8x16[26]);
    6282   205708000 :     SEARCH_BEST(sad_8x16[27], p_best_sad8x16[27], p_best_mv8x16[27]);
    6283   205708000 :     SEARCH_BEST(sad_8x16[28], p_best_sad8x16[28], p_best_mv8x16[28]);
    6284   205708000 :     SEARCH_BEST(sad_8x16[29], p_best_sad8x16[29], p_best_mv8x16[29]);
    6285   205708000 :     SEARCH_BEST(sad_8x16[30], p_best_sad8x16[30], p_best_mv8x16[30]);
    6286   205708000 :     SEARCH_BEST(sad_8x16[31], p_best_sad8x16[31], p_best_mv8x16[31]);
    6287             : 
    6288   308562000 :     SEARCH_CALC_BEST(p_sad32x32[0], p_sad32x32[1], p_best_sad64x32[0],
    6289             :         p_best_mv64x32[0]);
    6290   308562000 :     SEARCH_CALC_BEST(p_sad32x32[2], p_sad32x32[3], p_best_sad64x32[1],
    6291             :         p_best_mv64x32[1]);
    6292   274277000 :     SEARCH_CALC_BEST(sad_32x16[0], sad_32x16[2], p_best_sad64x16[0],
    6293             :         p_best_mv64x16[0]);
    6294   274277000 :     SEARCH_CALC_BEST(sad_32x16[1], sad_32x16[3], p_best_sad64x16[1],
    6295             :         p_best_mv64x16[1]);
    6296   274277000 :     SEARCH_CALC_BEST(sad_32x16[4], sad_32x16[6], p_best_sad64x16[2],
    6297             :         p_best_mv64x16[2]);
    6298   274277000 :     SEARCH_CALC_BEST(sad_32x16[5], sad_32x16[7], p_best_sad64x16[3],
    6299             :         p_best_mv64x16[3]);
    6300   308562000 :     SEARCH_CALC_BEST(p_sad32x32[0], p_sad32x32[2], p_best_sad32x64[0],
    6301             :         p_best_mv32x64[0]);
    6302   308562000 :     SEARCH_CALC_BEST(p_sad32x32[1], p_sad32x32[3], p_best_sad32x64[1],
    6303             :         p_best_mv32x64[1]);
    6304   274277000 :     SEARCH_CALC_BEST(sad_16x32[0], sad_16x32[4], p_best_sad16x64[0],
    6305             :         p_best_mv16x64[0]);
    6306   274277000 :     SEARCH_CALC_BEST(sad_16x32[1], sad_16x32[5], p_best_sad16x64[1],
    6307             :         p_best_mv16x64[1]);
    6308   274277000 :     SEARCH_CALC_BEST(sad_16x32[2], sad_16x32[6], p_best_sad16x64[2],
    6309             :         p_best_mv16x64[2]);
    6310   274277000 :     SEARCH_CALC_BEST(sad_16x32[3], sad_16x32[7], p_best_sad16x64[3],
    6311             :         p_best_mv16x64[3]);
    6312   274277000 :     SEARCH_CALC_BEST(sad_16x8[0], sad_16x8[2], p_best_sad32x8[0],
    6313             :         p_best_mv32x8[0]);
    6314   274277000 :     SEARCH_CALC_BEST(sad_16x8[1], sad_16x8[3], p_best_sad32x8[1],
    6315             :         p_best_mv32x8[1]);
    6316   274277000 :     SEARCH_CALC_BEST(sad_16x8[4], sad_16x8[6], p_best_sad32x8[2],
    6317             :         p_best_mv32x8[2]);
    6318   274277000 :     SEARCH_CALC_BEST(sad_16x8[5], sad_16x8[7], p_best_sad32x8[3],
    6319             :         p_best_mv32x8[3]);
    6320   274277000 :     SEARCH_CALC_BEST(sad_16x8[8], sad_16x8[10], p_best_sad32x8[4],
    6321             :         p_best_mv32x8[4]);
    6322   274277000 :     SEARCH_CALC_BEST(sad_16x8[9], sad_16x8[11], p_best_sad32x8[5],
    6323             :         p_best_mv32x8[5]);
    6324   274277000 :     SEARCH_CALC_BEST(sad_16x8[12], sad_16x8[14], p_best_sad32x8[6],
    6325             :         p_best_mv32x8[6]);
    6326   274277000 :     SEARCH_CALC_BEST(sad_16x8[13], sad_16x8[15], p_best_sad32x8[7],
    6327             :         p_best_mv32x8[7]);
    6328   274277000 :     SEARCH_CALC_BEST(sad_16x8[16], sad_16x8[18], p_best_sad32x8[8],
    6329             :         p_best_mv32x8[8]);
    6330   274277000 :     SEARCH_CALC_BEST(sad_16x8[17], sad_16x8[19], p_best_sad32x8[9],
    6331             :         p_best_mv32x8[9]);
    6332   274277000 :     SEARCH_CALC_BEST(sad_16x8[20], sad_16x8[22], p_best_sad32x8[10],
    6333             :         p_best_mv32x8[10]);
    6334   274277000 :     SEARCH_CALC_BEST(sad_16x8[21], sad_16x8[23], p_best_sad32x8[11],
    6335             :         p_best_mv32x8[11]);
    6336   274277000 :     SEARCH_CALC_BEST(sad_16x8[24], sad_16x8[26], p_best_sad32x8[12],
    6337             :         p_best_mv32x8[12]);
    6338   274277000 :     SEARCH_CALC_BEST(sad_16x8[25], sad_16x8[27], p_best_sad32x8[13],
    6339             :         p_best_mv32x8[13]);
    6340   274277000 :     SEARCH_CALC_BEST(sad_16x8[28], sad_16x8[30], p_best_sad32x8[14],
    6341             :         p_best_mv32x8[14]);
    6342   274277000 :     SEARCH_CALC_BEST(sad_16x8[29], sad_16x8[31], p_best_sad32x8[15],
    6343             :         p_best_mv32x8[15]);
    6344   274277000 :     SEARCH_CALC_BEST(sad_8x16[0], sad_8x16[4], p_best_sad8x32[0],
    6345             :         p_best_mv8x32[0]);
    6346   274277000 :     SEARCH_CALC_BEST(sad_8x16[1], sad_8x16[5], p_best_sad8x32[1],
    6347             :         p_best_mv8x32[1]);
    6348   274277000 :     SEARCH_CALC_BEST(sad_8x16[2], sad_8x16[6], p_best_sad8x32[2],
    6349             :         p_best_mv8x32[2]);
    6350   274277000 :     SEARCH_CALC_BEST(sad_8x16[3], sad_8x16[7], p_best_sad8x32[3],
    6351             :         p_best_mv8x32[3]);
    6352   274277000 :     SEARCH_CALC_BEST(sad_8x16[8], sad_8x16[12], p_best_sad8x32[4],
    6353             :         p_best_mv8x32[4]);
    6354   274277000 :     SEARCH_CALC_BEST(sad_8x16[9], sad_8x16[13], p_best_sad8x32[5],
    6355             :         p_best_mv8x32[5]);
    6356   274277000 :     SEARCH_CALC_BEST(sad_8x16[10], sad_8x16[14], p_best_sad8x32[6],
    6357             :         p_best_mv8x32[6]);
    6358   274277000 :     SEARCH_CALC_BEST(sad_8x16[11], sad_8x16[15], p_best_sad8x32[7],
    6359             :         p_best_mv8x32[7]);
    6360   274277000 :     SEARCH_CALC_BEST(sad_8x16[16], sad_8x16[20], p_best_sad8x32[8],
    6361             :         p_best_mv8x32[8]);
    6362   274277000 :     SEARCH_CALC_BEST(sad_8x16[17], sad_8x16[21], p_best_sad8x32[9],
    6363             :         p_best_mv8x32[9]);
    6364   274277000 :     SEARCH_CALC_BEST(sad_8x16[18], sad_8x16[22], p_best_sad8x32[10],
    6365             :         p_best_mv8x32[10]);
    6366   274277000 :     SEARCH_CALC_BEST(sad_8x16[19], sad_8x16[23], p_best_sad8x32[11],
    6367             :         p_best_mv8x32[11]);
    6368   274277000 :     SEARCH_CALC_BEST(sad_8x16[24], sad_8x16[28], p_best_sad8x32[12],
    6369             :         p_best_mv8x32[12]);
    6370   274277000 :     SEARCH_CALC_BEST(sad_8x16[25], sad_8x16[29], p_best_sad8x32[13],
    6371             :         p_best_mv8x32[13]);
    6372   274277000 :     SEARCH_CALC_BEST(sad_8x16[26], sad_8x16[30], p_best_sad8x32[14],
    6373             :         p_best_mv8x32[14]);
    6374   274277000 :     SEARCH_CALC_BEST(sad_8x16[27], sad_8x16[31], p_best_sad8x32[15],
    6375             :         p_best_mv8x32[15]);
    6376             : 
    6377             : #undef SEARCH_CALC_BEST
    6378             : #undef SEARCH_BEST
    6379             : #undef ADD_VECS
    6380    34284600 : }
    6381             : 
    6382    34293400 : void ext_eight_sad_calculation_32x32_64x64_avx2(
    6383             :     uint32_t  p_sad16x16[16][8],
    6384             :     uint32_t *p_best_sad32x32,
    6385             :     uint32_t *p_best_sad64x64,
    6386             :     uint32_t *p_best_mv32x32,
    6387             :     uint32_t *p_best_mv64x64,
    6388             :     uint32_t  mv,
    6389             :     uint32_t p_sad32x32[4][8]) {
    6390    34293400 :     avx2_find_min_pos_init();
    6391             :     uint32_t si_a, si_b, si_c, si_d, si_e;
    6392             : 
    6393    68586800 :     const __m256i tmp0 = _mm256_add_epi32(
    6394             :         _mm256_loadu_si256((__m256i const *)p_sad16x16[0]),
    6395    34293400 :         _mm256_loadu_si256((__m256i const *)p_sad16x16[1]));
    6396             : 
    6397    68586800 :     const __m256i tmp1 = _mm256_add_epi32(
    6398    34293400 :         _mm256_loadu_si256((__m256i const *)p_sad16x16[2]),
    6399    34293400 :         _mm256_loadu_si256((__m256i const *)p_sad16x16[3]));
    6400             : 
    6401    34293400 :     const __m256i sad32_a = _mm256_add_epi32(tmp0, tmp1);
    6402             :     _mm256_storeu_si256((__m256i *)p_sad32x32[0], sad32_a);
    6403             : 
    6404    34293400 :     const __m256i tmp2 = _mm256_add_epi32(
    6405    34293400 :         _mm256_loadu_si256((__m256i const *)p_sad16x16[4]),
    6406    34293400 :         _mm256_loadu_si256((__m256i const *)p_sad16x16[5]));
    6407             : 
    6408    68586800 :     const __m256i tmp3 = _mm256_add_epi32(
    6409    34293400 :         _mm256_loadu_si256((__m256i const *)p_sad16x16[6]),
    6410    34293400 :         _mm256_loadu_si256((__m256i const *)p_sad16x16[7]));
    6411             : 
    6412    34293400 :     const __m256i sad32_b = _mm256_add_epi32(tmp2, tmp3);
    6413    34293400 :     _mm256_storeu_si256((__m256i *)p_sad32x32[1], sad32_b);
    6414             : 
    6415    34293400 :     const __m256i tmp4 = _mm256_add_epi32(
    6416    34293400 :         _mm256_loadu_si256((__m256i const *)p_sad16x16[8]),
    6417    34293400 :         _mm256_loadu_si256((__m256i const *)p_sad16x16[9]));
    6418             : 
    6419    68586800 :     const __m256i tmp5 = _mm256_add_epi32(
    6420    34293400 :         _mm256_loadu_si256((__m256i const *)p_sad16x16[10]),
    6421    34293400 :         _mm256_loadu_si256((__m256i const *)p_sad16x16[11]));
    6422             : 
    6423    34293400 :     const __m256i sad32_c = _mm256_add_epi32(tmp4, tmp5);
    6424    34293400 :     _mm256_storeu_si256((__m256i *)p_sad32x32[2], sad32_c);
    6425             : 
    6426    34293400 :     const __m256i tmp6 = _mm256_add_epi32(
    6427    34293400 :         _mm256_loadu_si256((__m256i const *)p_sad16x16[12]),
    6428    34293400 :         _mm256_loadu_si256((__m256i const *)p_sad16x16[13]));
    6429             : 
    6430    68586800 :     const __m256i tmp7 = _mm256_add_epi32(
    6431    34293400 :         _mm256_loadu_si256((__m256i const *)p_sad16x16[14]),
    6432    34293400 :         _mm256_loadu_si256((__m256i const *)p_sad16x16[15]));
    6433             : 
    6434    34293400 :     const __m256i sad32_d = _mm256_add_epi32(tmp6, tmp7);
    6435    34293400 :     _mm256_storeu_si256((__m256i *)p_sad32x32[3], sad32_d);
    6436             : 
    6437             :     DECLARE_ALIGNED(32, uint32_t, sad64x64[8]);
    6438    34293400 :     const __m256i tmp8 = _mm256_add_epi32(sad32_a, sad32_b);
    6439    34293400 :     const __m256i tmp9 = _mm256_add_epi32(sad32_c, sad32_d);
    6440    68586800 :     *((__m256i *)sad64x64) = _mm256_add_epi32(tmp8, tmp9);
    6441             : 
    6442             :     DECLARE_ALIGNED(32, uint32_t, computed_idx[8]);
    6443    34293400 :     __m256i search_idx_avx2 = _mm256_setr_epi32(0, 4, 8, 12, 16, 20, 24, 28);
    6444    68586800 :     __m256i mv_avx2 = _mm256_set1_epi32(mv);
    6445    34293400 :     __m256i new_mv_avx2 = _mm256_add_epi32(search_idx_avx2, mv_avx2);
    6446    68586800 :     new_mv_avx2 = _mm256_and_si256(new_mv_avx2, _mm256_set1_epi32(0xffff));
    6447   102880000 :     *(__m256i *)computed_idx = _mm256_or_si256(
    6448             :         new_mv_avx2, _mm256_and_si256(mv_avx2, _mm256_set1_epi32(0xffff0000)));
    6449             : 
    6450   171467000 :     avx2_find_min_pos(sad32_a, si_a);
    6451   171467000 :     avx2_find_min_pos(sad32_b, si_b);
    6452   171467000 :     avx2_find_min_pos(sad32_c, si_c);
    6453   137174000 :     avx2_find_min_pos(sad32_d, si_d);
    6454   171467000 :     avx2_find_min_pos(*(__m256i*)sad64x64, si_e);
    6455             : 
    6456    34293400 :     if (p_sad32x32[0][si_a] < p_best_sad32x32[0]) {
    6457      362090 :         p_best_sad32x32[0] = p_sad32x32[0][si_a];
    6458      362090 :         p_best_mv32x32[0] = computed_idx[si_a];
    6459             :     }
    6460             : 
    6461    34293400 :     if (p_sad32x32[1][si_b] < p_best_sad32x32[1]) {
    6462      381543 :         p_best_sad32x32[1] = p_sad32x32[1][si_b];
    6463      381543 :         p_best_mv32x32[1] = computed_idx[si_b];
    6464             :     }
    6465             : 
    6466    34293400 :     if (p_sad32x32[2][si_c] < p_best_sad32x32[2]) {
    6467      399085 :         p_best_sad32x32[2] = p_sad32x32[2][si_c];
    6468      399085 :         p_best_mv32x32[2] = computed_idx[si_c];
    6469             :     }
    6470             : 
    6471    34293400 :     if (p_sad32x32[3][si_d] < p_best_sad32x32[3]) {
    6472      420474 :         p_best_sad32x32[3] = p_sad32x32[3][si_d];
    6473      420474 :         p_best_mv32x32[3] = computed_idx[si_d];
    6474             :     }
    6475             : 
    6476    34293400 :     if (sad64x64[si_e] < p_best_sad64x64[0]) {
    6477      640618 :         p_best_sad64x64[0] = sad64x64[si_e];
    6478      640618 :         p_best_mv64x64[0] = computed_idx[si_e];
    6479             :     }
    6480    34293400 : }
    6481             : 
    6482             : 
    6483   125061000 : uint32_t nxm_sad_kernel_sub_sampled_helper_avx2(
    6484             :     const uint8_t  *src,
    6485             :     uint32_t  src_stride,
    6486             :     const uint8_t  *ref,
    6487             :     uint32_t  ref_stride,
    6488             :     uint32_t  height,
    6489             :     uint32_t  width)
    6490             : {
    6491   125061000 :     uint32_t nxm_sad = 0;
    6492             : 
    6493   125061000 :     switch (width) {
    6494    10956200 :     case 4:
    6495    10956200 :         nxm_sad = eb_compute4x_m_sad_avx2_intrin(src, src_stride, ref, ref_stride, height, width); break;
    6496    51512300 :     case 8:
    6497    51512300 :         nxm_sad = eb_compute8x_m_sad_avx2_intrin(src, src_stride, ref, ref_stride, height, width); break;
    6498    38875200 :     case 16:
    6499    38875200 :         nxm_sad = eb_compute16x_m_sad_avx2_intrin(src, src_stride, ref, ref_stride, height, width); break;
    6500           0 :     case 24:
    6501           0 :         nxm_sad = fast_loop_nxm_sad_kernel(src, src_stride, ref, ref_stride, height, width); break;
    6502    18907600 :     case 32:
    6503    18907600 :         nxm_sad = eb_compute32x_m_sad_avx2_intrin(src, src_stride, ref, ref_stride, height, width); break;
    6504           0 :     case 48:
    6505           0 :         nxm_sad = fast_loop_nxm_sad_kernel(src, src_stride, ref, ref_stride, height, width); break;
    6506     5089090 :     case 64:
    6507     5089090 :         nxm_sad = eb_compute64x_m_sad_avx2_intrin(src, src_stride, ref, ref_stride, height, width); break;
    6508           0 :     case 128:
    6509           0 :         nxm_sad = fast_loop_nxm_sad_kernel(src, src_stride, ref, ref_stride, height, width); break;
    6510   125174000 :     default:
    6511             :         assert(0);
    6512             :     }
    6513             : 
    6514   125174000 :     return nxm_sad;
    6515             : };
    6516             : 
    6517    22985400 : uint32_t nxm_sad_kernel_helper_avx2(
    6518             :     const uint8_t  *src,
    6519             :     uint32_t  src_stride,
    6520             :     const uint8_t  *ref,
    6521             :     uint32_t  ref_stride,
    6522             :     uint32_t  height,
    6523             :     uint32_t  width)
    6524             : {
    6525             : 
    6526    22985400 :     uint32_t nxm_sad = 0;
    6527             : 
    6528    22985400 :     switch (width) {
    6529           0 :     case 4:
    6530           0 :         nxm_sad = eb_compute4x_m_sad_avx2_intrin(src, src_stride, ref, ref_stride, height, width); break;
    6531    12654100 :     case 8:
    6532    12654100 :         nxm_sad = eb_compute8x_m_sad_avx2_intrin(src, src_stride, ref, ref_stride, height, width); break;
    6533     6309380 :     case 16:
    6534     6309380 :         nxm_sad = eb_compute16x_m_sad_avx2_intrin(src, src_stride, ref, ref_stride, height, width); break;
    6535           0 :     case 24:
    6536           0 :         nxm_sad = eb_compute24x_m_sad_avx2_intrin(src, src_stride, ref, ref_stride, height, width); break;
    6537     3228780 :     case 32:
    6538     3228780 :         nxm_sad = eb_compute32x_m_sad_avx2_intrin(src, src_stride, ref, ref_stride, height, width); break;
    6539           0 :     case 48:
    6540           0 :         nxm_sad = eb_compute48x_m_sad_avx2_intrin(src, src_stride, ref, ref_stride, height, width); break;
    6541      846887 :     case 64:
    6542      846887 :         nxm_sad = eb_compute64x_m_sad_avx2_intrin(src, src_stride, ref, ref_stride, height, width); break;
    6543           0 :     case 40:
    6544             :     case 52:
    6545           0 :         break; //void_func();
    6546    22989600 :     default:
    6547             :         assert(0);
    6548             :     }
    6549             : 
    6550    22989600 :     return nxm_sad;
    6551             : }
    6552             : 
    6553             : 

Generated by: LCOV version 1.14