PR #22784 opened by dgavriloff URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/22784 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/22784.patch
Continues d91b1559e0 and 8157aa1a3f. >From a292340b8f34e7ecd84d4605a5d09d23ad9bba7f Mon Sep 17 00:00:00 2001 From: dgavriloff <[email protected]> Date: Fri, 10 Apr 2026 13:21:29 -0700 Subject: [PATCH 1/2] avcodec/x86/me_cmp: Port 8-wide SAD/VSAD functions from MMXEXT to SSE2 Continues the work from d91b1559e0 and 8157aa1a3f which ported the 16-wide and (n)sse functions. The remaining 8-wide MMXEXT functions (sad8, sad8_x2, sad8_y2, sad8_approx_xy2, vsad_intra8, vsad8_approx) are always overridden on x86-64 where SSE2 is baseline. Replace with SSE2 implementations using movh for 8-byte loads and register-register psadbw. The upper qword is zero from movh zero-extension, so no horizontal reduction is needed for 8-wide. Old benchmarks (MMXEXT): pix_abs_1_0_c: 8.9 ( 1.00x) pix_abs_1_0_mmxext: 6.4 ( 1.38x) pix_abs_1_1_c: 85.3 ( 1.00x) pix_abs_1_1_mmxext: 9.2 ( 9.29x) pix_abs_1_2_c: 9.9 ( 1.00x) pix_abs_1_2_mmxext: 9.5 ( 1.04x) sad_1_c: 12.8 ( 1.00x) sad_1_mmxext: 6.5 ( 1.98x) vsad_5_c: 45.7 ( 1.00x) vsad_5_mmxext: 4.9 ( 9.39x) New benchmarks (SSE2): pix_abs_1_0_c: 8.9 ( 1.00x) pix_abs_1_0_sse2: 6.3 ( 1.41x) pix_abs_1_1_c: 86.4 ( 1.00x) pix_abs_1_1_sse2: 9.1 ( 9.54x) pix_abs_1_2_c: 9.9 ( 1.00x) pix_abs_1_2_sse2: 7.4 ( 1.34x) sad_1_c: 9.0 ( 1.00x) sad_1_sse2: 6.2 ( 1.45x) vsad_5_c: 45.8 ( 1.00x) vsad_5_sse2: 5.1 ( 8.92x) Signed-off-by: dgavriloff <[email protected]> --- libavcodec/x86/me_cmp.asm | 179 +++++++++++++++++++++++++---------- libavcodec/x86/me_cmp_init.c | 53 +++++------ 2 files changed, 154 insertions(+), 78 deletions(-) diff --git a/libavcodec/x86/me_cmp.asm b/libavcodec/x86/me_cmp.asm index 314b091fc8..ab2c97d8f8 100644 --- a/libavcodec/x86/me_cmp.asm +++ b/libavcodec/x86/me_cmp.asm @@ -390,6 +390,14 @@ cglobal sad%1u, 5, 5, 5, v, pix1, pix2, stride, h %else cglobal sad%1, 5, 5, 3, v, pix1, pix2, stride, h %endif +%if %1 < mmsize + movh m2, [pix2q] + movh m0, [pix1q] + psadbw m2, m0 + movh m1, [pix2q+strideq] + movh m0, [pix1q+strideq] + psadbw m1, m0 +%else movu m2, [pix2q] movu m1, [pix2q+strideq] %ifidn %2, u @@ -400,6 +408,7 @@ cglobal sad%1, 5, 5, 3, v, pix1, pix2, stride, h %else psadbw m2, [pix1q] psadbw m1, [pix1q+strideq] +%endif %endif paddw m2, m1 sub hd, 2 @@ -408,6 +417,16 @@ align 16 .loop: lea pix1q, [pix1q+strideq*2] lea pix2q, [pix2q+strideq*2] +%if %1 < mmsize + movh m0, [pix2q] + movh m1, [pix1q] + psadbw m0, m1 + paddw m2, m0 + movh m0, [pix2q+strideq] + movh m1, [pix1q+strideq] + psadbw m0, m1 + paddw m2, m0 +%else movu m0, [pix2q] movu m1, [pix2q+strideq] %ifidn %2, u @@ -421,9 +440,10 @@ align 16 %endif paddw m2, m0 paddw m2, m1 +%endif sub hd, 2 jg .loop -%if mmsize == 16 +%if %1 >= mmsize movhlps m0, m2 paddw m2, m0 %endif @@ -431,9 +451,8 @@ align 16 RET %endmacro -INIT_MMX mmxext -SAD 8 INIT_XMM sse2 +SAD 8 SAD 16 SAD 16, u @@ -443,19 +462,27 @@ SAD 16, u ;%1 = 8/16 %macro SAD_X2 1 cglobal sad%1_x2, 5, 5, 5, v, pix1, pix2, stride, h +%if %1 < mmsize + movh m0, [pix2q] + movh m3, [pix2q+1] + movh m2, [pix2q+strideq] + movh m4, [pix2q+strideq+1] + pavgb m0, m3 + pavgb m2, m4 + movh m3, [pix1q] + movh m4, [pix1q+strideq] + psadbw m0, m3 + psadbw m2, m4 +%else movu m0, [pix2q] movu m2, [pix2q+strideq] -%if mmsize == 16 movu m3, [pix2q+1] movu m4, [pix2q+strideq+1] pavgb m0, m3 pavgb m2, m4 -%else - pavgb m0, [pix2q+1] - pavgb m2, [pix2q+strideq+1] -%endif psadbw m0, [pix1q] psadbw m2, [pix1q+strideq] +%endif paddw m0, m2 sub hd, 2 @@ -463,24 +490,32 @@ align 16 .loop: lea pix1q, [pix1q+2*strideq] lea pix2q, [pix2q+2*strideq] +%if %1 < mmsize + movh m1, [pix2q] + movh m3, [pix2q+1] + movh m2, [pix2q+strideq] + movh m4, [pix2q+strideq+1] + pavgb m1, m3 + pavgb m2, m4 + movh m3, [pix1q] + movh m4, [pix1q+strideq] + psadbw m1, m3 + psadbw m2, m4 +%else movu m1, [pix2q] movu m2, [pix2q+strideq] -%if mmsize == 16 movu m3, [pix2q+1] movu m4, [pix2q+strideq+1] pavgb m1, m3 pavgb m2, m4 -%else - pavgb m1, [pix2q+1] - pavgb m2, [pix2q+strideq+1] -%endif psadbw m1, [pix1q] psadbw m2, [pix1q+strideq] +%endif paddw m0, m1 paddw m0, m2 sub hd, 2 jg .loop -%if mmsize == 16 +%if %1 >= mmsize movhlps m1, m0 paddw m0, m1 %endif @@ -488,9 +523,8 @@ align 16 RET %endmacro -INIT_MMX mmxext -SAD_X2 8 INIT_XMM sse2 +SAD_X2 8 SAD_X2 16 ;------------------------------------------------------------------------------------------ @@ -498,7 +532,18 @@ SAD_X2 16 ;------------------------------------------------------------------------------------------ ;%1 = 8/16 %macro SAD_Y2 1 -cglobal sad%1_y2, 5, 5, 4, v, pix1, pix2, stride, h +cglobal sad%1_y2, 5, 5, %1 < mmsize ? 5 : 4, v, pix1, pix2, stride, h +%if %1 < mmsize + movh m1, [pix2q] + movh m0, [pix2q+strideq] + movh m3, [pix2q+2*strideq] + pavgb m1, m0 + pavgb m0, m3 + movh m2, [pix1q] + psadbw m1, m2 + movh m2, [pix1q+strideq] + psadbw m0, m2 +%else movu m1, [pix2q] movu m0, [pix2q+strideq] movu m3, [pix2q+2*strideq] @@ -506,6 +551,7 @@ cglobal sad%1_y2, 5, 5, 4, v, pix1, pix2, stride, h pavgb m0, m3 psadbw m1, [pix1q] psadbw m0, [pix1q+strideq] +%endif paddw m0, m1 mova m1, m3 add pix2q, strideq @@ -515,18 +561,29 @@ align 16 .loop: lea pix1q, [pix1q+2*strideq] lea pix2q, [pix2q+2*strideq] +%if %1 < mmsize + movh m2, [pix2q] + movh m3, [pix2q+strideq] + pavgb m1, m2 + pavgb m2, m3 + movh m4, [pix1q] + psadbw m1, m4 + movh m4, [pix1q+strideq] + psadbw m2, m4 +%else movu m2, [pix2q] movu m3, [pix2q+strideq] pavgb m1, m2 pavgb m2, m3 psadbw m1, [pix1q] psadbw m2, [pix1q+strideq] +%endif paddw m0, m1 paddw m0, m2 mova m1, m3 sub hd, 2 jg .loop -%if mmsize == 16 +%if %1 >= mmsize movhlps m1, m0 paddw m0, m1 %endif @@ -534,9 +591,8 @@ align 16 RET %endmacro -INIT_MMX mmxext -SAD_Y2 8 INIT_XMM sse2 +SAD_Y2 8 SAD_Y2 16 ;------------------------------------------------------------------------------------------ @@ -642,26 +698,39 @@ SAD_XY2 16, a, u %macro SAD_APPROX_XY2 1 cglobal sad%1_approx_xy2, 5, 5, 7, v, pix1, pix2, stride, h mova m4, [pb_1] +%if %1 < mmsize + movh m1, [pix2q] + movh m5, [pix2q+1] + movh m0, [pix2q+strideq] + movh m6, [pix2q+strideq+1] + movh m3, [pix2q+2*strideq] + movh m2, [pix2q+2*strideq+1] + pavgb m1, m5 + pavgb m0, m6 + pavgb m3, m2 + psubusb m0, m4 + pavgb m1, m0 + pavgb m0, m3 + movh m2, [pix1q] + psadbw m1, m2 + movh m2, [pix1q+strideq] + psadbw m0, m2 +%else movu m1, [pix2q] movu m0, [pix2q+strideq] movu m3, [pix2q+2*strideq] -%if mmsize == 16 movu m5, [pix2q+1] movu m6, [pix2q+strideq+1] movu m2, [pix2q+2*strideq+1] pavgb m1, m5 pavgb m0, m6 pavgb m3, m2 -%else - pavgb m1, [pix2q+1] - pavgb m0, [pix2q+strideq+1] - pavgb m3, [pix2q+2*strideq+1] -%endif psubusb m0, m4 pavgb m1, m0 pavgb m0, m3 psadbw m1, [pix1q] psadbw m0, [pix1q+strideq] +%endif paddw m0, m1 mova m1, m3 add pix2q, strideq @@ -671,28 +740,39 @@ align 16 .loop: lea pix1q, [pix1q+2*strideq] lea pix2q, [pix2q+2*strideq] +%if %1 < mmsize + movh m2, [pix2q] + movh m5, [pix2q+1] + movh m3, [pix2q+strideq] + movh m6, [pix2q+strideq+1] + pavgb m2, m5 + pavgb m3, m6 + psubusb m2, m4 + pavgb m1, m2 + pavgb m2, m3 + movh m5, [pix1q] + psadbw m1, m5 + movh m5, [pix1q+strideq] + psadbw m2, m5 +%else movu m2, [pix2q] movu m3, [pix2q+strideq] -%if mmsize == 16 movu m5, [pix2q+1] movu m6, [pix2q+strideq+1] pavgb m2, m5 pavgb m3, m6 -%else - pavgb m2, [pix2q+1] - pavgb m3, [pix2q+strideq+1] -%endif psubusb m2, m4 pavgb m1, m2 pavgb m2, m3 psadbw m1, [pix1q] psadbw m2, [pix1q+strideq] +%endif paddw m0, m1 paddw m0, m2 mova m1, m3 sub hd, 2 jg .loop -%if mmsize == 16 +%if %1 >= mmsize movhlps m1, m0 paddw m0, m1 %endif @@ -700,9 +780,8 @@ align 16 RET %endmacro -INIT_MMX mmxext -SAD_APPROX_XY2 8 INIT_XMM sse2 +SAD_APPROX_XY2 8 SAD_APPROX_XY2 16 ;-------------------------------------------------------------------- @@ -732,7 +811,7 @@ cglobal vsad_intra%1, 5, 5, 3, v, pix1, pix2, lsize, h sub hd, 2 jg .loop -%if mmsize == 16 +%if %1 >= mmsize pshufd m1, m0, 0xe paddd m0, m1 %endif @@ -740,9 +819,8 @@ cglobal vsad_intra%1, 5, 5, 3, v, pix1, pix2, lsize, h RET %endmacro -INIT_MMX mmxext -VSAD_INTRA 8, a INIT_XMM sse2 +VSAD_INTRA 8, h VSAD_INTRA 16, a VSAD_INTRA 16, u @@ -760,15 +838,15 @@ cglobal vsad%1_approx, 5, 5, 5, v, pix1, pix2, lsize, h mova m1, [pb_80] mov%2 m0, [pix1q] mov%2 m4, [pix1q+lsizeq] -%if mmsize == 16 +%if %1 < mmsize + movh m3, [pix2q] + movh m2, [pix2q+lsizeq] +%else movu m3, [pix2q] movu m2, [pix2q+lsizeq] +%endif psubb m0, m3 psubb m4, m2 -%else - psubb m0, [pix2q] - psubb m4, [pix2q+lsizeq] -%endif pxor m0, m1 pxor m4, m1 psadbw m0, m4 @@ -778,17 +856,21 @@ cglobal vsad%1_approx, 5, 5, 5, v, pix1, pix2, lsize, h lea pix1q, [pix1q + 2*lsizeq] lea pix2q, [pix2q + 2*lsizeq] mov%2 m2, [pix1q] -%if mmsize == 16 - movu m3, [pix2q] - psubb m2, m3 +%if %1 < mmsize + movh m3, [pix2q] %else - psubb m2, [pix2q] + movu m3, [pix2q] %endif + psubb m2, m3 pxor m2, m1 psadbw m4, m2 paddw m0, m4 mov%2 m4, [pix1q+lsizeq] +%if %1 < mmsize + movh m3, [pix2q+lsizeq] +%else movu m3, [pix2q+lsizeq] +%endif psubb m4, m3 pxor m4, m1 psadbw m2, m4 @@ -796,7 +878,7 @@ cglobal vsad%1_approx, 5, 5, 5, v, pix1, pix2, lsize, h sub hd, 2 jg .loop -%if mmsize == 16 +%if %1 >= mmsize pshufd m1, m0, 0xe paddd m0, m1 %endif @@ -804,8 +886,7 @@ cglobal vsad%1_approx, 5, 5, 5, v, pix1, pix2, lsize, h RET %endmacro -INIT_MMX mmxext -VSAD_APPROX 8, a INIT_XMM sse2 +VSAD_APPROX 8, h VSAD_APPROX 16, a VSAD_APPROX 16, u diff --git a/libavcodec/x86/me_cmp_init.c b/libavcodec/x86/me_cmp_init.c index dbb4ef96bb..bf84988780 100644 --- a/libavcodec/x86/me_cmp_init.c +++ b/libavcodec/x86/me_cmp_init.c @@ -36,38 +36,38 @@ int ff_sse16_sse2(MPVEncContext *v, const uint8_t *pix1, const uint8_t *pix2, ptrdiff_t stride, int h); int ff_hf_noise8_ssse3(const uint8_t *pix1, ptrdiff_t stride, int h); int ff_hf_noise16_ssse3(const uint8_t *pix1, ptrdiff_t stride, int h); -int ff_sad8_mmxext(MPVEncContext *v, const uint8_t *pix1, const uint8_t *pix2, - ptrdiff_t stride, int h); +int ff_sad8_sse2(MPVEncContext *v, const uint8_t *pix1, const uint8_t *pix2, + ptrdiff_t stride, int h); int ff_sad16_sse2(MPVEncContext *v, const uint8_t *pix1, const uint8_t *pix2, ptrdiff_t stride, int h); int ff_sad16u_sse2(MPVEncContext *v, const uint8_t *pix1, const uint8_t *pix2, ptrdiff_t stride, int h); -int ff_sad8_x2_mmxext(MPVEncContext *v, const uint8_t *pix1, const uint8_t *pix2, - ptrdiff_t stride, int h); +int ff_sad8_x2_sse2(MPVEncContext *v, const uint8_t *pix1, const uint8_t *pix2, + ptrdiff_t stride, int h); int ff_sad16_x2_sse2(MPVEncContext *v, const uint8_t *pix1, const uint8_t *pix2, ptrdiff_t stride, int h); -int ff_sad8_y2_mmxext(MPVEncContext *v, const uint8_t *pix1, const uint8_t *pix2, - ptrdiff_t stride, int h); +int ff_sad8_y2_sse2(MPVEncContext *v, const uint8_t *pix1, const uint8_t *pix2, + ptrdiff_t stride, int h); int ff_sad16_y2_sse2(MPVEncContext *v, const uint8_t *pix1, const uint8_t *pix2, ptrdiff_t stride, int h); -int ff_sad8_approx_xy2_mmxext(MPVEncContext *v, const uint8_t *pix1, const uint8_t *pix2, - ptrdiff_t stride, int h); +int ff_sad8_approx_xy2_sse2(MPVEncContext *v, const uint8_t *pix1, const uint8_t *pix2, + ptrdiff_t stride, int h); int ff_sad8_xy2_sse2(MPVEncContext *v, const uint8_t *pix1, const uint8_t *pix2, ptrdiff_t stride, int h); int ff_sad16_approx_xy2_sse2(MPVEncContext *v, const uint8_t *pix1, const uint8_t *pix2, ptrdiff_t stride, int h); int ff_sad16_xy2_sse2(MPVEncContext *v, const uint8_t *pix1, const uint8_t *pix2, ptrdiff_t stride, int h); -int ff_vsad_intra8_mmxext(MPVEncContext *v, const uint8_t *pix1, const uint8_t *pix2, - ptrdiff_t stride, int h); +int ff_vsad_intra8_sse2(MPVEncContext *v, const uint8_t *pix1, const uint8_t *pix2, + ptrdiff_t stride, int h); int ff_vsad_intra16_sse2(MPVEncContext *v, const uint8_t *pix1, const uint8_t *pix2, ptrdiff_t stride, int h); int ff_vsad_intra16u_sse2(MPVEncContext *v, const uint8_t *pix1, const uint8_t *pix2, ptrdiff_t stride, int h); -int ff_vsad8_approx_mmxext(MPVEncContext *v, const uint8_t *pix1, const uint8_t *pix2, - ptrdiff_t stride, int h); +int ff_vsad8_approx_sse2(MPVEncContext *v, const uint8_t *pix1, const uint8_t *pix2, + ptrdiff_t stride, int h); int ff_vsad16_approx_sse2(MPVEncContext *v, const uint8_t *pix1, const uint8_t *pix2, - ptrdiff_t stride, int h); + ptrdiff_t stride, int h); int ff_vsad16u_approx_sse2(MPVEncContext *v, const uint8_t *pix1, const uint8_t *pix2, ptrdiff_t stride, int h); @@ -110,34 +110,26 @@ av_cold void ff_me_cmp_init_x86(MECmpContext *c, AVCodecContext *avctx) { int cpu_flags = av_get_cpu_flags(); - if (EXTERNAL_MMXEXT(cpu_flags)) { - c->sad[1] = ff_sad8_mmxext; - - c->pix_abs[1][0] = ff_sad8_mmxext; - c->pix_abs[1][1] = ff_sad8_x2_mmxext; - c->pix_abs[1][2] = ff_sad8_y2_mmxext; - - c->vsad[5] = ff_vsad_intra8_mmxext; - - if (!(avctx->flags & AV_CODEC_FLAG_BITEXACT)) { - c->pix_abs[1][3] = ff_sad8_approx_xy2_mmxext; - - c->vsad[1] = ff_vsad8_approx_mmxext; - } - } - if (EXTERNAL_SSE2(cpu_flags)) { c->sse[0] = ff_sse16_sse2; c->sse[1] = ff_sse8_sse2; c->sum_abs_dctelem = ff_sum_abs_dctelem_sse2; + c->sad[1] = ff_sad8_sse2; + c->pix_abs[0][0] = ff_sad16_sse2; c->pix_abs[0][1] = ff_sad16_x2_sse2; c->pix_abs[0][2] = ff_sad16_y2_sse2; c->pix_abs[0][3] = ff_sad16_xy2_sse2; + c->pix_abs[1][0] = ff_sad8_sse2; + c->pix_abs[1][1] = ff_sad8_x2_sse2; + c->pix_abs[1][2] = ff_sad8_y2_sse2; c->hadamard8_diff[0] = ff_hadamard8_diff16_sse2; c->hadamard8_diff[1] = ff_hadamard8_diff_sse2; + + c->vsad[5] = ff_vsad_intra8_sse2; + if (avctx->codec_id != AV_CODEC_ID_SNOW) { c->sad[0] = ff_sad16_sse2; @@ -159,6 +151,9 @@ av_cold void ff_me_cmp_init_x86(MECmpContext *c, AVCodecContext *avctx) c->pix_abs[1][3] = ff_sad8_xy2_sse2; } else { c->pix_abs[0][3] = ff_sad16_approx_xy2_sse2; + c->pix_abs[1][3] = ff_sad8_approx_xy2_sse2; + + c->vsad[1] = ff_vsad8_approx_sse2; } } -- 2.52.0 >From 5eefa978485bc573fc1abd1eb4c31a9d28376052 Mon Sep 17 00:00:00 2001 From: dgavriloff <[email protected]> Date: Fri, 10 Apr 2026 13:21:35 -0700 Subject: [PATCH 2/2] tests/checkasm/motion: Remove MMX emms handling No motion estimation functions use MMX anymore, so declare_func_emms(AV_CPU_FLAG_MMX, ...) can be simplified to declare_func(...). Signed-off-by: dgavriloff <[email protected]> --- tests/checkasm/motion.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/checkasm/motion.c b/tests/checkasm/motion.c index 960a41a8ed..2a6af1ab9d 100644 --- a/tests/checkasm/motion.c +++ b/tests/checkasm/motion.c @@ -51,10 +51,10 @@ static void test_motion(const char *name, me_cmp_func test_func) LOCAL_ALIGNED_16(uint8_t, img1, [WIDTH * HEIGHT]); LOCAL_ALIGNED_16(uint8_t, img2, [WIDTH * HEIGHT]); - declare_func_emms(AV_CPU_FLAG_MMX, int, MPVEncContext *c, - const uint8_t *blk1 /* align width (8 or 16) */, - const uint8_t *blk2 /* align 1 */, ptrdiff_t stride, - int h); + declare_func(int, MPVEncContext *c, + const uint8_t *blk1 /* align width (8 or 16) */, + const uint8_t *blk2 /* align 1 */, ptrdiff_t stride, + int h); if (test_func == NULL) { return; -- 2.52.0 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
