cmd/compile: propagate unsigned limits for Div and Mod if arguments are positive

I didn't implemented negative limits since prove is most useful for BCE which
should never be negative in the first place.

Change-Id: I302ee462cdc20bd4edff0618f7e49ff66fc2a007
Reviewed-on: https://go-review.googlesource.com/c/go/+/605136
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Keith Randall <khr@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Cherry Mui <cherryyz@google.com>
This commit is contained in:
Jorropo 2024-08-13 18:40:44 +02:00 committed by Keith Randall
parent d91a2e5b11
commit 68c431e89f
2 changed files with 101 additions and 0 deletions

View file

@ -1775,11 +1775,27 @@ func (ft *factsTable) flowLimit(v *Value) bool {
a := ft.limits[v.Args[0].ID]
b := ft.limits[v.Args[1].ID]
return ft.newLimit(v, a.mul(b.exp2(8), 8))
case OpMod64, OpMod32, OpMod16, OpMod8:
a := ft.limits[v.Args[0].ID]
b := ft.limits[v.Args[1].ID]
if !(a.nonnegative() && b.nonnegative()) {
// TODO: we could handle signed limits but I didn't bother.
break
}
fallthrough
case OpMod64u, OpMod32u, OpMod16u, OpMod8u:
a := ft.limits[v.Args[0].ID]
b := ft.limits[v.Args[1].ID]
// Underflow in the arithmetic below is ok, it gives to MaxUint64 which does nothing to the limit.
return ft.unsignedMax(v, minU(a.umax, b.umax-1))
case OpDiv64, OpDiv32, OpDiv16, OpDiv8:
a := ft.limits[v.Args[0].ID]
b := ft.limits[v.Args[1].ID]
if !(a.nonnegative() && b.nonnegative()) {
// TODO: we could handle signed limits but I didn't bother.
break
}
fallthrough
case OpDiv64u, OpDiv32u, OpDiv16u, OpDiv8u:
a := ft.limits[v.Args[0].ID]
b := ft.limits[v.Args[1].ID]