[PR] avcodec/x86/vc1dsp*: Improve loop filter, avoid MMX in loop filter, inv trans (PR #23949)

mkver via ffmpeg-devel <[email protected]> Wed, 29 Jul 2026 15:00:37 -0000
Newsgroups gmane.comp.video.ffmpeg.devel
Message-ID <178533723846.51.6110903665477993785@29965ddac10e>
PR #23949 opened by mkver
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23949
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23949.patch


>From 84fab7ff090d49e9fdaa9bde83770534602d82a2 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <[email protected]>
Date: Tue, 21 Jul 2026 17:57:24 +0200
Subject: [PATCH 01/10] avcodec/x86/vc1dsp_init: Avoid fpel wrappers

One can just reuse the already existing SIZExSIZE fpel
wrappers.

Signed-off-by: Andreas Rheinhardt <[email protected]>
---
 libavcodec/x86/fpel.asm      | 13 +++++++++++++
 libavcodec/x86/vc1dsp_init.c | 18 +-----------------
 2 files changed, 14 insertions(+), 17 deletions(-)

diff --git a/libavcodec/x86/fpel.asm b/libavcodec/x86/fpel.asm
index 598a57ab0d..e7d2dcc8f7 100644
--- a/libavcodec/x86/fpel.asm
+++ b/libavcodec/x86/fpel.asm
@@ -26,6 +26,18 @@
 SECTION .text
 
 INIT_XMM sse2
+
+%macro VC1_FPEL_FUNC 2 ; avg vs put, size
+%if CONFIG_VC1DSP
+; void ff_vc1_{avg,put}_mspel_mc00_{8,16}_sse2(uint8_t *dst, const uint8_t *src,
+;                                              ptrdiff_t stride, int rnd)
+; rnd is unused for fpel functions and for all supported ABIs
+; we can just reuse the SIZExSIZE functions.
+cglobal vc1_%1_mspel_mc00_%2
+%endif
+%endmacro
+
+VC1_FPEL_FUNC avg, 8
 ; void ff_avg_pixels8x8_sse2(uint8_t *block, const uint8_t *pixels,
 ;                            ptrdiff_t line_size)
 cglobal avg_pixels8x8, 3,5,6
@@ -67,6 +79,7 @@ avg_pixels8_after_prologue:
 %define LOAD movu
 %define SAVE mova
 %endif
+VC1_FPEL_FUNC %1, %2
 cglobal %1_pixels%2x%2, 3,5+4*%3,4
     mov         r3d, %2
     jmp         %1_pixels%2_after_prologue
diff --git a/libavcodec/x86/vc1dsp_init.c b/libavcodec/x86/vc1dsp_init.c
index d0705f6bfb..e5a177cb76 100644
--- a/libavcodec/x86/vc1dsp_init.c
+++ b/libavcodec/x86/vc1dsp_init.c
@@ -28,7 +28,6 @@
 #include "libavutil/cpu.h"
 #include "libavutil/x86/cpu.h"
 #include "libavcodec/vc1dsp.h"
-#include "fpel.h"
 #include "vc1dsp.h"
 #include "config.h"
 
@@ -63,18 +62,6 @@ static void vc1_h_loop_filter16_sse4(uint8_t *src, ptrdiff_t stride, int pq)
     ff_vc1_h_loop_filter8_sse4(src+8*stride, stride, pq);
 }
 
-#define DECLARE_FUNCTION(OP, DEPTH, INSN)                       \
-    static void OP##vc1_mspel_mc00_##DEPTH##INSN(uint8_t *dst,          \
-                             const uint8_t *src, ptrdiff_t stride, int rnd) \
-    {                                                                       \
-        ff_ ## OP ## pixels ## DEPTH ## INSN(dst, src, stride, DEPTH);     \
-    }
-
-DECLARE_FUNCTION(put_,  8, _sse2)
-DECLARE_FUNCTION(avg_,  8, _sse2)
-DECLARE_FUNCTION(put_, 16, _sse2)
-DECLARE_FUNCTION(avg_, 16, _sse2)
-
 void ff_put_vc1_chroma_mc8_nornd_ssse3(uint8_t *dst, const uint8_t *src,
                                        ptrdiff_t stride, int h, int x, int y);
 void ff_avg_vc1_chroma_mc8_nornd_ssse3(uint8_t *dst, const uint8_t *src,
@@ -132,10 +119,7 @@ av_cold void ff_vc1dsp_init_x86(VC1DSPContext *dsp)
     if (EXTERNAL_SSE2(cpu_flags)) {
         ASSIGN_LF816(sse2);
 
-        dsp->put_vc1_mspel_pixels_tab[0][0]      = put_vc1_mspel_mc00_16_sse2;
-        dsp->put_vc1_mspel_pixels_tab[1][0]      = put_vc1_mspel_mc00_8_sse2;
-        dsp->avg_vc1_mspel_pixels_tab[0][0]      = avg_vc1_mspel_mc00_16_sse2;
-        dsp->avg_vc1_mspel_pixels_tab[1][0]      = avg_vc1_mspel_mc00_8_sse2;
+        MSPEL_FUNCS(0, 0, sse2);
     }
     if (EXTERNAL_SSSE3(cpu_flags)) {
         ASSIGN_LF4(ssse3);
-- 
2.52.0


>From eec7dd83623d982ad1599cd8be3fbb5633e30315 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <[email protected]>
Date: Wed, 22 Jul 2026 11:34:40 +0200
Subject: [PATCH 02/10] avcodec/vc1dsp: Avoid negating unnecessarily

Due to the earlier "if (a1 < a0 || a2 < a0)" check
it is guaranteed that min(a1,a2) is < a0, allowing
simplifications.

Signed-off-by: Andreas Rheinhardt <[email protected]>
---
 libavcodec/vc1dsp.c | 12 +++---------
 1 file changed, 3 insertions(+), 9 deletions(-)

diff --git a/libavcodec/vc1dsp.c b/libavcodec/vc1dsp.c
index dd143b114c..355e4b8b02 100644
--- a/libavcodec/vc1dsp.c
+++ b/libavcodec/vc1dsp.c
@@ -166,17 +166,11 @@ static av_always_inline int vc1_filter_line(uint8_t *src, ptrdiff_t stride, int
             clip = ((clip ^ clip_sign) - clip_sign) >> 1;
             if (clip) {
                 int a3     = FFMIN(a1, a2);
-                int d      = 5 * (a3 - a0);
-                int d_sign = (d >> 31);
+                int d      = (5 * (a0 - a3)) >> 3;
 
-                d       = ((d ^ d_sign) - d_sign) >> 3;
-                d_sign ^= a0_sign;
-
-                if (d_sign ^ clip_sign)
-                    d = 0;
-                else {
+                if (a0_sign ^ clip_sign) {
                     d = FFMIN(d, clip);
-                    d = (d ^ d_sign) - d_sign; /* Restore sign */
+                    d = (d ^ clip_sign) - clip_sign; /* Restore sign */
                     src[-1 * stride] = av_clip_uint8(src[-1 * stride] - d);
                     src[ 0 * stride] = av_clip_uint8(src[ 0 * stride] + d);
                 }
-- 
2.52.0


>From c23d742fdf96a3caeb8fa6b85a92ca3848282874 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <[email protected]>
Date: Thu, 23 Jul 2026 01:19:49 +0200
Subject: [PATCH 03/10] avcodec/x86/vc1dsp_loopfilter: Avoid imul

Multipliying a GPR by 0x01010101 splats a byte to a dword;
the intention was to avoid vector shuffles lateron, yet
this is not true because the byte splat necessitates
a byte->word conversion lateron.

Signed-off-by: Andreas Rheinhardt <[email protected]>
---
 libavcodec/x86/vc1dsp_loopfilter.asm | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/libavcodec/x86/vc1dsp_loopfilter.asm b/libavcodec/x86/vc1dsp_loopfilter.asm
index f1367da5fa..373608588f 100644
--- a/libavcodec/x86/vc1dsp_loopfilter.asm
+++ b/libavcodec/x86/vc1dsp_loopfilter.asm
@@ -89,9 +89,10 @@ SECTION .text
     pxor    m5, m5
     movd    m3, r2d
 %if %1 > 4
-    punpcklbw m3, m3
+    SPLATW  m3, m3
+%else
+    pshufw  m3, m3, 0
 %endif
-    punpcklbw m3, m5
     pcmpgtw m3, m4  ; if (a0 < pq)
     pand    m6, m3
 
@@ -217,7 +218,6 @@ SECTION .text
     lea  r3, [4*r1]
     sub  r4, r3
     lea  r3, [r1+2*r1]
-    imul r2, 0x01010101
 %endmacro
 
 %macro START_H_FILTER 1
@@ -225,7 +225,6 @@ SECTION .text
 %if %1 > 4
     lea  r4, [r0+4*r1]
 %endif
-    imul r2, 0x01010101
 %endmacro
 
 INIT_XMM sse2
-- 
2.52.0


>From 1ce1e0194350b24cfc641ca648b7874d91776ee6 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <[email protected]>
Date: Thu, 23 Jul 2026 01:47:49 +0200
Subject: [PATCH 04/10] avcodec/x86/vc1dsp_loopfilter: Reduce number of GPRs
 used

Reuse the register that held pq for this instead of using
another one. This saves a push+pop on 32bit systems and avoids
REX prefixes on Unix64.

Signed-off-by: Andreas Rheinhardt <[email protected]>
---
 libavcodec/x86/vc1dsp_loopfilter.asm | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/libavcodec/x86/vc1dsp_loopfilter.asm b/libavcodec/x86/vc1dsp_loopfilter.asm
index 373608588f..0db1ebc8e3 100644
--- a/libavcodec/x86/vc1dsp_loopfilter.asm
+++ b/libavcodec/x86/vc1dsp_loopfilter.asm
@@ -235,9 +235,9 @@ cglobal vc1_v_loop_filter8, 3,5,8
     RET
 
 ; void ff_vc1_h_loop_filter8_sse2(uint8_t *src, ptrdiff_t stride, int pq)
-cglobal vc1_h_loop_filter8, 3,6,8
+cglobal vc1_h_loop_filter8, 3,5,8
     START_H_FILTER 8
-    VC1_H_LOOP_FILTER 8, r5
+    VC1_H_LOOP_FILTER 8, r2
     RET
 
 INIT_MMX ssse3
@@ -248,9 +248,9 @@ cglobal vc1_v_loop_filter4, 3,5,0
     RET
 
 ; void ff_vc1_h_loop_filter4_ssse3(uint8_t *src, ptrdiff_t stride, int pq)
-cglobal vc1_h_loop_filter4, 3,5,0
+cglobal vc1_h_loop_filter4, 3,4,0
     START_H_FILTER 4
-    VC1_H_LOOP_FILTER 4, r4
+    VC1_H_LOOP_FILTER 4, r2
     RET
 
 INIT_XMM ssse3
@@ -261,9 +261,9 @@ cglobal vc1_v_loop_filter8, 3,5,8
     RET
 
 ; void ff_vc1_h_loop_filter8_ssse3(uint8_t *src, ptrdiff_t stride, int pq)
-cglobal vc1_h_loop_filter8, 3,6,8
+cglobal vc1_h_loop_filter8, 3,5,8
     START_H_FILTER 8
-    VC1_H_LOOP_FILTER 8, r5
+    VC1_H_LOOP_FILTER 8, r2
     RET
 
 INIT_XMM sse4
-- 
2.52.0


>From 96ffce169807f5eea12a4882f8ad6f93d1e059a3 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <[email protected]>
Date: Mon, 27 Jul 2026 00:41:39 +0200
Subject: [PATCH 05/10] avcodec/x86/vc1dsp_loopfilter: Reorder instructions
 slightly

In particular, apply the rounding before adding the result
of the multiplication. No change in performance here.

Signed-off-by: Andreas Rheinhardt <[email protected]>
---
 libavcodec/x86/vc1dsp_loopfilter.asm | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/libavcodec/x86/vc1dsp_loopfilter.asm b/libavcodec/x86/vc1dsp_loopfilter.asm
index 0db1ebc8e3..fa42864ae1 100644
--- a/libavcodec/x86/vc1dsp_loopfilter.asm
+++ b/libavcodec/x86/vc1dsp_loopfilter.asm
@@ -60,12 +60,12 @@ SECTION .text
 ; in:  p1 p0 q0 q1, clobbers p0
 ; out: p1 = (2*(p1 - q1) - 5*(p0 - q0) + 4) >> 3
 %macro VC1_LOOP_FILTER_A0 4
-    psubw  %1, %4
     psubw  %2, %3
-    paddw  %1, %1
+    psubw  %1, %4
     pmullw %2, [pw_5]
-    psubw  %1, %2
+    paddw  %1, %1
     paddw  %1, [pw_4]
+    psubw  %1, %2
     psraw  %1, 3
 %endmacro
 
-- 
2.52.0


>From bf410d22a4c34cb60a6cbedbfad4cd226c62ad40 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <[email protected]>
Date: Thu, 23 Jul 2026 15:11:19 +0200
Subject: [PATCH 06/10] avcodec/x86/vc1dsp_loopfilter: Avoid unnecessary PABSW

The loop filter is only active if min(a1,a2)<abs(a0)
which is done via masking. Ergo the sign of min(a1,a2)-abs(a0)
is known (always negative) and one does not need to use
PABSW to get its absolute value.

This gives a small speedup. Old benchmarks:
  vc1dsp.vc1_h_loop_filter4_bestcase_c:            3.1
  vc1dsp.vc1_h_loop_filter4_bestcase_ssse3:       33.6 ( 0.09x)
  vc1dsp.vc1_h_loop_filter4_worstcase_c:          43.0
  vc1dsp.vc1_h_loop_filter4_worstcase_ssse3:      33.4 ( 1.29x)
  vc1dsp.vc1_h_loop_filter8_bestcase_c:            6.0
  vc1dsp.vc1_h_loop_filter8_bestcase_sse2:        38.4 ( 0.16x)
  vc1dsp.vc1_h_loop_filter8_bestcase_ssse3:       37.2 ( 0.16x)
  vc1dsp.vc1_h_loop_filter8_bestcase_sse4:        37.6 ( 0.16x)
  vc1dsp.vc1_h_loop_filter8_worstcase_c:          87.5
  vc1dsp.vc1_h_loop_filter8_worstcase_sse2:       38.4 ( 2.28x)
  vc1dsp.vc1_h_loop_filter8_worstcase_ssse3:      37.6 ( 2.32x)
  vc1dsp.vc1_h_loop_filter8_worstcase_sse4:       37.6 ( 2.32x)
  vc1dsp.vc1_h_loop_filter16_bestcase_c:          11.7
  vc1dsp.vc1_h_loop_filter16_bestcase_sse2:       42.0 ( 0.28x)
  vc1dsp.vc1_h_loop_filter16_bestcase_ssse3:      41.4 ( 0.28x)
  vc1dsp.vc1_h_loop_filter16_bestcase_sse4:       44.8 ( 0.26x)
  vc1dsp.vc1_h_loop_filter16_worstcase_c:        167.2
  vc1dsp.vc1_h_loop_filter16_worstcase_sse2:      41.8 ( 4.00x)
  vc1dsp.vc1_h_loop_filter16_worstcase_ssse3:     41.7 ( 3.92x)
  vc1dsp.vc1_h_loop_filter16_worstcase_sse4:      45.3 ( 3.69x)
  vc1dsp.vc1_v_loop_filter4_bestcase_c:            3.6
  vc1dsp.vc1_v_loop_filter4_bestcase_ssse3:       17.1 ( 0.21x)
  vc1dsp.vc1_v_loop_filter4_worstcase_c:          49.3
  vc1dsp.vc1_v_loop_filter4_worstcase_ssse3:      17.0 ( 2.89x)
  vc1dsp.vc1_v_loop_filter8_bestcase_c:            6.3
  vc1dsp.vc1_v_loop_filter8_bestcase_sse2:        17.7 ( 0.36x)
  vc1dsp.vc1_v_loop_filter8_bestcase_ssse3:       16.8 ( 0.38x)
  vc1dsp.vc1_v_loop_filter8_worstcase_c:          85.8
  vc1dsp.vc1_v_loop_filter8_worstcase_sse2:       17.7 ( 4.83x)
  vc1dsp.vc1_v_loop_filter8_worstcase_ssse3:      16.7 ( 5.12x)
  vc1dsp.vc1_v_loop_filter16_bestcase_c:          12.7
  vc1dsp.vc1_v_loop_filter16_bestcase_sse2:       26.4 ( 0.48x)
  vc1dsp.vc1_v_loop_filter16_bestcase_ssse3:      24.0 ( 0.53x)
  vc1dsp.vc1_v_loop_filter16_worstcase_c:        170.1
  vc1dsp.vc1_v_loop_filter16_worstcase_sse2:      25.7 ( 6.63x)
  vc1dsp.vc1_v_loop_filter16_worstcase_ssse3:     25.2 ( 6.75x)

New benchmarks:
  vc1dsp.vc1_h_loop_filter4_bestcase_c:            3.0
  vc1dsp.vc1_h_loop_filter4_bestcase_ssse3:       32.4 ( 0.09x)
  vc1dsp.vc1_h_loop_filter4_worstcase_c:          42.3
  vc1dsp.vc1_h_loop_filter4_worstcase_ssse3:      32.7 ( 1.29x)
  vc1dsp.vc1_h_loop_filter8_bestcase_c:            6.1
  vc1dsp.vc1_h_loop_filter8_bestcase_sse2:        37.1 ( 0.17x)
  vc1dsp.vc1_h_loop_filter8_bestcase_ssse3:       36.4 ( 0.17x)
  vc1dsp.vc1_h_loop_filter8_bestcase_sse4:        36.6 ( 0.17x)
  vc1dsp.vc1_h_loop_filter8_worstcase_c:          87.2
  vc1dsp.vc1_h_loop_filter8_worstcase_sse2:       36.9 ( 2.36x)
  vc1dsp.vc1_h_loop_filter8_worstcase_ssse3:      35.8 ( 2.35x)
  vc1dsp.vc1_h_loop_filter8_worstcase_sse4:       36.7 ( 2.38x)
  vc1dsp.vc1_h_loop_filter16_bestcase_c:          12.0
  vc1dsp.vc1_h_loop_filter16_bestcase_sse2:       40.0 ( 0.30x)
  vc1dsp.vc1_h_loop_filter16_bestcase_ssse3:      39.8 ( 0.30x)
  vc1dsp.vc1_h_loop_filter16_bestcase_sse4:       44.4 ( 0.27x)
  vc1dsp.vc1_h_loop_filter16_worstcase_c:        166.4
  vc1dsp.vc1_h_loop_filter16_worstcase_sse2:      39.9 ( 4.17x)
  vc1dsp.vc1_h_loop_filter16_worstcase_ssse3:     39.7 ( 4.19x)
  vc1dsp.vc1_h_loop_filter16_worstcase_sse4:      43.8 ( 3.80x)
  vc1dsp.vc1_v_loop_filter4_bestcase_c:            3.6
  vc1dsp.vc1_v_loop_filter4_bestcase_ssse3:       16.3 ( 0.22x)
  vc1dsp.vc1_v_loop_filter4_worstcase_c:          49.3
  vc1dsp.vc1_v_loop_filter4_worstcase_ssse3:      16.2 ( 3.04x)
  vc1dsp.vc1_v_loop_filter8_bestcase_c:            6.4
  vc1dsp.vc1_v_loop_filter8_bestcase_sse2:        16.3 ( 0.39x)
  vc1dsp.vc1_v_loop_filter8_bestcase_ssse3:       15.8 ( 0.40x)
  vc1dsp.vc1_v_loop_filter8_worstcase_c:          85.7
  vc1dsp.vc1_v_loop_filter8_worstcase_sse2:       16.3 ( 5.24x)
  vc1dsp.vc1_v_loop_filter8_worstcase_ssse3:      15.8 ( 5.42x)
  vc1dsp.vc1_v_loop_filter16_bestcase_c:          12.7
  vc1dsp.vc1_v_loop_filter16_bestcase_sse2:       24.7 ( 0.52x)
  vc1dsp.vc1_v_loop_filter16_bestcase_ssse3:      22.7 ( 0.56x)
  vc1dsp.vc1_v_loop_filter16_worstcase_c:        169.4
  vc1dsp.vc1_v_loop_filter16_worstcase_sse2:      24.1 ( 7.03x)
  vc1dsp.vc1_v_loop_filter16_worstcase_ssse3:     24.6 ( 6.88x)

Signed-off-by: Andreas Rheinhardt <[email protected]>
---
 libavcodec/x86/vc1dsp_loopfilter.asm | 68 ++++++++++++----------------
 1 file changed, 28 insertions(+), 40 deletions(-)

diff --git a/libavcodec/x86/vc1dsp_loopfilter.asm b/libavcodec/x86/vc1dsp_loopfilter.asm
index fa42864ae1..883896a3ed 100644
--- a/libavcodec/x86/vc1dsp_loopfilter.asm
+++ b/libavcodec/x86/vc1dsp_loopfilter.asm
@@ -74,56 +74,44 @@ SECTION .text
 ; %1: size
 ; out: m0=p0' m1=q0'
 %macro VC1_FILTER 1
-    PABSW   m4, m7
     PABSW   m3, m6
+    movd    m6, r2d
     PABSW   m2, m5
-    mova    m6, m4
+    PABSW   m4, m7
+    PSHUFLW m6, m6, 0
     pminsw  m3, m2
-    pcmpgtw m6, m3  ; if (a2 < a0 || a1 < a0)
-    psubw   m3, m4
-    pmullw  m3, [pw_5]   ; 5*(a3 - a0)
-    PABSW   m2, m3
-    psraw   m2, 3   ; abs(d/8)
-    pxor    m7, m3  ; d_sign ^= a0_sign
-
-    pxor    m5, m5
-    movd    m3, r2d
+    pcmpgtw m2, m4, m3   ; if (a2 < a0 || a1 < a0)
 %if %1 > 4
-    SPLATW  m3, m3
-%else
-    pshufw  m3, m3, 0
+    punpcklqdq m6, m6
 %endif
-    pcmpgtw m3, m4  ; if (a0 < pq)
-    pand    m6, m3
-
-    mova    m3, m0
-    psubw   m3, m1
-    PABSW   m4, m3
-    psraw   m4, 1
-    pxor    m3, m7  ; d_sign ^ clip_sign
+    pcmpgtw m6, m4       ; if (a0 < pq)
+    psubw   m4, m3
+    psubw   m3, m0, m1   ; clip
+    pmullw  m4, [pw_5]   ; 5*(a0 - a3)
+    PABSW   m5, m3
+    pand    m6, m2       ; if (min(a1,a2) < a0 && a0 < pq)
+    psraw   m5, 1        ; final clip
+    psraw   m4, 3        ; d = (5*(a0 - a3)) >> 3
+    pxor    m2, m2
+    pminsw  m4, m5       ; d = min(d, clip)
     psraw   m3, 15
-    pminsw  m2, m4  ; min(d, clip)
-    pcmpgtw m4, m5
-    pand    m6, m4  ; filt3 (C return value)
+    pcmpgtw m5, m2       ; if (clip)
+    pxor    m7, m3       ; a0_sign ^ clip_sign
+    pand    m6, m5       ; filt3 (C return value)
 
 ; each set of 4 pixels is not filtered if the 3rd is not
-%if mmsize==16
-    pshuflw m4, m6, 0xaa
+    PSHUFLW m5, m6, q2222
+    psraw   m7, 15       ; a0_sign ^ clip_sign as mask
+    pand    m4, m6
 %if %1 > 4
-    pshufhw m4, m4, 0xaa
+    pshufhw m5, m5, q2222
 %endif
-%else
-    pshufw  m4, m6, 0xaa
-%endif
-    pandn   m3, m4
-    pand    m2, m6
-    pand    m3, m2  ; d final
-
-    psraw   m7, 15
-    pxor    m3, m7
-    psubw   m3, m7
-    psubw   m0, m3
-    paddw   m1, m3
+    pxor    m4, m3
+    pand    m5, m7
+    psubw   m4, m3
+    pand    m4, m5
+    psubw   m0, m4
+    paddw   m1, m4
     packuswb m0, m0
     packuswb m1, m1
 %endmacro
-- 
2.52.0


>From fca75b752ea59416e269066bb02b76cf7085c4f6 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <[email protected]>
Date: Fri, 24 Jul 2026 13:07:35 +0200
Subject: [PATCH 07/10] avcodec/x86/vc1dsp_loopfilter: Use psignw when
 available

The VC1 loop filter uses something equivalent to
if (a0_sign ^ clip_sign) {
    if (clip_sign) d = -d;
} else d = 0;
which can be mapped to psignw.

Old benchmarks:
  vc1dsp.vc1_h_loop_filter4_bestcase_c:            3.0
  vc1dsp.vc1_h_loop_filter4_bestcase_ssse3:       32.4 ( 0.09x)
  vc1dsp.vc1_h_loop_filter4_worstcase_c:          42.3
  vc1dsp.vc1_h_loop_filter4_worstcase_ssse3:      32.7 ( 1.29x)
  vc1dsp.vc1_h_loop_filter8_bestcase_c:            6.1
  vc1dsp.vc1_h_loop_filter8_bestcase_sse2:        37.1 ( 0.17x)
  vc1dsp.vc1_h_loop_filter8_bestcase_ssse3:       36.4 ( 0.17x)
  vc1dsp.vc1_h_loop_filter8_bestcase_sse4:        36.6 ( 0.17x)
  vc1dsp.vc1_h_loop_filter8_worstcase_c:          87.2
  vc1dsp.vc1_h_loop_filter8_worstcase_sse2:       36.9 ( 2.36x)
  vc1dsp.vc1_h_loop_filter8_worstcase_ssse3:      35.8 ( 2.35x)
  vc1dsp.vc1_h_loop_filter8_worstcase_sse4:       36.7 ( 2.38x)
  vc1dsp.vc1_h_loop_filter16_bestcase_c:          12.0
  vc1dsp.vc1_h_loop_filter16_bestcase_sse2:       40.0 ( 0.30x)
  vc1dsp.vc1_h_loop_filter16_bestcase_ssse3:      39.8 ( 0.30x)
  vc1dsp.vc1_h_loop_filter16_bestcase_sse4:       44.4 ( 0.27x)
  vc1dsp.vc1_h_loop_filter16_worstcase_c:        166.4
  vc1dsp.vc1_h_loop_filter16_worstcase_sse2:      39.9 ( 4.17x)
  vc1dsp.vc1_h_loop_filter16_worstcase_ssse3:     39.7 ( 4.19x)
  vc1dsp.vc1_h_loop_filter16_worstcase_sse4:      43.8 ( 3.80x)
  vc1dsp.vc1_v_loop_filter4_bestcase_c:            3.6
  vc1dsp.vc1_v_loop_filter4_bestcase_ssse3:       16.3 ( 0.22x)
  vc1dsp.vc1_v_loop_filter4_worstcase_c:          49.3
  vc1dsp.vc1_v_loop_filter4_worstcase_ssse3:      16.2 ( 3.04x)
  vc1dsp.vc1_v_loop_filter8_bestcase_c:            6.4
  vc1dsp.vc1_v_loop_filter8_bestcase_sse2:        16.3 ( 0.39x)
  vc1dsp.vc1_v_loop_filter8_bestcase_ssse3:       15.8 ( 0.40x)
  vc1dsp.vc1_v_loop_filter8_worstcase_c:          85.7
  vc1dsp.vc1_v_loop_filter8_worstcase_sse2:       16.3 ( 5.24x)
  vc1dsp.vc1_v_loop_filter8_worstcase_ssse3:      15.8 ( 5.42x)
  vc1dsp.vc1_v_loop_filter16_bestcase_c:          12.7
  vc1dsp.vc1_v_loop_filter16_bestcase_sse2:       24.7 ( 0.52x)
  vc1dsp.vc1_v_loop_filter16_bestcase_ssse3:      22.7 ( 0.56x)
  vc1dsp.vc1_v_loop_filter16_worstcase_c:        169.4
  vc1dsp.vc1_v_loop_filter16_worstcase_sse2:      24.1 ( 7.03x)
  vc1dsp.vc1_v_loop_filter16_worstcase_ssse3:     24.6 ( 6.88x)

New benchmarks:
  vc1dsp.vc1_h_loop_filter4_bestcase_c:            3.0
  vc1dsp.vc1_h_loop_filter4_bestcase_ssse3:       32.0 ( 0.09x)
  vc1dsp.vc1_h_loop_filter4_worstcase_c:          43.2
  vc1dsp.vc1_h_loop_filter4_worstcase_ssse3:      31.8 ( 1.36x)
  vc1dsp.vc1_h_loop_filter8_bestcase_c:            6.0
  vc1dsp.vc1_h_loop_filter8_bestcase_sse2:        36.9 ( 0.16x)
  vc1dsp.vc1_h_loop_filter8_bestcase_ssse3:       35.5 ( 0.17x)
  vc1dsp.vc1_h_loop_filter8_bestcase_sse4:        36.2 ( 0.17x)
  vc1dsp.vc1_h_loop_filter8_worstcase_c:          87.3
  vc1dsp.vc1_h_loop_filter8_worstcase_sse2:       37.6 ( 2.33x)
  vc1dsp.vc1_h_loop_filter8_worstcase_ssse3:      35.3 ( 2.40x)
  vc1dsp.vc1_h_loop_filter8_worstcase_sse4:       36.1 ( 2.42x)
  vc1dsp.vc1_h_loop_filter16_bestcase_c:          11.8
  vc1dsp.vc1_h_loop_filter16_bestcase_sse2:       40.1 ( 0.29x)
  vc1dsp.vc1_h_loop_filter16_bestcase_ssse3:      39.2 ( 0.30x)
  vc1dsp.vc1_h_loop_filter16_bestcase_sse4:       42.9 ( 0.28x)
  vc1dsp.vc1_h_loop_filter16_worstcase_c:        166.5
  vc1dsp.vc1_h_loop_filter16_worstcase_sse2:      39.8 ( 4.18x)
  vc1dsp.vc1_h_loop_filter16_worstcase_ssse3:     39.1 ( 4.26x)
  vc1dsp.vc1_h_loop_filter16_worstcase_sse4:      42.9 ( 3.88x)
  vc1dsp.vc1_v_loop_filter4_bestcase_c:            3.6
  vc1dsp.vc1_v_loop_filter4_bestcase_ssse3:       15.7 ( 0.22x)
  vc1dsp.vc1_v_loop_filter4_worstcase_c:          49.1
  vc1dsp.vc1_v_loop_filter4_worstcase_ssse3:      15.8 ( 3.10x)
  vc1dsp.vc1_v_loop_filter8_bestcase_c:            6.4
  vc1dsp.vc1_v_loop_filter8_bestcase_sse2:        16.3 ( 0.39x)
  vc1dsp.vc1_v_loop_filter8_bestcase_ssse3:       15.3 ( 0.42x)
  vc1dsp.vc1_v_loop_filter8_worstcase_c:          85.7
  vc1dsp.vc1_v_loop_filter8_worstcase_sse2:       16.3 ( 5.26x)
  vc1dsp.vc1_v_loop_filter8_worstcase_ssse3:      15.2 ( 5.62x)
  vc1dsp.vc1_v_loop_filter16_bestcase_c:          13.6
  vc1dsp.vc1_v_loop_filter16_bestcase_sse2:       24.8 ( 0.55x)
  vc1dsp.vc1_v_loop_filter16_bestcase_ssse3:      21.3 ( 0.64x)
  vc1dsp.vc1_v_loop_filter16_worstcase_c:        170.0
  vc1dsp.vc1_v_loop_filter16_worstcase_sse2:      23.9 ( 7.11x)
  vc1dsp.vc1_v_loop_filter16_worstcase_ssse3:     23.3 ( 7.28x)

Signed-off-by: Andreas Rheinhardt <[email protected]>
---
 libavcodec/x86/vc1dsp_loopfilter.asm | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/libavcodec/x86/vc1dsp_loopfilter.asm b/libavcodec/x86/vc1dsp_loopfilter.asm
index 883896a3ed..7f4783afa7 100644
--- a/libavcodec/x86/vc1dsp_loopfilter.asm
+++ b/libavcodec/x86/vc1dsp_loopfilter.asm
@@ -94,21 +94,40 @@ SECTION .text
     psraw   m4, 3        ; d = (5*(a0 - a3)) >> 3
     pxor    m2, m2
     pminsw  m4, m5       ; d = min(d, clip)
+%if cpuflag(ssse3)
+    ; m3 and m7 are in the -255..255 range, so that every bit in each word's
+    ; upper half coincides with the sign bit. When subtracting as bytes
+    ; the upper byte of every word is 0 if m3 and m7 have the same sign,
+    ; 1 if m7 (a0_sign) is negative/set but m3 is not and -1 else.
+    ; After the right shift by eight bits below, the value of the word
+    ; coincides with the current value of the upper byte.
+    psubb   m3, m7
+    pcmpgtw m5, m2       ; if (clip)
+%else
     psraw   m3, 15
     pcmpgtw m5, m2       ; if (clip)
     pxor    m7, m3       ; a0_sign ^ clip_sign
+%endif
     pand    m6, m5       ; filt3 (C return value)
 
 ; each set of 4 pixels is not filtered if the 3rd is not
     PSHUFLW m5, m6, q2222
+%if cpuflag(ssse3)
+    psraw   m3, 8
+%else
     psraw   m7, 15       ; a0_sign ^ clip_sign as mask
+%endif
     pand    m4, m6
 %if %1 > 4
     pshufhw m5, m5, q2222
 %endif
+%if cpuflag(ssse3)
+    psignw  m4, m3
+%else
     pxor    m4, m3
     pand    m5, m7
     psubw   m4, m3
+%endif
     pand    m4, m5
     psubw   m0, m4
     paddw   m1, m4
-- 
2.52.0


>From 7c460deac89b378435909cb39c28293c5bd94994 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <[email protected]>
Date: Sat, 25 Jul 2026 22:45:56 +0200
Subject: [PATCH 08/10] avcodec/x86/vc1dsp_loopfilter: Don't use MMX regs in
 horiz. loop filter

Using XMM registers in this SSSE3 function leads to fewer shuffles
when transposing the input; it also allows to combine calculating
a1 and a2. Because of this, codesize is the same as before (on Unix64)
although MMX instructions are shorter.

Old benchmarks:
  vc1dsp.vc1_h_loop_filter4_bestcase_c:           3.0
  vc1dsp.vc1_h_loop_filter4_bestcase_ssse3:      32.0 ( 0.09x)
  vc1dsp.vc1_h_loop_filter4_worstcase_c:         42.9
  vc1dsp.vc1_h_loop_filter4_worstcase_ssse3:     31.9 ( 1.35x)

New benchmarks:
  vc1dsp.vc1_h_loop_filter4_bestcase_c:           3.0
  vc1dsp.vc1_h_loop_filter4_bestcase_ssse3:      29.9 ( 0.10x)
  vc1dsp.vc1_h_loop_filter4_worstcase_c:         43.7
  vc1dsp.vc1_h_loop_filter4_worstcase_ssse3:     29.9 ( 1.46x)

Hint: checkasm's benchmark always uses the same buffer that is
partially updated by the horizontal loop filter function (the
middle two of eight columns are updated using word-sized stores).
They therefore lead to store-to-load-forwarding failure. If
checkasm_alternate were used to alternate between two buffers,
the benchmarks would be as follows:

Old benchmarks:
  vc1dsp.vc1_h_loop_filter4_bestcase_c:           3.0
  vc1dsp.vc1_h_loop_filter4_bestcase_ssse3:      16.4 ( 0.18x)
  vc1dsp.vc1_h_loop_filter4_worstcase_c:         23.9
  vc1dsp.vc1_h_loop_filter4_worstcase_ssse3:     16.3 ( 1.47x)

New benchmarks:
  vc1dsp.vc1_h_loop_filter4_bestcase_c:           3.0
  vc1dsp.vc1_h_loop_filter4_bestcase_ssse3:      15.1 ( 0.20x)
  vc1dsp.vc1_h_loop_filter4_worstcase_c:         23.6
  vc1dsp.vc1_h_loop_filter4_worstcase_ssse3:     15.2 ( 1.55x)

Notice that at some callsites, the partially modified buffer
is immediately reloaded again*, so that both scenarios can happen.

*: See the TT_4X4 and TT_4X8 cases at the end of vc1_p_h_loop_filter()
or vc1_b_h_intfi_loop_filter() or the luma field blocks in
vc1_p_h_intfr_loop_filter().

Signed-off-by: Andreas Rheinhardt <[email protected]>
---
 libavcodec/x86/vc1dsp_loopfilter.asm | 58 +++++++++++++++++-----------
 1 file changed, 36 insertions(+), 22 deletions(-)

diff --git a/libavcodec/x86/vc1dsp_loopfilter.asm b/libavcodec/x86/vc1dsp_loopfilter.asm
index 7f4783afa7..819693e4a3 100644
--- a/libavcodec/x86/vc1dsp_loopfilter.asm
+++ b/libavcodec/x86/vc1dsp_loopfilter.asm
@@ -42,11 +42,7 @@ SECTION .text
     pextrw %4, %5, %6+3
 %else
     movd  %6d, %5
-%if mmsize==16
     psrldq %5, 4
-%else
-    psrlq  %5, 32
-%endif
     mov    %1, %6w
     shr    %6, 16
     mov    %2, %6w
@@ -71,12 +67,16 @@ SECTION .text
 
 ; in: p0 q0 a0 a1 a2
 ;     m0 m1 m7 m6 m5
-; %1: size
+; %1: size, %2: if set, m6 contains a1, a2
 ; out: m0=p0' m1=q0'
-%macro VC1_FILTER 1
+%macro VC1_FILTER 2
     PABSW   m3, m6
     movd    m6, r2d
+%if %2
+    movhlps m2, m3
+%else
     PABSW   m2, m5
+%endif
     PABSW   m4, m7
     PSHUFLW m6, m6, 0
     pminsw  m3, m2
@@ -162,7 +162,7 @@ SECTION .text
     mova      m5, m1
     VC1_LOOP_FILTER_A0 m5, m2, m3, m4
 
-    VC1_FILTER %1
+    VC1_FILTER %1, 0
     mov%2 [r4+r3], m0
     mov%2 [r0],    m1
 %endmacro
@@ -171,13 +171,6 @@ SECTION .text
 ;     NOTE: UNPACK_8TO16 this number of 8 bit numbers are in half a register
 ; 2nd (optional) param: temp register to use for storing words
 %macro VC1_H_LOOP_FILTER 1-2
-%if %1 == 4
-    movq      m0, [r0     -4]
-    movq      m1, [r0+  r1-4]
-    movq      m2, [r0+2*r1-4]
-    movq      m3, [r0+  r3-4]
-    TRANSPOSE4x4B 0, 1, 2, 3, 4
-%else
     movq      m0, [r0     -4]
     movq      m4, [r0+  r1-4]
     movq      m1, [r0+2*r1-4]
@@ -191,11 +184,11 @@ SECTION .text
     punpcklbw m2, m6
     punpcklbw m3, m7
     TRANSPOSE4x4W 0, 1, 2, 3, 4
-%endif
-    pxor      m5, m5
 
+    pxor      m5, m5
     UNPACK_8TO16 bw, 6, 0, 5
     UNPACK_8TO16 bw, 7, 1, 5
+
     VC1_LOOP_FILTER_A0 m6, m0, m7, m1
     UNPACK_8TO16 bw, 4, 2, 5
     mova    m0, m1                      ; m0 = p0
@@ -205,14 +198,12 @@ SECTION .text
     VC1_LOOP_FILTER_A0 m5, m2, m1, m3
     SWAP 1, 4                           ; m1 = q0
 
-    VC1_FILTER %1
+    VC1_FILTER %1, 0
     punpcklbw m0, m1
 %if %0 > 1
     STORE_4_WORDS [r0-1], [r0+r1-1], [r0+2*r1-1], [r0+r3-1], m0, %2
-%if %1 > 4
     psrldq m0, 4
     STORE_4_WORDS [r4-1], [r4+r1-1], [r4+2*r1-1], [r4+r3-1], m0, %2
-%endif
 %else
     STORE_4_WORDS [r0-1], [r0+r1-1], [r0+2*r1-1], [r0+r3-1], m0, 0
     STORE_4_WORDS [r4-1], [r4+r1-1], [r4+2*r1-1], [r4+r3-1], m0, 4
@@ -254,13 +245,36 @@ cglobal vc1_v_loop_filter4, 3,5,0
     VC1_V_LOOP_FILTER 4, d
     RET
 
+INIT_XMM ssse3
 ; void ff_vc1_h_loop_filter4_ssse3(uint8_t *src, ptrdiff_t stride, int pq)
-cglobal vc1_h_loop_filter4, 3,4,0
+cglobal vc1_h_loop_filter4, 3,4,8
     START_H_FILTER 4
-    VC1_H_LOOP_FILTER 4, r2
+    movq           m0, [r0     -4]
+    movq           m1, [r0+  r1-4]
+    movq           m2, [r0+2*r1-4]
+    movq           m3, [r0+  r3-4]
+    punpcklbw      m0, m1
+    punpcklbw      m2, m3
+    SBUTTERFLY     wd, 0, 2, 1
+    ; m0 now contains lines -4..-1, m2 0..4 as dwords
+    pxor           m5, m5
+    SBUTTERFLY     dq, 0, 2, 1
+    ; m0 now contains lines -4 0 -3 1, m2 -2 2 -1 3
+    UNPACK_8TO16   bw, 6, 0, 5
+    UNPACK_8TO16   bw, 7, 2, 5
+    ; m0, m2, m6, m7 contain two unpacked lines each, namely:
+    ; m6: -4, 0; m0: -3, 1; m7: -2, 2; m2: -1, 3
+    movhlps        m5, m0                        ; 1
+    movhlps        m1, m6                        ; 0
+    VC1_LOOP_FILTER_A0 m6, m0, m7, m2            ; m6: a1, a2
+    mova           m0, m2
+    VC1_LOOP_FILTER_A0 m7, m2, m1, m5
+
+    VC1_FILTER      4, 1
+    punpcklbw      m0, m1
+    STORE_4_WORDS [r0-1], [r0+r1-1], [r0+2*r1-1], [r0+r3-1], m0, r2
     RET
 
-INIT_XMM ssse3
 ; void ff_vc1_v_loop_filter8_ssse3(uint8_t *src, ptrdiff_t stride, int pq)
 cglobal vc1_v_loop_filter8, 3,5,8
     START_V_FILTER
-- 
2.52.0


>From 6a13b427903f7e83da5e45d40d06acb2f9617956 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <[email protected]>
Date: Mon, 27 Jul 2026 00:21:24 +0200
Subject: [PATCH 09/10] avcodec/x86/vc1dsp_loopfilter: Don't use MMX regs

Up until now ff_vc1_v_loop_filter4_ssse3 used MMX registers
despite being an SSSE3 function. Porting it to XMM registers
didn't lead to any change in benchmarks here, but abides
by the ABI (one function less that does not omit emms).
Unfortunately the size of the function increased by 64B
by this.

Signed-off-by: Andreas Rheinhardt <[email protected]>
---
 libavcodec/x86/vc1dsp_loopfilter.asm | 9 ++++-----
 tests/checkasm/vc1dsp.c              | 2 +-
 2 files changed, 5 insertions(+), 6 deletions(-)

diff --git a/libavcodec/x86/vc1dsp_loopfilter.asm b/libavcodec/x86/vc1dsp_loopfilter.asm
index 819693e4a3..3a6af89f9e 100644
--- a/libavcodec/x86/vc1dsp_loopfilter.asm
+++ b/libavcodec/x86/vc1dsp_loopfilter.asm
@@ -78,7 +78,7 @@ SECTION .text
     PABSW   m2, m5
 %endif
     PABSW   m4, m7
-    PSHUFLW m6, m6, 0
+    pshuflw m6, m6, 0
     pminsw  m3, m2
     pcmpgtw m2, m4, m3   ; if (a2 < a0 || a1 < a0)
 %if %1 > 4
@@ -111,7 +111,7 @@ SECTION .text
     pand    m6, m5       ; filt3 (C return value)
 
 ; each set of 4 pixels is not filtered if the 3rd is not
-    PSHUFLW m5, m6, q2222
+    pshuflw m5, m6, q2222
 %if cpuflag(ssse3)
     psraw   m3, 8
 %else
@@ -238,14 +238,13 @@ cglobal vc1_h_loop_filter8, 3,5,8
     VC1_H_LOOP_FILTER 8, r2
     RET
 
-INIT_MMX ssse3
+INIT_XMM ssse3
 ; void ff_vc1_v_loop_filter4_ssse3(uint8_t *src, ptrdiff_t stride, int pq)
-cglobal vc1_v_loop_filter4, 3,5,0
+cglobal vc1_v_loop_filter4, 3,5,8
     START_V_FILTER
     VC1_V_LOOP_FILTER 4, d
     RET
 
-INIT_XMM ssse3
 ; void ff_vc1_h_loop_filter4_ssse3(uint8_t *src, ptrdiff_t stride, int pq)
 cglobal vc1_h_loop_filter4, 3,4,8
     START_H_FILTER 4
diff --git a/tests/checkasm/vc1dsp.c b/tests/checkasm/vc1dsp.c
index d4acf38e46..c8e8699e9f 100644
--- a/tests/checkasm/vc1dsp.c
+++ b/tests/checkasm/vc1dsp.c
@@ -354,7 +354,7 @@ static void check_loop_filter(void)
 
     for (size_t k = 0; k < FF_ARRAY_ELEMS(tests); ++k) {
         void (*func)(uint8_t *, ptrdiff_t, int) = *(void **)((intptr_t) &h + tests[k].offset);
-        declare_func_emms(AV_CPU_FLAG_MMX, void, uint8_t *, ptrdiff_t, int);
+        declare_func(void, uint8_t *, ptrdiff_t, int);
         if (check_func(func, "vc1dsp.%s", tests[k].name)) {
             for (int count = 1000; count > 0; --count) {
                 int pq = rnd() % 31 + 1;
-- 
2.52.0


>From 100a540eced6c6acb926fea8bc6cbd5e4770ee88 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <[email protected]>
Date: Wed, 29 Jul 2026 16:40:40 +0200
Subject: [PATCH 10/10] avcodec/x86/vc1dsp_inv_trans: Port to SSE2

No change in performance here.

Signed-off-by: Andreas Rheinhardt <[email protected]>
---
 libavcodec/x86/vc1dsp_init.c        | 27 +++++++++----------
 libavcodec/x86/vc1dsp_inv_trans.asm | 41 +++++++++++++++--------------
 tests/checkasm/vc1dsp.c             |  2 +-
 3 files changed, 35 insertions(+), 35 deletions(-)

diff --git a/libavcodec/x86/vc1dsp_init.c b/libavcodec/x86/vc1dsp_init.c
index e5a177cb76..6c86b646f9 100644
--- a/libavcodec/x86/vc1dsp_init.c
+++ b/libavcodec/x86/vc1dsp_init.c
@@ -66,14 +66,14 @@ void ff_put_vc1_chroma_mc8_nornd_ssse3(uint8_t *dst, const uint8_t *src,
                                        ptrdiff_t stride, int h, int x, int y);
 void ff_avg_vc1_chroma_mc8_nornd_ssse3(uint8_t *dst, const uint8_t *src,
                                        ptrdiff_t stride, int h, int x, int y);
-void ff_vc1_inv_trans_4x4_dc_mmxext(uint8_t *dest, ptrdiff_t linesize,
-                                    int16_t *block);
-void ff_vc1_inv_trans_4x8_dc_mmxext(uint8_t *dest, ptrdiff_t linesize,
-                                    int16_t *block);
-void ff_vc1_inv_trans_8x4_dc_mmxext(uint8_t *dest, ptrdiff_t linesize,
-                                    int16_t *block);
-void ff_vc1_inv_trans_8x8_dc_mmxext(uint8_t *dest, ptrdiff_t linesize,
-                                    int16_t *block);
+void ff_vc1_inv_trans_4x4_dc_sse2(uint8_t *dest, ptrdiff_t linesize,
+                                  int16_t *block);
+void ff_vc1_inv_trans_4x8_dc_sse2(uint8_t *dest, ptrdiff_t linesize,
+                                  int16_t *block);
+void ff_vc1_inv_trans_8x4_dc_sse2(uint8_t *dest, ptrdiff_t linesize,
+                                  int16_t *block);
+void ff_vc1_inv_trans_8x8_dc_sse2(uint8_t *dest, ptrdiff_t linesize,
+                                  int16_t *block);
 
 #define MSPEL_FUNC(OP, X, Y, SIZE, XMM)                                     \
     void ff_vc1_ ## OP ## _mspel_mc ## X ## Y ## _ ## SIZE ##_ ## XMM       \
@@ -110,13 +110,12 @@ av_cold void ff_vc1dsp_init_x86(VC1DSPContext *dsp)
         dsp->vc1_v_loop_filter16 = vc1_v_loop_filter16_ ## EXT; \
         dsp->vc1_h_loop_filter16 = vc1_h_loop_filter16_ ## EXT
 
-    if (EXTERNAL_MMXEXT(cpu_flags)) {
-        dsp->vc1_inv_trans_8x8_dc                = ff_vc1_inv_trans_8x8_dc_mmxext;
-        dsp->vc1_inv_trans_4x8_dc                = ff_vc1_inv_trans_4x8_dc_mmxext;
-        dsp->vc1_inv_trans_8x4_dc                = ff_vc1_inv_trans_8x4_dc_mmxext;
-        dsp->vc1_inv_trans_4x4_dc                = ff_vc1_inv_trans_4x4_dc_mmxext;
-    }
     if (EXTERNAL_SSE2(cpu_flags)) {
+        dsp->vc1_inv_trans_8x8_dc                = ff_vc1_inv_trans_8x8_dc_sse2;
+        dsp->vc1_inv_trans_4x8_dc                = ff_vc1_inv_trans_4x8_dc_sse2;
+        dsp->vc1_inv_trans_8x4_dc                = ff_vc1_inv_trans_8x4_dc_sse2;
+        dsp->vc1_inv_trans_4x4_dc                = ff_vc1_inv_trans_4x4_dc_sse2;
+
         ASSIGN_LF816(sse2);
 
         MSPEL_FUNCS(0, 0, sse2);
diff --git a/libavcodec/x86/vc1dsp_inv_trans.asm b/libavcodec/x86/vc1dsp_inv_trans.asm
index e1b74de6c4..788ffa24a8 100644
--- a/libavcodec/x86/vc1dsp_inv_trans.asm
+++ b/libavcodec/x86/vc1dsp_inv_trans.asm
@@ -23,9 +23,13 @@
 
 SECTION .text
 
-%macro INV_TRANS_INIT 0
+%macro INV_TRANS_INIT 1 ; width
     movd       m0, blockd
+%if %1 == 4
+    pshuflw    m0, m0, 0
+%else
     SPLATW     m0, m0
+%endif
     pxor       m1, m1
     psubw      m1, m0
     packuswb   m0, m0
@@ -54,9 +58,9 @@ SECTION .text
     mov%1 [linesize3q +destq], m5
 %endmacro
 
-; ff_vc1_inv_trans_?x?_dc_mmxext(uint8_t *dest, ptrdiff_t linesize, int16_t *block)
-INIT_MMX mmxext
-cglobal vc1_inv_trans_4x4_dc, 3,4,0, dest, linesize, block
+INIT_XMM sse2
+; ff_vc1_inv_trans_?x?_dc_sse2(uint8_t *dest, ptrdiff_t linesize, int16_t *block)
+cglobal vc1_inv_trans_4x4_dc, 3,4,6, dest, linesize, block
     movsx         r3d, WORD [blockq]
     mov        blockd, r3d             ; dc
     shl        blockd, 4               ; 16 * dc
@@ -67,13 +71,12 @@ cglobal vc1_inv_trans_4x4_dc, 3,4,0, dest, linesize, block
     lea        blockd, [blockq+r3+64]  ; 17 * dc + 64
     sar        blockd, 7               ; >> 7
 
-    INV_TRANS_INIT
+    INV_TRANS_INIT  4
 
-    INV_TRANS_PROCESS h
+    INV_TRANS_PROCESS d
     RET
 
-INIT_MMX mmxext
-cglobal vc1_inv_trans_4x8_dc, 3,4,0, dest, linesize, block
+cglobal vc1_inv_trans_4x8_dc, 3,4,6, dest, linesize, block
     movsx         r3d, WORD [blockq]
     mov        blockd, r3d             ; dc
     shl        blockd, 4               ; 16 * dc
@@ -83,15 +86,14 @@ cglobal vc1_inv_trans_4x8_dc, 3,4,0, dest, linesize, block
     lea        blockd, [blockq*3+64]   ; 12 * dc + 64
     sar        blockd, 7               ; >> 7
 
-    INV_TRANS_INIT
+    INV_TRANS_INIT  4
 
-    INV_TRANS_PROCESS h
+    INV_TRANS_PROCESS d
     lea         destq, [destq+linesizeq*4]
-    INV_TRANS_PROCESS h
+    INV_TRANS_PROCESS d
     RET
 
-INIT_MMX mmxext
-cglobal vc1_inv_trans_8x4_dc, 3,4,0, dest, linesize, block
+cglobal vc1_inv_trans_8x4_dc, 3,4,6, dest, linesize, block
     movsx      blockd, WORD [blockq]   ; dc
     lea        blockd, [blockq*3+1]    ;  3 * dc + 1
     sar        blockd, 1               ; >> 1
@@ -100,22 +102,21 @@ cglobal vc1_inv_trans_8x4_dc, 3,4,0, dest, linesize, block
     lea        blockd, [blockq+r3+64]  ; 17 * dc + 64
     sar        blockd, 7               ; >> 7
 
-    INV_TRANS_INIT
+    INV_TRANS_INIT  8
 
-    INV_TRANS_PROCESS a
+    INV_TRANS_PROCESS q
     RET
 
-INIT_MMX mmxext
-cglobal vc1_inv_trans_8x8_dc, 3,3,0, dest, linesize, block
+cglobal vc1_inv_trans_8x8_dc, 3,3,6, dest, linesize, block
     movsx      blockd, WORD [blockq]   ; dc
     lea        blockd, [blockq*3+1]    ;  3 * dc + 1
     sar        blockd, 1               ; >> 1
     lea        blockd, [blockq*3+16]   ;  3 * dc + 16
     sar        blockd, 5               ; >> 5
 
-    INV_TRANS_INIT
+    INV_TRANS_INIT  8
 
-    INV_TRANS_PROCESS a
+    INV_TRANS_PROCESS q
     lea         destq, [destq+linesizeq*4]
-    INV_TRANS_PROCESS a
+    INV_TRANS_PROCESS q
     RET
diff --git a/tests/checkasm/vc1dsp.c b/tests/checkasm/vc1dsp.c
index c8e8699e9f..52049a4aa3 100644
--- a/tests/checkasm/vc1dsp.c
+++ b/tests/checkasm/vc1dsp.c
@@ -310,7 +310,7 @@ static void check_inv_trans_adding(void)
         void (*func)(uint8_t *, ptrdiff_t, int16_t *) = *(void **)((intptr_t) &h + tests[k].offset);
         if (check_func(func, "vc1dsp.%s", tests[k].name)) {
             matrix *coeffs;
-            declare_func_emms(AV_CPU_FLAG_MMX, void, uint8_t *, ptrdiff_t, int16_t *);
+            declare_func(void, uint8_t *, ptrdiff_t, int16_t *);
             RANDOMIZE_BUFFER16(inv_trans_in, 8 * 8);
             RANDOMIZE_BUFFER8(inv_trans_out, 10 * 24);
             coeffs = generate_inverse_quantized_transform_coefficients(tests[k].width, tests[k].height);
-- 
2.52.0

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