1
0
mirror of https://github.com/golang/go synced 2024-11-22 04:14:42 -07:00

cmd/compile: compute bits.Len*'s limits from argument's limits

Change-Id: Ie3c7e5eaba6a9a29389018625c4b784d07c6f173
Reviewed-on: https://go-review.googlesource.com/c/go/+/603537
Reviewed-by: David Chase <drchase@google.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>
This commit is contained in:
Jorropo 2024-08-07 20:20:21 +02:00 committed by Keith Randall
parent 9b6efc25cd
commit 0c7523ff59
2 changed files with 122 additions and 1 deletions

View File

@ -1666,6 +1666,27 @@ func (ft *factsTable) flowLimit(v *Value) bool {
return ft.unsignedMax(v, 7)
}
case OpBitLen64:
a := ft.limits[v.Args[0].ID]
return ft.unsignedMinMax(v,
uint64(bits.Len64(a.umin)),
uint64(bits.Len64(a.umax)))
case OpBitLen32:
a := ft.limits[v.Args[0].ID]
return ft.unsignedMinMax(v,
uint64(bits.Len32(uint32(a.umin))),
uint64(bits.Len32(uint32(a.umax))))
case OpBitLen16:
a := ft.limits[v.Args[0].ID]
return ft.unsignedMinMax(v,
uint64(bits.Len16(uint16(a.umin))),
uint64(bits.Len16(uint16(a.umax))))
case OpBitLen8:
a := ft.limits[v.Args[0].ID]
return ft.unsignedMinMax(v,
uint64(bits.Len8(uint8(a.umin))),
uint64(bits.Len8(uint8(a.umax))))
// Masks.
case OpAnd64, OpAnd32, OpAnd16, OpAnd8:
// AND can only make the value smaller.

View File

@ -8,7 +8,10 @@
package main
import "math"
import (
"math"
"math/bits"
)
func f0(a []int) int {
a[0] = 1
@ -1193,6 +1196,103 @@ func f22(b bool, x, y int) int {
return 0
}
func bitLen64(x uint64, ensureBothBranchesCouldHappen bool) int {
const max = math.MaxUint64
sz := bits.Len64(max)
if x >= max>>3 {
return 42
}
if x <= max>>6 {
return 42
}
y := bits.Len64(x)
if ensureBothBranchesCouldHappen {
if sz-6 <= y && y <= sz-3 { // ERROR "Proved Leq64$"
return -42
}
} else {
if y < sz-6 || sz-3 < y { // ERROR "Disproved Less64$"
return 1337
}
}
return y
}
func bitLen32(x uint32, ensureBothBranchesCouldHappen bool) int {
const max = math.MaxUint32
sz := bits.Len32(max)
if x >= max>>3 {
return 42
}
if x <= max>>6 {
return 42
}
y := bits.Len32(x)
if ensureBothBranchesCouldHappen {
if sz-6 <= y && y <= sz-3 { // ERROR "Proved Leq64$"
return -42
}
} else {
if y < sz-6 || sz-3 < y { // ERROR "Disproved Less64$"
return 1337
}
}
return y
}
func bitLen16(x uint16, ensureBothBranchesCouldHappen bool) int {
const max = math.MaxUint16
sz := bits.Len16(max)
if x >= max>>3 {
return 42
}
if x <= max>>6 {
return 42
}
y := bits.Len16(x)
if ensureBothBranchesCouldHappen {
if sz-6 <= y && y <= sz-3 { // ERROR "Proved Leq64$"
return -42
}
} else {
if y < sz-6 || sz-3 < y { // ERROR "Disproved Less64$"
return 1337
}
}
return y
}
func bitLen8(x uint8, ensureBothBranchesCouldHappen bool) int {
const max = math.MaxUint8
sz := bits.Len8(max)
if x >= max>>3 {
return 42
}
if x <= max>>6 {
return 42
}
y := bits.Len8(x)
if ensureBothBranchesCouldHappen {
if sz-6 <= y && y <= sz-3 { // ERROR "Proved Leq64$"
return -42
}
} else {
if y < sz-6 || sz-3 < y { // ERROR "Disproved Less64$"
return 1337
}
}
return y
}
//go:noinline
func useInt(a int) {
}