Commit 7e5e538121 for ffmpeg
commit 7e5e538121205128e1e8cd5c919f6e187f781af2
Author: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Date: Thu Nov 5 22:15:24 2026 +0100
avcodec/x86/vp8dsp: Don't use mmx regs in vp8_idct_add
This makes the VP8 decoder ABI compliant.*
Old benchmarks:
vp8_idct_add_c: 135.6
vp8_idct_add_sse: 35.3 ( 3.84x)
New benchmarks:
vp8_idct_add_c: 134.1
vp8_idct_add_sse2: 23.7 ( 5.66x)
*: Previously, it was possible to call alloc/free functions
via av_frame_ref() while having an invalid FPU state; this happens
only when slice threading is in use or if the user has overridden
the execute2 callback (the default one issues emms).
Reviewed-by: Lynne <dev@lynne.ee>
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
diff --git a/libavcodec/x86/vp8dsp.asm b/libavcodec/x86/vp8dsp.asm
index 41dea20c36..26d747f8a5 100644
--- a/libavcodec/x86/vp8dsp.asm
+++ b/libavcodec/x86/vp8dsp.asm
@@ -149,8 +149,8 @@ filter_h6_shuf3: db 2, 5, 3, 6, 4, 7, 5, 8, 6, 9, 7, 10, 8, 11, 9, 12
filter_h2_shuf: db 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8
filter_h2_shuf2: db 0, 1, 1, 2, 2, 3, 3, 4, 8, 9, 9, 10, 10, 11, 11, 12
-pw_20091: times 4 dw 20091
-pw_17734: times 4 dw 17734
+pw_20091: times 8 dw 20091
+pw_17734: times 8 dw 17734
pw_3_3_0_0: times 2 dw 3, 3, 0, 0
cextern pw_4
@@ -990,63 +990,81 @@ cglobal vp8_idct_dc_add4uv, 3, 3, 6, dst, block, stride
; void ff_vp8_idct_add_<opt>(uint8_t *dst, int16_t block[16], ptrdiff_t stride);
;-----------------------------------------------------------------------------
-; calculate %1=mul_35468(%1)-mul_20091(%2); %2=mul_20091(%1)+mul_35468(%2)
-; this macro assumes that m6/m7 have words for 20091/17734 loaded
-%macro VP8_MULTIPLY_SUMSUB 4
- mova %3, %1
- mova %4, %2
- pmulhw %3, m6 ;20091(1)
- pmulhw %4, m6 ;20091(2)
- paddw %3, %1
- paddw %4, %2
- paddw %1, %1
- paddw %2, %2
- pmulhw %1, m7 ;35468(1)
- pmulhw %2, m7 ;35468(2)
- psubw %1, %4
- paddw %2, %3
+; calculate %1=mul_20091(low %1)+mul_35468(high %1), %2=mul_35468(low %1)-mul_20091(high %1);
+; this macro assumes that m5/m6 have words for 17734/20091 loaded
+%macro VP8_MULTIPLY_SUMSUB 3
+ pmulhw %3, %1, m6 ; 20091(1, 3)
+ paddw %3, %1 ; MUL_20091(1, 3)
+ paddw %1, %1
+ pmulhw %1, m5 ; MUL_35468(1, 3)
+ MOVHL %2, %3 ; MUL_20091(3)
+ psubw %2, %1 ; MUL_20091(3)-MUL_35468(1)=-t2
+ punpckhqdq %1, %1
+ paddw %1, %3 ; MUL_35468(3)+MUL_20091(1)=t3
%endmacro
; calculate x0=%1+%3; x1=%1-%3
-; x2=mul_35468(%2)-mul_20091(%4); x3=mul_20091(%2)+mul_35468(%4)
+; Inputs 2 and 4 are supposed to be contained in the low and high half of %2
+; x2=mul_35468(2)-mul_20091(4); x3=mul_20091(2)+mul_35468(4)
; %1=x0+x3 (tmp0); %2=x1+x2 (tmp1); %3=x1-x2 (tmp2); %4=x0-x3 (tmp3)
-; %5/%6 are temporary registers
-; we assume m6/m7 have constant words 20091/17734 loaded in them
-%macro VP8_IDCT_TRANSFORM4x4_1D 6
+; %5 is a clobber reg
+; we assume m5/m6 have constant words 17734/20091 loaded in them
+%macro VP8_IDCT_TRANSFORM4x4_1D 5
SUMSUB_BA w, %3, %1, %5 ;t0, t1
- VP8_MULTIPLY_SUMSUB m%2, m%4, m%5,m%6 ;t2, t3
- SUMSUB_BA w, %4, %3, %5 ;tmp0, tmp3
- SUMSUB_BA w, %2, %1, %5 ;tmp1, tmp2
- SWAP %4, %1
+ VP8_MULTIPLY_SUMSUB m%2, m%4, m%5 ;t3, -t2
+
+ SUMSUB_BA w, %2, %3, %5 ;tmp0=t0+t3, tmp3=t0-t3
+ SUMSUB_BA w, %4, %1, %5 ;tmp2=-t2+t1, tmp1=t1+t2
+ SWAP %1, %2 ; %1 = tmp0, %2 = tmp1
SWAP %4, %3
%endmacro
-INIT_MMX sse
-cglobal vp8_idct_add, 3, 3, 0, dst, block, stride
+%macro VP8_STORE_DIFFx2 8 ; add, tmp1, tmp2, tmp3, zero, shift, source, stride
+ movd %3, [%7]
+ movd %4, [%7+%8]
+ psraw %1, %6
+ MOVHL %2, %1
+ punpcklbw %3, %5
+ punpcklbw %4, %5
+ paddw %3, %1
+ paddw %4, %2
+ packuswb %3, %5
+ packuswb %4, %5
+ movd [%7], %3
+ movd [%7+%8], %4
+%endmacro
+
+INIT_XMM sse2
+cglobal vp8_idct_add, 3, 3, 7, dst, block, stride
; load block data
movq m0, [blockq+ 0]
movq m1, [blockq+ 8]
movq m2, [blockq+16]
- movq m3, [blockq+24]
- movq m6, [pw_20091]
- movq m7, [pw_17734]
- xorps xmm0, xmm0
- movaps [blockq+ 0], xmm0
- movaps [blockq+16], xmm0
+ movhps m1, [blockq+24]
+ mova m6, [pw_20091]
+ mova m5, [pw_17734]
+ xorps m4, m4
+ movaps [blockq+ 0], m4
+ movaps [blockq+16], m4
; actual IDCT
- VP8_IDCT_TRANSFORM4x4_1D 0, 1, 2, 3, 4, 5
- TRANSPOSE4x4W 0, 1, 2, 3, 4
+ VP8_IDCT_TRANSFORM4x4_1D 0, 1, 2, 3, 4
+ punpcklwd m0, m1
+ punpcklwd m2, m3
+ SBUTTERFLY dq, 0, 2, 1
+ punpckhqdq m1, m0, m2
paddw m0, [pw_4]
- VP8_IDCT_TRANSFORM4x4_1D 0, 1, 2, 3, 4, 5
- TRANSPOSE4x4W 0, 1, 2, 3, 4
+ VP8_IDCT_TRANSFORM4x4_1D 0, 1, 2, 3, 4
+ punpcklwd m0, m1
+ punpcklwd m2, m3
+ SBUTTERFLY dq, 0, 2, 1
; store
pxor m4, m4
DEFINE_ARGS dst1, dst2, stride
lea dst2q, [dst1q+2*strideq]
- STORE_DIFFx2 m0, m1, m6, m7, m4, 3, dst1q, strideq, movd
- STORE_DIFFx2 m2, m3, m6, m7, m4, 3, dst2q, strideq, movd
+ VP8_STORE_DIFFx2 m0, m1, m5, m6, m4, 3, dst1q, strideq
+ VP8_STORE_DIFFx2 m2, m3, m5, m6, m4, 3, dst2q, strideq
RET
diff --git a/libavcodec/x86/vp8dsp_init.c b/libavcodec/x86/vp8dsp_init.c
index a12e64c5ce..4b73dc3921 100644
--- a/libavcodec/x86/vp8dsp_init.c
+++ b/libavcodec/x86/vp8dsp_init.c
@@ -172,7 +172,7 @@ void ff_vp8_idct_dc_add4y_sse2(uint8_t *dst, int16_t block[4][16],
void ff_vp8_idct_dc_add4uv_sse2(uint8_t *dst, int16_t block[4][16],
ptrdiff_t stride);
void ff_vp8_luma_dc_wht_sse2(int16_t block[4][4][16], int16_t dc[16]);
-void ff_vp8_idct_add_sse(uint8_t *dst, int16_t block[16], ptrdiff_t stride);
+void ff_vp8_idct_add_sse2(uint8_t *dst, int16_t block[16], ptrdiff_t stride);
#define DECLARE_LOOP_FILTER(NAME) \
void ff_vp8_v_loop_filter_simple_ ## NAME(uint8_t *dst, \
@@ -272,10 +272,6 @@ av_cold void ff_vp8dsp_init_x86(VP8DSPContext *c)
{
int cpu_flags = av_get_cpu_flags();
- if (EXTERNAL_SSE(cpu_flags)) {
- c->vp8_idct_add = ff_vp8_idct_add_sse;
- }
-
if (EXTERNAL_SSE2_SLOW(cpu_flags)) {
c->vp8_v_loop_filter_simple = ff_vp8_v_loop_filter_simple_sse2;
@@ -285,6 +281,7 @@ av_cold void ff_vp8dsp_init_x86(VP8DSPContext *c)
c->vp8_v_loop_filter16y = ff_vp8_v_loop_filter16y_mbedge_sse2;
c->vp8_v_loop_filter8uv = ff_vp8_v_loop_filter8uv_mbedge_sse2;
+ c->vp8_idct_add = ff_vp8_idct_add_sse2;
c->vp8_luma_dc_wht = ff_vp8_luma_dc_wht_sse2;
}
diff --git a/tests/checkasm/vp8dsp.c b/tests/checkasm/vp8dsp.c
index eeb487c6b1..43729689a0 100644
--- a/tests/checkasm/vp8dsp.c
+++ b/tests/checkasm/vp8dsp.c
@@ -120,7 +120,7 @@ static void check_idct(VP8DSPContext *d, bool is_vp7)
LOCAL_ALIGNED_16(int16_t, subcoef0, [4 * 4]);
LOCAL_ALIGNED_16(int16_t, subcoef1, [4 * 4]);
int dc;
- declare_func_emms(AV_CPU_FLAG_MMX, void, uint8_t *dst, int16_t *block, ptrdiff_t stride);
+ declare_func(void, uint8_t *dst, int16_t *block, ptrdiff_t stride);
randomize_buffers(src, dst, 4, coef);