}
}
+func signedAddOverflowsOrUnderflows(a, b int64, t *types.Type) bool {
+ r := a + b
+ switch t.Size() {
+ case 8:
+ return (a >= 0 && b >= 0 && r < 0) || (a < 0 && b < 0 && r >= 0)
+ case 4:
+ return r < math.MinInt32 || math.MaxInt32 < r
+ case 2:
+ return r < math.MinInt16 || math.MaxInt16 < r
+ case 1:
+ return r < math.MinInt8 || math.MaxInt8 < r
+ default:
+ panic("unreachable")
+ }
+}
+
func addLocalFacts(ft *factsTable, b *Block) {
// Propagate constant ranges among values in this block.
// We do this before the second loop so that we have the
}
ft.update(b, v, v.Args[0], unsigned, r)
}
+ if x.min >= 0 && !signedAddOverflowsOrUnderflows(x.max, y.max, v.Type) {
+ r := gt
+ if !x.nonzero() {
+ r |= eq
+ }
+ ft.update(b, v, v.Args[1], signed, r)
+ }
+ if y.min >= 0 && !signedAddOverflowsOrUnderflows(x.max, y.max, v.Type) {
+ r := gt
+ if !y.nonzero() {
+ r |= eq
+ }
+ ft.update(b, v, v.Args[0], signed, r)
+ }
case OpAnd64, OpAnd32, OpAnd16, OpAnd8:
ft.update(b, v, v.Args[0], unsigned, lt|eq)
ft.update(b, v, v.Args[1], unsigned, lt|eq)
}
}
+func transitiveProofsThroughNonOverflowingSignedAddPositive(x, y, z int64) {
+ x &= 1<<62 - 1
+ y &= 1<<62 - 1
+
+ a := x + y
+ if a > z {
+ return
+ }
+
+ if x > z { // ERROR "Disproved Less64$"
+ return
+ }
+ if y > z { // ERROR "Disproved Less64$"
+ return
+ }
+ if a == x {
+ return
+ }
+ if a == y {
+ return
+ }
+
+ x |= 1
+ y |= 1
+ a = x + y
+ if a == x { // ERROR "Disproved Eq64$"
+ return
+ }
+ if a == y { // ERROR "Disproved Eq64$"
+ return
+ }
+}
+
+func transitiveProofsThroughOverflowingSignedAddPositive(x, y, z int64) {
+ if x < 0 || y < 0 {
+ return
+ }
+
+ a := x + y
+ if a > z {
+ return
+ }
+
+ if x > z {
+ return
+ }
+ if y > z {
+ return
+ }
+ if a == x {
+ return
+ }
+ if a == y {
+ return
+ }
+
+ x |= 1
+ y |= 1
+ a = x + y
+ if a == x { // ERROR "Disproved Eq64$"
+ return
+ }
+ if a == y { // ERROR "Disproved Eq64$"
+ return
+ }
+}
+
//go:noinline
func useInt(a int) {
}
package main
func f0i(x int) int {
- if x == 20 {
- return x // ERROR "Proved.+is constant 20$"
- }
+ if x == 20 {
+ return x // ERROR "Proved.+is constant 20$"
+ }
- if (x + 20) == 20 {
- return x + 5 // ERROR "Proved.+is constant 0$" "Proved.+is constant 5$"
- }
+ if (x + 20) == 20 {
+ return x + 5 // ERROR "Proved.+is constant 0$" "Proved.+is constant 5$" "x\+d >=? w"
+ }
- return x / 2
+ return x / 2
}
func f0u(x uint) uint {
- if x == 20 {
- return x // ERROR "Proved.+is constant 20$"
- }
+ if x == 20 {
+ return x // ERROR "Proved.+is constant 20$"
+ }
- if (x + 20) == 20 {
- return x + 5 // ERROR "Proved.+is constant 0$" "Proved.+is constant 5$"
- }
+ if (x + 20) == 20 {
+ return x + 5 // ERROR "Proved.+is constant 0$" "Proved.+is constant 5$" "x\+d >=? w"
+ }
- return x / 2
+ return x / 2
}