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]
}
return z
}
+func mod64sPositiveWithSmallerDividendMax(a, b int64, ensureBothBranchesCouldHappen bool) int64 {
+ if a < 0 || b < 0 {
+ return 42
+ }
+ a &= 0xff
+ b &= 0xfff
+
+ z := a % b // ERROR "Proved Mod64 does not need fix-up$"
+
+ if ensureBothBranchesCouldHappen {
+ if z > 0xff { // ERROR "Disproved Less64$"
+ return 42
+ }
+ } else {
+ if z <= 0xff { // ERROR "Proved Leq64$"
+ return 1337
+ }
+ }
+ return z
+}
+func mod64sPositiveWithSmallerDivisorMax(a, b int64, ensureBothBranchesCouldHappen bool) int64 {
+ if a < 0 || b < 0 {
+ return 42
+ }
+ a &= 0xfff
+ b &= 0xff
+
+ z := a % b // ERROR "Proved Mod64 does not need fix-up$"
+
+ if ensureBothBranchesCouldHappen {
+ if z > 0xff-1 { // ERROR "Disproved Less64$"
+ return 42
+ }
+ } else {
+ if z <= 0xff-1 { // ERROR "Proved Leq64$"
+ return 1337
+ }
+ }
+ return z
+}
+func mod64sPositiveWithIdenticalMax(a, b int64, ensureBothBranchesCouldHappen bool) int64 {
+ if a < 0 || b < 0 {
+ return 42
+ }
+ a &= 0xfff
+ b &= 0xfff
+
+ z := a % b // ERROR "Proved Mod64 does not need fix-up$"
+
+ if ensureBothBranchesCouldHappen {
+ if z > 0xfff-1 { // ERROR "Disproved Less64$"
+ return 42
+ }
+ } else {
+ if z <= 0xfff-1 { // ERROR "Proved Leq64$"
+ return 1337
+ }
+ }
+ return z
+}
func div64u(a, b uint64, ensureAllBranchesCouldHappen func() bool) uint64 {
a &= 0xffff
}
return z
}
+func div64s(a, b int64, ensureAllBranchesCouldHappen func() bool) int64 {
+ if a < 0 || b < 0 {
+ return 42
+ }
+ a &= 0xffff
+ a |= 0xfff
+ b &= 0xff
+ b |= 0xf
+
+ z := a / b // ERROR "(Proved Div64 does not need fix-up|Proved Neq64)$"
+
+ if ensureAllBranchesCouldHappen() && z > 0xffff/0xf { // ERROR "Disproved Less64$"
+ return 42
+ }
+ if ensureAllBranchesCouldHappen() && z <= 0xffff/0xf { // ERROR "Proved Leq64$"
+ return 1337
+ }
+ if ensureAllBranchesCouldHappen() && z < 0xfff/0xff { // ERROR "Disproved Less64$"
+ return 42
+ }
+ if ensureAllBranchesCouldHappen() && z >= 0xfff/0xff { // ERROR "Proved Leq64$"
+ return 42
+ }
+ return z
+}
//go:noinline
func useInt(a int) {