From e34f5a942dd934b7105d356abd3b99811750ddee Mon Sep 17 00:00:00 2001
From: Sergey Fedorov <barracuda@macos-powerpc.org>
Date: Sat, 15 Aug 2026 20:35:37 +0000
Subject: [PATCH 37/38] avcodec/h264: G4-only whole-block MC prefetch, from
 PowerVLC

prefetch_motion() spreads one macroblock's worth of prefetch over the
next 4 (luma) or 8 (chroma) macroblocks, on the stated assumption that a
64-byte cache line covers four macroblock columns at once.  A 7450 (G4)
has 32-byte lines, so each touch brings in a quarter of what it does on
the CPU the code was tuned for -- and the rolling scheme only pays while
the motion vector stays put across those macroblocks.  Motion
compensation there is memory-latency bound (instruction-level sampling
puts the stalls on the first consumer of every reference load), so fetch
the whole block instead: 32 dcbt per macroblock and list, 1 KiB into a
32 KiB L1, still issued four macroblocks ahead.

From PowerVLC (github.com/Olsro/powervlc, contrib/src/ffmpeg, their
patch 0004): 1080p24 High 14.78 -> 14.92 fps (+1.0%), and 16.99 -> 17.18
(+1.1%) with NONREF deblocking, on a 1.42 GHz 7447A; 720p unchanged
(its reference frames already fit the L2).  Bit-identical output -- dcbt
is only a hint.

Gated ARCH_PPC && !_ARCH_PWR4: the 970 (G5) has 128-byte lines, which
makes the upstream rolling scheme cheaper there, and there is no G5
measurement for the whole-block variant yet -- the G5 build keeps
upstream behavior until a bench says otherwise.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PRRFPPzH3qXUcq8Ask5LZh
---
 libavcodec/h264_mb.c | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/libavcodec/h264_mb.c b/libavcodec/h264_mb.c
index 67fa980..ce219ac 100644
--- a/libavcodec/h264_mb.c
+++ b/libavcodec/h264_mb.c
@@ -495,6 +495,32 @@ static av_always_inline void prefetch_motion(const H264Context *h, H264SliceCont
         int off       =  mx * (1<< pixel_shift) +
                         (my + (sl->mb_x & 3) * 4) * sl->mb_linesize +
                         (64 << pixel_shift);
+#if ARCH_PPC && !defined(_ARCH_PWR4)
+        /* The scheme below spreads one macroblock's worth of prefetch over
+         * the next 4 (luma) or 8 (chroma) macroblocks, assuming a 64-byte
+         * line covers four macroblock columns at once.  A 7450 (G4) has
+         * 32-byte lines, so each touch brings in a quarter of what it does
+         * on the CPU the code was tuned for -- and the rolling scheme only
+         * pays while the motion vector stays put across those macroblocks.
+         * Motion compensation there is memory-latency bound, so fetch the
+         * whole block instead: 32 dcbt per macroblock and list, 1 KiB into
+         * a 32 KiB L1, still issued four macroblocks ahead.
+         * From PowerVLC (github.com/Olsro/powervlc, contrib/src/ffmpeg):
+         * 1080p24 High 14.78 -> 14.92 fps (+1.0%) on a 1.42 GHz 7447A,
+         * 720p unchanged.  Kept off the 970 (G5, _ARCH_PWR4): its 128-byte
+         * lines make the upstream scheme cheaper, and there is no G5
+         * measurement for this one yet. */
+        off = mx * (1 << pixel_shift) + my * sl->mb_linesize + (64 << pixel_shift);
+        h->vdsp.prefetch(src[0] + off, sl->linesize, 16);
+        if (chroma_idc == 3 /* yuv444 */) {
+            h->vdsp.prefetch(src[1] + off, sl->linesize, 16);
+            h->vdsp.prefetch(src[2] + off, sl->linesize, 16);
+        } else {
+            off = ((mx >> 1) + 64) * (1 << pixel_shift) + (my >> 1) * sl->uvlinesize;
+            h->vdsp.prefetch(src[1] + off, sl->uvlinesize, 8);
+            h->vdsp.prefetch(src[2] + off, sl->uvlinesize, 8);
+        }
+#else
         h->vdsp.prefetch(src[0] + off, sl->linesize, 4);
         if (chroma_idc == 3 /* yuv444 */) {
             h->vdsp.prefetch(src[1] + off, sl->linesize, 4);
@@ -503,6 +529,7 @@ static av_always_inline void prefetch_motion(const H264Context *h, H264SliceCont
             off= ((mx>>1)+64) * (1<<pixel_shift) + ((my>>1) + (sl->mb_x&7))*sl->uvlinesize;
             h->vdsp.prefetch(src[1] + off, src[2] - src[1], 2);
         }
+#endif
     }
 }
 
-- 
2.43.0

