PR #25776 opened by zuxy URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25776 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25776.patch
Following the same pattern in h264, this series of patches removes all use of MMX registers in said area and replace them with bit exact implementations with XMM registers; performance neutral or better. >From 22d6974349b99a77c34d24149bf1ad0d4b0b206f Mon Sep 17 00:00:00 2001 From: Zuxy Meng <[email protected]> Date: Mon, 2 Nov 2026 20:04:28 -0800 Subject: [PATCH 1/4] avcodec/x86/vp9: convert DC predictors MMX to XMM Convert the 4x4 and 8x8 DC, DC-top and DC-left predictors from MMX to XMM registers, keeping the SSSE3 instructions and the _ssse3 symbol names. Benchmarks (checkasm, Zen 4, pinned, median of 3, cycles): the converted functions measure 0.5-1.7 cycles, unchanged within noise (dc_4x4_ssse3 0.8 -> 1.0, dc_8x8_ssse3 1.8 -> 1.7, dc_top/left_4x4/8x8 likewise). An untouched control, dc_left/top_32x32_ssse3, moved 1.3-1.5x between the same runs, so the noise floor exceeds any signal at this size. checkasm --test=vp9dsp passes (1272/1272). --- libavcodec/x86/vp9intrapred.asm | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/libavcodec/x86/vp9intrapred.asm b/libavcodec/x86/vp9intrapred.asm index 22390ca8317..4f1ee85c98d 100644 --- a/libavcodec/x86/vp9intrapred.asm +++ b/libavcodec/x86/vp9intrapred.asm @@ -93,10 +93,11 @@ SECTION .text ; dc_NxN(uint8_t *dst, ptrdiff_t stride, const uint8_t *l, const uint8_t *a) -INIT_MMX ssse3 -cglobal vp9_ipred_dc_4x4, 4, 4, 0, dst, stride, l, a +INIT_XMM ssse3 +cglobal vp9_ipred_dc_4x4, 4, 4, 2, dst, stride, l, a movd m0, [lq] - punpckldq m0, [aq] + movq m1, [aq] + punpckldq m0, m1 pxor m1, m1 psadbw m0, m1 pmulhrsw m0, [pw_4096] @@ -108,7 +109,7 @@ cglobal vp9_ipred_dc_4x4, 4, 4, 0, dst, stride, l, a movd [dstq+strideq*1], m0 RET -cglobal vp9_ipred_dc_8x8, 4, 4, 0, dst, stride, l, a +cglobal vp9_ipred_dc_8x8, 4, 4, 3, dst, stride, l, a movq m0, [lq] movq m1, [aq] DEFINE_ARGS dst, stride, stride3 @@ -215,7 +216,7 @@ DC_16to32_FUNCS ; dc_top/left_NxN(uint8_t *dst, ptrdiff_t stride, const uint8_t *l, const uint8_t *a) %macro DC_1D_4to8_FUNCS 2 ; dir (top or left), arg (a or l) -cglobal vp9_ipred_dc_%1_4x4, 4, 4, 0, dst, stride, l, a +cglobal vp9_ipred_dc_%1_4x4, 4, 4, 2, dst, stride, l, a movd m0, [%2q] pxor m1, m1 psadbw m0, m1 @@ -228,7 +229,7 @@ cglobal vp9_ipred_dc_%1_4x4, 4, 4, 0, dst, stride, l, a movd [dstq+strideq*1], m0 RET -cglobal vp9_ipred_dc_%1_8x8, 4, 4, 0, dst, stride, l, a +cglobal vp9_ipred_dc_%1_8x8, 4, 4, 2, dst, stride, l, a movq m0, [%2q] DEFINE_ARGS dst, stride, stride3 lea stride3q, [strideq*3] @@ -248,7 +249,7 @@ cglobal vp9_ipred_dc_%1_8x8, 4, 4, 0, dst, stride, l, a RET %endmacro -INIT_MMX ssse3 +INIT_XMM ssse3 DC_1D_4to8_FUNCS top, a DC_1D_4to8_FUNCS left, l -- 2.54.0 >From ae867082bab8ee152af9c7e2a76ae859dcd6fd56 Mon Sep 17 00:00:00 2001 From: Zuxy Meng <[email protected]> Date: Mon, 2 Nov 2026 20:08:38 -0800 Subject: [PATCH 2/4] avcodec/x86/vp9: convert v_8x8 and tm_4x4 predictors MMX to XMM Convert ff_vp9_ipred_v_8x8 (plain 8-byte row copies) from MMX to SSE and ff_vp9_ipred_tm_4x4 from MMX/SSSE3 to XMM/SSSE3, keeping the _ssse3 name for the latter. Benchmarks (checkasm, Zen 4, pinned, median of 3, cycles): vp9_vert_8x8: 1.2 -> 1.2 (measurement floor, plain copies) vp9_tm_4x4_ssse3: 9.3 -> 9.7 (1.04x, noise) checkasm --test=vp9dsp passes (1272/1272, fresh build). --- libavcodec/x86/vp9dsp_init.c | 4 ++-- libavcodec/x86/vp9intrapred.asm | 27 ++++++++++++++------------- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/libavcodec/x86/vp9dsp_init.c b/libavcodec/x86/vp9dsp_init.c index 7b2fd27203d..d259009c80e 100644 --- a/libavcodec/x86/vp9dsp_init.c +++ b/libavcodec/x86/vp9dsp_init.c @@ -155,7 +155,7 @@ void ff_vp9_ipred_##type##_##size##x##size##_##opt(uint8_t *dst, ptrdiff_t strid ipred_func(4, hd, mmxext); ipred_func(4, vl, mmxext); -ipred_func(8, v, mmx); +ipred_func(8, v, sse); #define ipred_dc_funcs(size, opt) \ ipred_func(size, dc, opt); \ @@ -271,7 +271,6 @@ av_cold void ff_vp9dsp_init_x86(VP9DSPContext *dsp, int bpp, int bitexact) dsp->itxfm_add[4 /* lossless */][DCT_ADST] = dsp->itxfm_add[4 /* lossless */][ADST_ADST] = ff_vp9_iwht_iwht_4x4_add_mmx; } - init_ipred(8, mmx, v, VERT); } if (EXTERNAL_MMXEXT(cpu_flags)) { @@ -287,6 +286,7 @@ av_cold void ff_vp9dsp_init_x86(VP9DSPContext *dsp, int bpp, int bitexact) init_fpel_func(2, 0, 16, put, , sse); init_fpel_func(1, 0, 32, put, , sse); init_fpel_func(0, 0, 64, put, , sse); + init_ipred(8, sse, v, VERT); init_ipred(16, sse, v, VERT); init_ipred(32, sse, v, VERT); } diff --git a/libavcodec/x86/vp9intrapred.asm b/libavcodec/x86/vp9intrapred.asm index 4f1ee85c98d..147f3bad68e 100644 --- a/libavcodec/x86/vp9intrapred.asm +++ b/libavcodec/x86/vp9intrapred.asm @@ -327,20 +327,21 @@ INIT_XMM ssse3 DC_1D_16to32_FUNCS top, a DC_1D_16to32_FUNCS left, l -INIT_MMX mmx -cglobal vp9_ipred_v_8x8, 4, 4, 0, dst, stride, l, a - movq m0, [aq] +INIT_XMM sse +cglobal vp9_ipred_v_8x8, 4, 4, 1, dst, stride, l, a + xorps m0, m0 + movlps m0, [aq] DEFINE_ARGS dst, stride, stride3 lea stride3q, [strideq*3] - movq [dstq+strideq*0], m0 - movq [dstq+strideq*1], m0 - movq [dstq+strideq*2], m0 - movq [dstq+stride3q ], m0 + movlps [dstq+strideq*0], m0 + movlps [dstq+strideq*1], m0 + movlps [dstq+strideq*2], m0 + movlps [dstq+stride3q ], m0 lea dstq, [dstq+strideq*4] - movq [dstq+strideq*0], m0 - movq [dstq+strideq*1], m0 - movq [dstq+strideq*2], m0 - movq [dstq+stride3q ], m0 + movlps [dstq+strideq*0], m0 + movlps [dstq+strideq*1], m0 + movlps [dstq+strideq*2], m0 + movlps [dstq+stride3q ], m0 RET INIT_XMM sse @@ -513,8 +514,8 @@ H_XMM_FUNCS 4, 8 INIT_XMM avx H_XMM_FUNCS 4, 8 -INIT_MMX ssse3 -cglobal vp9_ipred_tm_4x4, 4, 4, 0, dst, stride, l, a +INIT_XMM ssse3 +cglobal vp9_ipred_tm_4x4, 4, 4, 5, dst, stride, l, a pxor m1, m1 movd m0, [aq] pinsrw m2, [aq-1], 0 -- 2.54.0 >From f6dc8a42390d94f5c3dc22d6ab30b1c95f2019d5 Mon Sep 17 00:00:00 2001 From: Zuxy Meng <[email protected]> Date: Mon, 2 Nov 2026 20:14:00 -0800 Subject: [PATCH 3/4] avcodec/x86/vp9: convert dl/vl/hd 4x4 predictors MMX to XMM Convert the 4x4 diag-down-left, vert-left and hor-down predictors from MMX/MMXEXT to XMM registers. dl keeps the _ssse3 name (it uses pshufb); vl and hd use only SSE2 instructions, so they are _sse2 from the start. Benchmarks (checkasm, Zen 4, pinned, median of 3, cycles): vp9_diag_downleft_4x4_ssse3: 1.9 -> 1.1 vp9_vert_left_4x4_sse2: 1.8 (mmxext) -> 1.1 vp9_hor_down_4x4_sse2: 2.2 (mmxext) -> 1.8 checkasm --test=vp9dsp passes (1272/1272, fresh build). --- libavcodec/x86/vp9dsp_init.c | 27 ++++++++++++++++++--------- libavcodec/x86/vp9intrapred.asm | 24 +++++++++++++++--------- 2 files changed, 33 insertions(+), 18 deletions(-) diff --git a/libavcodec/x86/vp9dsp_init.c b/libavcodec/x86/vp9dsp_init.c index d259009c80e..7bba68d3595 100644 --- a/libavcodec/x86/vp9dsp_init.c +++ b/libavcodec/x86/vp9dsp_init.c @@ -153,8 +153,6 @@ lpf_funcs(88, 16, avx); void ff_vp9_ipred_##type##_##size##x##size##_##opt(uint8_t *dst, ptrdiff_t stride, \ const uint8_t *l, const uint8_t *a) -ipred_func(4, hd, mmxext); -ipred_func(4, vl, mmxext); ipred_func(8, v, sse); #define ipred_dc_funcs(size, opt) \ @@ -191,8 +189,15 @@ ipred_func(4, h, sse2); ipred_dc_funcs(size, opt); \ ipred_dir_tm_h_funcs(size, opt) -// FIXME hd/vl_4x4_ssse3 does not exist -ipred_all_funcs(4, ssse3); +ipred_dc_funcs(4, ssse3); +ipred_func(4, tm, ssse3); +ipred_func(4, dl, ssse3); +ipred_func(4, dr, ssse3); +ipred_func(4, hd, sse2); +ipred_func(4, hu, ssse3); +ipred_func(4, vl, sse2); +ipred_func(4, vr, ssse3); +ipred_func(4, h, ssse3); ipred_all_funcs(8, ssse3); ipred_all_funcs(16, ssse3); ipred_all_funcs(32, ssse3); @@ -239,8 +244,6 @@ av_cold void ff_vp9dsp_init_x86(VP9DSPContext *dsp, int bpp, int bitexact) #define init_ipred(sz, opt, t, e) \ dsp->intra_pred[TX_##sz##X##sz][e##_PRED] = ff_vp9_ipred_##t##_##sz##x##sz##_##opt -#define ff_vp9_ipred_hd_4x4_ssse3 ff_vp9_ipred_hd_4x4_mmxext -#define ff_vp9_ipred_vl_4x4_ssse3 ff_vp9_ipred_vl_4x4_mmxext #define init_dir_tm_ipred(sz, opt) do { \ init_ipred(sz, opt, dl, DIAG_DOWN_LEFT); \ init_ipred(sz, opt, dr, DIAG_DOWN_RIGHT); \ @@ -278,8 +281,6 @@ av_cold void ff_vp9dsp_init_x86(VP9DSPContext *dsp, int bpp, int bitexact) dsp->loop_filter_8[0][1] = ff_vp9_loop_filter_v_4_8_mmxext; dsp->loop_filter_8[1][0] = ff_vp9_loop_filter_h_8_8_mmxext; dsp->loop_filter_8[1][1] = ff_vp9_loop_filter_v_8_8_mmxext; - dsp->intra_pred[TX_4X4][HOR_DOWN_PRED] = ff_vp9_ipred_hd_4x4_mmxext; - dsp->intra_pred[TX_4X4][VERT_LEFT_PRED] = ff_vp9_ipred_vl_4x4_mmxext; } if (EXTERNAL_SSE(cpu_flags)) { @@ -323,6 +324,8 @@ av_cold void ff_vp9dsp_init_x86(VP9DSPContext *dsp, int bpp, int bitexact) init_dir_tm_h_ipred(16, sse2); init_dir_tm_h_ipred(32, sse2); init_ipred(4, sse2, h, HOR); + init_ipred(4, sse2, vl, VERT_LEFT); + init_ipred(4, sse2, hd, HOR_DOWN); } if (EXTERNAL_SSSE3(cpu_flags)) { @@ -345,7 +348,13 @@ av_cold void ff_vp9dsp_init_x86(VP9DSPContext *dsp, int bpp, int bitexact) dsp->itxfm_add[TX_32X32][DCT_ADST] = dsp->itxfm_add[TX_32X32][DCT_DCT] = ff_vp9_idct_idct_32x32_add_ssse3; init_lpf(ssse3); - init_all_ipred(4, ssse3); + init_dc_ipred(4, ssse3); + init_ipred(4, ssse3, dl, DIAG_DOWN_LEFT); + init_ipred(4, ssse3, dr, DIAG_DOWN_RIGHT); + init_ipred(4, ssse3, hu, HOR_UP); + init_ipred(4, ssse3, tm, TM_VP8); + init_ipred(4, ssse3, vr, VERT_RIGHT); + init_ipred(4, ssse3, h, HOR); init_all_ipred(8, ssse3); init_all_ipred(16, ssse3); init_all_ipred(32, ssse3); diff --git a/libavcodec/x86/vp9intrapred.asm b/libavcodec/x86/vp9intrapred.asm index 147f3bad68e..08ba474b3e3 100644 --- a/libavcodec/x86/vp9intrapred.asm +++ b/libavcodec/x86/vp9intrapred.asm @@ -733,15 +733,15 @@ TM_XMM_FUNCS pavgb m%1, m%2 %endmacro -INIT_MMX ssse3 -cglobal vp9_ipred_dl_4x4, 4, 4, 0, dst, stride, l, a +INIT_XMM ssse3 +cglobal vp9_ipred_dl_4x4, 4, 4, 4, dst, stride, l, a movq m1, [aq] pshufb m0, m1, [pb_0to5_2x7] pshufb m2, m1, [pb_2to6_3x7] psrlq m1, 8 LOWPASS 0, 1, 2, 3 - pshufw m1, m0, q3321 + pshuflw m1, m0, q3321 movd [dstq+strideq*0], m0 movd [dstq+strideq*2], m1 psrlq m0, 8 @@ -1025,8 +1025,8 @@ DR_XMM_FUNCS ; vl -INIT_MMX mmxext -cglobal vp9_ipred_vl_4x4, 4, 4, 0, dst, stride, l, a +INIT_XMM sse2 +cglobal vp9_ipred_vl_4x4, 4, 4, 4, dst, stride, l, a movq m0, [aq] psrlq m1, m0, 8 psrlq m2, m1, 8 @@ -1390,10 +1390,11 @@ VR_XMM_FUNCS 6 ; hd -INIT_MMX mmxext -cglobal vp9_ipred_hd_4x4, 4, 4, 0, dst, stride, l, a +INIT_XMM sse2 +cglobal vp9_ipred_hd_4x4, 4, 4, 4, dst, stride, l, a movd m0, [lq] - punpckldq m0, [aq-1] + movq m3, [aq-1] + punpckldq m0, m3 DEFINE_ARGS dst, stride, stride3 lea stride3q, [strideq*3] psrlq m1, m0, 8 @@ -1407,7 +1408,12 @@ cglobal vp9_ipred_hd_4x4, 4, 4, 0, dst, stride, l, a ; AEBF | m2 contains EFGHIJxx punpcklbw m1, m2 - punpckhdq m0, m1, m2 + ; punpckhdq would take dwords 2-3, which are the high half + ; of the XMM register, not words 4-7 of the 8-byte value. + ; Shift the second dword of each input down instead. + psrlq m0, m1, 32 + psrlq m2, m2, 32 + punpckldq m0, m2 ; m1 contains AEBFCGDH ; m0 contains CGDHIJxx -- 2.54.0 >From 4c48de0fc726c2618aaa2af45243ebcf78be22db Mon Sep 17 00:00:00 2001 From: Zuxy Meng <[email protected]> Date: Mon, 2 Nov 2026 21:04:28 -0800 Subject: [PATCH 4/4] avcodec/x86/vp9: convert dr/vr/hu 4x4 predictors MMX to XMM Convert the last three 8-bit 4x4 directional predictors from MMX/MMXEXT to XMM registers. vr and hu keep the _ssse3 symbol names (they use pshufb/pmulhrsw); dr uses only SSE2 instructions once palignr is eliminated, so it is _sse2 from the start. Benchmarks (checkasm, Zen 4, pinned to CPU 3, median of 3 interleaved pairs, cycles; 10/12bpp lines unchanged): vp9_diag_downright_4x4_8bpp_sse2: 1.6 -> 1.6 vp9_vert_right_4x4_8bpp_ssse3: 9.6 -> 8.9 vp9_hor_up_4x4_8bpp_ssse3: 2.3 -> 2.2 checkasm --test=vp9dsp passes (1272/1272 over 6 seeds), --- libavcodec/x86/vp9dsp_init.c | 4 +-- libavcodec/x86/vp9intrapred.asm | 47 ++++++++++++++++++++------------- 2 files changed, 30 insertions(+), 21 deletions(-) diff --git a/libavcodec/x86/vp9dsp_init.c b/libavcodec/x86/vp9dsp_init.c index 7bba68d3595..3e8e1fc8ca4 100644 --- a/libavcodec/x86/vp9dsp_init.c +++ b/libavcodec/x86/vp9dsp_init.c @@ -192,7 +192,7 @@ ipred_dir_tm_h_funcs(size, opt) ipred_dc_funcs(4, ssse3); ipred_func(4, tm, ssse3); ipred_func(4, dl, ssse3); -ipred_func(4, dr, ssse3); +ipred_func(4, dr, sse2); ipred_func(4, hd, sse2); ipred_func(4, hu, ssse3); ipred_func(4, vl, sse2); @@ -324,6 +324,7 @@ av_cold void ff_vp9dsp_init_x86(VP9DSPContext *dsp, int bpp, int bitexact) init_dir_tm_h_ipred(16, sse2); init_dir_tm_h_ipred(32, sse2); init_ipred(4, sse2, h, HOR); + init_ipred(4, sse2, dr, DIAG_DOWN_RIGHT); init_ipred(4, sse2, vl, VERT_LEFT); init_ipred(4, sse2, hd, HOR_DOWN); } @@ -350,7 +351,6 @@ av_cold void ff_vp9dsp_init_x86(VP9DSPContext *dsp, int bpp, int bitexact) init_lpf(ssse3); init_dc_ipred(4, ssse3); init_ipred(4, ssse3, dl, DIAG_DOWN_LEFT); - init_ipred(4, ssse3, dr, DIAG_DOWN_RIGHT); init_ipred(4, ssse3, hu, HOR_UP); init_ipred(4, ssse3, tm, TM_VP8); init_ipred(4, ssse3, vr, VERT_RIGHT); diff --git a/libavcodec/x86/vp9intrapred.asm b/libavcodec/x86/vp9intrapred.asm index 08ba474b3e3..0f2ff32c388 100644 --- a/libavcodec/x86/vp9intrapred.asm +++ b/libavcodec/x86/vp9intrapred.asm @@ -56,9 +56,9 @@ pb_2to6_11x7: db 2, 3, 4, 5, 6 pb_1toE_2xF: db 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 15 pb_2toE_3xF: db 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 15, 15 pb_13456_3xm1: db 1, 3, 4, 5, 6 - times 3 db -1 + times 11 db -1 pb_6012_4xm1: db 6, 0, 1, 2 - times 4 db -1 + times 12 db -1 pb_6xm1_246_8toE: times 6 db -1 db 2, 4, 6, 8, 9, 10, 11, 12, 13, 14 pb_6xm1_BDF_0to6: times 6 db -1 @@ -68,7 +68,7 @@ pb_02468ACE_13579BDF: db 0, 2, 4, 6, 8, 10, 12, 14, 1, 3, 5, 7, 9, 11, 13, 15 pb_15x0_1xm1: times 15 db 0 db -1 pb_0to2_5x3: db 0, 1, 2 - times 5 db 3 + times 13 db 3 pb_6xm1_2x0: times 6 db -1 times 2 db 0 pb_6x0_2xm1: times 6 db 0 @@ -898,16 +898,18 @@ DL_XMM_FUNCS ; dr -INIT_MMX ssse3 -cglobal vp9_ipred_dr_4x4, 4, 4, 0, dst, stride, l, a +INIT_XMM sse2 +cglobal vp9_ipred_dr_4x4, 4, 4, 4, dst, stride, l, a movd m0, [lq] - punpckldq m0, [aq-1] + movd m1, [aq-1] + punpckldq m0, m1 movd m1, [aq+3] DEFINE_ARGS dst, stride, stride3 lea stride3q, [strideq*3] - palignr m1, m0, 1 - psrlq m2, m1, 8 - LOWPASS 0, 1, 2, 3 + punpcklqdq m2, m0, m1 + psrldq m2, 1 + psrlq m1, m2, 8 + LOWPASS 0, 2, 1, 3 movd [dstq+stride3q ], m0 psrlq m0, 8 @@ -1194,15 +1196,18 @@ VL_XMM_FUNCS ; vr -INIT_MMX ssse3 -cglobal vp9_ipred_vr_4x4, 4, 4, 0, dst, stride, l, a +INIT_XMM ssse3 +cglobal vp9_ipred_vr_4x4, 4, 4, 5, dst, stride, l, a movq m1, [aq-1] - punpckldq m2, [lq] + movq m4, [lq] + punpckldq m2, m4 movd m0, [aq] DEFINE_ARGS dst, stride, stride3 lea stride3q, [strideq*3] pavgb m0, m1 - palignr m1, m2, 5 + psrlq m2, 40 + psllq m1, 24 + por m1, m2 psrlq m2, m1, 8 psllq m3, m1, 8 LOWPASS 2, 1, 3, 4 @@ -1604,8 +1609,8 @@ HD_XMM_FUNCS INIT_XMM avx HD_XMM_FUNCS -INIT_MMX ssse3 -cglobal vp9_ipred_hu_4x4, 3, 3, 0, dst, stride, l +INIT_XMM ssse3 +cglobal vp9_ipred_hu_4x4, 3, 3, 4, dst, stride, l movd m0, [lq] pshufb m0, [pb_0to2_5x3] psrlq m1, m0, 8 @@ -1614,12 +1619,16 @@ cglobal vp9_ipred_hu_4x4, 3, 3, 0, dst, stride, l pavgb m1, m0 DEFINE_ARGS dst, stride, stride3 lea stride3q, [strideq*3] - SBUTTERFLY bw, 1, 2, 0 - palignr m2, m1, 2 + psrldq m3, m1, 4 + psrldq m0, m2, 4 + punpcklbw m1, m2 + punpcklbw m3, m0 + punpcklqdq m2, m1, m3 + psrldq m2, 2 movd [dstq+strideq*0], m1 movd [dstq+strideq*1], m2 - punpckhdq m1, m1 - punpckhdq m2, m2 + psrlq m1, 32 + psrlq m2, 32 movd [dstq+strideq*2], m1 movd [dstq+stride3q ], m2 RET -- 2.54.0 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
