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

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2016, 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 <immintrin.h>  // avx2
      13             : 
      14             : #include "./av1_rtcd.h"
      15             : #include "./aom_dsp_rtcd.h"
      16             : 
      17             : #include "aom_dsp/x86/fwd_txfm_avx2.h"
      18             : #include "aom_dsp/txfm_common.h"
      19             : #include "aom_dsp/x86/txfm_common_avx2.h"
      20             : 
      21           0 : static int32_t get_16x16_sum(const int16_t *input, int stride) {
      22             :   __m256i r0, r1, r2, r3, u0, u1;
      23           0 :   __m256i zero = _mm256_setzero_si256();
      24           0 :   __m256i sum = _mm256_setzero_si256();
      25           0 :   const int16_t *blockBound = input + (stride << 4);
      26             :   __m128i v0, v1;
      27             : 
      28           0 :   while (input < blockBound) {
      29           0 :     r0 = _mm256_loadu_si256((__m256i const *)input);
      30           0 :     r1 = _mm256_loadu_si256((__m256i const *)(input + stride));
      31           0 :     r2 = _mm256_loadu_si256((__m256i const *)(input + 2 * stride));
      32           0 :     r3 = _mm256_loadu_si256((__m256i const *)(input + 3 * stride));
      33             : 
      34           0 :     u0 = _mm256_add_epi16(r0, r1);
      35           0 :     u1 = _mm256_add_epi16(r2, r3);
      36           0 :     sum = _mm256_add_epi16(sum, u0);
      37           0 :     sum = _mm256_add_epi16(sum, u1);
      38             : 
      39           0 :     input += stride << 2;
      40             :   }
      41             : 
      42             :   // unpack 16 int16_t into 2x8 int32_t
      43           0 :   u0 = _mm256_unpacklo_epi16(zero, sum);
      44           0 :   u1 = _mm256_unpackhi_epi16(zero, sum);
      45           0 :   u0 = _mm256_srai_epi32(u0, 16);
      46           0 :   u1 = _mm256_srai_epi32(u1, 16);
      47           0 :   sum = _mm256_add_epi32(u0, u1);
      48             : 
      49           0 :   u0 = _mm256_srli_si256(sum, 8);
      50           0 :   u1 = _mm256_add_epi32(sum, u0);
      51             : 
      52           0 :   v0 = _mm_add_epi32(_mm256_extracti128_si256(u1, 1),
      53             :                      _mm256_castsi256_si128(u1));
      54           0 :   v1 = _mm_srli_si128(v0, 4);
      55           0 :   v0 = _mm_add_epi32(v0, v1);
      56           0 :   return (int32_t)_mm_extract_epi32(v0, 0);
      57             : }
      58             : 
      59           0 : void aom_fdct16x16_1_avx2(const int16_t *input, tran_low_t *output,
      60             :                           int stride) {
      61           0 :   int32_t dc = get_16x16_sum(input, stride);
      62           0 :   output[0] = (tran_low_t)(dc >> 1);
      63             :   _mm256_zeroupper();
      64           0 : }
      65             : 
      66           0 : static INLINE void load_buffer_16x16(const int16_t *input, int stride,
      67             :                                      int flipud, int fliplr, __m256i *in) {
      68           0 :   if (!flipud) {
      69           0 :     in[0] = _mm256_loadu_si256((const __m256i *)(input + 0 * stride));
      70           0 :     in[1] = _mm256_loadu_si256((const __m256i *)(input + 1 * stride));
      71           0 :     in[2] = _mm256_loadu_si256((const __m256i *)(input + 2 * stride));
      72           0 :     in[3] = _mm256_loadu_si256((const __m256i *)(input + 3 * stride));
      73           0 :     in[4] = _mm256_loadu_si256((const __m256i *)(input + 4 * stride));
      74           0 :     in[5] = _mm256_loadu_si256((const __m256i *)(input + 5 * stride));
      75           0 :     in[6] = _mm256_loadu_si256((const __m256i *)(input + 6 * stride));
      76           0 :     in[7] = _mm256_loadu_si256((const __m256i *)(input + 7 * stride));
      77           0 :     in[8] = _mm256_loadu_si256((const __m256i *)(input + 8 * stride));
      78           0 :     in[9] = _mm256_loadu_si256((const __m256i *)(input + 9 * stride));
      79           0 :     in[10] = _mm256_loadu_si256((const __m256i *)(input + 10 * stride));
      80           0 :     in[11] = _mm256_loadu_si256((const __m256i *)(input + 11 * stride));
      81           0 :     in[12] = _mm256_loadu_si256((const __m256i *)(input + 12 * stride));
      82           0 :     in[13] = _mm256_loadu_si256((const __m256i *)(input + 13 * stride));
      83           0 :     in[14] = _mm256_loadu_si256((const __m256i *)(input + 14 * stride));
      84           0 :     in[15] = _mm256_loadu_si256((const __m256i *)(input + 15 * stride));
      85             :   } else {
      86           0 :     in[0] = _mm256_loadu_si256((const __m256i *)(input + 15 * stride));
      87           0 :     in[1] = _mm256_loadu_si256((const __m256i *)(input + 14 * stride));
      88           0 :     in[2] = _mm256_loadu_si256((const __m256i *)(input + 13 * stride));
      89           0 :     in[3] = _mm256_loadu_si256((const __m256i *)(input + 12 * stride));
      90           0 :     in[4] = _mm256_loadu_si256((const __m256i *)(input + 11 * stride));
      91           0 :     in[5] = _mm256_loadu_si256((const __m256i *)(input + 10 * stride));
      92           0 :     in[6] = _mm256_loadu_si256((const __m256i *)(input + 9 * stride));
      93           0 :     in[7] = _mm256_loadu_si256((const __m256i *)(input + 8 * stride));
      94           0 :     in[8] = _mm256_loadu_si256((const __m256i *)(input + 7 * stride));
      95           0 :     in[9] = _mm256_loadu_si256((const __m256i *)(input + 6 * stride));
      96           0 :     in[10] = _mm256_loadu_si256((const __m256i *)(input + 5 * stride));
      97           0 :     in[11] = _mm256_loadu_si256((const __m256i *)(input + 4 * stride));
      98           0 :     in[12] = _mm256_loadu_si256((const __m256i *)(input + 3 * stride));
      99           0 :     in[13] = _mm256_loadu_si256((const __m256i *)(input + 2 * stride));
     100           0 :     in[14] = _mm256_loadu_si256((const __m256i *)(input + 1 * stride));
     101           0 :     in[15] = _mm256_loadu_si256((const __m256i *)(input + 0 * stride));
     102             :   }
     103             : 
     104           0 :   if (fliplr) {
     105           0 :     mm256_reverse_epi16(&in[0]);
     106           0 :     mm256_reverse_epi16(&in[1]);
     107           0 :     mm256_reverse_epi16(&in[2]);
     108           0 :     mm256_reverse_epi16(&in[3]);
     109           0 :     mm256_reverse_epi16(&in[4]);
     110           0 :     mm256_reverse_epi16(&in[5]);
     111           0 :     mm256_reverse_epi16(&in[6]);
     112           0 :     mm256_reverse_epi16(&in[7]);
     113           0 :     mm256_reverse_epi16(&in[8]);
     114           0 :     mm256_reverse_epi16(&in[9]);
     115           0 :     mm256_reverse_epi16(&in[10]);
     116           0 :     mm256_reverse_epi16(&in[11]);
     117           0 :     mm256_reverse_epi16(&in[12]);
     118           0 :     mm256_reverse_epi16(&in[13]);
     119           0 :     mm256_reverse_epi16(&in[14]);
     120           0 :     mm256_reverse_epi16(&in[15]);
     121             :   }
     122             : 
     123           0 :   in[0] = _mm256_slli_epi16(in[0], 2);
     124           0 :   in[1] = _mm256_slli_epi16(in[1], 2);
     125           0 :   in[2] = _mm256_slli_epi16(in[2], 2);
     126           0 :   in[3] = _mm256_slli_epi16(in[3], 2);
     127           0 :   in[4] = _mm256_slli_epi16(in[4], 2);
     128           0 :   in[5] = _mm256_slli_epi16(in[5], 2);
     129           0 :   in[6] = _mm256_slli_epi16(in[6], 2);
     130           0 :   in[7] = _mm256_slli_epi16(in[7], 2);
     131           0 :   in[8] = _mm256_slli_epi16(in[8], 2);
     132           0 :   in[9] = _mm256_slli_epi16(in[9], 2);
     133           0 :   in[10] = _mm256_slli_epi16(in[10], 2);
     134           0 :   in[11] = _mm256_slli_epi16(in[11], 2);
     135           0 :   in[12] = _mm256_slli_epi16(in[12], 2);
     136           0 :   in[13] = _mm256_slli_epi16(in[13], 2);
     137           0 :   in[14] = _mm256_slli_epi16(in[14], 2);
     138           0 :   in[15] = _mm256_slli_epi16(in[15], 2);
     139           0 : }
     140             : 
     141           0 : static INLINE void write_buffer_16x16(const __m256i *in, tran_low_t *output) {
     142             :   int i;
     143           0 :   for (i = 0; i < 16; ++i) {
     144           0 :     storeu_output_avx2(&in[i], output + (i << 4));
     145             :   }
     146           0 : }
     147             : 
     148           0 : static void right_shift_16x16(__m256i *in) {
     149           0 :   const __m256i one = _mm256_set1_epi16(1);
     150           0 :   __m256i s0 = _mm256_srai_epi16(in[0], 15);
     151           0 :   __m256i s1 = _mm256_srai_epi16(in[1], 15);
     152           0 :   __m256i s2 = _mm256_srai_epi16(in[2], 15);
     153           0 :   __m256i s3 = _mm256_srai_epi16(in[3], 15);
     154           0 :   __m256i s4 = _mm256_srai_epi16(in[4], 15);
     155           0 :   __m256i s5 = _mm256_srai_epi16(in[5], 15);
     156           0 :   __m256i s6 = _mm256_srai_epi16(in[6], 15);
     157           0 :   __m256i s7 = _mm256_srai_epi16(in[7], 15);
     158           0 :   __m256i s8 = _mm256_srai_epi16(in[8], 15);
     159           0 :   __m256i s9 = _mm256_srai_epi16(in[9], 15);
     160           0 :   __m256i s10 = _mm256_srai_epi16(in[10], 15);
     161           0 :   __m256i s11 = _mm256_srai_epi16(in[11], 15);
     162           0 :   __m256i s12 = _mm256_srai_epi16(in[12], 15);
     163           0 :   __m256i s13 = _mm256_srai_epi16(in[13], 15);
     164           0 :   __m256i s14 = _mm256_srai_epi16(in[14], 15);
     165           0 :   __m256i s15 = _mm256_srai_epi16(in[15], 15);
     166             : 
     167           0 :   in[0] = _mm256_add_epi16(in[0], one);
     168           0 :   in[1] = _mm256_add_epi16(in[1], one);
     169           0 :   in[2] = _mm256_add_epi16(in[2], one);
     170           0 :   in[3] = _mm256_add_epi16(in[3], one);
     171           0 :   in[4] = _mm256_add_epi16(in[4], one);
     172           0 :   in[5] = _mm256_add_epi16(in[5], one);
     173           0 :   in[6] = _mm256_add_epi16(in[6], one);
     174           0 :   in[7] = _mm256_add_epi16(in[7], one);
     175           0 :   in[8] = _mm256_add_epi16(in[8], one);
     176           0 :   in[9] = _mm256_add_epi16(in[9], one);
     177           0 :   in[10] = _mm256_add_epi16(in[10], one);
     178           0 :   in[11] = _mm256_add_epi16(in[11], one);
     179           0 :   in[12] = _mm256_add_epi16(in[12], one);
     180           0 :   in[13] = _mm256_add_epi16(in[13], one);
     181           0 :   in[14] = _mm256_add_epi16(in[14], one);
     182           0 :   in[15] = _mm256_add_epi16(in[15], one);
     183             : 
     184           0 :   in[0] = _mm256_sub_epi16(in[0], s0);
     185           0 :   in[1] = _mm256_sub_epi16(in[1], s1);
     186           0 :   in[2] = _mm256_sub_epi16(in[2], s2);
     187           0 :   in[3] = _mm256_sub_epi16(in[3], s3);
     188           0 :   in[4] = _mm256_sub_epi16(in[4], s4);
     189           0 :   in[5] = _mm256_sub_epi16(in[5], s5);
     190           0 :   in[6] = _mm256_sub_epi16(in[6], s6);
     191           0 :   in[7] = _mm256_sub_epi16(in[7], s7);
     192           0 :   in[8] = _mm256_sub_epi16(in[8], s8);
     193           0 :   in[9] = _mm256_sub_epi16(in[9], s9);
     194           0 :   in[10] = _mm256_sub_epi16(in[10], s10);
     195           0 :   in[11] = _mm256_sub_epi16(in[11], s11);
     196           0 :   in[12] = _mm256_sub_epi16(in[12], s12);
     197           0 :   in[13] = _mm256_sub_epi16(in[13], s13);
     198           0 :   in[14] = _mm256_sub_epi16(in[14], s14);
     199           0 :   in[15] = _mm256_sub_epi16(in[15], s15);
     200             : 
     201           0 :   in[0] = _mm256_srai_epi16(in[0], 2);
     202           0 :   in[1] = _mm256_srai_epi16(in[1], 2);
     203           0 :   in[2] = _mm256_srai_epi16(in[2], 2);
     204           0 :   in[3] = _mm256_srai_epi16(in[3], 2);
     205           0 :   in[4] = _mm256_srai_epi16(in[4], 2);
     206           0 :   in[5] = _mm256_srai_epi16(in[5], 2);
     207           0 :   in[6] = _mm256_srai_epi16(in[6], 2);
     208           0 :   in[7] = _mm256_srai_epi16(in[7], 2);
     209           0 :   in[8] = _mm256_srai_epi16(in[8], 2);
     210           0 :   in[9] = _mm256_srai_epi16(in[9], 2);
     211           0 :   in[10] = _mm256_srai_epi16(in[10], 2);
     212           0 :   in[11] = _mm256_srai_epi16(in[11], 2);
     213           0 :   in[12] = _mm256_srai_epi16(in[12], 2);
     214           0 :   in[13] = _mm256_srai_epi16(in[13], 2);
     215           0 :   in[14] = _mm256_srai_epi16(in[14], 2);
     216           0 :   in[15] = _mm256_srai_epi16(in[15], 2);
     217           0 : }
     218             : 
     219           0 : static void fdct16_avx2(__m256i *in) {
     220             :   // sequence: cospi_L_H = pairs(L, H) and L first
     221           0 :   const __m256i cospi_p16_m16 = pair256_set_epi16(cospi_16_64, -cospi_16_64);
     222           0 :   const __m256i cospi_p16_p16 = pair256_set_epi16(cospi_16_64, cospi_16_64);
     223           0 :   const __m256i cospi_p24_p08 = pair256_set_epi16(cospi_24_64, cospi_8_64);
     224           0 :   const __m256i cospi_m08_p24 = pair256_set_epi16(-cospi_8_64, cospi_24_64);
     225           0 :   const __m256i cospi_m24_m08 = pair256_set_epi16(-cospi_24_64, -cospi_8_64);
     226             : 
     227           0 :   const __m256i cospi_p28_p04 = pair256_set_epi16(cospi_28_64, cospi_4_64);
     228           0 :   const __m256i cospi_m04_p28 = pair256_set_epi16(-cospi_4_64, cospi_28_64);
     229           0 :   const __m256i cospi_p12_p20 = pair256_set_epi16(cospi_12_64, cospi_20_64);
     230           0 :   const __m256i cospi_m20_p12 = pair256_set_epi16(-cospi_20_64, cospi_12_64);
     231             : 
     232           0 :   const __m256i cospi_p30_p02 = pair256_set_epi16(cospi_30_64, cospi_2_64);
     233           0 :   const __m256i cospi_m02_p30 = pair256_set_epi16(-cospi_2_64, cospi_30_64);
     234             : 
     235           0 :   const __m256i cospi_p14_p18 = pair256_set_epi16(cospi_14_64, cospi_18_64);
     236           0 :   const __m256i cospi_m18_p14 = pair256_set_epi16(-cospi_18_64, cospi_14_64);
     237             : 
     238           0 :   const __m256i cospi_p22_p10 = pair256_set_epi16(cospi_22_64, cospi_10_64);
     239           0 :   const __m256i cospi_m10_p22 = pair256_set_epi16(-cospi_10_64, cospi_22_64);
     240             : 
     241           0 :   const __m256i cospi_p06_p26 = pair256_set_epi16(cospi_6_64, cospi_26_64);
     242           0 :   const __m256i cospi_m26_p06 = pair256_set_epi16(-cospi_26_64, cospi_6_64);
     243             : 
     244             :   __m256i u0, u1, u2, u3, u4, u5, u6, u7;
     245             :   __m256i s0, s1, s2, s3, s4, s5, s6, s7;
     246             :   __m256i t0, t1, t2, t3, t4, t5, t6, t7;
     247             :   __m256i v0, v1, v2, v3;
     248             :   __m256i x0, x1;
     249             : 
     250             :   // 0, 4, 8, 12
     251           0 :   u0 = _mm256_add_epi16(in[0], in[15]);
     252           0 :   u1 = _mm256_add_epi16(in[1], in[14]);
     253           0 :   u2 = _mm256_add_epi16(in[2], in[13]);
     254           0 :   u3 = _mm256_add_epi16(in[3], in[12]);
     255           0 :   u4 = _mm256_add_epi16(in[4], in[11]);
     256           0 :   u5 = _mm256_add_epi16(in[5], in[10]);
     257           0 :   u6 = _mm256_add_epi16(in[6], in[9]);
     258           0 :   u7 = _mm256_add_epi16(in[7], in[8]);
     259             : 
     260           0 :   s0 = _mm256_add_epi16(u0, u7);
     261           0 :   s1 = _mm256_add_epi16(u1, u6);
     262           0 :   s2 = _mm256_add_epi16(u2, u5);
     263           0 :   s3 = _mm256_add_epi16(u3, u4);
     264             : 
     265             :   // 0, 8
     266           0 :   v0 = _mm256_add_epi16(s0, s3);
     267           0 :   v1 = _mm256_add_epi16(s1, s2);
     268             : 
     269           0 :   x0 = _mm256_unpacklo_epi16(v0, v1);
     270           0 :   x1 = _mm256_unpackhi_epi16(v0, v1);
     271             : 
     272           0 :   t0 = butter_fly(&x0, &x1, &cospi_p16_p16);
     273           0 :   t1 = butter_fly(&x0, &x1, &cospi_p16_m16);
     274             : 
     275             :   // 4, 12
     276           0 :   v0 = _mm256_sub_epi16(s1, s2);
     277           0 :   v1 = _mm256_sub_epi16(s0, s3);
     278             : 
     279           0 :   x0 = _mm256_unpacklo_epi16(v0, v1);
     280           0 :   x1 = _mm256_unpackhi_epi16(v0, v1);
     281             : 
     282           0 :   t2 = butter_fly(&x0, &x1, &cospi_p24_p08);
     283           0 :   t3 = butter_fly(&x0, &x1, &cospi_m08_p24);
     284             : 
     285             :   // 2, 6, 10, 14
     286           0 :   s0 = _mm256_sub_epi16(u3, u4);
     287           0 :   s1 = _mm256_sub_epi16(u2, u5);
     288           0 :   s2 = _mm256_sub_epi16(u1, u6);
     289           0 :   s3 = _mm256_sub_epi16(u0, u7);
     290             : 
     291           0 :   v0 = s0;  // output[4]
     292           0 :   v3 = s3;  // output[7]
     293             : 
     294           0 :   x0 = _mm256_unpacklo_epi16(s2, s1);
     295           0 :   x1 = _mm256_unpackhi_epi16(s2, s1);
     296             : 
     297           0 :   v2 = butter_fly(&x0, &x1, &cospi_p16_p16);  // output[5]
     298           0 :   v1 = butter_fly(&x0, &x1, &cospi_p16_m16);  // output[6]
     299             : 
     300           0 :   s0 = _mm256_add_epi16(v0, v1);  // step[4]
     301           0 :   s1 = _mm256_sub_epi16(v0, v1);  // step[5]
     302           0 :   s2 = _mm256_sub_epi16(v3, v2);  // step[6]
     303           0 :   s3 = _mm256_add_epi16(v3, v2);  // step[7]
     304             : 
     305             :   // 2, 14
     306           0 :   x0 = _mm256_unpacklo_epi16(s0, s3);
     307           0 :   x1 = _mm256_unpackhi_epi16(s0, s3);
     308             : 
     309           0 :   t4 = butter_fly(&x0, &x1, &cospi_p28_p04);
     310           0 :   t5 = butter_fly(&x0, &x1, &cospi_m04_p28);
     311             : 
     312             :   // 10, 6
     313           0 :   x0 = _mm256_unpacklo_epi16(s1, s2);
     314           0 :   x1 = _mm256_unpackhi_epi16(s1, s2);
     315           0 :   t6 = butter_fly(&x0, &x1, &cospi_p12_p20);
     316           0 :   t7 = butter_fly(&x0, &x1, &cospi_m20_p12);
     317             : 
     318             :   // 1, 3, 5, 7, 9, 11, 13, 15
     319           0 :   s0 = _mm256_sub_epi16(in[7], in[8]);  // step[8]
     320           0 :   s1 = _mm256_sub_epi16(in[6], in[9]);  // step[9]
     321           0 :   u2 = _mm256_sub_epi16(in[5], in[10]);
     322           0 :   u3 = _mm256_sub_epi16(in[4], in[11]);
     323           0 :   u4 = _mm256_sub_epi16(in[3], in[12]);
     324           0 :   u5 = _mm256_sub_epi16(in[2], in[13]);
     325           0 :   s6 = _mm256_sub_epi16(in[1], in[14]);  // step[14]
     326           0 :   s7 = _mm256_sub_epi16(in[0], in[15]);  // step[15]
     327             : 
     328           0 :   in[0] = t0;
     329           0 :   in[8] = t1;
     330           0 :   in[4] = t2;
     331           0 :   in[12] = t3;
     332           0 :   in[2] = t4;
     333           0 :   in[14] = t5;
     334           0 :   in[10] = t6;
     335           0 :   in[6] = t7;
     336             : 
     337           0 :   x0 = _mm256_unpacklo_epi16(u5, u2);
     338           0 :   x1 = _mm256_unpackhi_epi16(u5, u2);
     339             : 
     340           0 :   s2 = butter_fly(&x0, &x1, &cospi_p16_p16);  // step[13]
     341           0 :   s5 = butter_fly(&x0, &x1, &cospi_p16_m16);  // step[10]
     342             : 
     343           0 :   x0 = _mm256_unpacklo_epi16(u4, u3);
     344           0 :   x1 = _mm256_unpackhi_epi16(u4, u3);
     345             : 
     346           0 :   s3 = butter_fly(&x0, &x1, &cospi_p16_p16);  // step[12]
     347           0 :   s4 = butter_fly(&x0, &x1, &cospi_p16_m16);  // step[11]
     348             : 
     349           0 :   u0 = _mm256_add_epi16(s0, s4);  // output[8]
     350           0 :   u1 = _mm256_add_epi16(s1, s5);
     351           0 :   u2 = _mm256_sub_epi16(s1, s5);
     352           0 :   u3 = _mm256_sub_epi16(s0, s4);
     353           0 :   u4 = _mm256_sub_epi16(s7, s3);
     354           0 :   u5 = _mm256_sub_epi16(s6, s2);
     355           0 :   u6 = _mm256_add_epi16(s6, s2);
     356           0 :   u7 = _mm256_add_epi16(s7, s3);
     357             : 
     358             :   // stage 4
     359           0 :   s0 = u0;
     360           0 :   s3 = u3;
     361           0 :   s4 = u4;
     362           0 :   s7 = u7;
     363             : 
     364           0 :   x0 = _mm256_unpacklo_epi16(u1, u6);
     365           0 :   x1 = _mm256_unpackhi_epi16(u1, u6);
     366             : 
     367           0 :   s1 = butter_fly(&x0, &x1, &cospi_m08_p24);
     368           0 :   s6 = butter_fly(&x0, &x1, &cospi_p24_p08);
     369             : 
     370           0 :   x0 = _mm256_unpacklo_epi16(u2, u5);
     371           0 :   x1 = _mm256_unpackhi_epi16(u2, u5);
     372             : 
     373           0 :   s2 = butter_fly(&x0, &x1, &cospi_m24_m08);
     374           0 :   s5 = butter_fly(&x0, &x1, &cospi_m08_p24);
     375             : 
     376             :   // stage 5
     377           0 :   u0 = _mm256_add_epi16(s0, s1);
     378           0 :   u1 = _mm256_sub_epi16(s0, s1);
     379           0 :   u2 = _mm256_sub_epi16(s3, s2);
     380           0 :   u3 = _mm256_add_epi16(s3, s2);
     381           0 :   u4 = _mm256_add_epi16(s4, s5);
     382           0 :   u5 = _mm256_sub_epi16(s4, s5);
     383           0 :   u6 = _mm256_sub_epi16(s7, s6);
     384           0 :   u7 = _mm256_add_epi16(s7, s6);
     385             : 
     386             :   // stage 6
     387           0 :   x0 = _mm256_unpacklo_epi16(u0, u7);
     388           0 :   x1 = _mm256_unpackhi_epi16(u0, u7);
     389           0 :   in[1] = butter_fly(&x0, &x1, &cospi_p30_p02);
     390           0 :   in[15] = butter_fly(&x0, &x1, &cospi_m02_p30);
     391             : 
     392           0 :   x0 = _mm256_unpacklo_epi16(u1, u6);
     393           0 :   x1 = _mm256_unpackhi_epi16(u1, u6);
     394           0 :   in[9] = butter_fly(&x0, &x1, &cospi_p14_p18);
     395           0 :   in[7] = butter_fly(&x0, &x1, &cospi_m18_p14);
     396             : 
     397           0 :   x0 = _mm256_unpacklo_epi16(u2, u5);
     398           0 :   x1 = _mm256_unpackhi_epi16(u2, u5);
     399           0 :   in[5] = butter_fly(&x0, &x1, &cospi_p22_p10);
     400           0 :   in[11] = butter_fly(&x0, &x1, &cospi_m10_p22);
     401             : 
     402           0 :   x0 = _mm256_unpacklo_epi16(u3, u4);
     403           0 :   x1 = _mm256_unpackhi_epi16(u3, u4);
     404           0 :   in[13] = butter_fly(&x0, &x1, &cospi_p06_p26);
     405           0 :   in[3] = butter_fly(&x0, &x1, &cospi_m26_p06);
     406           0 : }
     407             : 
     408           0 : void fadst16_avx2(__m256i *in) {
     409           0 :   const __m256i cospi_p01_p31 = pair256_set_epi16(cospi_1_64, cospi_31_64);
     410           0 :   const __m256i cospi_p31_m01 = pair256_set_epi16(cospi_31_64, -cospi_1_64);
     411           0 :   const __m256i cospi_p05_p27 = pair256_set_epi16(cospi_5_64, cospi_27_64);
     412           0 :   const __m256i cospi_p27_m05 = pair256_set_epi16(cospi_27_64, -cospi_5_64);
     413           0 :   const __m256i cospi_p09_p23 = pair256_set_epi16(cospi_9_64, cospi_23_64);
     414           0 :   const __m256i cospi_p23_m09 = pair256_set_epi16(cospi_23_64, -cospi_9_64);
     415           0 :   const __m256i cospi_p13_p19 = pair256_set_epi16(cospi_13_64, cospi_19_64);
     416           0 :   const __m256i cospi_p19_m13 = pair256_set_epi16(cospi_19_64, -cospi_13_64);
     417           0 :   const __m256i cospi_p17_p15 = pair256_set_epi16(cospi_17_64, cospi_15_64);
     418           0 :   const __m256i cospi_p15_m17 = pair256_set_epi16(cospi_15_64, -cospi_17_64);
     419           0 :   const __m256i cospi_p21_p11 = pair256_set_epi16(cospi_21_64, cospi_11_64);
     420           0 :   const __m256i cospi_p11_m21 = pair256_set_epi16(cospi_11_64, -cospi_21_64);
     421           0 :   const __m256i cospi_p25_p07 = pair256_set_epi16(cospi_25_64, cospi_7_64);
     422           0 :   const __m256i cospi_p07_m25 = pair256_set_epi16(cospi_7_64, -cospi_25_64);
     423           0 :   const __m256i cospi_p29_p03 = pair256_set_epi16(cospi_29_64, cospi_3_64);
     424           0 :   const __m256i cospi_p03_m29 = pair256_set_epi16(cospi_3_64, -cospi_29_64);
     425           0 :   const __m256i cospi_p04_p28 = pair256_set_epi16(cospi_4_64, cospi_28_64);
     426           0 :   const __m256i cospi_p28_m04 = pair256_set_epi16(cospi_28_64, -cospi_4_64);
     427           0 :   const __m256i cospi_p20_p12 = pair256_set_epi16(cospi_20_64, cospi_12_64);
     428           0 :   const __m256i cospi_p12_m20 = pair256_set_epi16(cospi_12_64, -cospi_20_64);
     429           0 :   const __m256i cospi_m28_p04 = pair256_set_epi16(-cospi_28_64, cospi_4_64);
     430           0 :   const __m256i cospi_m12_p20 = pair256_set_epi16(-cospi_12_64, cospi_20_64);
     431           0 :   const __m256i cospi_p08_p24 = pair256_set_epi16(cospi_8_64, cospi_24_64);
     432           0 :   const __m256i cospi_p24_m08 = pair256_set_epi16(cospi_24_64, -cospi_8_64);
     433           0 :   const __m256i cospi_m24_p08 = pair256_set_epi16(-cospi_24_64, cospi_8_64);
     434           0 :   const __m256i cospi_m16_m16 = _mm256_set1_epi16((int16_t)-cospi_16_64);
     435           0 :   const __m256i cospi_p16_p16 = _mm256_set1_epi16((int16_t)cospi_16_64);
     436           0 :   const __m256i cospi_p16_m16 = pair256_set_epi16(cospi_16_64, -cospi_16_64);
     437           0 :   const __m256i cospi_m16_p16 = pair256_set_epi16(-cospi_16_64, cospi_16_64);
     438           0 :   const __m256i zero = _mm256_setzero_si256();
     439           0 :   const __m256i dct_rounding = _mm256_set1_epi32(DCT_CONST_ROUNDING);
     440             :   __m256i s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15;
     441             :   __m256i x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;
     442             :   __m256i u0, u1, u2, u3, u4, u5, u6, u7, u8, u9, u10, u11, u12, u13, u14, u15;
     443             :   __m256i v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15;
     444             :   __m256i y0, y1;
     445             : 
     446             :   // stage 1, s takes low 256 bits; x takes high 256 bits
     447           0 :   y0 = _mm256_unpacklo_epi16(in[15], in[0]);
     448           0 :   y1 = _mm256_unpackhi_epi16(in[15], in[0]);
     449           0 :   s0 = _mm256_madd_epi16(y0, cospi_p01_p31);
     450           0 :   x0 = _mm256_madd_epi16(y1, cospi_p01_p31);
     451           0 :   s1 = _mm256_madd_epi16(y0, cospi_p31_m01);
     452           0 :   x1 = _mm256_madd_epi16(y1, cospi_p31_m01);
     453             : 
     454           0 :   y0 = _mm256_unpacklo_epi16(in[13], in[2]);
     455           0 :   y1 = _mm256_unpackhi_epi16(in[13], in[2]);
     456           0 :   s2 = _mm256_madd_epi16(y0, cospi_p05_p27);
     457           0 :   x2 = _mm256_madd_epi16(y1, cospi_p05_p27);
     458           0 :   s3 = _mm256_madd_epi16(y0, cospi_p27_m05);
     459           0 :   x3 = _mm256_madd_epi16(y1, cospi_p27_m05);
     460             : 
     461           0 :   y0 = _mm256_unpacklo_epi16(in[11], in[4]);
     462           0 :   y1 = _mm256_unpackhi_epi16(in[11], in[4]);
     463           0 :   s4 = _mm256_madd_epi16(y0, cospi_p09_p23);
     464           0 :   x4 = _mm256_madd_epi16(y1, cospi_p09_p23);
     465           0 :   s5 = _mm256_madd_epi16(y0, cospi_p23_m09);
     466           0 :   x5 = _mm256_madd_epi16(y1, cospi_p23_m09);
     467             : 
     468           0 :   y0 = _mm256_unpacklo_epi16(in[9], in[6]);
     469           0 :   y1 = _mm256_unpackhi_epi16(in[9], in[6]);
     470           0 :   s6 = _mm256_madd_epi16(y0, cospi_p13_p19);
     471           0 :   x6 = _mm256_madd_epi16(y1, cospi_p13_p19);
     472           0 :   s7 = _mm256_madd_epi16(y0, cospi_p19_m13);
     473           0 :   x7 = _mm256_madd_epi16(y1, cospi_p19_m13);
     474             : 
     475           0 :   y0 = _mm256_unpacklo_epi16(in[7], in[8]);
     476           0 :   y1 = _mm256_unpackhi_epi16(in[7], in[8]);
     477           0 :   s8 = _mm256_madd_epi16(y0, cospi_p17_p15);
     478           0 :   x8 = _mm256_madd_epi16(y1, cospi_p17_p15);
     479           0 :   s9 = _mm256_madd_epi16(y0, cospi_p15_m17);
     480           0 :   x9 = _mm256_madd_epi16(y1, cospi_p15_m17);
     481             : 
     482           0 :   y0 = _mm256_unpacklo_epi16(in[5], in[10]);
     483           0 :   y1 = _mm256_unpackhi_epi16(in[5], in[10]);
     484           0 :   s10 = _mm256_madd_epi16(y0, cospi_p21_p11);
     485           0 :   x10 = _mm256_madd_epi16(y1, cospi_p21_p11);
     486           0 :   s11 = _mm256_madd_epi16(y0, cospi_p11_m21);
     487           0 :   x11 = _mm256_madd_epi16(y1, cospi_p11_m21);
     488             : 
     489           0 :   y0 = _mm256_unpacklo_epi16(in[3], in[12]);
     490           0 :   y1 = _mm256_unpackhi_epi16(in[3], in[12]);
     491           0 :   s12 = _mm256_madd_epi16(y0, cospi_p25_p07);
     492           0 :   x12 = _mm256_madd_epi16(y1, cospi_p25_p07);
     493           0 :   s13 = _mm256_madd_epi16(y0, cospi_p07_m25);
     494           0 :   x13 = _mm256_madd_epi16(y1, cospi_p07_m25);
     495             : 
     496           0 :   y0 = _mm256_unpacklo_epi16(in[1], in[14]);
     497           0 :   y1 = _mm256_unpackhi_epi16(in[1], in[14]);
     498           0 :   s14 = _mm256_madd_epi16(y0, cospi_p29_p03);
     499           0 :   x14 = _mm256_madd_epi16(y1, cospi_p29_p03);
     500           0 :   s15 = _mm256_madd_epi16(y0, cospi_p03_m29);
     501           0 :   x15 = _mm256_madd_epi16(y1, cospi_p03_m29);
     502             : 
     503             :   // u takes low 256 bits; v takes high 256 bits
     504           0 :   u0 = _mm256_add_epi32(s0, s8);
     505           0 :   u1 = _mm256_add_epi32(s1, s9);
     506           0 :   u2 = _mm256_add_epi32(s2, s10);
     507           0 :   u3 = _mm256_add_epi32(s3, s11);
     508           0 :   u4 = _mm256_add_epi32(s4, s12);
     509           0 :   u5 = _mm256_add_epi32(s5, s13);
     510           0 :   u6 = _mm256_add_epi32(s6, s14);
     511           0 :   u7 = _mm256_add_epi32(s7, s15);
     512             : 
     513           0 :   u8 = _mm256_sub_epi32(s0, s8);
     514           0 :   u9 = _mm256_sub_epi32(s1, s9);
     515           0 :   u10 = _mm256_sub_epi32(s2, s10);
     516           0 :   u11 = _mm256_sub_epi32(s3, s11);
     517           0 :   u12 = _mm256_sub_epi32(s4, s12);
     518           0 :   u13 = _mm256_sub_epi32(s5, s13);
     519           0 :   u14 = _mm256_sub_epi32(s6, s14);
     520           0 :   u15 = _mm256_sub_epi32(s7, s15);
     521             : 
     522           0 :   v0 = _mm256_add_epi32(x0, x8);
     523           0 :   v1 = _mm256_add_epi32(x1, x9);
     524           0 :   v2 = _mm256_add_epi32(x2, x10);
     525           0 :   v3 = _mm256_add_epi32(x3, x11);
     526           0 :   v4 = _mm256_add_epi32(x4, x12);
     527           0 :   v5 = _mm256_add_epi32(x5, x13);
     528           0 :   v6 = _mm256_add_epi32(x6, x14);
     529           0 :   v7 = _mm256_add_epi32(x7, x15);
     530             : 
     531           0 :   v8 = _mm256_sub_epi32(x0, x8);
     532           0 :   v9 = _mm256_sub_epi32(x1, x9);
     533           0 :   v10 = _mm256_sub_epi32(x2, x10);
     534           0 :   v11 = _mm256_sub_epi32(x3, x11);
     535           0 :   v12 = _mm256_sub_epi32(x4, x12);
     536           0 :   v13 = _mm256_sub_epi32(x5, x13);
     537           0 :   v14 = _mm256_sub_epi32(x6, x14);
     538           0 :   v15 = _mm256_sub_epi32(x7, x15);
     539             : 
     540             :   // low 256 bits rounding
     541           0 :   u8 = _mm256_add_epi32(u8, dct_rounding);
     542           0 :   u9 = _mm256_add_epi32(u9, dct_rounding);
     543           0 :   u10 = _mm256_add_epi32(u10, dct_rounding);
     544           0 :   u11 = _mm256_add_epi32(u11, dct_rounding);
     545           0 :   u12 = _mm256_add_epi32(u12, dct_rounding);
     546           0 :   u13 = _mm256_add_epi32(u13, dct_rounding);
     547           0 :   u14 = _mm256_add_epi32(u14, dct_rounding);
     548           0 :   u15 = _mm256_add_epi32(u15, dct_rounding);
     549             : 
     550           0 :   u8 = _mm256_srai_epi32(u8, DCT_CONST_BITS);
     551           0 :   u9 = _mm256_srai_epi32(u9, DCT_CONST_BITS);
     552           0 :   u10 = _mm256_srai_epi32(u10, DCT_CONST_BITS);
     553           0 :   u11 = _mm256_srai_epi32(u11, DCT_CONST_BITS);
     554           0 :   u12 = _mm256_srai_epi32(u12, DCT_CONST_BITS);
     555           0 :   u13 = _mm256_srai_epi32(u13, DCT_CONST_BITS);
     556           0 :   u14 = _mm256_srai_epi32(u14, DCT_CONST_BITS);
     557           0 :   u15 = _mm256_srai_epi32(u15, DCT_CONST_BITS);
     558             : 
     559             :   // high 256 bits rounding
     560           0 :   v8 = _mm256_add_epi32(v8, dct_rounding);
     561           0 :   v9 = _mm256_add_epi32(v9, dct_rounding);
     562           0 :   v10 = _mm256_add_epi32(v10, dct_rounding);
     563           0 :   v11 = _mm256_add_epi32(v11, dct_rounding);
     564           0 :   v12 = _mm256_add_epi32(v12, dct_rounding);
     565           0 :   v13 = _mm256_add_epi32(v13, dct_rounding);
     566           0 :   v14 = _mm256_add_epi32(v14, dct_rounding);
     567           0 :   v15 = _mm256_add_epi32(v15, dct_rounding);
     568             : 
     569           0 :   v8 = _mm256_srai_epi32(v8, DCT_CONST_BITS);
     570           0 :   v9 = _mm256_srai_epi32(v9, DCT_CONST_BITS);
     571           0 :   v10 = _mm256_srai_epi32(v10, DCT_CONST_BITS);
     572           0 :   v11 = _mm256_srai_epi32(v11, DCT_CONST_BITS);
     573           0 :   v12 = _mm256_srai_epi32(v12, DCT_CONST_BITS);
     574           0 :   v13 = _mm256_srai_epi32(v13, DCT_CONST_BITS);
     575           0 :   v14 = _mm256_srai_epi32(v14, DCT_CONST_BITS);
     576           0 :   v15 = _mm256_srai_epi32(v15, DCT_CONST_BITS);
     577             : 
     578             :   // Saturation pack 32-bit to 16-bit
     579           0 :   x8 = _mm256_packs_epi32(u8, v8);
     580           0 :   x9 = _mm256_packs_epi32(u9, v9);
     581           0 :   x10 = _mm256_packs_epi32(u10, v10);
     582           0 :   x11 = _mm256_packs_epi32(u11, v11);
     583           0 :   x12 = _mm256_packs_epi32(u12, v12);
     584           0 :   x13 = _mm256_packs_epi32(u13, v13);
     585           0 :   x14 = _mm256_packs_epi32(u14, v14);
     586           0 :   x15 = _mm256_packs_epi32(u15, v15);
     587             : 
     588             :   // stage 2
     589           0 :   y0 = _mm256_unpacklo_epi16(x8, x9);
     590           0 :   y1 = _mm256_unpackhi_epi16(x8, x9);
     591           0 :   s8 = _mm256_madd_epi16(y0, cospi_p04_p28);
     592           0 :   x8 = _mm256_madd_epi16(y1, cospi_p04_p28);
     593           0 :   s9 = _mm256_madd_epi16(y0, cospi_p28_m04);
     594           0 :   x9 = _mm256_madd_epi16(y1, cospi_p28_m04);
     595             : 
     596           0 :   y0 = _mm256_unpacklo_epi16(x10, x11);
     597           0 :   y1 = _mm256_unpackhi_epi16(x10, x11);
     598           0 :   s10 = _mm256_madd_epi16(y0, cospi_p20_p12);
     599           0 :   x10 = _mm256_madd_epi16(y1, cospi_p20_p12);
     600           0 :   s11 = _mm256_madd_epi16(y0, cospi_p12_m20);
     601           0 :   x11 = _mm256_madd_epi16(y1, cospi_p12_m20);
     602             : 
     603           0 :   y0 = _mm256_unpacklo_epi16(x12, x13);
     604           0 :   y1 = _mm256_unpackhi_epi16(x12, x13);
     605           0 :   s12 = _mm256_madd_epi16(y0, cospi_m28_p04);
     606           0 :   x12 = _mm256_madd_epi16(y1, cospi_m28_p04);
     607           0 :   s13 = _mm256_madd_epi16(y0, cospi_p04_p28);
     608           0 :   x13 = _mm256_madd_epi16(y1, cospi_p04_p28);
     609             : 
     610           0 :   y0 = _mm256_unpacklo_epi16(x14, x15);
     611           0 :   y1 = _mm256_unpackhi_epi16(x14, x15);
     612           0 :   s14 = _mm256_madd_epi16(y0, cospi_m12_p20);
     613           0 :   x14 = _mm256_madd_epi16(y1, cospi_m12_p20);
     614           0 :   s15 = _mm256_madd_epi16(y0, cospi_p20_p12);
     615           0 :   x15 = _mm256_madd_epi16(y1, cospi_p20_p12);
     616             : 
     617           0 :   x0 = _mm256_add_epi32(u0, u4);
     618           0 :   s0 = _mm256_add_epi32(v0, v4);
     619           0 :   x1 = _mm256_add_epi32(u1, u5);
     620           0 :   s1 = _mm256_add_epi32(v1, v5);
     621           0 :   x2 = _mm256_add_epi32(u2, u6);
     622           0 :   s2 = _mm256_add_epi32(v2, v6);
     623           0 :   x3 = _mm256_add_epi32(u3, u7);
     624           0 :   s3 = _mm256_add_epi32(v3, v7);
     625             : 
     626           0 :   v8 = _mm256_sub_epi32(u0, u4);
     627           0 :   v9 = _mm256_sub_epi32(v0, v4);
     628           0 :   v10 = _mm256_sub_epi32(u1, u5);
     629           0 :   v11 = _mm256_sub_epi32(v1, v5);
     630           0 :   v12 = _mm256_sub_epi32(u2, u6);
     631           0 :   v13 = _mm256_sub_epi32(v2, v6);
     632           0 :   v14 = _mm256_sub_epi32(u3, u7);
     633           0 :   v15 = _mm256_sub_epi32(v3, v7);
     634             : 
     635           0 :   v8 = _mm256_add_epi32(v8, dct_rounding);
     636           0 :   v9 = _mm256_add_epi32(v9, dct_rounding);
     637           0 :   v10 = _mm256_add_epi32(v10, dct_rounding);
     638           0 :   v11 = _mm256_add_epi32(v11, dct_rounding);
     639           0 :   v12 = _mm256_add_epi32(v12, dct_rounding);
     640           0 :   v13 = _mm256_add_epi32(v13, dct_rounding);
     641           0 :   v14 = _mm256_add_epi32(v14, dct_rounding);
     642           0 :   v15 = _mm256_add_epi32(v15, dct_rounding);
     643             : 
     644           0 :   v8 = _mm256_srai_epi32(v8, DCT_CONST_BITS);
     645           0 :   v9 = _mm256_srai_epi32(v9, DCT_CONST_BITS);
     646           0 :   v10 = _mm256_srai_epi32(v10, DCT_CONST_BITS);
     647           0 :   v11 = _mm256_srai_epi32(v11, DCT_CONST_BITS);
     648           0 :   v12 = _mm256_srai_epi32(v12, DCT_CONST_BITS);
     649           0 :   v13 = _mm256_srai_epi32(v13, DCT_CONST_BITS);
     650           0 :   v14 = _mm256_srai_epi32(v14, DCT_CONST_BITS);
     651           0 :   v15 = _mm256_srai_epi32(v15, DCT_CONST_BITS);
     652             : 
     653           0 :   x4 = _mm256_packs_epi32(v8, v9);
     654           0 :   x5 = _mm256_packs_epi32(v10, v11);
     655           0 :   x6 = _mm256_packs_epi32(v12, v13);
     656           0 :   x7 = _mm256_packs_epi32(v14, v15);
     657             : 
     658           0 :   u8 = _mm256_add_epi32(s8, s12);
     659           0 :   u9 = _mm256_add_epi32(s9, s13);
     660           0 :   u10 = _mm256_add_epi32(s10, s14);
     661           0 :   u11 = _mm256_add_epi32(s11, s15);
     662           0 :   u12 = _mm256_sub_epi32(s8, s12);
     663           0 :   u13 = _mm256_sub_epi32(s9, s13);
     664           0 :   u14 = _mm256_sub_epi32(s10, s14);
     665           0 :   u15 = _mm256_sub_epi32(s11, s15);
     666             : 
     667           0 :   v8 = _mm256_add_epi32(x8, x12);
     668           0 :   v9 = _mm256_add_epi32(x9, x13);
     669           0 :   v10 = _mm256_add_epi32(x10, x14);
     670           0 :   v11 = _mm256_add_epi32(x11, x15);
     671           0 :   v12 = _mm256_sub_epi32(x8, x12);
     672           0 :   v13 = _mm256_sub_epi32(x9, x13);
     673           0 :   v14 = _mm256_sub_epi32(x10, x14);
     674           0 :   v15 = _mm256_sub_epi32(x11, x15);
     675             : 
     676           0 :   u12 = _mm256_add_epi32(u12, dct_rounding);
     677           0 :   u13 = _mm256_add_epi32(u13, dct_rounding);
     678           0 :   u14 = _mm256_add_epi32(u14, dct_rounding);
     679           0 :   u15 = _mm256_add_epi32(u15, dct_rounding);
     680             : 
     681           0 :   u12 = _mm256_srai_epi32(u12, DCT_CONST_BITS);
     682           0 :   u13 = _mm256_srai_epi32(u13, DCT_CONST_BITS);
     683           0 :   u14 = _mm256_srai_epi32(u14, DCT_CONST_BITS);
     684           0 :   u15 = _mm256_srai_epi32(u15, DCT_CONST_BITS);
     685             : 
     686           0 :   v12 = _mm256_add_epi32(v12, dct_rounding);
     687           0 :   v13 = _mm256_add_epi32(v13, dct_rounding);
     688           0 :   v14 = _mm256_add_epi32(v14, dct_rounding);
     689           0 :   v15 = _mm256_add_epi32(v15, dct_rounding);
     690             : 
     691           0 :   v12 = _mm256_srai_epi32(v12, DCT_CONST_BITS);
     692           0 :   v13 = _mm256_srai_epi32(v13, DCT_CONST_BITS);
     693           0 :   v14 = _mm256_srai_epi32(v14, DCT_CONST_BITS);
     694           0 :   v15 = _mm256_srai_epi32(v15, DCT_CONST_BITS);
     695             : 
     696           0 :   x12 = _mm256_packs_epi32(u12, v12);
     697           0 :   x13 = _mm256_packs_epi32(u13, v13);
     698           0 :   x14 = _mm256_packs_epi32(u14, v14);
     699           0 :   x15 = _mm256_packs_epi32(u15, v15);
     700             : 
     701             :   // stage 3
     702           0 :   y0 = _mm256_unpacklo_epi16(x4, x5);
     703           0 :   y1 = _mm256_unpackhi_epi16(x4, x5);
     704           0 :   s4 = _mm256_madd_epi16(y0, cospi_p08_p24);
     705           0 :   x4 = _mm256_madd_epi16(y1, cospi_p08_p24);
     706           0 :   s5 = _mm256_madd_epi16(y0, cospi_p24_m08);
     707           0 :   x5 = _mm256_madd_epi16(y1, cospi_p24_m08);
     708             : 
     709           0 :   y0 = _mm256_unpacklo_epi16(x6, x7);
     710           0 :   y1 = _mm256_unpackhi_epi16(x6, x7);
     711           0 :   s6 = _mm256_madd_epi16(y0, cospi_m24_p08);
     712           0 :   x6 = _mm256_madd_epi16(y1, cospi_m24_p08);
     713           0 :   s7 = _mm256_madd_epi16(y0, cospi_p08_p24);
     714           0 :   x7 = _mm256_madd_epi16(y1, cospi_p08_p24);
     715             : 
     716           0 :   y0 = _mm256_unpacklo_epi16(x12, x13);
     717           0 :   y1 = _mm256_unpackhi_epi16(x12, x13);
     718           0 :   s12 = _mm256_madd_epi16(y0, cospi_p08_p24);
     719           0 :   x12 = _mm256_madd_epi16(y1, cospi_p08_p24);
     720           0 :   s13 = _mm256_madd_epi16(y0, cospi_p24_m08);
     721           0 :   x13 = _mm256_madd_epi16(y1, cospi_p24_m08);
     722             : 
     723           0 :   y0 = _mm256_unpacklo_epi16(x14, x15);
     724           0 :   y1 = _mm256_unpackhi_epi16(x14, x15);
     725           0 :   s14 = _mm256_madd_epi16(y0, cospi_m24_p08);
     726           0 :   x14 = _mm256_madd_epi16(y1, cospi_m24_p08);
     727           0 :   s15 = _mm256_madd_epi16(y0, cospi_p08_p24);
     728           0 :   x15 = _mm256_madd_epi16(y1, cospi_p08_p24);
     729             : 
     730           0 :   u0 = _mm256_add_epi32(x0, x2);
     731           0 :   v0 = _mm256_add_epi32(s0, s2);
     732           0 :   u1 = _mm256_add_epi32(x1, x3);
     733           0 :   v1 = _mm256_add_epi32(s1, s3);
     734           0 :   u2 = _mm256_sub_epi32(x0, x2);
     735           0 :   v2 = _mm256_sub_epi32(s0, s2);
     736           0 :   u3 = _mm256_sub_epi32(x1, x3);
     737           0 :   v3 = _mm256_sub_epi32(s1, s3);
     738             : 
     739           0 :   u0 = _mm256_add_epi32(u0, dct_rounding);
     740           0 :   v0 = _mm256_add_epi32(v0, dct_rounding);
     741           0 :   u1 = _mm256_add_epi32(u1, dct_rounding);
     742           0 :   v1 = _mm256_add_epi32(v1, dct_rounding);
     743           0 :   u2 = _mm256_add_epi32(u2, dct_rounding);
     744           0 :   v2 = _mm256_add_epi32(v2, dct_rounding);
     745           0 :   u3 = _mm256_add_epi32(u3, dct_rounding);
     746           0 :   v3 = _mm256_add_epi32(v3, dct_rounding);
     747             : 
     748           0 :   u0 = _mm256_srai_epi32(u0, DCT_CONST_BITS);
     749           0 :   v0 = _mm256_srai_epi32(v0, DCT_CONST_BITS);
     750           0 :   u1 = _mm256_srai_epi32(u1, DCT_CONST_BITS);
     751           0 :   v1 = _mm256_srai_epi32(v1, DCT_CONST_BITS);
     752           0 :   u2 = _mm256_srai_epi32(u2, DCT_CONST_BITS);
     753           0 :   v2 = _mm256_srai_epi32(v2, DCT_CONST_BITS);
     754           0 :   u3 = _mm256_srai_epi32(u3, DCT_CONST_BITS);
     755           0 :   v3 = _mm256_srai_epi32(v3, DCT_CONST_BITS);
     756             : 
     757           0 :   in[0] = _mm256_packs_epi32(u0, v0);
     758           0 :   x1 = _mm256_packs_epi32(u1, v1);
     759           0 :   x2 = _mm256_packs_epi32(u2, v2);
     760           0 :   x3 = _mm256_packs_epi32(u3, v3);
     761             : 
     762             :   // Rounding on s4 + s6, s5 + s7, s4 - s6, s5 - s7
     763           0 :   u4 = _mm256_add_epi32(s4, s6);
     764           0 :   u5 = _mm256_add_epi32(s5, s7);
     765           0 :   u6 = _mm256_sub_epi32(s4, s6);
     766           0 :   u7 = _mm256_sub_epi32(s5, s7);
     767             : 
     768           0 :   v4 = _mm256_add_epi32(x4, x6);
     769           0 :   v5 = _mm256_add_epi32(x5, x7);
     770           0 :   v6 = _mm256_sub_epi32(x4, x6);
     771           0 :   v7 = _mm256_sub_epi32(x5, x7);
     772             : 
     773           0 :   u4 = _mm256_add_epi32(u4, dct_rounding);
     774           0 :   u5 = _mm256_add_epi32(u5, dct_rounding);
     775           0 :   u6 = _mm256_add_epi32(u6, dct_rounding);
     776           0 :   u7 = _mm256_add_epi32(u7, dct_rounding);
     777             : 
     778           0 :   u4 = _mm256_srai_epi32(u4, DCT_CONST_BITS);
     779           0 :   u5 = _mm256_srai_epi32(u5, DCT_CONST_BITS);
     780           0 :   u6 = _mm256_srai_epi32(u6, DCT_CONST_BITS);
     781           0 :   u7 = _mm256_srai_epi32(u7, DCT_CONST_BITS);
     782             : 
     783           0 :   v4 = _mm256_add_epi32(v4, dct_rounding);
     784           0 :   v5 = _mm256_add_epi32(v5, dct_rounding);
     785           0 :   v6 = _mm256_add_epi32(v6, dct_rounding);
     786           0 :   v7 = _mm256_add_epi32(v7, dct_rounding);
     787             : 
     788           0 :   v4 = _mm256_srai_epi32(v4, DCT_CONST_BITS);
     789           0 :   v5 = _mm256_srai_epi32(v5, DCT_CONST_BITS);
     790           0 :   v6 = _mm256_srai_epi32(v6, DCT_CONST_BITS);
     791           0 :   v7 = _mm256_srai_epi32(v7, DCT_CONST_BITS);
     792             : 
     793           0 :   x4 = _mm256_packs_epi32(u4, v4);
     794           0 :   in[12] = _mm256_packs_epi32(u5, v5);
     795           0 :   x6 = _mm256_packs_epi32(u6, v6);
     796           0 :   x7 = _mm256_packs_epi32(u7, v7);
     797             : 
     798           0 :   u0 = _mm256_add_epi32(u8, u10);
     799           0 :   v0 = _mm256_add_epi32(v8, v10);
     800           0 :   u1 = _mm256_add_epi32(u9, u11);
     801           0 :   v1 = _mm256_add_epi32(v9, v11);
     802           0 :   u2 = _mm256_sub_epi32(u8, u10);
     803           0 :   v2 = _mm256_sub_epi32(v8, v10);
     804           0 :   u3 = _mm256_sub_epi32(u9, u11);
     805           0 :   v3 = _mm256_sub_epi32(v9, v11);
     806             : 
     807           0 :   u0 = _mm256_add_epi32(u0, dct_rounding);
     808           0 :   v0 = _mm256_add_epi32(v0, dct_rounding);
     809           0 :   u1 = _mm256_add_epi32(u1, dct_rounding);
     810           0 :   v1 = _mm256_add_epi32(v1, dct_rounding);
     811           0 :   u2 = _mm256_add_epi32(u2, dct_rounding);
     812           0 :   v2 = _mm256_add_epi32(v2, dct_rounding);
     813           0 :   u3 = _mm256_add_epi32(u3, dct_rounding);
     814           0 :   v3 = _mm256_add_epi32(v3, dct_rounding);
     815             : 
     816           0 :   u0 = _mm256_srai_epi32(u0, DCT_CONST_BITS);
     817           0 :   v0 = _mm256_srai_epi32(v0, DCT_CONST_BITS);
     818           0 :   u1 = _mm256_srai_epi32(u1, DCT_CONST_BITS);
     819           0 :   v1 = _mm256_srai_epi32(v1, DCT_CONST_BITS);
     820           0 :   u2 = _mm256_srai_epi32(u2, DCT_CONST_BITS);
     821           0 :   v2 = _mm256_srai_epi32(v2, DCT_CONST_BITS);
     822           0 :   u3 = _mm256_srai_epi32(u3, DCT_CONST_BITS);
     823           0 :   v3 = _mm256_srai_epi32(v3, DCT_CONST_BITS);
     824             : 
     825           0 :   x8 = _mm256_packs_epi32(u0, v0);
     826           0 :   in[14] = _mm256_packs_epi32(u1, v1);
     827           0 :   x10 = _mm256_packs_epi32(u2, v2);
     828           0 :   x11 = _mm256_packs_epi32(u3, v3);
     829             : 
     830             :   // Rounding on s12 + s14, s13 + s15, s12 - s14, s13 - s15
     831           0 :   u12 = _mm256_add_epi32(s12, s14);
     832           0 :   u13 = _mm256_add_epi32(s13, s15);
     833           0 :   u14 = _mm256_sub_epi32(s12, s14);
     834           0 :   u15 = _mm256_sub_epi32(s13, s15);
     835             : 
     836           0 :   v12 = _mm256_add_epi32(x12, x14);
     837           0 :   v13 = _mm256_add_epi32(x13, x15);
     838           0 :   v14 = _mm256_sub_epi32(x12, x14);
     839           0 :   v15 = _mm256_sub_epi32(x13, x15);
     840             : 
     841           0 :   u12 = _mm256_add_epi32(u12, dct_rounding);
     842           0 :   u13 = _mm256_add_epi32(u13, dct_rounding);
     843           0 :   u14 = _mm256_add_epi32(u14, dct_rounding);
     844           0 :   u15 = _mm256_add_epi32(u15, dct_rounding);
     845             : 
     846           0 :   u12 = _mm256_srai_epi32(u12, DCT_CONST_BITS);
     847           0 :   u13 = _mm256_srai_epi32(u13, DCT_CONST_BITS);
     848           0 :   u14 = _mm256_srai_epi32(u14, DCT_CONST_BITS);
     849           0 :   u15 = _mm256_srai_epi32(u15, DCT_CONST_BITS);
     850             : 
     851           0 :   v12 = _mm256_add_epi32(v12, dct_rounding);
     852           0 :   v13 = _mm256_add_epi32(v13, dct_rounding);
     853           0 :   v14 = _mm256_add_epi32(v14, dct_rounding);
     854           0 :   v15 = _mm256_add_epi32(v15, dct_rounding);
     855             : 
     856           0 :   v12 = _mm256_srai_epi32(v12, DCT_CONST_BITS);
     857           0 :   v13 = _mm256_srai_epi32(v13, DCT_CONST_BITS);
     858           0 :   v14 = _mm256_srai_epi32(v14, DCT_CONST_BITS);
     859           0 :   v15 = _mm256_srai_epi32(v15, DCT_CONST_BITS);
     860             : 
     861           0 :   x12 = _mm256_packs_epi32(u12, v12);
     862           0 :   x13 = _mm256_packs_epi32(u13, v13);
     863           0 :   x14 = _mm256_packs_epi32(u14, v14);
     864           0 :   x15 = _mm256_packs_epi32(u15, v15);
     865           0 :   in[2] = x12;
     866             : 
     867             :   // stage 4
     868           0 :   y0 = _mm256_unpacklo_epi16(x2, x3);
     869           0 :   y1 = _mm256_unpackhi_epi16(x2, x3);
     870           0 :   s2 = _mm256_madd_epi16(y0, cospi_m16_m16);
     871           0 :   x2 = _mm256_madd_epi16(y1, cospi_m16_m16);
     872           0 :   s3 = _mm256_madd_epi16(y0, cospi_p16_m16);
     873           0 :   x3 = _mm256_madd_epi16(y1, cospi_p16_m16);
     874             : 
     875           0 :   y0 = _mm256_unpacklo_epi16(x6, x7);
     876           0 :   y1 = _mm256_unpackhi_epi16(x6, x7);
     877           0 :   s6 = _mm256_madd_epi16(y0, cospi_p16_p16);
     878           0 :   x6 = _mm256_madd_epi16(y1, cospi_p16_p16);
     879           0 :   s7 = _mm256_madd_epi16(y0, cospi_m16_p16);
     880           0 :   x7 = _mm256_madd_epi16(y1, cospi_m16_p16);
     881             : 
     882           0 :   y0 = _mm256_unpacklo_epi16(x10, x11);
     883           0 :   y1 = _mm256_unpackhi_epi16(x10, x11);
     884           0 :   s10 = _mm256_madd_epi16(y0, cospi_p16_p16);
     885           0 :   x10 = _mm256_madd_epi16(y1, cospi_p16_p16);
     886           0 :   s11 = _mm256_madd_epi16(y0, cospi_m16_p16);
     887           0 :   x11 = _mm256_madd_epi16(y1, cospi_m16_p16);
     888             : 
     889           0 :   y0 = _mm256_unpacklo_epi16(x14, x15);
     890           0 :   y1 = _mm256_unpackhi_epi16(x14, x15);
     891           0 :   s14 = _mm256_madd_epi16(y0, cospi_m16_m16);
     892           0 :   x14 = _mm256_madd_epi16(y1, cospi_m16_m16);
     893           0 :   s15 = _mm256_madd_epi16(y0, cospi_p16_m16);
     894           0 :   x15 = _mm256_madd_epi16(y1, cospi_p16_m16);
     895             : 
     896             :   // Rounding
     897           0 :   u2 = _mm256_add_epi32(s2, dct_rounding);
     898           0 :   u3 = _mm256_add_epi32(s3, dct_rounding);
     899           0 :   u6 = _mm256_add_epi32(s6, dct_rounding);
     900           0 :   u7 = _mm256_add_epi32(s7, dct_rounding);
     901             : 
     902           0 :   u10 = _mm256_add_epi32(s10, dct_rounding);
     903           0 :   u11 = _mm256_add_epi32(s11, dct_rounding);
     904           0 :   u14 = _mm256_add_epi32(s14, dct_rounding);
     905           0 :   u15 = _mm256_add_epi32(s15, dct_rounding);
     906             : 
     907           0 :   u2 = _mm256_srai_epi32(u2, DCT_CONST_BITS);
     908           0 :   u3 = _mm256_srai_epi32(u3, DCT_CONST_BITS);
     909           0 :   u6 = _mm256_srai_epi32(u6, DCT_CONST_BITS);
     910           0 :   u7 = _mm256_srai_epi32(u7, DCT_CONST_BITS);
     911             : 
     912           0 :   u10 = _mm256_srai_epi32(u10, DCT_CONST_BITS);
     913           0 :   u11 = _mm256_srai_epi32(u11, DCT_CONST_BITS);
     914           0 :   u14 = _mm256_srai_epi32(u14, DCT_CONST_BITS);
     915           0 :   u15 = _mm256_srai_epi32(u15, DCT_CONST_BITS);
     916             : 
     917           0 :   v2 = _mm256_add_epi32(x2, dct_rounding);
     918           0 :   v3 = _mm256_add_epi32(x3, dct_rounding);
     919           0 :   v6 = _mm256_add_epi32(x6, dct_rounding);
     920           0 :   v7 = _mm256_add_epi32(x7, dct_rounding);
     921             : 
     922           0 :   v10 = _mm256_add_epi32(x10, dct_rounding);
     923           0 :   v11 = _mm256_add_epi32(x11, dct_rounding);
     924           0 :   v14 = _mm256_add_epi32(x14, dct_rounding);
     925           0 :   v15 = _mm256_add_epi32(x15, dct_rounding);
     926             : 
     927           0 :   v2 = _mm256_srai_epi32(v2, DCT_CONST_BITS);
     928           0 :   v3 = _mm256_srai_epi32(v3, DCT_CONST_BITS);
     929           0 :   v6 = _mm256_srai_epi32(v6, DCT_CONST_BITS);
     930           0 :   v7 = _mm256_srai_epi32(v7, DCT_CONST_BITS);
     931             : 
     932           0 :   v10 = _mm256_srai_epi32(v10, DCT_CONST_BITS);
     933           0 :   v11 = _mm256_srai_epi32(v11, DCT_CONST_BITS);
     934           0 :   v14 = _mm256_srai_epi32(v14, DCT_CONST_BITS);
     935           0 :   v15 = _mm256_srai_epi32(v15, DCT_CONST_BITS);
     936             : 
     937           0 :   in[7] = _mm256_packs_epi32(u2, v2);
     938           0 :   in[8] = _mm256_packs_epi32(u3, v3);
     939             : 
     940           0 :   in[4] = _mm256_packs_epi32(u6, v6);
     941           0 :   in[11] = _mm256_packs_epi32(u7, v7);
     942             : 
     943           0 :   in[6] = _mm256_packs_epi32(u10, v10);
     944           0 :   in[9] = _mm256_packs_epi32(u11, v11);
     945             : 
     946           0 :   in[5] = _mm256_packs_epi32(u14, v14);
     947           0 :   in[10] = _mm256_packs_epi32(u15, v15);
     948             : 
     949           0 :   in[1] = _mm256_sub_epi16(zero, x8);
     950           0 :   in[3] = _mm256_sub_epi16(zero, x4);
     951           0 :   in[13] = _mm256_sub_epi16(zero, x13);
     952           0 :   in[15] = _mm256_sub_epi16(zero, x1);
     953           0 : }
     954             : 
     955             : #if CONFIG_EXT_TX
     956           0 : static void fidtx16_avx2(__m256i *in) {
     957           0 :   txfm_scaling16_avx2((int16_t)Sqrt2, in);
     958           0 : }
     959             : #endif
     960             : 
     961           0 : void av1_fht16x16_avx2(const int16_t *input, tran_low_t *output, int stride,
     962             :                        int tx_type) {
     963             :   __m256i in[16];
     964             : 
     965           0 :   switch (tx_type) {
     966             :     case DCT_DCT:
     967           0 :       load_buffer_16x16(input, stride, 0, 0, in);
     968           0 :       fdct16_avx2(in);
     969           0 :       mm256_transpose_16x16(in, in);
     970           0 :       right_shift_16x16(in);
     971           0 :       fdct16_avx2(in);
     972           0 :       break;
     973             :     case ADST_DCT:
     974           0 :       load_buffer_16x16(input, stride, 0, 0, in);
     975           0 :       fadst16_avx2(in);
     976           0 :       mm256_transpose_16x16(in, in);
     977           0 :       right_shift_16x16(in);
     978           0 :       fdct16_avx2(in);
     979           0 :       break;
     980             :     case DCT_ADST:
     981           0 :       load_buffer_16x16(input, stride, 0, 0, in);
     982           0 :       fdct16_avx2(in);
     983           0 :       mm256_transpose_16x16(in, in);
     984           0 :       right_shift_16x16(in);
     985           0 :       fadst16_avx2(in);
     986           0 :       break;
     987             :     case ADST_ADST:
     988           0 :       load_buffer_16x16(input, stride, 0, 0, in);
     989           0 :       fadst16_avx2(in);
     990           0 :       mm256_transpose_16x16(in, in);
     991           0 :       right_shift_16x16(in);
     992           0 :       fadst16_avx2(in);
     993           0 :       break;
     994             : #if CONFIG_EXT_TX
     995             :     case FLIPADST_DCT:
     996           0 :       load_buffer_16x16(input, stride, 1, 0, in);
     997           0 :       fadst16_avx2(in);
     998           0 :       mm256_transpose_16x16(in, in);
     999           0 :       right_shift_16x16(in);
    1000           0 :       fdct16_avx2(in);
    1001           0 :       break;
    1002             :     case DCT_FLIPADST:
    1003           0 :       load_buffer_16x16(input, stride, 0, 1, in);
    1004           0 :       fdct16_avx2(in);
    1005           0 :       mm256_transpose_16x16(in, in);
    1006           0 :       right_shift_16x16(in);
    1007           0 :       fadst16_avx2(in);
    1008           0 :       break;
    1009             :     case FLIPADST_FLIPADST:
    1010           0 :       load_buffer_16x16(input, stride, 1, 1, in);
    1011           0 :       fadst16_avx2(in);
    1012           0 :       mm256_transpose_16x16(in, in);
    1013           0 :       right_shift_16x16(in);
    1014           0 :       fadst16_avx2(in);
    1015           0 :       break;
    1016             :     case ADST_FLIPADST:
    1017           0 :       load_buffer_16x16(input, stride, 0, 1, in);
    1018           0 :       fadst16_avx2(in);
    1019           0 :       mm256_transpose_16x16(in, in);
    1020           0 :       right_shift_16x16(in);
    1021           0 :       fadst16_avx2(in);
    1022           0 :       break;
    1023             :     case FLIPADST_ADST:
    1024           0 :       load_buffer_16x16(input, stride, 1, 0, in);
    1025           0 :       fadst16_avx2(in);
    1026           0 :       mm256_transpose_16x16(in, in);
    1027           0 :       right_shift_16x16(in);
    1028           0 :       fadst16_avx2(in);
    1029           0 :       break;
    1030             :     case IDTX:
    1031           0 :       load_buffer_16x16(input, stride, 0, 0, in);
    1032           0 :       fidtx16_avx2(in);
    1033           0 :       mm256_transpose_16x16(in, in);
    1034           0 :       right_shift_16x16(in);
    1035           0 :       fidtx16_avx2(in);
    1036           0 :       break;
    1037             :     case V_DCT:
    1038           0 :       load_buffer_16x16(input, stride, 0, 0, in);
    1039           0 :       fdct16_avx2(in);
    1040           0 :       mm256_transpose_16x16(in, in);
    1041           0 :       right_shift_16x16(in);
    1042           0 :       fidtx16_avx2(in);
    1043           0 :       break;
    1044             :     case H_DCT:
    1045           0 :       load_buffer_16x16(input, stride, 0, 0, in);
    1046           0 :       fidtx16_avx2(in);
    1047           0 :       mm256_transpose_16x16(in, in);
    1048           0 :       right_shift_16x16(in);
    1049           0 :       fdct16_avx2(in);
    1050           0 :       break;
    1051             :     case V_ADST:
    1052           0 :       load_buffer_16x16(input, stride, 0, 0, in);
    1053           0 :       fadst16_avx2(in);
    1054           0 :       mm256_transpose_16x16(in, in);
    1055           0 :       right_shift_16x16(in);
    1056           0 :       fidtx16_avx2(in);
    1057           0 :       break;
    1058             :     case H_ADST:
    1059           0 :       load_buffer_16x16(input, stride, 0, 0, in);
    1060           0 :       fidtx16_avx2(in);
    1061           0 :       mm256_transpose_16x16(in, in);
    1062           0 :       right_shift_16x16(in);
    1063           0 :       fadst16_avx2(in);
    1064           0 :       break;
    1065             :     case V_FLIPADST:
    1066           0 :       load_buffer_16x16(input, stride, 1, 0, in);
    1067           0 :       fadst16_avx2(in);
    1068           0 :       mm256_transpose_16x16(in, in);
    1069           0 :       right_shift_16x16(in);
    1070           0 :       fidtx16_avx2(in);
    1071           0 :       break;
    1072             :     case H_FLIPADST:
    1073           0 :       load_buffer_16x16(input, stride, 0, 1, in);
    1074           0 :       fidtx16_avx2(in);
    1075           0 :       mm256_transpose_16x16(in, in);
    1076           0 :       right_shift_16x16(in);
    1077           0 :       fadst16_avx2(in);
    1078           0 :       break;
    1079             : #endif  // CONFIG_EXT_TX
    1080           0 :     default: assert(0); break;
    1081             :   }
    1082           0 :   mm256_transpose_16x16(in, in);
    1083           0 :   write_buffer_16x16(in, output);
    1084             :   _mm256_zeroupper();
    1085           0 : }
    1086             : 
    1087           0 : void aom_fdct32x32_1_avx2(const int16_t *input, tran_low_t *output,
    1088             :                           int stride) {
    1089             :   // left and upper corner
    1090           0 :   int32_t sum = get_16x16_sum(input, stride);
    1091             :   // right and upper corner
    1092           0 :   sum += get_16x16_sum(input + 16, stride);
    1093             :   // left and lower corner
    1094           0 :   sum += get_16x16_sum(input + (stride << 4), stride);
    1095             :   // right and lower corner
    1096           0 :   sum += get_16x16_sum(input + (stride << 4) + 16, stride);
    1097             : 
    1098           0 :   sum >>= 3;
    1099           0 :   output[0] = (tran_low_t)sum;
    1100             :   _mm256_zeroupper();
    1101           0 : }
    1102             : 
    1103           0 : static void mm256_vectors_swap(__m256i *a0, __m256i *a1, const int size) {
    1104           0 :   int i = 0;
    1105             :   __m256i temp;
    1106           0 :   while (i < size) {
    1107           0 :     temp = a0[i];
    1108           0 :     a0[i] = a1[i];
    1109           0 :     a1[i] = temp;
    1110           0 :     i++;
    1111             :   }
    1112           0 : }
    1113             : 
    1114           0 : static void mm256_transpose_32x32(__m256i *in0, __m256i *in1) {
    1115           0 :   mm256_transpose_16x16(in0, in0);
    1116           0 :   mm256_transpose_16x16(&in0[16], &in0[16]);
    1117           0 :   mm256_transpose_16x16(in1, in1);
    1118           0 :   mm256_transpose_16x16(&in1[16], &in1[16]);
    1119           0 :   mm256_vectors_swap(&in0[16], in1, 16);
    1120           0 : }
    1121             : 
    1122           0 : static void prepare_16x16_even(const __m256i *in, __m256i *even) {
    1123           0 :   even[0] = _mm256_add_epi16(in[0], in[31]);
    1124           0 :   even[1] = _mm256_add_epi16(in[1], in[30]);
    1125           0 :   even[2] = _mm256_add_epi16(in[2], in[29]);
    1126           0 :   even[3] = _mm256_add_epi16(in[3], in[28]);
    1127           0 :   even[4] = _mm256_add_epi16(in[4], in[27]);
    1128           0 :   even[5] = _mm256_add_epi16(in[5], in[26]);
    1129           0 :   even[6] = _mm256_add_epi16(in[6], in[25]);
    1130           0 :   even[7] = _mm256_add_epi16(in[7], in[24]);
    1131           0 :   even[8] = _mm256_add_epi16(in[8], in[23]);
    1132           0 :   even[9] = _mm256_add_epi16(in[9], in[22]);
    1133           0 :   even[10] = _mm256_add_epi16(in[10], in[21]);
    1134           0 :   even[11] = _mm256_add_epi16(in[11], in[20]);
    1135           0 :   even[12] = _mm256_add_epi16(in[12], in[19]);
    1136           0 :   even[13] = _mm256_add_epi16(in[13], in[18]);
    1137           0 :   even[14] = _mm256_add_epi16(in[14], in[17]);
    1138           0 :   even[15] = _mm256_add_epi16(in[15], in[16]);
    1139           0 : }
    1140             : 
    1141           0 : static void prepare_16x16_odd(const __m256i *in, __m256i *odd) {
    1142           0 :   odd[0] = _mm256_sub_epi16(in[15], in[16]);
    1143           0 :   odd[1] = _mm256_sub_epi16(in[14], in[17]);
    1144           0 :   odd[2] = _mm256_sub_epi16(in[13], in[18]);
    1145           0 :   odd[3] = _mm256_sub_epi16(in[12], in[19]);
    1146           0 :   odd[4] = _mm256_sub_epi16(in[11], in[20]);
    1147           0 :   odd[5] = _mm256_sub_epi16(in[10], in[21]);
    1148           0 :   odd[6] = _mm256_sub_epi16(in[9], in[22]);
    1149           0 :   odd[7] = _mm256_sub_epi16(in[8], in[23]);
    1150           0 :   odd[8] = _mm256_sub_epi16(in[7], in[24]);
    1151           0 :   odd[9] = _mm256_sub_epi16(in[6], in[25]);
    1152           0 :   odd[10] = _mm256_sub_epi16(in[5], in[26]);
    1153           0 :   odd[11] = _mm256_sub_epi16(in[4], in[27]);
    1154           0 :   odd[12] = _mm256_sub_epi16(in[3], in[28]);
    1155           0 :   odd[13] = _mm256_sub_epi16(in[2], in[29]);
    1156           0 :   odd[14] = _mm256_sub_epi16(in[1], in[30]);
    1157           0 :   odd[15] = _mm256_sub_epi16(in[0], in[31]);
    1158           0 : }
    1159             : 
    1160           0 : static void collect_16col(const __m256i *even, const __m256i *odd,
    1161             :                           __m256i *out) {
    1162             :   // fdct16_avx2() already maps the output
    1163           0 :   out[0] = even[0];
    1164           0 :   out[2] = even[1];
    1165           0 :   out[4] = even[2];
    1166           0 :   out[6] = even[3];
    1167           0 :   out[8] = even[4];
    1168           0 :   out[10] = even[5];
    1169           0 :   out[12] = even[6];
    1170           0 :   out[14] = even[7];
    1171           0 :   out[16] = even[8];
    1172           0 :   out[18] = even[9];
    1173           0 :   out[20] = even[10];
    1174           0 :   out[22] = even[11];
    1175           0 :   out[24] = even[12];
    1176           0 :   out[26] = even[13];
    1177           0 :   out[28] = even[14];
    1178           0 :   out[30] = even[15];
    1179             : 
    1180           0 :   out[1] = odd[0];
    1181           0 :   out[17] = odd[1];
    1182           0 :   out[9] = odd[2];
    1183           0 :   out[25] = odd[3];
    1184           0 :   out[5] = odd[4];
    1185           0 :   out[21] = odd[5];
    1186           0 :   out[13] = odd[6];
    1187           0 :   out[29] = odd[7];
    1188           0 :   out[3] = odd[8];
    1189           0 :   out[19] = odd[9];
    1190           0 :   out[11] = odd[10];
    1191           0 :   out[27] = odd[11];
    1192           0 :   out[7] = odd[12];
    1193           0 :   out[23] = odd[13];
    1194           0 :   out[15] = odd[14];
    1195           0 :   out[31] = odd[15];
    1196           0 : }
    1197             : 
    1198           0 : static void collect_coeffs(const __m256i *first_16col_even,
    1199             :                            const __m256i *first_16col_odd,
    1200             :                            const __m256i *second_16col_even,
    1201             :                            const __m256i *second_16col_odd, __m256i *in0,
    1202             :                            __m256i *in1) {
    1203           0 :   collect_16col(first_16col_even, first_16col_odd, in0);
    1204           0 :   collect_16col(second_16col_even, second_16col_odd, in1);
    1205           0 : }
    1206             : 
    1207           0 : static void fdct16_odd_avx2(__m256i *in) {
    1208             :   // sequence: cospi_L_H = pairs(L, H) and L first
    1209           0 :   const __m256i cospi_p16_p16 = pair256_set_epi16(cospi_16_64, cospi_16_64);
    1210           0 :   const __m256i cospi_m16_p16 = pair256_set_epi16(-cospi_16_64, cospi_16_64);
    1211           0 :   const __m256i cospi_m08_p24 = pair256_set_epi16(-cospi_8_64, cospi_24_64);
    1212           0 :   const __m256i cospi_p24_p08 = pair256_set_epi16(cospi_24_64, cospi_8_64);
    1213           0 :   const __m256i cospi_m24_m08 = pair256_set_epi16(-cospi_24_64, -cospi_8_64);
    1214           0 :   const __m256i cospi_m04_p28 = pair256_set_epi16(-cospi_4_64, cospi_28_64);
    1215           0 :   const __m256i cospi_p28_p04 = pair256_set_epi16(cospi_28_64, cospi_4_64);
    1216           0 :   const __m256i cospi_m28_m04 = pair256_set_epi16(-cospi_28_64, -cospi_4_64);
    1217           0 :   const __m256i cospi_m20_p12 = pair256_set_epi16(-cospi_20_64, cospi_12_64);
    1218           0 :   const __m256i cospi_p12_p20 = pair256_set_epi16(cospi_12_64, cospi_20_64);
    1219           0 :   const __m256i cospi_m12_m20 = pair256_set_epi16(-cospi_12_64, -cospi_20_64);
    1220             : 
    1221           0 :   const __m256i cospi_p31_p01 = pair256_set_epi16(cospi_31_64, cospi_1_64);
    1222           0 :   const __m256i cospi_m01_p31 = pair256_set_epi16(-cospi_1_64, cospi_31_64);
    1223           0 :   const __m256i cospi_p15_p17 = pair256_set_epi16(cospi_15_64, cospi_17_64);
    1224           0 :   const __m256i cospi_m17_p15 = pair256_set_epi16(-cospi_17_64, cospi_15_64);
    1225           0 :   const __m256i cospi_p23_p09 = pair256_set_epi16(cospi_23_64, cospi_9_64);
    1226           0 :   const __m256i cospi_m09_p23 = pair256_set_epi16(-cospi_9_64, cospi_23_64);
    1227           0 :   const __m256i cospi_p07_p25 = pair256_set_epi16(cospi_7_64, cospi_25_64);
    1228           0 :   const __m256i cospi_m25_p07 = pair256_set_epi16(-cospi_25_64, cospi_7_64);
    1229           0 :   const __m256i cospi_p27_p05 = pair256_set_epi16(cospi_27_64, cospi_5_64);
    1230           0 :   const __m256i cospi_m05_p27 = pair256_set_epi16(-cospi_5_64, cospi_27_64);
    1231           0 :   const __m256i cospi_p11_p21 = pair256_set_epi16(cospi_11_64, cospi_21_64);
    1232           0 :   const __m256i cospi_m21_p11 = pair256_set_epi16(-cospi_21_64, cospi_11_64);
    1233           0 :   const __m256i cospi_p19_p13 = pair256_set_epi16(cospi_19_64, cospi_13_64);
    1234           0 :   const __m256i cospi_m13_p19 = pair256_set_epi16(-cospi_13_64, cospi_19_64);
    1235           0 :   const __m256i cospi_p03_p29 = pair256_set_epi16(cospi_3_64, cospi_29_64);
    1236           0 :   const __m256i cospi_m29_p03 = pair256_set_epi16(-cospi_29_64, cospi_3_64);
    1237             : 
    1238             :   __m256i x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;
    1239             :   __m256i y0, y1, y2, y3, y4, y5, y6, y7, y8, y9, y10, y11, y12, y13, y14, y15;
    1240             :   __m256i u0, u1;
    1241             : 
    1242             :   // stage 1 is in prepare_16x16_odd()
    1243             : 
    1244             :   // stage 2
    1245           0 :   y0 = in[0];
    1246           0 :   y1 = in[1];
    1247           0 :   y2 = in[2];
    1248           0 :   y3 = in[3];
    1249             : 
    1250           0 :   u0 = _mm256_unpacklo_epi16(in[4], in[11]);
    1251           0 :   u1 = _mm256_unpackhi_epi16(in[4], in[11]);
    1252           0 :   y4 = butter_fly(&u0, &u1, &cospi_m16_p16);
    1253           0 :   y11 = butter_fly(&u0, &u1, &cospi_p16_p16);
    1254             : 
    1255           0 :   u0 = _mm256_unpacklo_epi16(in[5], in[10]);
    1256           0 :   u1 = _mm256_unpackhi_epi16(in[5], in[10]);
    1257           0 :   y5 = butter_fly(&u0, &u1, &cospi_m16_p16);
    1258           0 :   y10 = butter_fly(&u0, &u1, &cospi_p16_p16);
    1259             : 
    1260           0 :   u0 = _mm256_unpacklo_epi16(in[6], in[9]);
    1261           0 :   u1 = _mm256_unpackhi_epi16(in[6], in[9]);
    1262           0 :   y6 = butter_fly(&u0, &u1, &cospi_m16_p16);
    1263           0 :   y9 = butter_fly(&u0, &u1, &cospi_p16_p16);
    1264             : 
    1265           0 :   u0 = _mm256_unpacklo_epi16(in[7], in[8]);
    1266           0 :   u1 = _mm256_unpackhi_epi16(in[7], in[8]);
    1267           0 :   y7 = butter_fly(&u0, &u1, &cospi_m16_p16);
    1268           0 :   y8 = butter_fly(&u0, &u1, &cospi_p16_p16);
    1269             : 
    1270           0 :   y12 = in[12];
    1271           0 :   y13 = in[13];
    1272           0 :   y14 = in[14];
    1273           0 :   y15 = in[15];
    1274             : 
    1275             :   // stage 3
    1276           0 :   x0 = _mm256_add_epi16(y0, y7);
    1277           0 :   x1 = _mm256_add_epi16(y1, y6);
    1278           0 :   x2 = _mm256_add_epi16(y2, y5);
    1279           0 :   x3 = _mm256_add_epi16(y3, y4);
    1280           0 :   x4 = _mm256_sub_epi16(y3, y4);
    1281           0 :   x5 = _mm256_sub_epi16(y2, y5);
    1282           0 :   x6 = _mm256_sub_epi16(y1, y6);
    1283           0 :   x7 = _mm256_sub_epi16(y0, y7);
    1284           0 :   x8 = _mm256_sub_epi16(y15, y8);
    1285           0 :   x9 = _mm256_sub_epi16(y14, y9);
    1286           0 :   x10 = _mm256_sub_epi16(y13, y10);
    1287           0 :   x11 = _mm256_sub_epi16(y12, y11);
    1288           0 :   x12 = _mm256_add_epi16(y12, y11);
    1289           0 :   x13 = _mm256_add_epi16(y13, y10);
    1290           0 :   x14 = _mm256_add_epi16(y14, y9);
    1291           0 :   x15 = _mm256_add_epi16(y15, y8);
    1292             : 
    1293             :   // stage 4
    1294           0 :   y0 = x0;
    1295           0 :   y1 = x1;
    1296           0 :   y6 = x6;
    1297           0 :   y7 = x7;
    1298           0 :   y8 = x8;
    1299           0 :   y9 = x9;
    1300           0 :   y14 = x14;
    1301           0 :   y15 = x15;
    1302             : 
    1303           0 :   u0 = _mm256_unpacklo_epi16(x2, x13);
    1304           0 :   u1 = _mm256_unpackhi_epi16(x2, x13);
    1305           0 :   y2 = butter_fly(&u0, &u1, &cospi_m08_p24);
    1306           0 :   y13 = butter_fly(&u0, &u1, &cospi_p24_p08);
    1307             : 
    1308           0 :   u0 = _mm256_unpacklo_epi16(x3, x12);
    1309           0 :   u1 = _mm256_unpackhi_epi16(x3, x12);
    1310           0 :   y3 = butter_fly(&u0, &u1, &cospi_m08_p24);
    1311           0 :   y12 = butter_fly(&u0, &u1, &cospi_p24_p08);
    1312             : 
    1313           0 :   u0 = _mm256_unpacklo_epi16(x4, x11);
    1314           0 :   u1 = _mm256_unpackhi_epi16(x4, x11);
    1315           0 :   y4 = butter_fly(&u0, &u1, &cospi_m24_m08);
    1316           0 :   y11 = butter_fly(&u0, &u1, &cospi_m08_p24);
    1317             : 
    1318           0 :   u0 = _mm256_unpacklo_epi16(x5, x10);
    1319           0 :   u1 = _mm256_unpackhi_epi16(x5, x10);
    1320           0 :   y5 = butter_fly(&u0, &u1, &cospi_m24_m08);
    1321           0 :   y10 = butter_fly(&u0, &u1, &cospi_m08_p24);
    1322             : 
    1323             :   // stage 5
    1324           0 :   x0 = _mm256_add_epi16(y0, y3);
    1325           0 :   x1 = _mm256_add_epi16(y1, y2);
    1326           0 :   x2 = _mm256_sub_epi16(y1, y2);
    1327           0 :   x3 = _mm256_sub_epi16(y0, y3);
    1328           0 :   x4 = _mm256_sub_epi16(y7, y4);
    1329           0 :   x5 = _mm256_sub_epi16(y6, y5);
    1330           0 :   x6 = _mm256_add_epi16(y6, y5);
    1331           0 :   x7 = _mm256_add_epi16(y7, y4);
    1332             : 
    1333           0 :   x8 = _mm256_add_epi16(y8, y11);
    1334           0 :   x9 = _mm256_add_epi16(y9, y10);
    1335           0 :   x10 = _mm256_sub_epi16(y9, y10);
    1336           0 :   x11 = _mm256_sub_epi16(y8, y11);
    1337           0 :   x12 = _mm256_sub_epi16(y15, y12);
    1338           0 :   x13 = _mm256_sub_epi16(y14, y13);
    1339           0 :   x14 = _mm256_add_epi16(y14, y13);
    1340           0 :   x15 = _mm256_add_epi16(y15, y12);
    1341             : 
    1342             :   // stage 6
    1343           0 :   y0 = x0;
    1344           0 :   y3 = x3;
    1345           0 :   y4 = x4;
    1346           0 :   y7 = x7;
    1347           0 :   y8 = x8;
    1348           0 :   y11 = x11;
    1349           0 :   y12 = x12;
    1350           0 :   y15 = x15;
    1351             : 
    1352           0 :   u0 = _mm256_unpacklo_epi16(x1, x14);
    1353           0 :   u1 = _mm256_unpackhi_epi16(x1, x14);
    1354           0 :   y1 = butter_fly(&u0, &u1, &cospi_m04_p28);
    1355           0 :   y14 = butter_fly(&u0, &u1, &cospi_p28_p04);
    1356             : 
    1357           0 :   u0 = _mm256_unpacklo_epi16(x2, x13);
    1358           0 :   u1 = _mm256_unpackhi_epi16(x2, x13);
    1359           0 :   y2 = butter_fly(&u0, &u1, &cospi_m28_m04);
    1360           0 :   y13 = butter_fly(&u0, &u1, &cospi_m04_p28);
    1361             : 
    1362           0 :   u0 = _mm256_unpacklo_epi16(x5, x10);
    1363           0 :   u1 = _mm256_unpackhi_epi16(x5, x10);
    1364           0 :   y5 = butter_fly(&u0, &u1, &cospi_m20_p12);
    1365           0 :   y10 = butter_fly(&u0, &u1, &cospi_p12_p20);
    1366             : 
    1367           0 :   u0 = _mm256_unpacklo_epi16(x6, x9);
    1368           0 :   u1 = _mm256_unpackhi_epi16(x6, x9);
    1369           0 :   y6 = butter_fly(&u0, &u1, &cospi_m12_m20);
    1370           0 :   y9 = butter_fly(&u0, &u1, &cospi_m20_p12);
    1371             : 
    1372             :   // stage 7
    1373           0 :   x0 = _mm256_add_epi16(y0, y1);
    1374           0 :   x1 = _mm256_sub_epi16(y0, y1);
    1375           0 :   x2 = _mm256_sub_epi16(y3, y2);
    1376           0 :   x3 = _mm256_add_epi16(y3, y2);
    1377           0 :   x4 = _mm256_add_epi16(y4, y5);
    1378           0 :   x5 = _mm256_sub_epi16(y4, y5);
    1379           0 :   x6 = _mm256_sub_epi16(y7, y6);
    1380           0 :   x7 = _mm256_add_epi16(y7, y6);
    1381             : 
    1382           0 :   x8 = _mm256_add_epi16(y8, y9);
    1383           0 :   x9 = _mm256_sub_epi16(y8, y9);
    1384           0 :   x10 = _mm256_sub_epi16(y11, y10);
    1385           0 :   x11 = _mm256_add_epi16(y11, y10);
    1386           0 :   x12 = _mm256_add_epi16(y12, y13);
    1387           0 :   x13 = _mm256_sub_epi16(y12, y13);
    1388           0 :   x14 = _mm256_sub_epi16(y15, y14);
    1389           0 :   x15 = _mm256_add_epi16(y15, y14);
    1390             : 
    1391             :   // stage 8
    1392           0 :   u0 = _mm256_unpacklo_epi16(x0, x15);
    1393           0 :   u1 = _mm256_unpackhi_epi16(x0, x15);
    1394           0 :   in[0] = butter_fly(&u0, &u1, &cospi_p31_p01);
    1395           0 :   in[15] = butter_fly(&u0, &u1, &cospi_m01_p31);
    1396             : 
    1397           0 :   u0 = _mm256_unpacklo_epi16(x1, x14);
    1398           0 :   u1 = _mm256_unpackhi_epi16(x1, x14);
    1399           0 :   in[1] = butter_fly(&u0, &u1, &cospi_p15_p17);
    1400           0 :   in[14] = butter_fly(&u0, &u1, &cospi_m17_p15);
    1401             : 
    1402           0 :   u0 = _mm256_unpacklo_epi16(x2, x13);
    1403           0 :   u1 = _mm256_unpackhi_epi16(x2, x13);
    1404           0 :   in[2] = butter_fly(&u0, &u1, &cospi_p23_p09);
    1405           0 :   in[13] = butter_fly(&u0, &u1, &cospi_m09_p23);
    1406             : 
    1407           0 :   u0 = _mm256_unpacklo_epi16(x3, x12);
    1408           0 :   u1 = _mm256_unpackhi_epi16(x3, x12);
    1409           0 :   in[3] = butter_fly(&u0, &u1, &cospi_p07_p25);
    1410           0 :   in[12] = butter_fly(&u0, &u1, &cospi_m25_p07);
    1411             : 
    1412           0 :   u0 = _mm256_unpacklo_epi16(x4, x11);
    1413           0 :   u1 = _mm256_unpackhi_epi16(x4, x11);
    1414           0 :   in[4] = butter_fly(&u0, &u1, &cospi_p27_p05);
    1415           0 :   in[11] = butter_fly(&u0, &u1, &cospi_m05_p27);
    1416             : 
    1417           0 :   u0 = _mm256_unpacklo_epi16(x5, x10);
    1418           0 :   u1 = _mm256_unpackhi_epi16(x5, x10);
    1419           0 :   in[5] = butter_fly(&u0, &u1, &cospi_p11_p21);
    1420           0 :   in[10] = butter_fly(&u0, &u1, &cospi_m21_p11);
    1421             : 
    1422           0 :   u0 = _mm256_unpacklo_epi16(x6, x9);
    1423           0 :   u1 = _mm256_unpackhi_epi16(x6, x9);
    1424           0 :   in[6] = butter_fly(&u0, &u1, &cospi_p19_p13);
    1425           0 :   in[9] = butter_fly(&u0, &u1, &cospi_m13_p19);
    1426             : 
    1427           0 :   u0 = _mm256_unpacklo_epi16(x7, x8);
    1428           0 :   u1 = _mm256_unpackhi_epi16(x7, x8);
    1429           0 :   in[7] = butter_fly(&u0, &u1, &cospi_p03_p29);
    1430           0 :   in[8] = butter_fly(&u0, &u1, &cospi_m29_p03);
    1431           0 : }
    1432             : 
    1433           0 : static void fdct32_avx2(__m256i *in0, __m256i *in1) {
    1434             :   __m256i even0[16], even1[16], odd0[16], odd1[16];
    1435           0 :   prepare_16x16_even(in0, even0);
    1436           0 :   fdct16_avx2(even0);
    1437             : 
    1438           0 :   prepare_16x16_odd(in0, odd0);
    1439           0 :   fdct16_odd_avx2(odd0);
    1440             : 
    1441           0 :   prepare_16x16_even(in1, even1);
    1442           0 :   fdct16_avx2(even1);
    1443             : 
    1444           0 :   prepare_16x16_odd(in1, odd1);
    1445           0 :   fdct16_odd_avx2(odd1);
    1446             : 
    1447           0 :   collect_coeffs(even0, odd0, even1, odd1, in0, in1);
    1448             : 
    1449           0 :   mm256_transpose_32x32(in0, in1);
    1450           0 : }
    1451             : 
    1452           0 : static INLINE void write_buffer_32x32(const __m256i *in0, const __m256i *in1,
    1453             :                                       tran_low_t *output) {
    1454           0 :   int i = 0;
    1455           0 :   const int stride = 32;
    1456           0 :   tran_low_t *coeff = output;
    1457           0 :   while (i < 32) {
    1458           0 :     storeu_output_avx2(&in0[i], coeff);
    1459           0 :     storeu_output_avx2(&in1[i], coeff + 16);
    1460           0 :     coeff += stride;
    1461           0 :     i += 1;
    1462             :   }
    1463           0 : }
    1464             : 
    1465             : #if CONFIG_EXT_TX
    1466           0 : static void fhalfright32_16col_avx2(__m256i *in) {
    1467           0 :   int i = 0;
    1468           0 :   const __m256i zero = _mm256_setzero_si256();
    1469           0 :   const __m256i sqrt2 = _mm256_set1_epi16((int16_t)Sqrt2);
    1470           0 :   const __m256i dct_rounding = _mm256_set1_epi32(DCT_CONST_ROUNDING);
    1471             :   __m256i x0, x1;
    1472             : 
    1473           0 :   while (i < 16) {
    1474           0 :     in[i] = _mm256_slli_epi16(in[i], 2);
    1475           0 :     x0 = _mm256_unpacklo_epi16(in[i + 16], zero);
    1476           0 :     x1 = _mm256_unpackhi_epi16(in[i + 16], zero);
    1477           0 :     x0 = _mm256_madd_epi16(x0, sqrt2);
    1478           0 :     x1 = _mm256_madd_epi16(x1, sqrt2);
    1479           0 :     x0 = _mm256_add_epi32(x0, dct_rounding);
    1480           0 :     x1 = _mm256_add_epi32(x1, dct_rounding);
    1481           0 :     x0 = _mm256_srai_epi32(x0, DCT_CONST_BITS);
    1482           0 :     x1 = _mm256_srai_epi32(x1, DCT_CONST_BITS);
    1483           0 :     in[i + 16] = _mm256_packs_epi32(x0, x1);
    1484           0 :     i += 1;
    1485             :   }
    1486           0 :   fdct16_avx2(&in[16]);
    1487           0 : }
    1488             : 
    1489           0 : static void fhalfright32_avx2(__m256i *in0, __m256i *in1) {
    1490           0 :   fhalfright32_16col_avx2(in0);
    1491           0 :   fhalfright32_16col_avx2(in1);
    1492           0 :   mm256_vectors_swap(in0, &in0[16], 16);
    1493           0 :   mm256_vectors_swap(in1, &in1[16], 16);
    1494           0 :   mm256_transpose_32x32(in0, in1);
    1495           0 : }
    1496             : #endif  // CONFIG_EXT_TX
    1497             : 
    1498           0 : static INLINE void load_buffer_32x32(const int16_t *input, int stride,
    1499             :                                      int flipud, int fliplr, __m256i *in0,
    1500             :                                      __m256i *in1) {
    1501             :   // Load 4 16x16 blocks
    1502           0 :   const int16_t *topL = input;
    1503           0 :   const int16_t *topR = input + 16;
    1504           0 :   const int16_t *botL = input + 16 * stride;
    1505           0 :   const int16_t *botR = input + 16 * stride + 16;
    1506             : 
    1507             :   const int16_t *tmp;
    1508             : 
    1509           0 :   if (flipud) {
    1510             :     // Swap left columns
    1511           0 :     tmp = topL;
    1512           0 :     topL = botL;
    1513           0 :     botL = tmp;
    1514             :     // Swap right columns
    1515           0 :     tmp = topR;
    1516           0 :     topR = botR;
    1517           0 :     botR = tmp;
    1518             :   }
    1519             : 
    1520           0 :   if (fliplr) {
    1521             :     // Swap top rows
    1522           0 :     tmp = topL;
    1523           0 :     topL = topR;
    1524           0 :     topR = tmp;
    1525             :     // Swap bottom rows
    1526           0 :     tmp = botL;
    1527           0 :     botL = botR;
    1528           0 :     botR = tmp;
    1529             :   }
    1530             : 
    1531             :   // load first 16 columns
    1532           0 :   load_buffer_16x16(topL, stride, flipud, fliplr, in0);
    1533           0 :   load_buffer_16x16(botL, stride, flipud, fliplr, in0 + 16);
    1534             : 
    1535             :   // load second 16 columns
    1536           0 :   load_buffer_16x16(topR, stride, flipud, fliplr, in1);
    1537           0 :   load_buffer_16x16(botR, stride, flipud, fliplr, in1 + 16);
    1538           0 : }
    1539             : 
    1540           0 : static INLINE void right_shift_32x32_16col(int bit, __m256i *in) {
    1541           0 :   int i = 0;
    1542           0 :   const __m256i rounding = _mm256_set1_epi16((1 << bit) >> 1);
    1543             :   __m256i sign;
    1544           0 :   while (i < 32) {
    1545           0 :     sign = _mm256_srai_epi16(in[i], 15);
    1546           0 :     in[i] = _mm256_add_epi16(in[i], rounding);
    1547           0 :     in[i] = _mm256_add_epi16(in[i], sign);
    1548           0 :     in[i] = _mm256_srai_epi16(in[i], bit);
    1549           0 :     i += 1;
    1550             :   }
    1551           0 : }
    1552             : 
    1553             : // Positive rounding
    1554           0 : static INLINE void right_shift_32x32(__m256i *in0, __m256i *in1) {
    1555           0 :   const int bit = 4;
    1556           0 :   right_shift_32x32_16col(bit, in0);
    1557           0 :   right_shift_32x32_16col(bit, in1);
    1558           0 : }
    1559             : 
    1560             : #if CONFIG_EXT_TX
    1561           0 : static void fidtx32_avx2(__m256i *in0, __m256i *in1) {
    1562           0 :   int i = 0;
    1563           0 :   while (i < 32) {
    1564           0 :     in0[i] = _mm256_slli_epi16(in0[i], 2);
    1565           0 :     in1[i] = _mm256_slli_epi16(in1[i], 2);
    1566           0 :     i += 1;
    1567             :   }
    1568           0 :   mm256_transpose_32x32(in0, in1);
    1569           0 : }
    1570             : #endif
    1571             : 
    1572           0 : void av1_fht32x32_avx2(const int16_t *input, tran_low_t *output, int stride,
    1573             :                        int tx_type) {
    1574             :   __m256i in0[32];  // left 32 columns
    1575             :   __m256i in1[32];  // right 32 columns
    1576             : 
    1577           0 :   switch (tx_type) {
    1578             :     case DCT_DCT:
    1579           0 :       load_buffer_32x32(input, stride, 0, 0, in0, in1);
    1580           0 :       fdct32_avx2(in0, in1);
    1581           0 :       right_shift_32x32(in0, in1);
    1582           0 :       fdct32_avx2(in0, in1);
    1583           0 :       break;
    1584             : #if CONFIG_EXT_TX
    1585             :     case ADST_DCT:
    1586           0 :       load_buffer_32x32(input, stride, 0, 0, in0, in1);
    1587           0 :       fhalfright32_avx2(in0, in1);
    1588           0 :       right_shift_32x32(in0, in1);
    1589           0 :       fdct32_avx2(in0, in1);
    1590           0 :       break;
    1591             :     case DCT_ADST:
    1592           0 :       load_buffer_32x32(input, stride, 0, 0, in0, in1);
    1593           0 :       fdct32_avx2(in0, in1);
    1594           0 :       right_shift_32x32(in0, in1);
    1595           0 :       fhalfright32_avx2(in0, in1);
    1596           0 :       break;
    1597             :     case ADST_ADST:
    1598           0 :       load_buffer_32x32(input, stride, 0, 0, in0, in1);
    1599           0 :       fhalfright32_avx2(in0, in1);
    1600           0 :       right_shift_32x32(in0, in1);
    1601           0 :       fhalfright32_avx2(in0, in1);
    1602           0 :       break;
    1603             :     case FLIPADST_DCT:
    1604           0 :       load_buffer_32x32(input, stride, 1, 0, in0, in1);
    1605           0 :       fhalfright32_avx2(in0, in1);
    1606           0 :       right_shift_32x32(in0, in1);
    1607           0 :       fdct32_avx2(in0, in1);
    1608           0 :       break;
    1609             :     case DCT_FLIPADST:
    1610           0 :       load_buffer_32x32(input, stride, 0, 1, in0, in1);
    1611           0 :       fdct32_avx2(in0, in1);
    1612           0 :       right_shift_32x32(in0, in1);
    1613           0 :       fhalfright32_avx2(in0, in1);
    1614           0 :       break;
    1615             :     case FLIPADST_FLIPADST:
    1616           0 :       load_buffer_32x32(input, stride, 1, 1, in0, in1);
    1617           0 :       fhalfright32_avx2(in0, in1);
    1618           0 :       right_shift_32x32(in0, in1);
    1619           0 :       fhalfright32_avx2(in0, in1);
    1620           0 :       break;
    1621             :     case ADST_FLIPADST:
    1622           0 :       load_buffer_32x32(input, stride, 0, 1, in0, in1);
    1623           0 :       fhalfright32_avx2(in0, in1);
    1624           0 :       right_shift_32x32(in0, in1);
    1625           0 :       fhalfright32_avx2(in0, in1);
    1626           0 :       break;
    1627             :     case FLIPADST_ADST:
    1628           0 :       load_buffer_32x32(input, stride, 1, 0, in0, in1);
    1629           0 :       fhalfright32_avx2(in0, in1);
    1630           0 :       right_shift_32x32(in0, in1);
    1631           0 :       fhalfright32_avx2(in0, in1);
    1632           0 :       break;
    1633             :     case IDTX:
    1634           0 :       load_buffer_32x32(input, stride, 0, 0, in0, in1);
    1635           0 :       fidtx32_avx2(in0, in1);
    1636           0 :       right_shift_32x32(in0, in1);
    1637           0 :       fidtx32_avx2(in0, in1);
    1638           0 :       break;
    1639             :     case V_DCT:
    1640           0 :       load_buffer_32x32(input, stride, 0, 0, in0, in1);
    1641           0 :       fdct32_avx2(in0, in1);
    1642           0 :       right_shift_32x32(in0, in1);
    1643           0 :       fidtx32_avx2(in0, in1);
    1644           0 :       break;
    1645             :     case H_DCT:
    1646           0 :       load_buffer_32x32(input, stride, 0, 0, in0, in1);
    1647           0 :       fidtx32_avx2(in0, in1);
    1648           0 :       right_shift_32x32(in0, in1);
    1649           0 :       fdct32_avx2(in0, in1);
    1650           0 :       break;
    1651             :     case V_ADST:
    1652           0 :       load_buffer_32x32(input, stride, 0, 0, in0, in1);
    1653           0 :       fhalfright32_avx2(in0, in1);
    1654           0 :       right_shift_32x32(in0, in1);
    1655           0 :       fidtx32_avx2(in0, in1);
    1656           0 :       break;
    1657             :     case H_ADST:
    1658           0 :       load_buffer_32x32(input, stride, 0, 0, in0, in1);
    1659           0 :       fidtx32_avx2(in0, in1);
    1660           0 :       right_shift_32x32(in0, in1);
    1661           0 :       fhalfright32_avx2(in0, in1);
    1662           0 :       break;
    1663             :     case V_FLIPADST:
    1664           0 :       load_buffer_32x32(input, stride, 1, 0, in0, in1);
    1665           0 :       fhalfright32_avx2(in0, in1);
    1666           0 :       right_shift_32x32(in0, in1);
    1667           0 :       fidtx32_avx2(in0, in1);
    1668           0 :       break;
    1669             :     case H_FLIPADST:
    1670           0 :       load_buffer_32x32(input, stride, 0, 1, in0, in1);
    1671           0 :       fidtx32_avx2(in0, in1);
    1672           0 :       right_shift_32x32(in0, in1);
    1673           0 :       fhalfright32_avx2(in0, in1);
    1674           0 :       break;
    1675             : #endif  // CONFIG_EXT_TX
    1676           0 :     default: assert(0); break;
    1677             :   }
    1678           0 :   write_buffer_32x32(in0, in1, output);
    1679             :   _mm256_zeroupper();
    1680           0 : }

Generated by: LCOV version 1.13