LCOV - code coverage report
Current view: top level - ASM_SSSE3 - variance_impl_ssse3.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 49 0.0 %
Date: 2019-11-25 17:38:06 Functions: 0 2 0.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2018, Alliance for Open Media. All rights reserved
       3             :  *
       4             :  * This source code is subject to the terms of the BSD 2 Clause License and
       5             :  * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
       6             :  * was not distributed with this source code in the LICENSE file, you can
       7             :  * obtain it at www.aomedia.org/license/software. If the Alliance for Open
       8             :  * Media Patent License 1.0 was not distributed with this source code in the
       9             :  * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
      10             :  */
      11             : 
      12             : #include <tmmintrin.h>
      13             : 
      14             : // #include "config/aom_config.h"
      15             : #include "aom_dsp_rtcd.h"
      16             : 
      17             : #include "synonyms.h"
      18             : 
      19           0 : void aom_var_filter_block2d_bil_first_pass_ssse3(
      20             :     const uint8_t *a, uint16_t *b, unsigned int src_pixels_per_line,
      21             :     unsigned int pixel_step, unsigned int output_height,
      22             :     unsigned int output_width, const uint8_t *filter) {
      23             :   // Note: filter[0], filter[1] could be {128, 0}, where 128 will overflow
      24             :   // in computation using _mm_maddubs_epi16.
      25             :   // Change {128, 0} to {64, 0} and reduce FILTER_BITS by 1 to avoid overflow.
      26           0 :   const int16_t round = (1 << (FILTER_BITS - 1)) >> 1;
      27           0 :   const __m128i r = _mm_set1_epi16(round);
      28           0 :   const uint8_t f0 = filter[0] >> 1;
      29           0 :   const uint8_t f1 = filter[1] >> 1;
      30           0 :   const __m128i filters = _mm_setr_epi8(f0, f1, f0, f1, f0, f1, f0, f1, f0, f1,
      31             :                                         f0, f1, f0, f1, f0, f1);
      32             :   unsigned int i, j;
      33             :   (void)pixel_step;
      34             : 
      35           0 :   if (output_width >= 8) {
      36           0 :     for (i = 0; i < output_height; ++i) {
      37           0 :       for (j = 0; j < output_width; j += 8) {
      38             :         // load source
      39           0 :         __m128i source_low = xx_loadl_64(a);
      40           0 :         __m128i source_hi = xx_loadl_64(a + 1);
      41             : 
      42             :         // unpack to:
      43             :         // { a[0], a[1], a[1], a[2], a[2], a[3], a[3], a[4],
      44             :         //   a[4], a[5], a[5], a[6], a[6], a[7], a[7], a[8] }
      45           0 :         __m128i source = _mm_unpacklo_epi8(source_low, source_hi);
      46             : 
      47             :         // b[i] = a[i] * filter[0] + a[i + 1] * filter[1]
      48           0 :         __m128i res = _mm_maddubs_epi16(source, filters);
      49             : 
      50             :         // round
      51           0 :         res = _mm_srai_epi16(_mm_add_epi16(res, r), FILTER_BITS - 1);
      52             : 
      53           0 :         xx_storeu_128(b, res);
      54             : 
      55           0 :         a += 8;
      56           0 :         b += 8;
      57             :       }
      58             : 
      59           0 :       a += src_pixels_per_line - output_width;
      60             :     }
      61             :   } else {
      62             :     const __m128i shuffle_mask =
      63           0 :         _mm_setr_epi8(0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8);
      64           0 :     for (i = 0; i < output_height; ++i) {
      65             :       // load source, only first 5 values are meaningful:
      66             :       // { a[0], a[1], a[2], a[3], a[4], xxxx }
      67           0 :       __m128i source = xx_loadl_64(a);
      68             : 
      69             :       // shuffle, up to the first 8 are useful
      70             :       // { a[0], a[1], a[1], a[2], a[2], a[3], a[3], a[4],
      71             :       //   a[4], a[5], a[5], a[6], a[6], a[7], a[7], a[8] }
      72           0 :       __m128i source_shuffle = _mm_shuffle_epi8(source, shuffle_mask);
      73             : 
      74           0 :       __m128i res = _mm_maddubs_epi16(source_shuffle, filters);
      75           0 :       res = _mm_srai_epi16(_mm_add_epi16(res, r), FILTER_BITS - 1);
      76             : 
      77           0 :       xx_storel_64(b, res);
      78             : 
      79           0 :       a += src_pixels_per_line;
      80           0 :       b += output_width;
      81             :     }
      82             :   }
      83           0 : }
      84             : 
      85           0 : void aom_var_filter_block2d_bil_second_pass_ssse3(
      86             :     const uint16_t *a, uint8_t *b, unsigned int src_pixels_per_line,
      87             :     unsigned int pixel_step, unsigned int output_height,
      88             :     unsigned int output_width, const uint8_t *filter) {
      89           0 :   const int16_t round = (1 << FILTER_BITS) >> 1;
      90           0 :   const __m128i r = _mm_set1_epi32(round);
      91             :   const __m128i filters =
      92           0 :       _mm_setr_epi16(filter[0], filter[1], filter[0], filter[1], filter[0],
      93           0 :                      filter[1], filter[0], filter[1]);
      94             :   const __m128i shuffle_mask =
      95           0 :       _mm_setr_epi8(0, 1, 8, 9, 2, 3, 10, 11, 4, 5, 12, 13, 6, 7, 14, 15);
      96             :   const __m128i mask =
      97           0 :       _mm_setr_epi8(0, 4, 8, 12, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1);
      98             :   unsigned int i, j;
      99             : 
     100           0 :   for (i = 0; i < output_height; ++i) {
     101           0 :     for (j = 0; j < output_width; j += 4) {
     102             :       // load source as:
     103             :       // { a[0], a[1], a[2], a[3], a[w], a[w+1], a[w+2], a[w+3] }
     104           0 :       __m128i source1 = xx_loadl_64(a);
     105           0 :       __m128i source2 = xx_loadl_64(a + pixel_step);
     106           0 :       __m128i source = _mm_unpacklo_epi64(source1, source2);
     107             : 
     108             :       // shuffle source to:
     109             :       // { a[0], a[w], a[1], a[w+1], a[2], a[w+2], a[3], a[w+3] }
     110           0 :       __m128i source_shuffle = _mm_shuffle_epi8(source, shuffle_mask);
     111             : 
     112             :       // b[i] = a[i] * filter[0] + a[w + i] * filter[1]
     113           0 :       __m128i res = _mm_madd_epi16(source_shuffle, filters);
     114             : 
     115             :       // round
     116           0 :       res = _mm_srai_epi32(_mm_add_epi32(res, r), FILTER_BITS);
     117             : 
     118             :       // shuffle to get each lower 8 bit of every 32 bit
     119           0 :       res = _mm_shuffle_epi8(res, mask);
     120             : 
     121           0 :       xx_storel_32(b, res);
     122             : 
     123           0 :       a += 4;
     124           0 :       b += 4;
     125             :     }
     126             : 
     127           0 :     a += src_pixels_per_line - output_width;
     128             :   }
     129           0 : }

Generated by: LCOV version 1.14