Commit 5e11c7f81b for ffmpeg
commit 5e11c7f81becf63e03d6f12125214a4b758f2002
Author: Ramiro Polla <ramiro.polla@gmail.com>
Date: Mon Nov 2 01:14:12 2026 +0100
avcodec/x86/cabac: improve ILP of the get_cabac LPS range lookup
Each decision computes its range from the range of the previous one, so
the instructions that go from one range to the next are the critical
path of get_cabac, and their latency limits decoding speed.
The LPS range lookup in the x86-64 PIC version builds its table address
from the state and two bits of the range. It combined the state and the
range first with an lea, so the lea had to wait for the range. Add the
state to the table address instead, which doesn't depend on the range,
and let the load add the range part. This takes the lea off the
critical path:
before: index = state + 2 * (range & 0xC0)
RangeLPS = tables[index]
after: base = tables + state
RangeLPS = base[2 * (range & 0xC0)]
Speedup of single-threaded H.264 decoding on an i9-13900K:
P-core E-core
1080p 3M +0.7% +0.7%
1080p 15M +2.2% +1.0%
1080p 30M +3.1% +1.2%
4K 150M +3.0% +1.1%
Geometric Mean +2.3% +1.0%
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Ramiro Polla <ramiro.polla@gmail.com>
diff --git a/libavcodec/x86/cabac.h b/libavcodec/x86/cabac.h
index 249c18f000..308c99a52d 100644
--- a/libavcodec/x86/cabac.h
+++ b/libavcodec/x86/cabac.h
@@ -86,10 +86,10 @@
#define BRANCHLESS_GET_CABAC(ret, retq, statep, low, lowword, range, rangeq, tmp, tmpbyte, byte, end, norm_off, lps_off, mlps_off, tables) \
"movzbl "statep" , "ret" \n\t"\
+ "lea ("tables", "retq"), %%rcx \n\t"\
"mov "range" , "tmp" \n\t"\
"and $0xC0 , "range" \n\t"\
- "lea ("ret", "range", 2), %%ecx \n\t"\
- "movzbl "lps_off"("tables", %%rcx), "range" \n\t"\
+ "movzbl "lps_off"(%%rcx, "rangeq", 2), "range" \n\t"\
"sub "range" , "tmp" \n\t"\
"mov "tmp" , %%ecx \n\t"\
"shl $17 , "tmp" \n\t"\