LCOV - code coverage report
Current view: top level - ASM_AVX2 - EbRestorationPick_AVX2.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 105 213 49.3 %
Date: 2019-11-25 17:38:06 Functions: 2 2 100.0 %

          Line data    Source code
       1             : /*
       2             : * Copyright(c) 2019 Intel Corporation
       3             : * SPDX - License - Identifier: BSD - 2 - Clause - Patent
       4             : */
       5             : 
       6             : #include "EbDefinitions.h"
       7             : #include "EbRestoration.h"
       8             : #include <immintrin.h>
       9             : #include<math.h>
      10             : 
      11   103486000 : static INLINE void avx2_mul_epi16_epi32(__m256i *a, __m256i *b, __m256i *out) {
      12             :   __m256i a_32[2];
      13             :   __m256i b_32[2];
      14             : 
      15   103486000 :   a_32[0] = _mm256_cvtepi16_epi32(_mm256_extracti128_si256(*a, 1));
      16   103486000 :   a_32[1] = _mm256_cvtepi16_epi32(_mm256_extracti128_si256(*a, 0));
      17             : 
      18   103486000 :   b_32[0] = _mm256_cvtepi16_epi32(_mm256_extracti128_si256(*b, 1));
      19   103486000 :   b_32[1] = _mm256_cvtepi16_epi32(_mm256_extracti128_si256(*b, 0));
      20             : 
      21   103486000 :   out[0] = _mm256_mullo_epi32(a_32[0], b_32[0]);
      22   103486000 :   out[1] = _mm256_mullo_epi32(a_32[1], b_32[1]);
      23   103486000 : }
      24        4800 : void get_proj_subspace_avx2(const uint8_t *src8, int width, int height,
      25             :                             int src_stride, const uint8_t *dat8,
      26             :                             int dat_stride, int use_highbitdepth,
      27             :                             int32_t *flt0, int flt0_stride, int32_t *flt1,
      28             :                             int flt1_stride, int *xq,
      29             :                             const SgrParamsType *params) {
      30             :   int i, j;
      31        4800 :   double H[2][2] = { { 0, 0 }, { 0, 0 } };
      32        4800 :   double C[2] = { 0, 0 };
      33             :   double Det;
      34             :   double x[2];
      35        4800 :   const int size = width * height;
      36             : 
      37        4800 :   aom_clear_system_state();
      38        4800 :   RunEmms();
      39             : 
      40             :   // Default
      41        4800 :   xq[0] = 0;
      42        4800 :   xq[1] = 0;
      43             : 
      44             :   __m256i  H_00, H_01, H_11;
      45             :   __m256i  C_0, C_1;
      46        4800 :   H_00 = _mm256_setzero_si256();
      47        4800 :   H_01 = _mm256_setzero_si256();
      48        4800 :   H_11 = _mm256_setzero_si256();
      49        4800 :   C_0 = _mm256_setzero_si256();
      50        4800 :   C_1 = _mm256_setzero_si256();
      51             : 
      52             :   __m256i u_256, s_256, f1_256, f2_256;
      53             :   __m256i f1_256_tmp, f2_256_tmp;
      54             :   __m256i out[2];
      55        4800 :   int avx2_cnt = 0;
      56             : 
      57        4800 :   if (!use_highbitdepth) {
      58        4800 :     const uint8_t *src = src8;
      59        4800 :     const uint8_t *dat = dat8;
      60     1379910 :     for (i = 0; i < height; ++i) {
      61    22096000 :       for (j = 0, avx2_cnt = 0; avx2_cnt < width / 16; j += 16, ++avx2_cnt) {
      62    41441900 :         u_256 = _mm256_cvtepu8_epi16(_mm_loadu_si128(
      63    20720900 :             (const __m128i *)(dat + i * dat_stride + j)));
      64    20720900 :         u_256 = _mm256_slli_epi16(u_256, SGRPROJ_RST_BITS);
      65             : 
      66    20720900 :         s_256 = _mm256_cvtepu8_epi16(_mm_loadu_si128(
      67    20720900 :             (const __m128i *)(src + i * src_stride + j)));
      68    20720900 :         s_256 = _mm256_slli_epi16(s_256, SGRPROJ_RST_BITS);
      69    20720900 :         s_256 = _mm256_sub_epi16(s_256, u_256);
      70             : 
      71    20720900 :         if (params->r[0] > 0) {
      72    15544100 :           f1_256 = _mm256_loadu_si256(
      73    15544100 :               (const __m256i *)(flt0 + i * flt0_stride + j));
      74    15544100 :           f1_256_tmp = _mm256_loadu_si256(
      75    15544100 :               (const __m256i *)(flt0 + i * flt0_stride + j + 8));
      76             : 
      77    15544100 :           f1_256 = _mm256_hadd_epi16(f1_256, f1_256_tmp);
      78    15544100 :           f1_256 = _mm256_permute4x64_epi64(f1_256, 0xD8);
      79    31088100 :           f1_256 = _mm256_sub_epi16(f1_256, u_256);
      80             :         } else
      81     5176880 :           f1_256 = _mm256_set1_epi16(0);
      82    20720900 :         if (params->r[1] > 0) {
      83    18134000 :           f2_256 = _mm256_loadu_si256(
      84    18134000 :               (const __m256i *)(flt1 + i * flt1_stride + j));
      85    18134000 :           f2_256_tmp = _mm256_loadu_si256(
      86    18134000 :               (const __m256i *)(flt1 + i * flt1_stride + j + 8));
      87             : 
      88    18134000 :           f2_256 = _mm256_hadd_epi16(f2_256, f2_256_tmp);
      89    18134000 :           f2_256 = _mm256_permute4x64_epi64(f2_256, 0xD8);
      90    36268000 :           f2_256 = _mm256_sub_epi16(f2_256, u_256);
      91             :         } else
      92     2586940 :           f2_256 = _mm256_set1_epi16(0);
      93             :         //    H[0][0] += f1 * f1;
      94    20720900 :         avx2_mul_epi16_epi32(&f1_256, &f1_256, out);
      95    20722100 :         H_00 = _mm256_add_epi32(H_00, out[0]);
      96    20722100 :         H_00 = _mm256_add_epi32(H_00, out[1]);
      97             : 
      98             :         //    H[1][1] += f2 * f2;
      99    20722100 :         avx2_mul_epi16_epi32(&f2_256, &f2_256, out);
     100    20720000 :         H_11 = _mm256_add_epi32(H_11, out[0]);
     101    20720000 :         H_11 = _mm256_add_epi32(H_11, out[1]);
     102             :         //    H[0][1] += f1 * f2;
     103    20720000 :         avx2_mul_epi16_epi32(&f1_256, &f2_256, out);
     104    20714200 :         H_01 = _mm256_add_epi32(H_01, out[0]);
     105    20714200 :         H_01 = _mm256_add_epi32(H_01, out[1]);
     106             : 
     107             :         //    C[0] += f1 * s;
     108    20714200 :         avx2_mul_epi16_epi32(&f1_256, &s_256, out);
     109    20713900 :         C_0 = _mm256_add_epi32(C_0, out[0]);
     110    20713900 :         C_0 = _mm256_add_epi32(C_0, out[1]);
     111             : 
     112             :         //    C[1] += f2 * s;
     113    20713900 :         avx2_mul_epi16_epi32(&f2_256, &s_256, out);
     114    20713700 :         C_1 = _mm256_add_epi32(C_1, out[0]);
     115    41427300 :         C_1 = _mm256_add_epi32(C_1, out[1]);
     116             :       }
     117             : 
     118             :       //Complement when width not divided by 16
     119     1375110 :       for (; j < width; ++j) {
     120           0 :         const double u = (double)(dat[i * dat_stride + j] << SGRPROJ_RST_BITS);
     121           0 :         const double s =
     122           0 :             (double)(src[i * src_stride + j] << SGRPROJ_RST_BITS) - u;
     123           0 :         const double f1 =
     124           0 :             (params->r[0] > 0) ? (double)flt0[i * flt0_stride + j] - u : 0;
     125           0 :         const double f2 =
     126           0 :             (params->r[1] > 0) ? (double)flt1[i * flt1_stride + j] - u : 0;
     127           0 :         H[0][0] += f1 * f1;
     128           0 :         H[1][1] += f2 * f2;
     129           0 :         H[0][1] += f1 * f2;
     130           0 :         C[0] += f1 * s;
     131           0 :         C[1] += f2 * s;
     132             :       }
     133             : 
     134             :       //Summary in each row, to not overflow 32 bits value H_
     135     1375110 :       H_00 = _mm256_hadd_epi32(H_00, H_00);//indexes 0,1,4,5
     136     1375110 :       H_00 = _mm256_hadd_epi32(H_00, H_00);//indexes 0,4
     137     1375110 :       H[0][0] += (double)_mm256_extract_epi32(H_00, 0) +
     138     1375110 :           _mm256_extract_epi32(H_00, 4);
     139             : 
     140     1375110 :       H_11 = _mm256_hadd_epi32(H_11, H_11);//indexes 0,1,4,5
     141     1375110 :       H_11 = _mm256_hadd_epi32(H_11, H_11);//indexes 0,4
     142     1375110 :       H[1][1] += (double)_mm256_extract_epi32(H_11, 0) +
     143     1375110 :           _mm256_extract_epi32(H_11, 4);
     144             : 
     145     1375110 :       H_01 = _mm256_hadd_epi32(H_01, H_01);//indexes 0,1,4,5
     146     1375110 :       H_01 = _mm256_hadd_epi32(H_01, H_01);//indexes 0,4
     147     1375110 :       H[0][1] += (double)_mm256_extract_epi32(H_01, 0) +
     148     1375110 :           _mm256_extract_epi32(H_01, 4);
     149             : 
     150     1375110 :       C_0 = _mm256_hadd_epi32(C_0, C_0);//indexes 0,1,4,5
     151     1375110 :       C_0 = _mm256_hadd_epi32(C_0, C_0);//indexes 0,4
     152     1375110 :       C[0] += (double)_mm256_extract_epi32(C_0, 0) +
     153     1375110 :           _mm256_extract_epi32(C_0, 4);
     154             : 
     155     1375110 :       C_1 = _mm256_hadd_epi32(C_1, C_1);//indexes 0,1,4,5
     156     1375110 :       C_1 = _mm256_hadd_epi32(C_1, C_1);//indexes 0,4
     157     1375110 :       C[1] += (double)_mm256_extract_epi32(C_1, 0) +
     158     1375110 :           _mm256_extract_epi32(C_1, 4);
     159             : 
     160     1375110 :       H_00 = _mm256_setzero_si256();
     161     1375110 :       H_01 = _mm256_setzero_si256();
     162     1375110 :       H_11 = _mm256_setzero_si256();
     163     1375110 :       C_0 = _mm256_setzero_si256();
     164     1375110 :       C_1 = _mm256_setzero_si256();
     165             :     }
     166             :   } else {
     167           0 :     const uint16_t *src = CONVERT_TO_SHORTPTR(src8);
     168           0 :     const uint16_t *dat = CONVERT_TO_SHORTPTR(dat8);
     169             : 
     170           0 :     for (i = 0; i < height; ++i) {
     171           0 :       for (j = 0, avx2_cnt = 0; avx2_cnt < width / 16; j += 16, ++avx2_cnt) {
     172           0 :         u_256 = _mm256_loadu_si256(
     173           0 :             (const __m256i *)(dat + i * dat_stride + j));
     174           0 :         u_256 = _mm256_slli_epi16(u_256, SGRPROJ_RST_BITS);
     175             : 
     176           0 :         s_256 = _mm256_loadu_si256(
     177           0 :             (const __m256i *)(src + i * src_stride + j));
     178           0 :         s_256 = _mm256_slli_epi16(s_256, SGRPROJ_RST_BITS);
     179           0 :         s_256 = _mm256_sub_epi16(s_256, u_256);
     180             : 
     181           0 :         if (params->r[0] > 0) {
     182           0 :           f1_256 = _mm256_loadu_si256(
     183           0 :               (const __m256i *)(flt0 + i * flt0_stride + j));
     184           0 :           f1_256_tmp = _mm256_loadu_si256(
     185           0 :               (const __m256i *)(flt0 + i * flt0_stride + j + 8));
     186             : 
     187           0 :           f1_256 = _mm256_hadd_epi16(f1_256, f1_256_tmp);
     188           0 :           f1_256 = _mm256_permute4x64_epi64(f1_256, 0xD8);
     189           0 :           f1_256 = _mm256_sub_epi16(f1_256, u_256);
     190             :         } else
     191           0 :           f1_256 = _mm256_set1_epi16(0);
     192           0 :         if (params->r[1] > 0) {
     193           0 :           f2_256 = _mm256_loadu_si256(
     194           0 :               (const __m256i *)(flt1 + i * flt1_stride + j));
     195           0 :           f2_256_tmp = _mm256_loadu_si256(
     196           0 :               (const __m256i *)(flt1 + i * flt1_stride + j + 8));
     197             : 
     198           0 :           f2_256 = _mm256_hadd_epi16(f2_256, f2_256_tmp);
     199           0 :           f2_256 = _mm256_permute4x64_epi64(f2_256, 0xD8);
     200           0 :           f2_256 = _mm256_sub_epi16(f2_256, u_256);
     201             :         } else
     202           0 :           f2_256 = _mm256_set1_epi16(0);
     203             :         //    H[0][0] += f1 * f1;
     204           0 :         avx2_mul_epi16_epi32(&f1_256, &f1_256, out);
     205           0 :         H_00 = _mm256_add_epi32(H_00, out[0]);
     206           0 :         H_00 = _mm256_add_epi32(H_00, out[1]);
     207             : 
     208             :         //    H[1][1] += f2 * f2;
     209           0 :         avx2_mul_epi16_epi32(&f2_256, &f2_256, out);
     210           0 :         H_11 = _mm256_add_epi32(H_11, out[0]);
     211           0 :         H_11 = _mm256_add_epi32(H_11, out[1]);
     212             :         //    H[0][1] += f1 * f2;
     213           0 :         avx2_mul_epi16_epi32(&f1_256, &f2_256, out);
     214           0 :         H_01 = _mm256_add_epi32(H_01, out[0]);
     215           0 :         H_01 = _mm256_add_epi32(H_01, out[1]);
     216             : 
     217             :         //    C[0] += f1 * s;
     218           0 :         avx2_mul_epi16_epi32(&f1_256, &s_256, out);
     219           0 :         C_0 = _mm256_add_epi32(C_0, out[0]);
     220           0 :         C_0 = _mm256_add_epi32(C_0, out[1]);
     221             : 
     222             :         //    C[1] += f2 * s;
     223           0 :         avx2_mul_epi16_epi32(&f2_256, &s_256, out);
     224           0 :         C_1 = _mm256_add_epi32(C_1, out[0]);
     225           0 :         C_1 = _mm256_add_epi32(C_1, out[1]);
     226             :       }
     227             : 
     228             :       //Complement when width not divided by 16
     229           0 :       for (; j < width; ++j) {
     230           0 :         const double u = (double)(dat[i * dat_stride + j] << SGRPROJ_RST_BITS);
     231           0 :         const double s =
     232           0 :             (double)(src[i * src_stride + j] << SGRPROJ_RST_BITS) - u;
     233           0 :         const double f1 =
     234           0 :             (params->r[0] > 0) ? (double)flt0[i * flt0_stride + j] - u : 0;
     235           0 :         const double f2 =
     236           0 :             (params->r[1] > 0) ? (double)flt1[i * flt1_stride + j] - u : 0;
     237           0 :         H[0][0] += f1 * f1;
     238           0 :         H[1][1] += f2 * f2;
     239           0 :         H[0][1] += f1 * f2;
     240           0 :         C[0] += f1 * s;
     241           0 :         C[1] += f2 * s;
     242             :       }
     243             : 
     244             :       //Summary in each row, to not overflow 32 bits value H_
     245           0 :       H_00 = _mm256_hadd_epi32(H_00, H_00);//indexes 0,1,4,5
     246           0 :       H_00 = _mm256_hadd_epi32(H_00, H_00);//indexes 0,4
     247           0 :       H[0][0] += (double)_mm256_extract_epi32(H_00, 0) +
     248           0 :           _mm256_extract_epi32(H_00, 4);
     249             : 
     250           0 :       H_11 = _mm256_hadd_epi32(H_11, H_11);//indexes 0,1,4,5
     251           0 :       H_11 = _mm256_hadd_epi32(H_11, H_11);//indexes 0,4
     252           0 :       H[1][1] += (double)_mm256_extract_epi32(H_11, 0) +
     253           0 :           _mm256_extract_epi32(H_11, 4);
     254             : 
     255           0 :       H_01 = _mm256_hadd_epi32(H_01, H_01);//indexes 0,1,4,5
     256           0 :       H_01 = _mm256_hadd_epi32(H_01, H_01);//indexes 0,4
     257           0 :       H[0][1] += (double)_mm256_extract_epi32(H_01, 0) +
     258           0 :           _mm256_extract_epi32(H_01, 4);
     259             : 
     260           0 :       C_0 = _mm256_hadd_epi32(C_0, C_0);//indexes 0,1,4,5
     261           0 :       C_0 = _mm256_hadd_epi32(C_0, C_0);//indexes 0,4
     262           0 :       C[0] += (double)_mm256_extract_epi32(C_0, 0) +
     263           0 :           _mm256_extract_epi32(C_0, 4);
     264             : 
     265           0 :       C_1 = _mm256_hadd_epi32(C_1, C_1);//indexes 0,1,4,5
     266           0 :       C_1 = _mm256_hadd_epi32(C_1, C_1);//indexes 0,4
     267           0 :       C[1] += (double)_mm256_extract_epi32(C_1, 0) +
     268           0 :           _mm256_extract_epi32(C_1, 4);
     269             : 
     270           0 :       H_00 = _mm256_setzero_si256();
     271           0 :       H_01 = _mm256_setzero_si256();
     272           0 :       H_11 = _mm256_setzero_si256();
     273           0 :       C_0 = _mm256_setzero_si256();
     274           0 :       C_1 = _mm256_setzero_si256();
     275             :     }
     276             :   }
     277             : 
     278           0 :   H[0][0] /= size;
     279           0 :   H[0][1] /= size;
     280           0 :   H[1][1] /= size;
     281           0 :   H[1][0] = H[0][1];
     282           0 :   C[0] /= size;
     283           0 :   C[1] /= size;
     284           0 :   if (params->r[0] == 0) {
     285             :     // H matrix is now only the scalar H[1][1]
     286             :     // C vector is now only the scalar C[1]
     287        1200 :     Det = H[1][1];
     288        1200 :     if (Det < 1e-8) return;  // ill-posed, return default values
     289        1200 :     x[0] = 0;
     290        1200 :     x[1] = C[1] / Det;
     291             : 
     292        1200 :     xq[0] = 0;
     293        1200 :     xq[1] = (int)rint(x[1] * (1 << SGRPROJ_PRJ_BITS));
     294           0 :   } else if (params->r[1] == 0) {
     295             :     // H matrix is now only the scalar H[0][0]
     296             :     // C vector is now only the scalar C[0]
     297         600 :     Det = H[0][0];
     298         600 :     if (Det < 1e-8) return;  // ill-posed, return default values
     299         600 :     x[0] = C[0] / Det;
     300         600 :     x[1] = 0;
     301             : 
     302         600 :     xq[0] = (int)rint(x[0] * (1 << SGRPROJ_PRJ_BITS));
     303         600 :     xq[1] = 0;
     304             :   } else {
     305           0 :     Det = (H[0][0] * H[1][1] - H[0][1] * H[1][0]);
     306           0 :     if (Det < 1e-8) return;  // ill-posed, return default values
     307           0 :     x[0] = (H[1][1] * C[0] - H[0][1] * C[1]) / Det;
     308           0 :     x[1] = (H[0][0] * C[1] - H[1][0] * C[0]) / Det;
     309             : 
     310           0 :     xq[0] = (int)rint(x[0] * (1 << SGRPROJ_PRJ_BITS));
     311           0 :     xq[1] = (int)rint(x[1] * (1 << SGRPROJ_PRJ_BITS));
     312             :   }
     313             :  }

Generated by: LCOV version 1.14