aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAxel Wagner <axel.wagner.hh@googlemail.com>2025-11-19 09:28:16 +0100
committerSean Liao <sean@liao.dev>2025-11-23 03:49:34 -0800
commita18294bb6aa8f0dd656f2bcb6742f9de2936d0dc (patch)
tree7d9c0dfc5cfbfe4968c6edfaf6b955e06cbb12e9
parent437323ef7b933255c5c7fbb0775019e95f19b05e (diff)
downloadgo-a18294bb6aa8f0dd656f2bcb6742f9de2936d0dc.tar.xz
cmd/internal/obj/arm64, image/gif, runtime, sort: use math/bits to calculate log2
In several places the integer log2 is calculated using loops or similar mechanisms. math/bits.Len* provide a simpler and more efficient mechanisms for this. Annoyingly, every usage has slightly different ideas of what "log2" means and how non-positive inputs should be handled. I verified the replacements in each case by comparing the result for inputs from 0 to 1<<16. Change-Id: Ie962a74674802da363e0038d34c06979ccb41cf3 Reviewed-on: https://go-review.googlesource.com/c/go/+/721880 Reviewed-by: Mark Freeman <markfreeman@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Michael Knyszek <mknyszek@google.com>
-rw-r--r--src/cmd/internal/obj/arm64/asm7.go27
-rw-r--r--src/image/gif/writer.go15
-rw-r--r--src/runtime/stack.go9
-rw-r--r--src/sort/search_test.go10
4 files changed, 15 insertions, 46 deletions
diff --git a/src/cmd/internal/obj/arm64/asm7.go b/src/cmd/internal/obj/arm64/asm7.go
index ccf8eda495..7addf0ddad 100644
--- a/src/cmd/internal/obj/arm64/asm7.go
+++ b/src/cmd/internal/obj/arm64/asm7.go
@@ -1674,32 +1674,7 @@ func log2(x uint64) uint32 {
if x == 0 {
panic("log2 of 0")
}
- n := uint32(0)
- if x >= 1<<32 {
- x >>= 32
- n += 32
- }
- if x >= 1<<16 {
- x >>= 16
- n += 16
- }
- if x >= 1<<8 {
- x >>= 8
- n += 8
- }
- if x >= 1<<4 {
- x >>= 4
- n += 4
- }
- if x >= 1<<2 {
- x >>= 2
- n += 2
- }
- if x >= 1<<1 {
- x >>= 1
- n += 1
- }
- return n
+ return uint32(bits.Len64(x) - 1)
}
func autoclass(l int64) int {
diff --git a/src/image/gif/writer.go b/src/image/gif/writer.go
index 129d0ab282..2a3e33c145 100644
--- a/src/image/gif/writer.go
+++ b/src/image/gif/writer.go
@@ -15,6 +15,7 @@ import (
"image/draw"
"internal/byteorder"
"io"
+ "math/bits"
)
// Graphic control extension fields.
@@ -23,15 +24,11 @@ const (
gcBlockSize = 0x04
)
-var log2Lookup = [8]int{2, 4, 8, 16, 32, 64, 128, 256}
-
func log2(x int) int {
- for i, v := range log2Lookup {
- if x <= v {
- return i
- }
+ if x < 2 {
+ return 0
}
- return -1
+ return bits.Len(uint(x-1)) - 1
}
// writer is a buffered writer.
@@ -192,7 +189,7 @@ func (e *encoder) writeHeader() {
}
func encodeColorTable(dst []byte, p color.Palette, size int) (int, error) {
- if uint(size) >= uint(len(log2Lookup)) {
+ if uint(size) >= 8 {
return 0, errors.New("gif: cannot encode color table with more than 256 entries")
}
for i, c := range p {
@@ -212,7 +209,7 @@ func encodeColorTable(dst []byte, p color.Palette, size int) (int, error) {
dst[3*i+1] = g
dst[3*i+2] = b
}
- n := log2Lookup[size]
+ n := 1 << (size + 1)
if n > len(p) {
// Pad with black.
clear(dst[3*len(p) : 3*n])
diff --git a/src/runtime/stack.go b/src/runtime/stack.go
index 55e97e77af..c92accf188 100644
--- a/src/runtime/stack.go
+++ b/src/runtime/stack.go
@@ -12,6 +12,7 @@ import (
"internal/runtime/atomic"
"internal/runtime/gc"
"internal/runtime/sys"
+ "math/bits"
"unsafe"
)
@@ -181,12 +182,10 @@ func stackinit() {
// stacklog2 returns ⌊log_2(n)⌋.
func stacklog2(n uintptr) int {
- log2 := 0
- for n > 1 {
- n >>= 1
- log2++
+ if n == 0 {
+ return 0
}
- return log2
+ return bits.Len64(uint64(n))
}
// Allocates a stack from the free pool. Must be called with
diff --git a/src/sort/search_test.go b/src/sort/search_test.go
index 49813eaecb..b6ab900abe 100644
--- a/src/sort/search_test.go
+++ b/src/sort/search_test.go
@@ -5,6 +5,7 @@
package sort_test
import (
+ "math/bits"
"runtime"
. "sort"
stringspkg "strings"
@@ -135,13 +136,10 @@ func TestFind(t *testing.T) {
// log2 computes the binary logarithm of x, rounded up to the next integer.
// (log2(0) == 0, log2(1) == 0, log2(2) == 1, log2(3) == 2, etc.)
func log2(x int) int {
- n := 0
- for p := 1; p < x; p += p {
- // p == 2**n
- n++
+ if x < 1 {
+ return 0
}
- // p/2 < x <= p == 2**n
- return n
+ return bits.Len(uint(x - 1))
}
func TestSearchEfficiency(t *testing.T) {