[dev.regabi] go/constant: optimize BitLen

Avoids an unnecessary heap allocation when computing the bit length of
int64 values.

Change-Id: I69dfc510e461daf3e83b0b7b6c0707f6526a32d0
Reviewed-on: https://go-review.googlesource.com/c/go/+/272646
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Trust: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Robert Griesemer <gri@golang.org>
This commit is contained in:
Matthew Dempsky 2020-11-17 12:53:34 -08:00
parent 228b732ad9
commit 1abb12fc97
2 changed files with 27 additions and 1 deletions

View File

@ -17,6 +17,7 @@ import (
"go/token"
"math"
"math/big"
"math/bits"
"strconv"
"strings"
"sync"
@ -610,7 +611,11 @@ func Make(x interface{}) Value {
func BitLen(x Value) int {
switch x := x.(type) {
case int64Val:
return i64toi(x).val.BitLen()
u := uint64(x)
if x < 0 {
u = uint64(-x)
}
return 64 - bits.LeadingZeros64(u)
case intVal:
return x.val.BitLen()
case unknownVal:

View File

@ -655,3 +655,24 @@ func BenchmarkStringAdd(b *testing.B) {
})
}
}
var bitLenTests = []struct {
val int64
want int
}{
{0, 0},
{1, 1},
{-16, 5},
{1 << 61, 62},
{1 << 62, 63},
{-1 << 62, 63},
{-1 << 63, 64},
}
func TestBitLen(t *testing.T) {
for _, test := range bitLenTests {
if got := BitLen(MakeInt64(test.val)); got != test.want {
t.Errorf("%v: got %v, want %v", test.val, got, test.want)
}
}
}