[PR] avcodec/x86/lossless_videodsp: Optimize add_gradient_pred (PR #23964)
mkver via ffmpeg-devel <[email protected]> Thu, 30 Jul 2026 16:21:18 -0000
| Newsgroups | gmane.comp.video.ffmpeg.devel |
|---|---|
| Message-ID | <178542853089.51.15722820931004972984@29965ddac10e> |
PR #23964 opened by mkver URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23964 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23964.patch One could replace the pshufb with pslldq in the add_left_pred and add_left_pred_int16 functions; this would avoids some loads and save a few register (no more nonvolatile regs on win64!) and be certainly faster on the early SSSE3 CPUs where pshufb was slow. Yet uops.info says that pshufb has a latency of 1 on Zen5, but pslldq has a latency of 2. >From ea6ebf9a3b1f32207f285854f523c764e1e52cf5 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <[email protected]> Date: Thu, 30 Jul 2026 15:59:53 +0200 Subject: [PATCH 1/3] avcodec/x86/lossless_videodsp: Optimize add_gradient_pred Combinations of shift and add like pslldq m3, m2, 1 paddb m2, m3 are linear in the input register m2. This implies that instead of applying the same sequence of shifts and adds to two different registers and adding said registers one can just add the register first and then apply said sequence of shifts and adds once. Old benchmarks: add_gradient_pred_c: 2296.2 add_gradient_pred_ssse3: 570.4 ( 3.95x) add_gradient_pred_avx2: 308.8 ( 7.29x) New benchmarks: add_gradient_pred_c: 2315.6 add_gradient_pred_ssse3: 344.0 ( 6.72x) add_gradient_pred_avx2: 205.2 (11.28x) Signed-off-by: Andreas Rheinhardt <[email protected]> --- libavcodec/x86/lossless_videodsp.asm | 23 +++++------------------ 1 file changed, 5 insertions(+), 18 deletions(-) diff --git a/libavcodec/x86/lossless_videodsp.asm b/libavcodec/x86/lossless_videodsp.asm index 1761a2f08f..53adc67977 100644 --- a/libavcodec/x86/lossless_videodsp.asm +++ b/libavcodec/x86/lossless_videodsp.asm @@ -276,7 +276,7 @@ cglobal add_left_pred_int16_unaligned, 4,4,7, dst, src, mask, w, left ; void add_gradient_pred(uint8_t *src, const ptrdiff_t stride, const ptrdiff_t width) ;--------------------------------------------------------------------------------------------- %macro ADD_GRADIENT_PRED 0 -cglobal add_gradient_pred, 3,4,5, src, stride, width, tmp +cglobal add_gradient_pred, 3,4,4, src, stride, width, tmp mova xm0, [pb_15] ;load src - 1 in xm1 @@ -294,13 +294,13 @@ cglobal add_gradient_pred, 3,4,5, src, stride, width, tmp .loop: lea tmpq, [srcq + strideq] - mova m2, [tmpq + widthq] ; A = src[x-stride] + mova m2, [srcq + widthq] ; current val (src[x]) + paddb m2, [tmpq + widthq] ; add A = src[x-stride] movu m3, [tmpq + widthq - 1] ; B = src[x - (stride + 1)] - mova m4, [srcq + widthq] ; current val (src[x]) - psubb m2, m3; A - B + psubb m2, m3 ; cur + A - B -; prefix sum A-B +; prefix sum pslldq m3, m2, 1 paddb m2, m3 pslldq m3, m2, 2 @@ -310,19 +310,6 @@ cglobal add_gradient_pred, 3,4,5, src, stride, width, tmp pslldq m3, m2, 8 paddb m2, m3 -; prefix sum current val - pslldq m3, m4, 1 - paddb m4, m3 - pslldq m3, m4, 2 - paddb m4, m3 - pslldq m3, m4, 4 - paddb m4, m3 - pslldq m3, m4, 8 - paddb m4, m3 - -; last sum - paddb m2, m4 ; current + (A - B) - paddb xm1, xm2 ; += C mova [srcq + widthq], xm1 ; store -- 2.52.0 >From b064dd6b1ef2bc046270605d88389c99c814f8d0 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <[email protected]> Date: Thu, 30 Jul 2026 16:19:56 +0200 Subject: [PATCH 2/3] avcodec/x86/lossless_videodsp: Hoist calculation out of loop Signed-off-by: Andreas Rheinhardt <[email protected]> --- libavcodec/x86/lossless_videodsp.asm | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/libavcodec/x86/lossless_videodsp.asm b/libavcodec/x86/lossless_videodsp.asm index 53adc67977..833b581744 100644 --- a/libavcodec/x86/lossless_videodsp.asm +++ b/libavcodec/x86/lossless_videodsp.asm @@ -276,7 +276,7 @@ cglobal add_left_pred_int16_unaligned, 4,4,7, dst, src, mask, w, left ; void add_gradient_pred(uint8_t *src, const ptrdiff_t stride, const ptrdiff_t width) ;--------------------------------------------------------------------------------------------- %macro ADD_GRADIENT_PRED 0 -cglobal add_gradient_pred, 3,4,4, src, stride, width, tmp +cglobal add_gradient_pred, 3,3,4, src, stride, width mova xm0, [pb_15] ;load src - 1 in xm1 @@ -291,12 +291,13 @@ cglobal add_gradient_pred, 3,4,4, src, stride, width, tmp add srcq, widthq neg widthq neg strideq + add strideq, srcq + DEFINE_ARGS src, top, width .loop: - lea tmpq, [srcq + strideq] mova m2, [srcq + widthq] ; current val (src[x]) - paddb m2, [tmpq + widthq] ; add A = src[x-stride] - movu m3, [tmpq + widthq - 1] ; B = src[x - (stride + 1)] + paddb m2, [topq + widthq] ; add A = src[x-stride] + movu m3, [topq + widthq - 1] ; B = src[x - (stride + 1)] psubb m2, m3 ; cur + A - B -- 2.52.0 >From 6e999b2e1fe1326806ccdd363ee00f3bce43f1bb Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <[email protected]> Date: Thu, 30 Jul 2026 16:21:12 +0200 Subject: [PATCH 3/3] avcodec/x86/lossless_videodsp: Use memory operand where possible Signed-off-by: Andreas Rheinhardt <[email protected]> --- libavcodec/x86/lossless_videodsp.asm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/x86/lossless_videodsp.asm b/libavcodec/x86/lossless_videodsp.asm index 833b581744..5815c8e5ae 100644 --- a/libavcodec/x86/lossless_videodsp.asm +++ b/libavcodec/x86/lossless_videodsp.asm @@ -280,10 +280,10 @@ cglobal add_gradient_pred, 3,3,4, src, stride, width mova xm0, [pb_15] ;load src - 1 in xm1 - movd xm1, [srcq-1] %if cpuflag(avx2) - vpbroadcastb xm1, xm1 + vpbroadcastb xm1, [srcq-1] %else + movd xm1, [srcq-1] pxor xm2, xm2 pshufb xm1, xm2 %endif -- 2.52.0 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]