/*
* Copyright ( c ) 2021 , Alliance for Open Media . All rights reserved .
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1 . 0 . If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file , you can
* obtain it at www . aomedia . org / license / software . If the Alliance for Open
* Media Patent License 1 . 0 was not distributed with this source code in the
* PATENTS file , you can obtain it at www . aomedia . org / license / patent .
*/
#include <emmintrin.h> // SSE2
#include "config/av1_rtcd.h"
#include "aom/aom_integer.h"
static inline __m128i reduce_sum_epi64(__m128i reg) {
__m128i reg_hi = _mm_srli_si128(reg, 8 );
reg = _mm_add_epi64(reg, reg_hi);
return reg;
}
int64_t av1_block_error_lp_sse2(const int16_t *coeff, const int16_t *dqcoeff,
intptr_t block_size) {
assert(block_size % 16 == 0 );
assert(block_size >= 16 );
const __m128i zero = _mm_setzero_si128();
__m128i accum_0 = zero;
__m128i accum_1 = zero;
for (int i = 0 ; i < block_size; i += 16 ) {
// Load 8 elements for coeff and dqcoeff.
const __m128i _coeff_0 = _mm_loadu_si128((const __m128i *)coeff);
const __m128i _coeff_1 = _mm_loadu_si128((const __m128i *)(coeff + 8 ));
const __m128i _dqcoeff_0 = _mm_loadu_si128((const __m128i *)dqcoeff);
const __m128i _dqcoeff_1 = _mm_loadu_si128((const __m128i *)(dqcoeff + 8 ));
// Compute the diff
const __m128i diff_0 = _mm_sub_epi16(_dqcoeff_0, _coeff_0);
const __m128i diff_1 = _mm_sub_epi16(_dqcoeff_1, _coeff_1);
// Compute the error
const __m128i error_0 = _mm_madd_epi16(diff_0, diff_0);
const __m128i error_1 = _mm_madd_epi16(diff_1, diff_1);
const __m128i error_lo_0 = _mm_unpacklo_epi32(error_0, zero);
const __m128i error_lo_1 = _mm_unpacklo_epi32(error_1, zero);
const __m128i error_hi_0 = _mm_unpackhi_epi32(error_0, zero);
const __m128i error_hi_1 = _mm_unpackhi_epi32(error_1, zero);
// Accumulate
accum_0 = _mm_add_epi64(accum_0, error_lo_0);
accum_1 = _mm_add_epi64(accum_1, error_lo_1);
accum_0 = _mm_add_epi64(accum_0, error_hi_0);
accum_1 = _mm_add_epi64(accum_1, error_hi_1);
// Advance
coeff += 16 ;
dqcoeff += 16 ;
}
__m128i accum = _mm_add_epi64(accum_0, accum_1);
// Reduce sum the register
accum = reduce_sum_epi64(accum);
// Store the results.
#if AOM_ARCH_X86_64
return _mm_cvtsi128_si64(accum);
#else
int64_t result;
_mm_storel_epi64((__m128i *)&result, accum);
return result;
#endif // AOM_ARCH_X86_64
}
Messung V0.5 in Prozent C=94 H=99 G=96
¤ Dauer der Verarbeitung: 0.10 Sekunden
(vorverarbeitet am 2026-06-10)
¤
*© Formatika GbR, Deutschland