Commit 174f470813 for ffmpeg

commit 174f470813641991aae2ced845d460fb9c3bc572
Author: Niklas Haas <git@haasn.dev>
Date:   Sat Nov 7 14:13:51 2026 +0100

    swscale/ops_chain: re-order SwsOpImpl to store func with its data

    The only downside to doing this is that it makes the C code unable to
    reuse the CONTINUE() helper implicitly, but I don't think that's a huge
    loss.

    It also actually saves 16 bytes of data per ops chain, though that will
    become moot after the rest of the series.

    Signed-off-by: Niklas Haas <git@haasn.dev>

diff --git a/libswscale/aarch64/ops.c b/libswscale/aarch64/ops.c
index 19d0330a52..5755bac610 100644
--- a/libswscale/aarch64/ops.c
+++ b/libswscale/aarch64/ops.c
@@ -37,7 +37,7 @@ static_assert(offsetof_exec_in       == offsetof(SwsOpExec, in),       "SwsOpExe
 static_assert(offsetof_exec_out      == offsetof(SwsOpExec, out),      "SwsOpExec layout mismatch");
 static_assert(offsetof_exec_in_bump  == offsetof(SwsOpExec, in_bump),  "SwsOpExec layout mismatch");
 static_assert(offsetof_exec_out_bump == offsetof(SwsOpExec, out_bump), "SwsOpExec layout mismatch");
-static_assert(offsetof_impl_cont     == offsetof(SwsOpImpl, cont),     "SwsOpImpl layout mismatch");
+static_assert(offsetof_impl_func     == offsetof(SwsOpImpl, func),     "SwsOpImpl layout mismatch");
 static_assert(offsetof_impl_priv     == offsetof(SwsOpImpl, priv),     "SwsOpImpl layout mismatch");
 static_assert(sizeof_impl            == sizeof(SwsOpImpl),             "SwsOpImpl layout mismatch");

diff --git a/libswscale/aarch64/ops_asmgen.h b/libswscale/aarch64/ops_asmgen.h
index d77fcabe4d..33ba2d114e 100644
--- a/libswscale/aarch64/ops_asmgen.h
+++ b/libswscale/aarch64/ops_asmgen.h
@@ -61,7 +61,7 @@ typedef struct SwsAArch64Context {

     /* CPS-related variables. */
     RasmOp op0_func;
-    RasmOp op1_impl;
+    RasmOp op0_impl;
     RasmOp cont;
     RasmNode *load_cont_node;
     SwsAArch64OpRegs regs;
diff --git a/libswscale/aarch64/ops_impl.h b/libswscale/aarch64/ops_impl.h
index 2553805967..b8b952a1f6 100644
--- a/libswscale/aarch64/ops_impl.h
+++ b/libswscale/aarch64/ops_impl.h
@@ -91,7 +91,7 @@ static inline int linear_num_vregs(const SwsAArch64OpImplParams *params)
 #define offsetof_exec_out       32
 #define offsetof_exec_in_bump  128
 #define offsetof_exec_out_bump 160
-#define offsetof_impl_cont       0
+#define offsetof_impl_func       0
 #define offsetof_impl_priv       8
 #define sizeof_impl             24

diff --git a/libswscale/aarch64/ops_static.c b/libswscale/aarch64/ops_static.c
index 2a7933d675..62a0a42bdc 100644
--- a/libswscale/aarch64/ops_static.c
+++ b/libswscale/aarch64/ops_static.c
@@ -451,7 +451,7 @@ static void asmgen_process_frame(SwsAArch64Context *s, SwsCompMask imask, SwsCom

     /* CPS-related variables. */
     s->op0_func  = a64op_gpx(7);
-    s->op1_impl  = a64op_gpx(8);
+    s->op0_impl  = a64op_gpx(8);

     /* Read/Write data pointer padding. */
     LOOP(imask, i) { s->in_bump [i] = a64op_gpx(rw_gprs[(i * 4) + 2]); }
@@ -519,13 +519,13 @@ static void asmgen_process_cps(SwsAArch64Context *s, SwsCompMask mask)

     /* Load values from impl. */
     rasm_set_current_node(r, s->setup);
-    RasmOp impl_cont = a64op_off(s->impl, offsetof_impl_cont);
-    i_ldr(r, s->op0_func, impl_cont);                   CMT("SwsFuncPtr op0_func = impl->cont;");
-    i_add(r, s->op1_impl, s->impl, IMM(sizeof_impl));   CMT("SwsOpImpl *op1_impl = impl + 1;");
+    RasmOp impl_func = a64op_off(s->impl, offsetof_impl_func);
+    i_ldr(r, s->op0_func, impl_func);                   CMT("SwsFuncPtr op0_func = impl->func;");
+    i_mov(r, s->op0_impl, s->impl);                     CMT("SwsOpImpl *op0_impl = impl;");

     /* Reset impl and call first kernel. */
     rasm_set_current_node(r, s->loop);
-    i_mov(r, s->impl, s->op1_impl);                     CMT("impl = op1_impl;");
+    i_mov(r, s->impl, s->op0_impl);                     CMT("impl = op0_impl;");
     i_blr(r, s->op0_func);                              CMT("op0_func();");
 }

@@ -635,8 +635,8 @@ static void asmgen_op_cps(SwsAArch64Context *s, const SwsAArch64OpEntry *entry)
     } else {
         /* Load continuation address and increment impl pointer. */
         RasmNode *node = rasm_set_current_node(r, s->load_cont_node);
-        RasmOp impl_post = a64op_post(s->impl, sizeof_impl);
-        i_ldr(r, s->cont, impl_post);                   CMT("SwsFuncPtr cont = (impl++)->cont;");
+        RasmOp impl_pre = a64op_pre(s->impl, sizeof_impl);
+        i_ldr(r, s->cont, impl_pre);                    CMT("SwsFuncPtr cont = (++impl)->func;");
         rasm_set_current_node(r, node);
         /* Common end for remaining CPS functions. */
         i_br (r, s->cont);                              CMT("jump to cont");
diff --git a/libswscale/ops_chain.c b/libswscale/ops_chain.c
index 9eb4b242dc..0e2bd237a8 100644
--- a/libswscale/ops_chain.c
+++ b/libswscale/ops_chain.c
@@ -51,8 +51,8 @@ int ff_sws_op_chain_append(SwsOpChain *chain, SwsFuncPtr func, const void *ref,
         return AVERROR(EINVAL);

     av_assert1(func);
-    chain->impl[idx].cont = func;
-    chain->impl[idx + 1].priv = *priv;
+    chain->impl[idx].func = func;
+    chain->impl[idx].priv = *priv;
     chain->num_impl++;
     if (ref)
         chain->ref[chain->num_ref++] = av_refstruct_ref_c(ref);
diff --git a/libswscale/ops_chain.h b/libswscale/ops_chain.h
index b2dfd3f3ad..f660215520 100644
--- a/libswscale/ops_chain.h
+++ b/libswscale/ops_chain.h
@@ -71,7 +71,7 @@ static_assert(sizeof(SwsOpPriv) == 16, "SwsOpPriv size mismatch");
  */
 typedef void (*SwsFuncPtr)(void);
 typedef struct SwsOpImpl {
-    SwsFuncPtr cont; /* Continuation for this operation. */
+    SwsFuncPtr func; /* Function pointer for this operation. */
     SwsOpPriv  priv; /* Private data for this operation. */
 } SwsOpImpl;

@@ -87,7 +87,7 @@ static_assert(offsetof(SwsOpImpl, priv) == 8, "SwsOpImpl layout mismatch");
  */
 typedef struct SwsOpChain {
 #define SWS_MAX_OPS 16
-    SwsOpImpl impl[SWS_MAX_OPS + 1]; /* reserve extra space for the entrypoint */
+    SwsOpImpl impl[SWS_MAX_OPS];
     int num_impl;
     int cpu_flags;      /* set of all used CPU flags */
     int over_read[4];   /* chain over-reads input by this many bytes */
diff --git a/libswscale/uops_backend.c b/libswscale/uops_backend.c
index 3f62cbff96..b5554800a0 100644
--- a/libswscale/uops_backend.c
+++ b/libswscale/uops_backend.c
@@ -115,17 +115,21 @@ static void process_c(const SwsOpExec *exec, const void *priv,
     block_t x, y, z, w; /* allocate enough space for any intermediate */

     SwsOpIter iterdata;
-    SwsOpIter *iter = &iterdata; /* for CONTINUE() macro to work */
+    SwsOpIter *iter = &iterdata;
     iter->exec = exec;
     for (int i = 0; i < 4; i++) {
         iter->in[i]  = (uintptr_t) exec->in[i];
         iter->out[i] = (uintptr_t) exec->out[i];
     }

+    void (*entry)(SwsOpIter *, const SwsOpImpl *, void *, void *, void *, void *);
+    entry = (void (*)(SwsOpIter *, const SwsOpImpl *,
+                      void *, void *, void *, void *)) impl->func;
+
     for (iter->y = y_start; iter->y < y_end; iter->y++) {
         for (int block = bx_start; block < bx_end; block++) {
             iter->x = block * SWS_BLOCK_SIZE;
-            CONTINUE(&x, &y, &z, &w);
+            entry(iter, impl, &x, &y, &z, &w);
         }

         const int y_bump = exec->in_bump_y ? exec->in_bump_y[iter->y] : 0;
diff --git a/libswscale/uops_tmpl.h b/libswscale/uops_tmpl.h
index c684ad3645..3d04e7e31d 100644
--- a/libswscale/uops_tmpl.h
+++ b/libswscale/uops_tmpl.h
@@ -112,7 +112,7 @@ typedef struct SwsOpIter {
 #define CONTINUE(...)                                                           \
     ((void (*)(SwsOpIter *, const SwsOpImpl *,                                  \
                void *restrict x, void *restrict y,                              \
-               void *restrict z, void *restrict w)) impl->cont)                 \
+               void *restrict z, void *restrict w)) impl[1].func)               \
         (iter, &impl[1], __VA_ARGS__)

 /* Helper macros for common op setup code */
diff --git a/libswscale/x86/ops_common.asm b/libswscale/x86/ops_common.asm
index 9053147dca..5b4adc6325 100644
--- a/libswscale/x86/ops_common.asm
+++ b/libswscale/x86/ops_common.asm
@@ -33,8 +33,8 @@ cglobal sws_process%1_x86, 6, 7 + 2 * %1, 16
             ;   (see SwsOpFunc signature)
             ;
             ; Stack layout:
-            ;   [rsp +  0] = [qword] impl->cont (address of first kernel)
-            ;   [rsp +  8] = [qword] &impl[1]   (restore implq after chain)
+            ;   [rsp +  0] = [qword] impl->func (address of first kernel)
+            ;   [rsp +  8] = [qword] impl       (restore implq after chain)
             ;   [rsp + 16] = [dword] bx start   (restore after line finish)
             ;   [rsp + 20] = [dword] bx end     (loop counter limit)
             ;   [rsp + 24] = [dword] y end      (loop counter limit)
@@ -42,8 +42,7 @@ cglobal sws_process%1_x86, 6, 7 + 2 * %1, 16
             mov [rsp + 16], bxd
             mov [rsp + 20], tmp0d ; bx_end
             mov [rsp + 24], tmp1d ; y_end
-            mov tmp0q, [implq + SwsOpImpl.cont]
-            add implq, SwsOpImpl.next
+            mov tmp0q, [implq + SwsOpImpl.func]
             mov [rsp +  0], tmp0q
             mov [rsp +  8], implq
             movsxdifnidn bxq, bxd
diff --git a/libswscale/x86/ops_include.asm b/libswscale/x86/ops_include.asm
index b8f41ca07b..ab103b8f67 100644
--- a/libswscale/x86/ops_include.asm
+++ b/libswscale/x86/ops_include.asm
@@ -134,7 +134,7 @@ struc SwsOpExec
 endstruc

 struc SwsOpImpl
-    .cont resq 1
+    .func resq 1
     .priv resb 16
     .next resb 0
 endstruc
@@ -303,7 +303,7 @@ endstruc

 ; Load the next operation kernel's address to a register
 %macro LOAD_CONT 1 ; reg
-    mov %1, [implq + SwsOpImpl.cont]
+    mov %1, [implq + SwsOpImpl.next + SwsOpImpl.func]
 %endmacro

 ; Tail call into the next operation kernel, given that kernel's address