From: Matthew Dempsky Date: Tue, 17 Nov 2020 20:53:34 +0000 (-0800) Subject: [dev.regabi] go/constant: optimize BitLen X-Git-Tag: go1.17beta1~1539^2~475 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=1abb12fc97;p=gostls13.git [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 TryBot-Result: Go Bot Trust: Matthew Dempsky Reviewed-by: Robert Griesemer --- diff --git a/src/go/constant/value.go b/src/go/constant/value.go index 116c7575d9..59606dc479 100644 --- a/src/go/constant/value.go +++ b/src/go/constant/value.go @@ -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: diff --git a/src/go/constant/value_test.go b/src/go/constant/value_test.go index 1a5025cbbd..1ad6784f9a 100644 --- a/src/go/constant/value_test.go +++ b/src/go/constant/value_test.go @@ -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) + } + } +}