]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: compute bits.OnesCount's limits from argument's limits
authorJorropo <jorropo.pgm@gmail.com>
Sun, 9 Mar 2025 13:39:49 +0000 (14:39 +0100)
committerJorropo <jorropo.pgm@gmail.com>
Wed, 12 Mar 2025 03:17:36 +0000 (20:17 -0700)
Change-Id: Ia90d48ea0fab363c8592221fad88958b522edefe
Reviewed-on: https://go-review.googlesource.com/c/go/+/656159
Reviewed-by: David Chase <drchase@google.com>
Auto-Submit: Jorropo <jorropo.pgm@gmail.com>
Reviewed-by: Keith Randall <khr@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>

src/cmd/compile/internal/ssa/prove.go
test/prove_popcount.go

index 9fedbdbbc987ee0489a2271d9c425e579bb889eb..1b5989e6e55e3a8d257f162422699603508f099a 100644 (file)
@@ -1732,6 +1732,14 @@ func (ft *factsTable) flowLimit(v *Value) bool {
                        return ft.unsignedMax(v, uint64(bits.Len8(uint8(a.umax))-1))
                }
 
+       case OpPopCount64, OpPopCount32, OpPopCount16, OpPopCount8:
+               a := ft.limits[v.Args[0].ID]
+               changingBitsCount := uint64(bits.Len64(a.umax ^ a.umin))
+               sharedLeadingMask := ^(uint64(1)<<changingBitsCount - 1)
+               fixedBits := a.umax & sharedLeadingMask
+               min := uint64(bits.OnesCount64(fixedBits))
+               return ft.unsignedMinMax(v, min, min+changingBitsCount)
+
        case OpBitLen64:
                a := ft.limits[v.Args[0].ID]
                return ft.unsignedMinMax(v,
index 430df01ec354e2e5f6cfef5359c06d901199b4d9..1fe53defb097a0cd0ab4948fd1a7d2f21d764674 100644 (file)
@@ -33,5 +33,28 @@ func onesCountsBounds(x uint64, ensureAllBranchesCouldHappen func() bool) int {
        return z
 }
 
+func onesCountsTight(x uint64, ensureAllBranchesCouldHappen func() bool) int {
+       const maxv = 0xff0f
+       const minv = 0xff00
+       x = max(x, minv)
+       x = min(x, maxv)
+
+       z := bits.OnesCount64(x)
+
+       if ensureAllBranchesCouldHappen() && z > bits.OnesCount64(maxv) { // ERROR "Disproved Less64$"
+               return 42
+       }
+       if ensureAllBranchesCouldHappen() && z <= bits.OnesCount64(maxv) { // ERROR "Proved Leq64$"
+               return 4242
+       }
+       if ensureAllBranchesCouldHappen() && z < bits.OnesCount64(minv) { // ERROR "Disproved Less64$"
+               return 424242
+       }
+       if ensureAllBranchesCouldHappen() && z >= bits.OnesCount64(minv) { // ERROR "Proved Leq64$"
+               return 42424242
+       }
+       return z
+}
+
 func main() {
 }