Commit 948e0bf939 for aom
commit 948e0bf93907c638879856fee7e7ac55a14a2e1c
Author: Frank Galligan <fgalligan@google.com>
Date: Sat Oct 31 09:54:06 2026 -0700
av1: Optimize 8-pt inv txfm and DC fast paths
Inline VEX-compiled 8-point 1D inverse transforms into AVX2 callers, add
DC-only (eob == 1) fast paths for DCT_DCT inverse transforms, inline 8x8
forward transforms, and specialize power-of-two above_row copies in
reconintra.c.
Benchmarking results (incremental vs prev CL / cumulative vs baseline):
- Stock avifenc still-image (Default 1T): -2.02% / -28.83% encode time
- Stock avifenc still-image (Default 8T): -0.38% / -23.19% encode time
- 48-image multi-rate corpus (Full Suite 1T): -1.01% / -29.22% time
- Bit-exact output (1T and 8T)
TAG=agy
CONV=b929a630-a6cd-45a0-979c-1767c30178ee
Change-Id: I72e842559d7bcba88eef617ad6f467ac314475ad
diff --git a/av1/common/av1_inv_txfm1d_cfg.h b/av1/common/av1_inv_txfm1d_cfg.h
index 0f5b80aac9..0062214af1 100644
--- a/av1/common/av1_inv_txfm1d_cfg.h
+++ b/av1/common/av1_inv_txfm1d_cfg.h
@@ -36,7 +36,27 @@ static const int8_t inv_start_range[TX_SIZES_ALL] = {
7, // 64x16 transform
};
-extern const int8_t *av1_inv_txfm_shift_ls[TX_SIZES_ALL];
+static const int8_t av1_inv_txfm_shift_ls[TX_SIZES_ALL][2] = {
+ { 0, -4 }, // 4x4 transform
+ { -1, -4 }, // 8x8 transform
+ { -2, -4 }, // 16x16 transform
+ { -2, -4 }, // 32x32 transform
+ { -2, -4 }, // 64x64 transform
+ { 0, -4 }, // 4x8 transform
+ { 0, -4 }, // 8x4 transform
+ { -1, -4 }, // 8x16 transform
+ { -1, -4 }, // 16x8 transform
+ { -1, -4 }, // 16x32 transform
+ { -1, -4 }, // 32x16 transform
+ { -1, -4 }, // 32x64 transform
+ { -1, -4 }, // 64x32 transform
+ { -1, -4 }, // 4x16 transform
+ { -1, -4 }, // 16x4 transform
+ { -2, -4 }, // 8x32 transform
+ { -2, -4 }, // 32x8 transform
+ { -2, -4 }, // 16x64 transform
+ { -2, -4 }, // 64x16 transform
+};
// Values in both av1_inv_cos_bit_col and av1_inv_cos_bit_row are always 12
// for each valid row and col combination
diff --git a/av1/common/av1_inv_txfm2d.c b/av1/common/av1_inv_txfm2d.c
index 715fcb000f..f5f1c5f0b7 100644
--- a/av1/common/av1_inv_txfm2d.c
+++ b/av1/common/av1_inv_txfm2d.c
@@ -131,34 +131,6 @@ static inline TxfmFunc inv_txfm_type_to_func(TXFM_TYPE txfm_type) {
}
}
-static const int8_t inv_shift_4x4[2] = { 0, -4 };
-static const int8_t inv_shift_8x8[2] = { -1, -4 };
-static const int8_t inv_shift_16x16[2] = { -2, -4 };
-static const int8_t inv_shift_32x32[2] = { -2, -4 };
-static const int8_t inv_shift_64x64[2] = { -2, -4 };
-static const int8_t inv_shift_4x8[2] = { 0, -4 };
-static const int8_t inv_shift_8x4[2] = { 0, -4 };
-static const int8_t inv_shift_8x16[2] = { -1, -4 };
-static const int8_t inv_shift_16x8[2] = { -1, -4 };
-static const int8_t inv_shift_16x32[2] = { -1, -4 };
-static const int8_t inv_shift_32x16[2] = { -1, -4 };
-static const int8_t inv_shift_32x64[2] = { -1, -4 };
-static const int8_t inv_shift_64x32[2] = { -1, -4 };
-static const int8_t inv_shift_4x16[2] = { -1, -4 };
-static const int8_t inv_shift_16x4[2] = { -1, -4 };
-static const int8_t inv_shift_8x32[2] = { -2, -4 };
-static const int8_t inv_shift_32x8[2] = { -2, -4 };
-static const int8_t inv_shift_16x64[2] = { -2, -4 };
-static const int8_t inv_shift_64x16[2] = { -2, -4 };
-
-const int8_t *av1_inv_txfm_shift_ls[TX_SIZES_ALL] = {
- inv_shift_4x4, inv_shift_8x8, inv_shift_16x16, inv_shift_32x32,
- inv_shift_64x64, inv_shift_4x8, inv_shift_8x4, inv_shift_8x16,
- inv_shift_16x8, inv_shift_16x32, inv_shift_32x16, inv_shift_32x64,
- inv_shift_64x32, inv_shift_4x16, inv_shift_16x4, inv_shift_8x32,
- inv_shift_32x8, inv_shift_16x64, inv_shift_64x16,
-};
-
static const int8_t iadst4_range[7] = { 0, 1, 0, 0, 0, 0, 0 };
void av1_get_inv_txfm_cfg(TX_TYPE tx_type, TX_SIZE tx_size,
diff --git a/av1/common/reconintra.c b/av1/common/reconintra.c
index a4eaf77c88..09ddc1a51e 100644
--- a/av1/common/reconintra.c
+++ b/av1/common/reconintra.c
@@ -1081,6 +1081,26 @@ void av1_upsample_intra_edge_c(uint8_t *p, int sz) {
}
}
+static AOM_FORCE_INLINE void copy_above_row_lbd(uint8_t *above_row,
+ const uint8_t *above_ref,
+ int n_copy) {
+ if (n_copy == 4) {
+ memcpy(above_row, above_ref, 4);
+ } else if (n_copy == 8) {
+ memcpy(above_row, above_ref, 8);
+ } else if (n_copy == 16) {
+ memcpy(above_row, above_ref, 16);
+ } else if (n_copy == 32) {
+ memcpy(above_row, above_ref, 32);
+ } else if (n_copy == 64) {
+ memcpy(above_row, above_ref, 64);
+ } else if (n_copy == 128) {
+ memcpy(above_row, above_ref, 128);
+ } else {
+ memcpy(above_row, above_ref, n_copy);
+ }
+}
+
static void build_directional_and_filter_intra_predictors(
const uint8_t *ref, int ref_stride, uint8_t *dst, int dst_stride,
PREDICTION_MODE mode, int p_angle, FILTER_INTRA_MODE filter_intra_mode,
@@ -1148,7 +1168,7 @@ static void build_directional_and_filter_intra_predictors(
const int num_top_pixels_needed = txwpx + (n_topright_px >= 0 ? txhpx : 0);
if (n_top_px > 0) {
const int n_top_copy = n_top_px + (n_topright_px > 0 ? n_topright_px : 0);
- memcpy(above_row, above_ref, n_top_copy);
+ copy_above_row_lbd(above_row, above_ref, n_top_copy);
if (n_top_copy < num_top_pixels_needed)
memset(&above_row[n_top_copy], above_row[n_top_copy - 1],
num_top_pixels_needed - n_top_copy);
@@ -1305,10 +1325,11 @@ static void build_non_directional_intra_predictors(
}
if (need_above) {
- if (n_top_px > 0) {
- memcpy(above_row, above_ref, n_top_px);
- i = n_top_px;
- if (i < txwpx) memset(&above_row[i], above_row[i - 1], txwpx - i);
+ if (LIKELY(n_top_px == txwpx)) {
+ copy_above_row_lbd(above_row, above_ref, txwpx);
+ } else if (n_top_px > 0) {
+ copy_above_row_lbd(above_row, above_ref, n_top_px);
+ memset(&above_row[n_top_px], above_row[n_top_px - 1], txwpx - n_top_px);
} else {
const uint8_t val = (n_left_px > 0) ? left_ref[0] : 127;
memset(above_row, val, txwpx);
@@ -1400,6 +1421,26 @@ void av1_highbd_upsample_intra_edge_c(uint16_t *p, int sz, int bd) {
}
}
+static AOM_FORCE_INLINE void copy_above_row_hbd(uint16_t *above_row,
+ const uint16_t *above_ref,
+ int n_copy) {
+ if (n_copy == 4) {
+ memcpy(above_row, above_ref, 4 * sizeof(uint16_t));
+ } else if (n_copy == 8) {
+ memcpy(above_row, above_ref, 8 * sizeof(uint16_t));
+ } else if (n_copy == 16) {
+ memcpy(above_row, above_ref, 16 * sizeof(uint16_t));
+ } else if (n_copy == 32) {
+ memcpy(above_row, above_ref, 32 * sizeof(uint16_t));
+ } else if (n_copy == 64) {
+ memcpy(above_row, above_ref, 64 * sizeof(uint16_t));
+ } else if (n_copy == 128) {
+ memcpy(above_row, above_ref, 128 * sizeof(uint16_t));
+ } else {
+ memcpy(above_row, above_ref, n_copy * sizeof(uint16_t));
+ }
+}
+
static void highbd_build_directional_and_filter_intra_predictors(
const uint8_t *ref8, int ref_stride, uint8_t *dst8, int dst_stride,
PREDICTION_MODE mode, int p_angle, FILTER_INTRA_MODE filter_intra_mode,
@@ -1471,7 +1512,7 @@ static void highbd_build_directional_and_filter_intra_predictors(
const int num_top_pixels_needed = txwpx + (n_topright_px >= 0 ? txhpx : 0);
if (n_top_px > 0) {
const int n_top_copy = n_top_px + (n_topright_px > 0 ? n_topright_px : 0);
- memcpy(above_row, above_ref, n_top_copy * sizeof(above_ref[0]));
+ copy_above_row_hbd(above_row, above_ref, n_top_copy);
if (n_top_copy < num_top_pixels_needed)
aom_memset16(&above_row[n_top_copy], above_row[n_top_copy - 1],
num_top_pixels_needed - n_top_copy);
@@ -1635,10 +1676,12 @@ static void highbd_build_non_directional_intra_predictors(
}
if (need_above) {
- if (n_top_px > 0) {
- memcpy(above_row, above_ref, n_top_px * sizeof(above_ref[0]));
- i = n_top_px;
- if (i < txwpx) aom_memset16(&above_row[i], above_row[i - 1], (txwpx - i));
+ if (LIKELY(n_top_px == txwpx)) {
+ copy_above_row_hbd(above_row, above_ref, txwpx);
+ } else if (n_top_px > 0) {
+ copy_above_row_hbd(above_row, above_ref, n_top_px);
+ aom_memset16(&above_row[n_top_px], above_row[n_top_px - 1],
+ txwpx - n_top_px);
} else {
const int val = (n_left_px > 0) ? left_ref[0] : base - 1;
aom_memset16(above_row, val, txwpx);
diff --git a/av1/common/x86/av1_inv_txfm_avx2.c b/av1/common/x86/av1_inv_txfm_avx2.c
index 0766210791..8136091a02 100644
--- a/av1/common/x86/av1_inv_txfm_avx2.c
+++ b/av1/common/x86/av1_inv_txfm_avx2.c
@@ -1636,19 +1636,47 @@ static const transform_1d_avx2
static inline void lowbd_inv_txfm2d_add_no_identity_avx2(
const int32_t *input, uint8_t *output, int stride, TX_TYPE tx_type,
TX_SIZE tx_size, int eob) {
- __m256i buf1[64 * 16];
- int eobx, eoby;
- get_eobx_eoby_scan_default(&eobx, &eoby, tx_size, eob);
const int8_t *shift = av1_inv_txfm_shift_ls[tx_size];
- const int txw_idx = get_txw_idx(tx_size);
- const int txh_idx = get_txh_idx(tx_size);
const int txfm_size_col = tx_size_wide[tx_size];
const int txfm_size_row = tx_size_high[tx_size];
const int buf_size_w_div16 = txfm_size_col >> 4;
+ const int rect_type = get_rect_tx_log_ratio(txfm_size_col, txfm_size_row);
+
+ // DC-only (eob == 1) fast path for DCT_DCT: compute the constant 2D inverse
+ // DCT contribution once and add it directly to the reconstruction buffer.
+ if (eob == 1 && tx_type == DCT_DCT) {
+ const int32_t *cospi = cospi_arr(INV_COS_BIT);
+ const __m128i w = _mm_set1_epi16(cospi[32] * 8);
+ const __m128i s0 = _mm_set1_epi16(1 << (15 + shift[0]));
+ const __m128i s1 = _mm_set1_epi16(1 << (15 - 4));
+ __m128i dc = _mm_cvtsi32_si128(input[0]);
+ dc = _mm_packs_epi32(dc, dc);
+ if (rect_type == 1 || rect_type == -1) {
+ dc = _mm_mulhrs_epi16(dc, _mm_set1_epi16(NewInvSqrt2 * 8));
+ }
+ dc = _mm_mulhrs_epi16(dc, w);
+ dc = _mm_mulhrs_epi16(dc, s0);
+ dc = _mm_mulhrs_epi16(dc, w);
+ dc = _mm_mulhrs_epi16(dc, s1);
+
+ const __m256i res = _mm256_broadcastw_epi16(dc);
+ for (int i = 0; i < buf_size_w_div16; i++) {
+ uint8_t *out_col = output + 16 * i;
+ for (int r = 0; r < txfm_size_row; ++r) {
+ write_recon_w16_avx2(res, out_col + r * stride);
+ }
+ }
+ return;
+ }
+
+ __m256i buf1[64 * 4];
+ int eobx, eoby;
+ get_eobx_eoby_scan_default(&eobx, &eoby, tx_size, eob);
+ const int txw_idx = get_txw_idx(tx_size);
+ const int txh_idx = get_txh_idx(tx_size);
const int buf_size_nonzero_w = ((eobx + 16) >> 4) << 4;
const int buf_size_nonzero_h_div16 = (eoby + 16) >> 4;
const int input_stride = AOMMIN(32, txfm_size_row);
- const int rect_type = get_rect_tx_log_ratio(txfm_size_col, txfm_size_row);
const int fun_idx_x = lowbd_txfm_all_1d_zeros_idx[eobx];
const int fun_idx_y = lowbd_txfm_all_1d_zeros_idx[eoby];
@@ -1688,7 +1716,7 @@ static inline void lowbd_inv_txfm2d_add_no_identity_avx2(
}
}
}
- const __m256i scale1 = _mm256_set1_epi16(1 << (15 + shift[1]));
+ const __m256i scale1 = _mm256_set1_epi16(1 << (15 - 4));
for (int i = 0; i < buf_size_w_div16; i++) {
__m256i *buf1_cur = buf1 + i * txfm_size_row;
col_txfm(buf1_cur, buf1_cur);
@@ -1891,9 +1919,24 @@ static inline void lowbd_inv_txfm2d_add_v_identity_avx2(
}
}
+static void idct8_low1_avx2(const __m128i *input, __m128i *output) {
+ idct8_low1_ssse3_inline(input, output);
+}
+
+static void idct8_avx2(const __m128i *input, __m128i *output) {
+ idct8_sse2_inline(input, output);
+}
+
+static void iadst8_low1_avx2(const __m128i *input, __m128i *output) {
+ iadst8_low1_ssse3_inline(input, output);
+}
+
+static void iadst8_avx2(const __m128i *input, __m128i *output) {
+ iadst8_sse2_inline(input, output);
+}
+
static const transform_1d_ssse3 lowbd_txfm_all_1d_zeros_8x8_arr[2][2] = {
- { av1_idct8_low1_ssse3, av1_idct8_sse2 },
- { av1_iadst8_low1_ssse3, av1_iadst8_sse2 }
+ { idct8_low1_avx2, idct8_avx2 }, { iadst8_low1_avx2, iadst8_avx2 }
};
static inline void load_buffer_avx2(const int32_t *in, int stride,
@@ -2114,9 +2157,90 @@ static inline void round_shift_lowbd_write_buffer_avx2(__m128i *in, int bit,
static inline void lowbd_inv_txfm2d_8x8_no_identity_avx2(
const int32_t *input, uint8_t *output, int stride, TX_TYPE tx_type,
TX_SIZE tx_size, int eob) {
- __m128i buf1[8];
+ (void)tx_size;
+ __m128i buf0[8], buf1[8];
const int input_stride = 8;
- const int8_t *shift = av1_inv_txfm_shift_ls[tx_size];
+
+ if (tx_type == DCT_DCT) {
+ // DC-only (eob == 1) fast path for 8x8 DCT_DCT.
+ if (eob == 1) {
+ const int32_t *cospi = cospi_arr(INV_COS_BIT);
+ const __m128i w = _mm_set1_epi16(cospi[32] * 8);
+ const __m128i s0 = _mm_set1_epi16(1 << (15 - 1));
+ const __m128i s1 = _mm_set1_epi16(1 << (15 - 4));
+ __m128i dc = _mm_cvtsi32_si128(input[0]);
+ dc = _mm_packs_epi32(dc, dc);
+ dc = _mm_mulhrs_epi16(dc, w);
+ dc = _mm_mulhrs_epi16(dc, s0);
+ dc = _mm_mulhrs_epi16(dc, w);
+ dc = _mm_mulhrs_epi16(dc, s1);
+
+ const __m256i dc256 = _mm256_broadcastw_epi16(dc);
+ const __m256i zero = _mm256_setzero_si256();
+ const __m128i v0 = _mm_loadl_epi64((__m128i const *)(output));
+ const __m128i v1 = _mm_loadl_epi64((__m128i const *)(output + stride));
+ const __m128i v2 =
+ _mm_loadl_epi64((__m128i const *)(output + 2 * stride));
+ const __m128i v3 =
+ _mm_loadl_epi64((__m128i const *)(output + 3 * stride));
+ const __m128i v4 =
+ _mm_loadl_epi64((__m128i const *)(output + 4 * stride));
+ const __m128i v5 =
+ _mm_loadl_epi64((__m128i const *)(output + 5 * stride));
+ const __m128i v6 =
+ _mm_loadl_epi64((__m128i const *)(output + 6 * stride));
+ const __m128i v7 =
+ _mm_loadl_epi64((__m128i const *)(output + 7 * stride));
+
+ const __m256i v01 =
+ _mm256_inserti128_si256(_mm256_castsi128_si256(v0), v1, 1);
+ const __m256i v23 =
+ _mm256_inserti128_si256(_mm256_castsi128_si256(v2), v3, 1);
+ const __m256i v45 =
+ _mm256_inserti128_si256(_mm256_castsi128_si256(v4), v5, 1);
+ const __m256i v67 =
+ _mm256_inserti128_si256(_mm256_castsi128_si256(v6), v7, 1);
+
+ const __m256i x0 =
+ _mm256_adds_epi16(dc256, _mm256_unpacklo_epi8(v01, zero));
+ const __m256i x1 =
+ _mm256_adds_epi16(dc256, _mm256_unpacklo_epi8(v23, zero));
+ const __m256i x2 =
+ _mm256_adds_epi16(dc256, _mm256_unpacklo_epi8(v45, zero));
+ const __m256i x3 =
+ _mm256_adds_epi16(dc256, _mm256_unpacklo_epi8(v67, zero));
+
+ const __m256i res_0123 = _mm256_packus_epi16(x0, x1);
+ const __m256i res_4567 = _mm256_packus_epi16(x2, x3);
+ const __m128i res_02 = _mm256_castsi256_si128(res_0123);
+ const __m128i res_13 = _mm256_extracti128_si256(res_0123, 1);
+ const __m128i res_46 = _mm256_castsi256_si128(res_4567);
+ const __m128i res_57 = _mm256_extracti128_si256(res_4567, 1);
+
+ _mm_storel_epi64((__m128i *)(output), res_02);
+ _mm_storel_epi64((__m128i *)(output + stride), res_13);
+ _mm_storel_epi64((__m128i *)(output + 2 * stride),
+ _mm_unpackhi_epi64(res_02, res_02));
+ _mm_storel_epi64((__m128i *)(output + 3 * stride),
+ _mm_unpackhi_epi64(res_13, res_13));
+ _mm_storel_epi64((__m128i *)(output + 4 * stride), res_46);
+ _mm_storel_epi64((__m128i *)(output + 5 * stride), res_57);
+ _mm_storel_epi64((__m128i *)(output + 6 * stride),
+ _mm_unpackhi_epi64(res_46, res_46));
+ _mm_storel_epi64((__m128i *)(output + 7 * stride),
+ _mm_unpackhi_epi64(res_57, res_57));
+ return;
+ }
+
+ int lr_flip = 0;
+ load_buffer_avx2(input, input_stride, buf0);
+ idct8_sse2_inline(buf0, buf0);
+ round_and_transpose_avx2(buf0, buf1, -1, &lr_flip);
+ idct8_sse2_inline(buf1, buf1);
+ round_shift_lowbd_write_buffer_avx2(buf1, -4, output, stride, 0);
+ return;
+ }
+
assert(hitx_1d_tab[tx_type] < 2);
assert(vitx_1d_tab[tx_type] < 2);
const transform_1d_ssse3 row_txfm =
@@ -2129,17 +2253,11 @@ static inline void lowbd_inv_txfm2d_8x8_no_identity_avx2(
int ud_flip, lr_flip;
get_flip_cfg(tx_type, &ud_flip, &lr_flip);
- __m128i buf0[8];
- __m128i *buf0_cur = buf0;
- load_buffer_avx2(input, input_stride, buf0_cur);
+ load_buffer_avx2(input, input_stride, buf0);
row_txfm(buf0, buf0);
-
- assert(shift[0] < 0);
- __m128i *_buf1 = buf1;
- round_and_transpose_avx2(buf0, _buf1, shift[0], &lr_flip);
- assert(shift[1] < 0);
+ round_and_transpose_avx2(buf0, buf1, -1, &lr_flip);
col_txfm(buf1, buf1);
- round_shift_lowbd_write_buffer_avx2(buf1, shift[1], output, stride, ud_flip);
+ round_shift_lowbd_write_buffer_avx2(buf1, -4, output, stride, ud_flip);
}
// AVX2 implementation of 8x8 inverse transform. Observed that coding AVX2 for
diff --git a/av1/common/x86/av1_inv_txfm_ssse3.c b/av1/common/x86/av1_inv_txfm_ssse3.c
index 863c9cae29..0a83c8c672 100644
--- a/av1/common/x86/av1_inv_txfm_ssse3.c
+++ b/av1/common/x86/av1_inv_txfm_ssse3.c
@@ -79,74 +79,11 @@ static void idct4_w4_sse2(const __m128i *input, __m128i *output) {
}
void av1_idct8_low1_ssse3(const __m128i *input, __m128i *output) {
- const int32_t *cospi = cospi_arr(INV_COS_BIT);
-
- // stage 1
- __m128i x[2];
- x[0] = input[0];
-
- // stage 2
- // stage 3
- btf_16_ssse3(cospi[32], cospi[32], x[0], x[0], x[1]);
-
- // stage 4
- // stage 5
- output[0] = x[0];
- output[7] = x[0];
- output[1] = x[1];
- output[6] = x[1];
- output[2] = x[1];
- output[5] = x[1];
- output[3] = x[0];
- output[4] = x[0];
+ idct8_low1_ssse3_inline(input, output);
}
void av1_idct8_sse2(const __m128i *input, __m128i *output) {
- const int8_t cos_bit = INV_COS_BIT;
- const int32_t *cospi = cospi_arr(INV_COS_BIT);
- const __m128i __rounding = _mm_set1_epi32(1 << (INV_COS_BIT - 1));
-
- const __m128i cospi_p56_m08 = pair_set_epi16(cospi[56], -cospi[8]);
- const __m128i cospi_p08_p56 = pair_set_epi16(cospi[8], cospi[56]);
- const __m128i cospi_p24_m40 = pair_set_epi16(cospi[24], -cospi[40]);
- const __m128i cospi_p40_p24 = pair_set_epi16(cospi[40], cospi[24]);
- const __m128i cospi_p32_p32 = pair_set_epi16(cospi[32], cospi[32]);
- const __m128i cospi_p32_m32 = pair_set_epi16(cospi[32], -cospi[32]);
- const __m128i cospi_p48_m16 = pair_set_epi16(cospi[48], -cospi[16]);
- const __m128i cospi_p16_p48 = pair_set_epi16(cospi[16], cospi[48]);
- const __m128i cospi_m32_p32 = pair_set_epi16(-cospi[32], cospi[32]);
-
- // stage 1
- __m128i x[8];
- x[0] = input[0];
- x[1] = input[4];
- x[2] = input[2];
- x[3] = input[6];
- x[4] = input[1];
- x[5] = input[5];
- x[6] = input[3];
- x[7] = input[7];
-
- // stage 2
- btf_16_sse2(cospi_p56_m08, cospi_p08_p56, x[4], x[7], x[4], x[7]);
- btf_16_sse2(cospi_p24_m40, cospi_p40_p24, x[5], x[6], x[5], x[6]);
-
- // stage 3
- btf_16_sse2(cospi_p32_p32, cospi_p32_m32, x[0], x[1], x[0], x[1]);
- btf_16_sse2(cospi_p48_m16, cospi_p16_p48, x[2], x[3], x[2], x[3]);
- btf_16_adds_subs_sse2(x[4], x[5]);
- btf_16_subs_adds_sse2(x[7], x[6]);
-
- // stage 4
- btf_16_adds_subs_sse2(x[0], x[3]);
- btf_16_adds_subs_sse2(x[1], x[2]);
- btf_16_sse2(cospi_m32_p32, cospi_p32_p32, x[5], x[6], x[5], x[6]);
-
- // stage 5
- btf_16_adds_subs_out_sse2(output[0], output[7], x[0], x[7]);
- btf_16_adds_subs_out_sse2(output[1], output[6], x[1], x[6]);
- btf_16_adds_subs_out_sse2(output[2], output[5], x[2], x[5]);
- btf_16_adds_subs_out_sse2(output[3], output[4], x[3], x[4]);
+ idct8_sse2_inline(input, output);
}
static void idct8_w4_sse2(const __m128i *input, __m128i *output) {
@@ -1701,117 +1638,11 @@ static void iadst4_w4_sse2(const __m128i *input, __m128i *output) {
}
void av1_iadst8_low1_ssse3(const __m128i *input, __m128i *output) {
- const int8_t cos_bit = INV_COS_BIT;
- const int32_t *cospi = cospi_arr(INV_COS_BIT);
- const __m128i __zero = _mm_setzero_si128();
- const __m128i __rounding = _mm_set1_epi32(1 << (INV_COS_BIT - 1));
-
- const __m128i cospi_p16_p48 = pair_set_epi16(cospi[16], cospi[48]);
- const __m128i cospi_p48_m16 = pair_set_epi16(cospi[48], -cospi[16]);
- const __m128i cospi_p32_p32 = pair_set_epi16(cospi[32], cospi[32]);
- const __m128i cospi_p32_m32 = pair_set_epi16(cospi[32], -cospi[32]);
-
- // stage 1
- __m128i x[8];
- x[1] = input[0];
-
- // stage 2
- btf_16_ssse3(cospi[60], -cospi[4], x[1], x[0], x[1]);
-
- // stage 3
- x[4] = x[0];
- x[5] = x[1];
-
- // stage 4
- btf_16_sse2(cospi_p16_p48, cospi_p48_m16, x[4], x[5], x[4], x[5]);
-
- // stage 5
- x[2] = x[0];
- x[3] = x[1];
- x[6] = x[4];
- x[7] = x[5];
-
- // stage 6
- btf_16_sse2(cospi_p32_p32, cospi_p32_m32, x[2], x[3], x[2], x[3]);
- btf_16_sse2(cospi_p32_p32, cospi_p32_m32, x[6], x[7], x[6], x[7]);
-
- // stage 7
- output[0] = x[0];
- output[1] = _mm_subs_epi16(__zero, x[4]);
- output[2] = x[6];
- output[3] = _mm_subs_epi16(__zero, x[2]);
- output[4] = x[3];
- output[5] = _mm_subs_epi16(__zero, x[7]);
- output[6] = x[5];
- output[7] = _mm_subs_epi16(__zero, x[1]);
+ iadst8_low1_ssse3_inline(input, output);
}
void av1_iadst8_sse2(const __m128i *input, __m128i *output) {
- const int8_t cos_bit = INV_COS_BIT;
- const int32_t *cospi = cospi_arr(INV_COS_BIT);
- const __m128i __zero = _mm_setzero_si128();
- const __m128i __rounding = _mm_set1_epi32(1 << (INV_COS_BIT - 1));
-
- const __m128i cospi_p04_p60 = pair_set_epi16(cospi[4], cospi[60]);
- const __m128i cospi_p60_m04 = pair_set_epi16(cospi[60], -cospi[4]);
- const __m128i cospi_p20_p44 = pair_set_epi16(cospi[20], cospi[44]);
- const __m128i cospi_p44_m20 = pair_set_epi16(cospi[44], -cospi[20]);
- const __m128i cospi_p36_p28 = pair_set_epi16(cospi[36], cospi[28]);
- const __m128i cospi_p28_m36 = pair_set_epi16(cospi[28], -cospi[36]);
- const __m128i cospi_p52_p12 = pair_set_epi16(cospi[52], cospi[12]);
- const __m128i cospi_p12_m52 = pair_set_epi16(cospi[12], -cospi[52]);
- const __m128i cospi_p16_p48 = pair_set_epi16(cospi[16], cospi[48]);
- const __m128i cospi_p48_m16 = pair_set_epi16(cospi[48], -cospi[16]);
- const __m128i cospi_m48_p16 = pair_set_epi16(-cospi[48], cospi[16]);
- const __m128i cospi_p32_p32 = pair_set_epi16(cospi[32], cospi[32]);
- const __m128i cospi_p32_m32 = pair_set_epi16(cospi[32], -cospi[32]);
-
- // stage 1
- __m128i x[8];
- x[0] = input[7];
- x[1] = input[0];
- x[2] = input[5];
- x[3] = input[2];
- x[4] = input[3];
- x[5] = input[4];
- x[6] = input[1];
- x[7] = input[6];
-
- // stage 2
- btf_16_sse2(cospi_p04_p60, cospi_p60_m04, x[0], x[1], x[0], x[1]);
- btf_16_sse2(cospi_p20_p44, cospi_p44_m20, x[2], x[3], x[2], x[3]);
- btf_16_sse2(cospi_p36_p28, cospi_p28_m36, x[4], x[5], x[4], x[5]);
- btf_16_sse2(cospi_p52_p12, cospi_p12_m52, x[6], x[7], x[6], x[7]);
-
- // stage 3
- btf_16_adds_subs_sse2(x[0], x[4]);
- btf_16_adds_subs_sse2(x[1], x[5]);
- btf_16_adds_subs_sse2(x[2], x[6]);
- btf_16_adds_subs_sse2(x[3], x[7]);
-
- // stage 4
- btf_16_sse2(cospi_p16_p48, cospi_p48_m16, x[4], x[5], x[4], x[5]);
- btf_16_sse2(cospi_m48_p16, cospi_p16_p48, x[6], x[7], x[6], x[7]);
-
- // stage 5
- btf_16_adds_subs_sse2(x[0], x[2]);
- btf_16_adds_subs_sse2(x[1], x[3]);
- btf_16_adds_subs_sse2(x[4], x[6]);
- btf_16_adds_subs_sse2(x[5], x[7]);
-
- // stage 6
- btf_16_sse2(cospi_p32_p32, cospi_p32_m32, x[2], x[3], x[2], x[3]);
- btf_16_sse2(cospi_p32_p32, cospi_p32_m32, x[6], x[7], x[6], x[7]);
-
- // stage 7
- output[0] = x[0];
- output[1] = _mm_subs_epi16(__zero, x[4]);
- output[2] = x[6];
- output[3] = _mm_subs_epi16(__zero, x[2]);
- output[4] = x[3];
- output[5] = _mm_subs_epi16(__zero, x[7]);
- output[6] = x[5];
- output[7] = _mm_subs_epi16(__zero, x[1]);
+ iadst8_sse2_inline(input, output);
}
static void iadst8_w4_sse2(const __m128i *input, __m128i *output) {
@@ -2422,6 +2253,16 @@ static void lowbd_inv_txfm2d_add_4x4_ssse3(const int32_t *input,
const int txfm_size_col = tx_size_wide[tx_size];
const int txfm_size_row = tx_size_high[tx_size];
+ if (tx_type == DCT_DCT) {
+ load_buffer_32bit_to_16bit_w4(input, 4, buf, 4);
+ idct4_w4_sse2(buf, buf);
+ transpose_16bit_4x4(buf, buf);
+ idct4_w4_sse2(buf, buf);
+ round_shift_16bit_ssse3(buf, 4, -4);
+ lowbd_write_buffer_4xn_sse2(buf, output, stride, 0, 4);
+ return;
+ }
+
const transform_1d_ssse3 row_txfm =
lowbd_txfm_all_1d_w4_arr[txw_idx][hitx_1d_tab[tx_type]];
const transform_1d_ssse3 col_txfm =
@@ -2476,19 +2317,57 @@ static inline void round_shift_ssse3(const __m128i *input, __m128i *output,
static inline void lowbd_inv_txfm2d_add_no_identity_ssse3(
const int32_t *input, uint8_t *output, int stride, TX_TYPE tx_type,
TX_SIZE tx_size, int eob) {
+ const int8_t *shift = av1_inv_txfm_shift_ls[tx_size];
+ const int txfm_size_col = tx_size_wide[tx_size];
+ const int txfm_size_row = tx_size_high[tx_size];
+ const int rect_type = get_rect_tx_log_ratio(txfm_size_col, txfm_size_row);
+
+ // DC-only (eob == 1) fast path for DCT_DCT.
+ if (eob == 1 && tx_type == DCT_DCT) {
+ const int32_t *cospi = cospi_arr(INV_COS_BIT);
+ const __m128i w = _mm_set1_epi16(cospi[32] * 8);
+ const __m128i s0 = _mm_set1_epi16(1 << (15 + shift[0]));
+ const __m128i s1 = _mm_set1_epi16(1 << (15 - 4));
+ __m128i dc = _mm_cvtsi32_si128(input[0]);
+ dc = _mm_packs_epi32(dc, dc);
+ if (rect_type == 1 || rect_type == -1) {
+ dc = _mm_mulhrs_epi16(dc, _mm_set1_epi16(NewInvSqrt2 * 8));
+ }
+ dc = _mm_mulhrs_epi16(dc, w);
+ dc = _mm_mulhrs_epi16(dc, s0);
+ dc = _mm_mulhrs_epi16(dc, w);
+ dc = _mm_mulhrs_epi16(dc, s1);
+ dc = _mm_shuffle_epi32(_mm_unpacklo_epi16(dc, dc), 0);
+
+ if (txfm_size_col >= 16) {
+ for (int i = 0; i < (txfm_size_col >> 4); i++) {
+ uint8_t *out_col = output + 16 * i;
+ for (int r = 0; r < txfm_size_row; ++r) {
+ __m128i v = _mm_loadu_si128((__m128i const *)(out_col + r * stride));
+ __m128i u = lowbd_get_recon_16x16_sse2(v, dc, dc);
+ _mm_storeu_si128((__m128i *)(out_col + r * stride), u);
+ }
+ }
+ } else if (txfm_size_col == 8) {
+ for (int r = 0; r < txfm_size_row; ++r) {
+ const __m128i v =
+ _mm_loadl_epi64((__m128i const *)(output + r * stride));
+ const __m128i u = lowbd_get_recon_8x8_sse2(v, dc);
+ _mm_storel_epi64((__m128i *)(output + r * stride), u);
+ }
+ }
+ return;
+ }
+
__m128i buf1[64 * 8];
int eobx, eoby;
get_eobx_eoby_scan_default(&eobx, &eoby, tx_size, eob);
- const int8_t *shift = av1_inv_txfm_shift_ls[tx_size];
const int txw_idx = get_txw_idx(tx_size);
const int txh_idx = get_txh_idx(tx_size);
- const int txfm_size_col = tx_size_wide[tx_size];
- const int txfm_size_row = tx_size_high[tx_size];
const int buf_size_w_div8 = txfm_size_col >> 3;
const int buf_size_nonzero_w = ((eobx + 8) >> 3) << 3;
const int buf_size_nonzero_h_div8 = (eoby + 8) >> 3;
const int input_stride = AOMMIN(32, txfm_size_row);
- const int rect_type = get_rect_tx_log_ratio(txfm_size_col, txfm_size_row);
const int fun_idx_x = lowbd_txfm_all_1d_zeros_idx[eobx];
const int fun_idx_y = lowbd_txfm_all_1d_zeros_idx[eoby];
@@ -2526,7 +2405,7 @@ static inline void lowbd_inv_txfm2d_add_no_identity_ssse3(
}
for (int i = 0; i < buf_size_w_div8; i++) {
col_txfm(buf1 + i * txfm_size_row, buf1 + i * txfm_size_row);
- round_shift_16bit_ssse3(buf1 + i * txfm_size_row, txfm_size_row, shift[1]);
+ round_shift_16bit_ssse3(buf1 + i * txfm_size_row, txfm_size_row, -4);
}
if (txfm_size_col >= 16) {
diff --git a/av1/common/x86/av1_inv_txfm_ssse3.h b/av1/common/x86/av1_inv_txfm_ssse3.h
index c06f7a12f4..b27554b10e 100644
--- a/av1/common/x86/av1_inv_txfm_ssse3.h
+++ b/av1/common/x86/av1_inv_txfm_ssse3.h
@@ -19,6 +19,8 @@
#include "aom/aom_integer.h"
#include "aom_dsp/x86/transpose_sse2.h"
+#include "av1/common/av1_inv_txfm1d_cfg.h"
+#include "av1/common/x86/av1_txfm_sse2.h"
#ifdef __cplusplus
extern "C" {
@@ -232,6 +234,181 @@ void av1_lowbd_inv_txfm2d_add_v_identity_ssse3(const int32_t *input,
TX_TYPE tx_type, TX_SIZE tx_size,
int eob);
+static inline void idct8_low1_ssse3_inline(const __m128i *input,
+ __m128i *output) {
+ const int32_t *cospi = cospi_arr(INV_COS_BIT);
+
+ __m128i x[2];
+ x[0] = input[0];
+
+ btf_16_ssse3(cospi[32], cospi[32], x[0], x[0], x[1]);
+
+ output[0] = x[0];
+ output[7] = x[0];
+ output[1] = x[1];
+ output[6] = x[1];
+ output[2] = x[1];
+ output[5] = x[1];
+ output[3] = x[0];
+ output[4] = x[0];
+}
+
+static inline void idct8_sse2_inline(const __m128i *input, __m128i *output) {
+ const int8_t cos_bit = INV_COS_BIT;
+ const int32_t *cospi = cospi_arr(INV_COS_BIT);
+ const __m128i __rounding = _mm_set1_epi32(1 << (INV_COS_BIT - 1));
+
+ const __m128i cospi_p56_m08 = pair_set_epi16(cospi[56], -cospi[8]);
+ const __m128i cospi_p08_p56 = pair_set_epi16(cospi[8], cospi[56]);
+ const __m128i cospi_p24_m40 = pair_set_epi16(cospi[24], -cospi[40]);
+ const __m128i cospi_p40_p24 = pair_set_epi16(cospi[40], cospi[24]);
+ const __m128i cospi_p32_p32 = pair_set_epi16(cospi[32], cospi[32]);
+ const __m128i cospi_p32_m32 = pair_set_epi16(cospi[32], -cospi[32]);
+ const __m128i cospi_p48_m16 = pair_set_epi16(cospi[48], -cospi[16]);
+ const __m128i cospi_p16_p48 = pair_set_epi16(cospi[16], cospi[48]);
+ const __m128i cospi_m32_p32 = pair_set_epi16(-cospi[32], cospi[32]);
+
+ // stage 1
+ __m128i x[8];
+ x[0] = input[0];
+ x[1] = input[4];
+ x[2] = input[2];
+ x[3] = input[6];
+ x[4] = input[1];
+ x[5] = input[5];
+ x[6] = input[3];
+ x[7] = input[7];
+
+ // stage 2
+ btf_16_sse2(cospi_p56_m08, cospi_p08_p56, x[4], x[7], x[4], x[7]);
+ btf_16_sse2(cospi_p24_m40, cospi_p40_p24, x[5], x[6], x[5], x[6]);
+
+ // stage 3
+ btf_16_sse2(cospi_p32_p32, cospi_p32_m32, x[0], x[1], x[0], x[1]);
+ btf_16_sse2(cospi_p48_m16, cospi_p16_p48, x[2], x[3], x[2], x[3]);
+ btf_16_adds_subs_sse2(x[4], x[5]);
+ btf_16_subs_adds_sse2(x[7], x[6]);
+
+ // stage 4
+ btf_16_adds_subs_sse2(x[0], x[3]);
+ btf_16_adds_subs_sse2(x[1], x[2]);
+ btf_16_sse2(cospi_m32_p32, cospi_p32_p32, x[5], x[6], x[5], x[6]);
+
+ // stage 5
+ btf_16_adds_subs_out_sse2(output[0], output[7], x[0], x[7]);
+ btf_16_adds_subs_out_sse2(output[1], output[6], x[1], x[6]);
+ btf_16_adds_subs_out_sse2(output[2], output[5], x[2], x[5]);
+ btf_16_adds_subs_out_sse2(output[3], output[4], x[3], x[4]);
+}
+
+static inline void iadst8_low1_ssse3_inline(const __m128i *input,
+ __m128i *output) {
+ const int8_t cos_bit = INV_COS_BIT;
+ const int32_t *cospi = cospi_arr(INV_COS_BIT);
+ const __m128i __zero = _mm_setzero_si128();
+ const __m128i __rounding = _mm_set1_epi32(1 << (INV_COS_BIT - 1));
+
+ const __m128i cospi_p16_p48 = pair_set_epi16(cospi[16], cospi[48]);
+ const __m128i cospi_p48_m16 = pair_set_epi16(cospi[48], -cospi[16]);
+ const __m128i cospi_p32_p32 = pair_set_epi16(cospi[32], cospi[32]);
+ const __m128i cospi_p32_m32 = pair_set_epi16(cospi[32], -cospi[32]);
+
+ __m128i x[8];
+ x[1] = input[0];
+
+ btf_16_ssse3(cospi[60], -cospi[4], x[1], x[0], x[1]);
+
+ x[4] = x[0];
+ x[5] = x[1];
+
+ btf_16_sse2(cospi_p16_p48, cospi_p48_m16, x[4], x[5], x[4], x[5]);
+
+ x[2] = x[0];
+ x[3] = x[1];
+ x[6] = x[4];
+ x[7] = x[5];
+
+ btf_16_sse2(cospi_p32_p32, cospi_p32_m32, x[2], x[3], x[2], x[3]);
+ btf_16_sse2(cospi_p32_p32, cospi_p32_m32, x[6], x[7], x[6], x[7]);
+
+ output[0] = x[0];
+ output[1] = _mm_subs_epi16(__zero, x[4]);
+ output[2] = x[6];
+ output[3] = _mm_subs_epi16(__zero, x[2]);
+ output[4] = x[3];
+ output[5] = _mm_subs_epi16(__zero, x[7]);
+ output[6] = x[5];
+ output[7] = _mm_subs_epi16(__zero, x[1]);
+}
+
+static inline void iadst8_sse2_inline(const __m128i *input, __m128i *output) {
+ const int8_t cos_bit = INV_COS_BIT;
+ const int32_t *cospi = cospi_arr(INV_COS_BIT);
+ const __m128i __zero = _mm_setzero_si128();
+ const __m128i __rounding = _mm_set1_epi32(1 << (INV_COS_BIT - 1));
+
+ const __m128i cospi_p04_p60 = pair_set_epi16(cospi[4], cospi[60]);
+ const __m128i cospi_p60_m04 = pair_set_epi16(cospi[60], -cospi[4]);
+ const __m128i cospi_p20_p44 = pair_set_epi16(cospi[20], cospi[44]);
+ const __m128i cospi_p44_m20 = pair_set_epi16(cospi[44], -cospi[20]);
+ const __m128i cospi_p36_p28 = pair_set_epi16(cospi[36], cospi[28]);
+ const __m128i cospi_p28_m36 = pair_set_epi16(cospi[28], -cospi[36]);
+ const __m128i cospi_p52_p12 = pair_set_epi16(cospi[52], cospi[12]);
+ const __m128i cospi_p12_m52 = pair_set_epi16(cospi[12], -cospi[52]);
+ const __m128i cospi_p16_p48 = pair_set_epi16(cospi[16], cospi[48]);
+ const __m128i cospi_p48_m16 = pair_set_epi16(cospi[48], -cospi[16]);
+ const __m128i cospi_m48_p16 = pair_set_epi16(-cospi[48], cospi[16]);
+ const __m128i cospi_p32_p32 = pair_set_epi16(cospi[32], cospi[32]);
+ const __m128i cospi_p32_m32 = pair_set_epi16(cospi[32], -cospi[32]);
+
+ // stage 1
+ __m128i x[8];
+ x[0] = input[7];
+ x[1] = input[0];
+ x[2] = input[5];
+ x[3] = input[2];
+ x[4] = input[3];
+ x[5] = input[4];
+ x[6] = input[1];
+ x[7] = input[6];
+
+ // stage 2
+ btf_16_sse2(cospi_p04_p60, cospi_p60_m04, x[0], x[1], x[0], x[1]);
+ btf_16_sse2(cospi_p20_p44, cospi_p44_m20, x[2], x[3], x[2], x[3]);
+ btf_16_sse2(cospi_p36_p28, cospi_p28_m36, x[4], x[5], x[4], x[5]);
+ btf_16_sse2(cospi_p52_p12, cospi_p12_m52, x[6], x[7], x[6], x[7]);
+
+ // stage 3
+ btf_16_adds_subs_sse2(x[0], x[4]);
+ btf_16_adds_subs_sse2(x[1], x[5]);
+ btf_16_adds_subs_sse2(x[2], x[6]);
+ btf_16_adds_subs_sse2(x[3], x[7]);
+
+ // stage 4
+ btf_16_sse2(cospi_p16_p48, cospi_p48_m16, x[4], x[5], x[4], x[5]);
+ btf_16_sse2(cospi_m48_p16, cospi_p16_p48, x[6], x[7], x[6], x[7]);
+
+ // stage 5
+ btf_16_adds_subs_sse2(x[0], x[2]);
+ btf_16_adds_subs_sse2(x[1], x[3]);
+ btf_16_adds_subs_sse2(x[4], x[6]);
+ btf_16_adds_subs_sse2(x[5], x[7]);
+
+ // stage 6
+ btf_16_sse2(cospi_p32_p32, cospi_p32_m32, x[2], x[3], x[2], x[3]);
+ btf_16_sse2(cospi_p32_p32, cospi_p32_m32, x[6], x[7], x[6], x[7]);
+
+ // stage 7
+ output[0] = x[0];
+ output[1] = _mm_subs_epi16(__zero, x[4]);
+ output[2] = x[6];
+ output[3] = _mm_subs_epi16(__zero, x[2]);
+ output[4] = x[3];
+ output[5] = _mm_subs_epi16(__zero, x[7]);
+ output[6] = x[5];
+ output[7] = _mm_subs_epi16(__zero, x[1]);
+}
+
void av1_iadst8_low1_ssse3(const __m128i *input, __m128i *output);
void av1_idct8_low1_ssse3(const __m128i *input, __m128i *output);
diff --git a/av1/encoder/x86/av1_fwd_txfm2d_avx2.c b/av1/encoder/x86/av1_fwd_txfm2d_avx2.c
index cf3c1166b7..081f22058e 100644
--- a/av1/encoder/x86/av1_fwd_txfm2d_avx2.c
+++ b/av1/encoder/x86/av1_fwd_txfm2d_avx2.c
@@ -1633,44 +1633,6 @@ static const transform_1d_avx2 row_txfm16x16_cb13_arr[TX_TYPES] = {
fadst16x16_cb13_avx2 // H_FLIPADST
};
-static const transform_1d_sse2 col_txfm8x8_arr[TX_TYPES] = {
- fdct8x8_cb13_sse2, // DCT_DCT
- fadst8x8_cb13_sse2, // ADST_DCT
- fdct8x8_cb13_sse2, // DCT_ADST
- fadst8x8_cb13_sse2, // ADST_ADST
- fadst8x8_cb13_sse2, // FLIPADST_DCT
- fdct8x8_cb13_sse2, // DCT_FLIPADST
- fadst8x8_cb13_sse2, // FLIPADST_FLIPADST
- fadst8x8_cb13_sse2, // ADST_FLIPADST
- fadst8x8_cb13_sse2, // FLIPADST_ADST
- fidentity8x8_new_sse2, // IDTX
- fdct8x8_cb13_sse2, // V_DCT
- fidentity8x8_new_sse2, // H_DCT
- fadst8x8_cb13_sse2, // V_ADST
- fidentity8x8_new_sse2, // H_ADST
- fadst8x8_cb13_sse2, // V_FLIPADST
- fidentity8x8_new_sse2, // H_FLIPADST
-};
-
-static const transform_1d_sse2 row_txfm8x8_arr[TX_TYPES] = {
- fdct8x8_cb13_sse2, // DCT_DCT
- fdct8x8_cb13_sse2, // ADST_DCT
- fadst8x8_cb13_sse2, // DCT_ADST
- fadst8x8_cb13_sse2, // ADST_ADST
- fdct8x8_cb13_sse2, // FLIPADST_DCT
- fadst8x8_cb13_sse2, // DCT_FLIPADST
- fadst8x8_cb13_sse2, // FLIPADST_FLIPADST
- fadst8x8_cb13_sse2, // ADST_FLIPADST
- fadst8x8_cb13_sse2, // FLIPADST_ADST
- fidentity8x8_new_sse2, // IDTX
- fidentity8x8_new_sse2, // V_DCT
- fdct8x8_cb13_sse2, // H_DCT
- fidentity8x8_new_sse2, // V_ADST
- fadst8x8_cb13_sse2, // H_ADST
- fidentity8x8_new_sse2, // V_FLIPADST
- fadst8x8_cb13_sse2 // H_FLIPADST
-};
-
static inline void load_buffer_and_round_shift(const int16_t *in, int stride,
__m128i *out, int bit) {
out[0] = _mm_load_si128((const __m128i *)(in + 0 * stride));
@@ -1851,7 +1813,7 @@ static inline void store_buffer_16bit_to_32bit_w8_avx2(const __m128i *const in,
static void av1_lowbd_fwd_txfm2d_8x8_avx2(const int16_t *input, int32_t *output,
int stride, TX_TYPE tx_type, int bd) {
(void)bd;
- __m128i buf0[8], buf1[8], *buf;
+ __m128i buf0[8], buf1[8];
const int8_t *shift = av1_fwd_txfm_shift_ls[TX_8X8];
// Fast path for DCT_DCT: bypass function pointer table and flip checks.
@@ -1864,26 +1826,20 @@ static void av1_lowbd_fwd_txfm2d_8x8_avx2(const int16_t *input, int32_t *output,
return;
}
- const int txw_idx = get_txw_idx(TX_8X8);
- const int txh_idx = get_txh_idx(TX_8X8);
- const int cos_bit_col = av1_fwd_cos_bit_col[txw_idx][txh_idx];
- const int cos_bit_row = av1_fwd_cos_bit_row[txw_idx][txh_idx];
- const transform_1d_sse2 col_txfm = col_txfm8x8_arr[tx_type];
- const transform_1d_sse2 row_txfm = row_txfm8x8_arr[tx_type];
int ud_flip, lr_flip;
-
get_flip_cfg(tx_type, &ud_flip, &lr_flip);
- // Condition to check shift bit is avoided while round shifting, by assuming
- // that shift[0] will always be positive.
assert(shift[0] > 0);
if (ud_flip)
load_buffer_and_flip_round_shift(input, stride, buf0, shift[0]);
else
load_buffer_and_round_shift(input, stride, buf0, shift[0]);
- col_txfm(buf0, buf0, cos_bit_col);
- // Condition to check shift bit is avoided while round shifting, by assuming
- // that shift[1] will always be negative.
+ switch (vtx_tab[tx_type]) {
+ case DCT_1D: fdct8x8_new_sse2(buf0, buf0, 13); break;
+ case ADST_1D:
+ case FLIPADST_1D: fadst8x8_new_sse2(buf0, buf0, 13); break;
+ default: fidentity8x8_new_sse2(buf0, buf0, 13); break;
+ }
assert(shift[1] < 0);
if (lr_flip) {
@@ -1892,13 +1848,15 @@ static void av1_lowbd_fwd_txfm2d_8x8_avx2(const int16_t *input, int32_t *output,
transpose_round_shift_8x8(buf0, buf1, shift[1]);
}
- buf = buf1;
- row_txfm(buf, buf, cos_bit_row);
+ switch (htx_tab[tx_type]) {
+ case DCT_1D: fdct8x8_new_sse2(buf1, buf1, 13); break;
+ case ADST_1D:
+ case FLIPADST_1D: fadst8x8_new_sse2(buf1, buf1, 13); break;
+ default: fidentity8x8_new_sse2(buf1, buf1, 13); break;
+ }
- // Round and shift operation is avoided here as the shift bit is assumed to be
- // zero always.
assert(shift[2] == 0);
- store_buffer_16bit_to_32bit_w8_avx2(buf, output, 8, 8);
+ store_buffer_16bit_to_32bit_w8_avx2(buf1, output, 8, 8);
}
static void lowbd_fwd_txfm2d_16x16_avx2(const int16_t *input, int32_t *output,