diff options
| author | Nigel Tao <nigeltao@golang.org> | 2026-03-05 19:10:23 +1100 |
|---|---|---|
| committer | Nigel Tao <nigeltao@golang.org> | 2026-03-05 12:53:45 -0800 |
| commit | 94a89c61e494a756aef63edb9890170a1ff45faf (patch) | |
| tree | 5aab5145c94dbf4c78f34c38b8ce600cc52f29d2 /src/image | |
| parent | 1a8f9d8141bd5682f38d2320c8e8df4ae5891000 (diff) | |
| download | go-94a89c61e494a756aef63edb9890170a1ff45faf.tar.xz | |
image/jpeg: make decoder.receiveExtend branchless
On linux/amd64:
name old speed new speed delta
DecodeBaseline-8 76.4MB/s ± 0% 84.3MB/s ± 0% +10.38% (p=0.008 n=5+5)
DecodeProgressive-8 51.0MB/s ± 1% 52.6MB/s ± 0% +3.20% (p=0.008 n=5+5)
Thanks to David Le Corfec for the suggestion.
Updates #24499
Change-Id: I749102ff0b50044dfd6a73172a1aa03f89ad97bd
Reviewed-on: https://go-review.googlesource.com/c/go/+/750900
Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Reviewed-by: Nigel Tao <nigeltao@google.com>
Diffstat (limited to 'src/image')
| -rw-r--r-- | src/image/jpeg/huffman.go | 25 |
1 files changed, 22 insertions, 3 deletions
diff --git a/src/image/jpeg/huffman.go b/src/image/jpeg/huffman.go index 0b81fbae96..17a45fc614 100644 --- a/src/image/jpeg/huffman.go +++ b/src/image/jpeg/huffman.go @@ -70,6 +70,16 @@ func (d *decoder) ensureNBits(n int32) error { // receiveExtend is the composition of RECEIVE and EXTEND, specified in section // F.2.2.1. +// +// It returns the signed integer that's encoded in t bits, where t < 16. The +// possible return values are: +// +// - t == 0: 0 +// - t == 1: -1, +1 +// - t == 2: -3, -2, +2, +3 +// - t == 3: -7, -6, -5, -4, +4, +5, +6, +7 +// - ... +// - t == 15: -32767, -32766, ..., -16384, +16384, ..., +32766, +32767 func (d *decoder) receiveExtend(t uint8) (int32, error) { if d.bits.n < int32(t) { if err := d.ensureNBits(int32(t)); err != nil { @@ -80,9 +90,18 @@ func (d *decoder) receiveExtend(t uint8) (int32, error) { d.bits.m >>= t s := int32(1) << t x := int32(d.bits.a>>uint8(d.bits.n)) & (s - 1) - if x < s>>1 { - x += ((-1) << t) + 1 - } + + // This adjustment, assuming two's complement, is a branchless equivalent of: + // + // if x < s>>1 { + // x += ((-1) << t) + 1 + // } + // + // sign is either -1 or 0, depending on whether x is in the low or high + // half of the range 0 .. 1<<t. + sign := (x >> (t - 1)) - 1 + x += sign & (((-1) << t) + 1) + return x, nil } |
