PR #25636 opened by zuxy
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25636
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25636.patch

Convert ff_h264_loop_filter_strength from MMX to SSE2, following the
pattern of the qpel/IDCT/chroma conversions. 17% faster when benchmarked
on a Zen 4.


>From 2cf9758617f8e81dcadfbe8b960f25b065dfa95b Mon Sep 17 00:00:00 2001
From: Zuxy Meng <[email protected]>
Date: Fri, 30 Oct 2026 23:51:59 -0700
Subject: [PATCH] avcodec/x86/h264: convert deblock MMX to SSE2

Convert ff_h264_loop_filter_strength from MMX to SSE2, following the
pattern of the qpel/IDCT/chroma conversions. 17% faster when benchmarked
on a Zen 4.
---
 libavcodec/x86/h264_deblock.asm | 141 +++++++++++++++++---------------
 libavcodec/x86/h264dsp_init.c   |  14 ++--
 2 files changed, 84 insertions(+), 71 deletions(-)

diff --git a/libavcodec/x86/h264_deblock.asm b/libavcodec/x86/h264_deblock.asm
index 717349b9313..fa3ada865de 100644
--- a/libavcodec/x86/h264_deblock.asm
+++ b/libavcodec/x86/h264_deblock.asm
@@ -1,5 +1,5 @@
 ;*****************************************************************************
-;* MMX/SSE2/AVX-optimized H.264 deblocking code
+;* SSE2/AVX-optimized H.264 deblocking code
 ;*****************************************************************************
 ;* Copyright (C) 2005-2011 x264 project
 ;*
@@ -29,7 +29,7 @@
 SECTION_RODATA
 
 pb_A1: times 16 db 0xA1
-pb_3_1: times 4 db 3, 1
+pb_3_1: times 8 db 3, 1
 
 SECTION .text
 
@@ -1008,62 +1008,55 @@ DEBLOCK_CHROMA_XMM avx
     jnz %%.skip_loop_iter                       ; if (!(b_idx & mask_mv))
 %if bidir == 1
     movd             m2, [refq+b_idxq+d_idx+12] ; { ref0[bn] }
-    punpckldq        m2, [refq+b_idxq+d_idx+52] ; { ref0[bn], ref1[bn] }
-    pshufw           m0, [refq+b_idxq+12], 0x44 ; { ref0[b],  ref0[b]  }
-    pshufw           m1, [refq+b_idxq+52], 0x44 ; { ref1[b],  ref1[b]  }
-    pshufw           m3, m2, 0x4E               ; { ref1[bn], ref0[bn] }
+    movd             m3, [refq+b_idxq+d_idx+52] ; { ref1[bn] }
+    punpckldq        m2, m3                     ; { ref0[bn], ref1[bn] }
+    movd             m0, [refq+b_idxq+12]
+    pshuflw          m0, m0, q1010              ; { ref0[b],  ref0[b]  }
+    movd             m1, [refq+b_idxq+52]
+    pshuflw          m1, m1, q1010              ; { ref1[b],  ref1[b]  }
+    pshuflw          m3, m2, q1032              ; { ref1[bn], ref0[bn] }
     psubb            m0, m2                     ; { ref0[b] != ref0[bn],
                                                 ;   ref0[b] != ref1[bn] }
     psubb            m1, m3                     ; { ref1[b] != ref1[bn],
                                                 ;   ref1[b] != ref0[bn] }
 
     por              m0, m1
-    mova             m1, [mvq+b_idxq*4+(d_idx+12)*4]
-    mova             m2, [mvq+b_idxq*4+(d_idx+12)*4+mmsize]
+    movu             m1, [mvq+b_idxq*4+(d_idx+12)*4]
+    movu             m2, [mvq+b_idxq*4+12*4]
     mova             m3, m1
-    mova             m4, m2
-    psubw            m1, [mvq+b_idxq*4+12*4]
-    psubw            m2, [mvq+b_idxq*4+12*4+mmsize]
-    psubw            m3, [mvq+b_idxq*4+52*4]
-    psubw            m4, [mvq+b_idxq*4+52*4+mmsize]
-    packsswb         m1, m2
-    packsswb         m3, m4
-    paddb            m1, m6
-    paddb            m3, m6
-    psubusb          m1, m5 ; abs(mv[b] - mv[bn]) >= limit
-    psubusb          m3, m5
+    psubw            m1, m2
+    movu             m2, [mvq+b_idxq*4+52*4]
+    psubw            m3, m2
     packsswb         m1, m3
+    paddb            m1, m6
+    psubusb          m1, m5 ; abs(mv[b] - mv[bn]) >= limit
+    packsswb         m1, m1
 
     por              m0, m1
-    mova             m1, [mvq+b_idxq*4+(d_idx+52)*4]
-    mova             m2, [mvq+b_idxq*4+(d_idx+52)*4+mmsize]
+    movu             m1, [mvq+b_idxq*4+(d_idx+52)*4]
+    movu             m2, [mvq+b_idxq*4+12*4]
     mova             m3, m1
-    mova             m4, m2
-    psubw            m1, [mvq+b_idxq*4+12*4]
-    psubw            m2, [mvq+b_idxq*4+12*4+mmsize]
-    psubw            m3, [mvq+b_idxq*4+52*4]
-    psubw            m4, [mvq+b_idxq*4+52*4+mmsize]
-    packsswb         m1, m2
-    packsswb         m3, m4
-    paddb            m1, m6
-    paddb            m3, m6
-    psubusb          m1, m5 ; abs(mv[b] - mv[bn]) >= limit
-    psubusb          m3, m5
+    psubw            m1, m2
+    movu             m2, [mvq+b_idxq*4+52*4]
+    psubw            m3, m2
     packsswb         m1, m3
+    paddb            m1, m6
+    psubusb          m1, m5 ; abs(mv[b] - mv[bn]) >= limit
+    packsswb         m1, m1
 
-    pshufw           m1, m1, 0x4E
+    pshuflw          m1, m1, q1032
     por              m0, m1
-    pshufw           m1, m0, 0x4E
+    pshuflw          m1, m0, q1032
     pminub           m0, m1
 %else ; bidir == 0
     movd             m0, [refq+b_idxq+12]
-    psubb            m0, [refq+b_idxq+d_idx+12] ; ref[b] != ref[bn]
+    movq             m2, [refq+b_idxq+d_idx+12] ; ref[bn]
+    psubb            m0, m2                     ; ref[b] != ref[bn]
 
-    mova             m1, [mvq+b_idxq*4+12*4]
-    mova             m2, [mvq+b_idxq*4+12*4+mmsize]
-    psubw            m1, [mvq+b_idxq*4+(d_idx+12)*4]
-    psubw            m2, [mvq+b_idxq*4+(d_idx+12)*4+mmsize]
-    packsswb         m1, m2
+    movu             m1, [mvq+b_idxq*4+12*4]
+    movu             m2, [mvq+b_idxq*4+(d_idx+12)*4]
+    psubw            m1, m2
+    packsswb         m1, m1
     paddb            m1, m6
     psubusb          m1, m5 ; abs(mv[b] - mv[bn]) >= limit
     packsswb         m1, m1
@@ -1072,10 +1065,11 @@ DEBLOCK_CHROMA_XMM avx
 
 %%.skip_loop_iter:
     movd             m1, [nnzq+b_idxq+12]
-    por              m1, [nnzq+b_idxq+d_idx+12] ; nnz[b] || nnz[bn]
+    movq             m2, [nnzq+b_idxq+d_idx+12] ; nnz[bn]
+    por              m1, m2                     ; nnz[b] || nnz[bn]
 
-    pminub           m1, m7
-    pminub           m0, m7
+    pminub           m1, [pb_1]
+    pminub           m0, [pb_1]
     psllw            m1, 1
     pxor             m2, m2
     pmaxub           m1, m0
@@ -1087,13 +1081,12 @@ DEBLOCK_CHROMA_XMM avx
     jl %%.b_idx_loop
 %endmacro
 
-INIT_MMX mmxext
-cglobal h264_loop_filter_strength, 9, 9, 0, bs, nnz, ref, mv, bidir, edges, \
+INIT_XMM sse2
+cglobal h264_loop_filter_strength, 9, 9, 7, bs, nnz, ref, mv, bidir, edges, \
                                             step, mask_mv0, mask_mv1, field
 %define b_idxq bidirq
 %define b_idxd bidird
     cmp    dword fieldm, 0
-    mova             m7, [pb_1]
     mova             m5, [pb_3]
     je .nofield
     mova             m5, [pb_3_1]
@@ -1115,28 +1108,48 @@ cglobal h264_loop_filter_strength, 9, 9, 0, bs, nnz, 
ref, mv, bidir, edges, \
     loop_filter_strength_iteration edgesd, stepd, mask_mv1d, 1, -8,  0, 0
     loop_filter_strength_iteration     32,     8, mask_mv0d, 0, -1, -1, 0
 
-    mova             m0, [bsq+mmsize*0]
-    mova             m1, [bsq+mmsize*1]
-    mova             m2, [bsq+mmsize*2]
-    mova             m3, [bsq+mmsize*3]
-    TRANSPOSE4x4W 0, 1, 2, 3, 4
-    mova  [bsq+mmsize*0], m0
-    mova  [bsq+mmsize*1], m1
-    mova  [bsq+mmsize*2], m2
-    mova  [bsq+mmsize*3], m3
+    movu             m0, [bsq+8*0] ; [A|B]
+    movu             m1, [bsq+8*2] ; [C|D]
+    mova             m2, m0
+    movlhps          m2, m1        ; u0 = [A|C]
+    mova             m3, m1
+    movhlps          m3, m0        ; u1 = [B|D]
+    mova             m4, m2
+    punpcklwd        m4, m3        ; t01, low = [a0,b0,a1,b1]
+    mova             m0, m2
+    punpckhwd        m0, m3        ; s01, low = [c0,d0,c1,d1]
+    punpckldq        m4, m0        ; [out0|out1]
+    movu  [bsq+8*0], m4
+    pshufd           m2, m2, q3311 ; [(a2,a3)x2,(c2,c3)x2]
+    pshufd           m3, m3, q3311
+    mova             m4, m2
+    punpcklwd        m4, m3        ; low = [a2,b2,a3,b3]
+    punpckhwd        m2, m3        ; low = [c2,d2,c3,d3]
+    punpckldq        m4, m2        ; [out2|out3]
+    movu  [bsq+8*2], m4
     RET
 
 .bidir:
     loop_filter_strength_iteration edgesd, stepd, mask_mv1d, 1, -8,  0, 1
     loop_filter_strength_iteration     32,     8, mask_mv0d, 0, -1, -1, 1
 
-    mova             m0, [bsq+mmsize*0]
-    mova             m1, [bsq+mmsize*1]
-    mova             m2, [bsq+mmsize*2]
-    mova             m3, [bsq+mmsize*3]
-    TRANSPOSE4x4W 0, 1, 2, 3, 4
-    mova  [bsq+mmsize*0], m0
-    mova  [bsq+mmsize*1], m1
-    mova  [bsq+mmsize*2], m2
-    mova  [bsq+mmsize*3], m3
+    movu             m0, [bsq+8*0] ; [A|B]
+    movu             m1, [bsq+8*2] ; [C|D]
+    mova             m2, m0
+    movlhps          m2, m1        ; u0 = [A|C]
+    mova             m3, m1
+    movhlps          m3, m0        ; u1 = [B|D]
+    mova             m4, m2
+    punpcklwd        m4, m3        ; t01, low = [a0,b0,a1,b1]
+    mova             m0, m2
+    punpckhwd        m0, m3        ; s01, low = [c0,d0,c1,d1]
+    punpckldq        m4, m0        ; [out0|out1]
+    movu  [bsq+8*0], m4
+    pshufd           m2, m2, q3311 ; [(a2,a3)x2,(c2,c3)x2]
+    pshufd           m3, m3, q3311
+    mova             m4, m2
+    punpcklwd        m4, m3        ; low = [a2,b2,a3,b3]
+    punpckhwd        m2, m3        ; low = [c2,d2,c3,d3]
+    punpckldq        m4, m2        ; [out2|out3]
+    movu  [bsq+8*2], m4
     RET
diff --git a/libavcodec/x86/h264dsp_init.c b/libavcodec/x86/h264dsp_init.c
index d103fe041fb..3b9cb794a75 100644
--- a/libavcodec/x86/h264dsp_init.c
+++ b/libavcodec/x86/h264dsp_init.c
@@ -80,11 +80,11 @@ void ff_h264_luma_dc_dequant_idct_sse2(int16_t *output, 
int16_t *input, int qmul
 /***********************************/
 /* deblocking */
 
-void ff_h264_loop_filter_strength_mmxext(int16_t bS[2][4][4], uint8_t nnz[40],
-                                         int8_t ref[2][40],
-                                         int16_t mv[2][40][2],
-                                         int bidir, int edges, int step,
-                                         int mask_mv0, int mask_mv1, int 
field);
+void ff_h264_loop_filter_strength_sse2(int16_t bS[2][4][4], uint8_t nnz[40],
+                                       int8_t ref[2][40],
+                                       int16_t mv[2][40][2],
+                                       int bidir, int edges, int step,
+                                       int mask_mv0, int mask_mv1, int field);
 
 #define LF_FUNC(DIR, TYPE, DEPTH, OPT)                                        \
 void ff_deblock_ ## DIR ## _ ## TYPE ## _ ## DEPTH ## _ ## OPT(uint8_t *pix,  \
@@ -182,8 +182,8 @@ av_cold void ff_h264dsp_init_x86(H264DSPContext *c, const 
int bit_depth,
 {
     int cpu_flags = av_get_cpu_flags();
 
-    if (EXTERNAL_MMXEXT(cpu_flags) && chroma_format_idc <= 1)
-        c->loop_filter_strength = ff_h264_loop_filter_strength_mmxext;
+    if (EXTERNAL_SSE2(cpu_flags) && chroma_format_idc <= 1)
+        c->loop_filter_strength = ff_h264_loop_filter_strength_sse2;
 
     if (bit_depth == 8) {
         if (EXTERNAL_SSE2(cpu_flags)) {
-- 
2.54.0

_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to