Commit af25036ac0 for ffmpeg

commit af25036ac09146b5187adfc247a643b3f993545c
Author: Devin Heitmueller <dheitmueller@ltnglobal.com>
Date:   Wed Sep 16 15:59:03 2026 -0400

    avcodec/bitpacked: add AVX-512ICL unpacking

    Use a masked exact-width load and VBMI byte permutations to expand each
    40-byte group, then compact the planar Y, U, and V outputs. Handle an
    eight-pixel prefix separately so the hot loop can use the negative-width
    output-offset pattern from v210.

    The AVX-512ICL feature tier is required for vpermb. CPUs with baseline
    AVX-512 but without VBMI continue to use AVX2. Reuse one result register for
    all three output planes so the function also assembles for 32-bit x86.

    The implementation passed 300 consecutive checkasm seeds and assembled
    as ELF, Windows COFF, and Mach-O in both 32- and 64-bit modes.

    Benchmark command:
    ./tests/checkasm/checkasm --bench --test=bitpackeddec \
        --duration=1000000 60300

    Intel Xeon E-2356G, GCC 8.5, NASM 2.15.03:
    bitpacked_unpack_yuv422p10_c:          13502.8
    bitpacked_unpack_yuv422p10_ssse3:       3436.6 ( 3.93x)
    bitpacked_unpack_yuv422p10_avx2:        2222.8 ( 6.07x)
    bitpacked_unpack_yuv422p10_avx512icl:   1131.5 (11.93x)

diff --git a/libavcodec/x86/bitpacked.asm b/libavcodec/x86/bitpacked.asm
index db15a2f91f..deccdcd557 100644
--- a/libavcodec/x86/bitpacked.asm
+++ b/libavcodec/x86/bitpacked.asm
@@ -21,8 +21,27 @@

 %include "libavutil/x86/x86util.asm"

-SECTION_RODATA 32
+SECTION_RODATA 64

+unpack_shuf_avx512icl:
+    db  1, 0,  2, 1,  3, 2,  4, 3,  6, 5,  7, 6,  8, 7,  9, 8
+    db 11,10, 12,11, 13,12, 14,13, 16,15, 17,16, 18,17, 19,18
+    db 21,20, 22,21, 23,22, 24,23, 26,25, 27,26, 28,27, 29,28
+    db 31,30, 32,31, 33,32, 34,33, 36,35, 37,36, 38,37, 39,38
+y_shuf_avx512icl:
+    db  2, 3,  6, 7, 10,11, 14,15, 18,19, 22,23, 26,27, 30,31
+    db 34,35, 38,39, 42,43, 46,47, 50,51, 54,55, 58,59, 62,63
+    times 32 db 0
+u_shuf_avx512icl:
+    db  0, 1,  8, 9, 16,17, 24,25, 32,33, 40,41, 48,49, 56,57
+    times 48 db 0
+v_shuf_avx512icl:
+    db  4, 5, 12,13, 20,21, 28,29, 36,37, 44,45, 52,53, 60,61
+    times 48 db 0
+input_mask_avx512icl: dq 0x000000ffffffffff
+tail_mask_avx512icl:  dq 0x00000000000fffff
+
+ALIGN 32
 unpack_shuf_avx2:
     db 1,0, 2,1, 3,2, 4,3, 6,5, 7,6, 8,7, 9,8
     db 5,4, 6,5, 7,6, 8,7, 10,9, 11,10, 12,11, 13,12
@@ -184,3 +203,63 @@ cglobal bitpacked_unpack_yuv422p10, 5, 5, 8, src, y, u, v, w
 .ret:
     RET
 %endif
+
+%if HAVE_AVX512ICL_EXTERNAL
+INIT_ZMM avx512icl
+cglobal bitpacked_unpack_yuv422p10, 5, 5, 7, src, y, u, v, w
+    mova           m2, [unpack_shuf_avx512icl]
+    VBROADCASTI128 m3, [unpack_mult]
+    mova           m4, [y_shuf_avx512icl]
+    mova           m5, [u_shuf_avx512icl]
+    mova           m6, [v_shuf_avx512icl]
+    kmovq          k1, [input_mask_avx512icl]
+    kmovq          k2, [tail_mask_avx512icl]
+
+    test           wd, 8
+    jz             .setup
+    vmovdqu8       m0{k2}{z}, [srcq]
+    vpermb         m0, m2, m0
+    pmullw         m0, m3
+    psrlw          m0, 6
+
+    vpermb         m1, m4, m0
+    movu           [yq], xm1
+    vpermb         m1, m5, m0
+    movq           [uq], xm1
+    vpermb         m1, m6, m0
+    movq           [vq], xm1
+
+    add            srcq, 20
+    add            yq, 16
+    add            uq, 8
+    add            vq, 8
+    sub            wd, 8
+    jz             .ret
+
+.setup:
+    movsxdifnidn   wq, wd
+    lea            yq, [yq+2*wq]
+    add            uq, wq
+    add            vq, wq
+    neg            wq
+
+.loop:
+    vmovdqu8       m0{k1}{z}, [srcq]
+    vpermb         m0, m2, m0
+    pmullw         m0, m3
+    psrlw          m0, 6
+
+    vpermb         m1, m4, m0
+    movu           [yq+2*wq], ym1
+    vpermb         m1, m5, m0
+    movu           [uq+wq], xm1
+    vpermb         m1, m6, m0
+    movu           [vq+wq], xm1
+
+    add            srcq, 40
+    add            wq, 16
+    jl             .loop
+
+.ret:
+    RET
+%endif
diff --git a/libavcodec/x86/bitpacked_init.c b/libavcodec/x86/bitpacked_init.c
index 01fce4ba16..4c5295befb 100644
--- a/libavcodec/x86/bitpacked_init.c
+++ b/libavcodec/x86/bitpacked_init.c
@@ -32,6 +32,11 @@ void ff_bitpacked_unpack_yuv422p10_avx2(const uint8_t *src,
                                         uint16_t *y, uint16_t *u, uint16_t *v,
                                         int width);
 #endif
+#if HAVE_AVX512ICL_EXTERNAL
+void ff_bitpacked_unpack_yuv422p10_avx512icl(const uint8_t *src,
+                                             uint16_t *y, uint16_t *u,
+                                             uint16_t *v, int width);
+#endif

 av_cold void ff_bitpacked_init_x86(struct BitpackedContext *s)
 {
@@ -44,4 +49,9 @@ av_cold void ff_bitpacked_init_x86(struct BitpackedContext *s)
     if (EXTERNAL_AVX2(cpu_flags))
         s->unpack_yuv422p10 = ff_bitpacked_unpack_yuv422p10_avx2;
 #endif
+
+#if HAVE_AVX512ICL_EXTERNAL
+    if (EXTERNAL_AVX512ICL(cpu_flags))
+        s->unpack_yuv422p10 = ff_bitpacked_unpack_yuv422p10_avx512icl;
+#endif
 }