]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: add limits bruteforce tests for bitlen
authorJorropo <jorropo.pgm@gmail.com>
Sun, 7 Dec 2025 02:07:46 +0000 (03:07 +0100)
committerGopher Robot <gobot@golang.org>
Fri, 23 Jan 2026 20:08:57 +0000 (12:08 -0800)
This ensure BitLen is perfect within the limitations limits can represent.

Change-Id: I5c1770b4a9f6408fd68fe77b4ef2b2cdd52e26cb
Reviewed-on: https://go-review.googlesource.com/c/go/+/727781
Reviewed-by: Keith Randall <khr@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Jorropo <jorropo.pgm@gmail.com>
Reviewed-by: Keith Randall <khr@google.com>
Reviewed-by: Carlos Amedee <carlos@golang.org>
src/cmd/compile/internal/ssa/prove.go
src/cmd/compile/internal/ssa/prove_test.go

index 22de2dc7a559a1c3753421338e18905c4a2e141d..233d0b30d148b8001855d1d4fe3f7dc48956b71b 100644 (file)
@@ -428,6 +428,14 @@ func (l limit) ctz(b uint) limit {
        return noLimit.unsignedMax(uint64(min(uint(bits.TrailingZeros64(fixed)), b)))
 }
 
+// Similar to add, but computes the Len of the limit for bitsize b.
+func (l limit) bitlen(b uint) limit {
+       return noLimit.unsignedMinMax(
+               uint64(bits.Len64(l.umin)),
+               uint64(bits.Len64(l.umax)),
+       )
+}
+
 var noLimit = limit{math.MinInt64, math.MaxInt64, 0, math.MaxUint64}
 
 // a limitFact is a limit known for a particular value.
@@ -1941,26 +1949,10 @@ func (ft *factsTable) flowLimit(v *Value) {
                min := uint64(bits.OnesCount64(fixedBits))
                ft.unsignedMinMax(v, min, min+changingBitsCount)
 
-       case OpBitLen64:
-               a := ft.limits[v.Args[0].ID]
-               ft.unsignedMinMax(v,
-                       uint64(bits.Len64(a.umin)),
-                       uint64(bits.Len64(a.umax)))
-       case OpBitLen32:
-               a := ft.limits[v.Args[0].ID]
-               ft.unsignedMinMax(v,
-                       uint64(bits.Len32(uint32(a.umin))),
-                       uint64(bits.Len32(uint32(a.umax))))
-       case OpBitLen16:
-               a := ft.limits[v.Args[0].ID]
-               ft.unsignedMinMax(v,
-                       uint64(bits.Len16(uint16(a.umin))),
-                       uint64(bits.Len16(uint16(a.umax))))
-       case OpBitLen8:
-               a := ft.limits[v.Args[0].ID]
-               ft.unsignedMinMax(v,
-                       uint64(bits.Len8(uint8(a.umin))),
-                       uint64(bits.Len8(uint8(a.umax))))
+       case OpBitLen64, OpBitLen32, OpBitLen16, OpBitLen8:
+               a := v.Args[0]
+               al := ft.limits[a.ID]
+               ft.newLimit(v, al.bitlen(uint(a.Type.Size())*8))
 
        // Masks.
 
index 1d91736ff0068c83ab3cc33482decf76984efc92..969e68fee4fa2789032ff1cc500c679c2bf32ae1 100644 (file)
@@ -77,3 +77,7 @@ func TestLimitComUnsigned(t *testing.T) {
 func TestLimitCtzUnsigned(t *testing.T) {
        testLimitUnaryOpUnsigned8(t, "ctz", limit{-128, 127, 0, 8}, limit.ctz, func(x uint8) uint8 { return uint8(bits.TrailingZeros8(x)) })
 }
+
+func TestLimitBitlenUnsigned(t *testing.T) {
+       testLimitUnaryOpUnsigned8(t, "bitlen", limit{-128, 127, 0, 8}, limit.bitlen, func(x uint8) uint8 { return uint8(bits.Len8(x)) })
+}