mirror of
https://github.com/golang/go
synced 2024-11-25 12:17:56 -07:00
cmd/compile: compute Complement's limits from argument's limits
I was not sure this was correct so I exhaustively checked all possibilities: https://go.dev/play/p/hjmCLm4Iagz https://go.dev/play/p/R9RuRGKwCbN Change-Id: I85f053df825a4d77f978de42f8a1fcaf4b881def Reviewed-on: https://go-review.googlesource.com/c/go/+/605696 Reviewed-by: Keith Randall <khr@golang.org> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: David Chase <drchase@google.com> Reviewed-by: Keith Randall <khr@google.com> Reviewed-by: Carlos Amedee <carlos@golang.org>
This commit is contained in:
parent
4f2c0e5d08
commit
2f3165973f
@ -341,6 +341,42 @@ func (l limit) exp2(b uint) limit {
|
||||
return r
|
||||
}
|
||||
|
||||
// Similar to add, but computes the complement of the limit for bitsize b.
|
||||
func (l limit) com(b uint) limit {
|
||||
switch b {
|
||||
case 64:
|
||||
return limit{
|
||||
min: ^l.max,
|
||||
max: ^l.min,
|
||||
umin: ^l.umax,
|
||||
umax: ^l.umin,
|
||||
}
|
||||
case 32:
|
||||
return limit{
|
||||
min: int64(^int32(l.max)),
|
||||
max: int64(^int32(l.min)),
|
||||
umin: uint64(^uint32(l.umax)),
|
||||
umax: uint64(^uint32(l.umin)),
|
||||
}
|
||||
case 16:
|
||||
return limit{
|
||||
min: int64(^int16(l.max)),
|
||||
max: int64(^int16(l.min)),
|
||||
umin: uint64(^uint16(l.umax)),
|
||||
umax: uint64(^uint16(l.umin)),
|
||||
}
|
||||
case 8:
|
||||
return limit{
|
||||
min: int64(^int8(l.max)),
|
||||
max: int64(^int8(l.min)),
|
||||
umin: uint64(^uint8(l.umax)),
|
||||
umax: uint64(^uint8(l.umin)),
|
||||
}
|
||||
default:
|
||||
panic("unreachable")
|
||||
}
|
||||
}
|
||||
|
||||
var noLimit = limit{math.MinInt64, math.MaxInt64, 0, math.MaxUint64}
|
||||
|
||||
// a limitFact is a limit known for a particular value.
|
||||
@ -1714,6 +1750,9 @@ func (ft *factsTable) flowLimit(v *Value) bool {
|
||||
a := ft.limits[v.Args[0].ID]
|
||||
b := ft.limits[v.Args[1].ID]
|
||||
return ft.unsignedMax(v, 1<<bits.Len64(a.umax|b.umax)-1)
|
||||
case OpCom64, OpCom32, OpCom16, OpCom8:
|
||||
a := ft.limits[v.Args[0].ID]
|
||||
return ft.newLimit(v, a.com(uint(v.Type.Size())*8))
|
||||
|
||||
// Arithmetic.
|
||||
case OpAdd64:
|
||||
|
@ -1606,6 +1606,27 @@ func trunc64to16(a uint64, ensureAllBranchesCouldHappen func() bool) uint16 {
|
||||
return z
|
||||
}
|
||||
|
||||
func com64(a uint64, ensureAllBranchesCouldHappen func() bool) uint64 {
|
||||
a &= 0xffff
|
||||
a |= 0xff
|
||||
|
||||
z := ^a
|
||||
|
||||
if ensureAllBranchesCouldHappen() && z > ^uint64(0xff) { // ERROR "Disproved Less64U$"
|
||||
return 42
|
||||
}
|
||||
if ensureAllBranchesCouldHappen() && z <= ^uint64(0xff) { // ERROR "Proved Leq64U$"
|
||||
return 1337
|
||||
}
|
||||
if ensureAllBranchesCouldHappen() && z < ^uint64(0xffff) { // ERROR "Disproved Less64U$"
|
||||
return 42
|
||||
}
|
||||
if ensureAllBranchesCouldHappen() && z >= ^uint64(0xffff) { // ERROR "Proved Leq64U$"
|
||||
return 1337
|
||||
}
|
||||
return z
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
func useInt(a int) {
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user