From e34f5a942dd934b7105d356abd3b99811750ddee Mon Sep 17 00:00:00 2001 From: Sergey Fedorov 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 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<>1) + (sl->mb_x&7))*sl->uvlinesize; h->vdsp.prefetch(src[1] + off, src[2] - src[1], 2); } +#endif } } -- 2.43.0