Skip to content

Commit f32cf8e

Browse files
Jorropogopherbot
authored andcommitted
cmd/compile: learn transitive proofs for safe unsigned subs
I've split this into it's own CL to make git bisect more effective. Change-Id: I436ff21a3e2362b3924de25a458534eb9947e013 Reviewed-on: https://go-review.googlesource.com/c/go/+/685821 Reviewed-by: Keith Randall <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]> Reviewed-by: Keith Randall <[email protected]> Reviewed-by: Michael Knyszek <[email protected]> Auto-Submit: Michael Knyszek <[email protected]>
1 parent d574856 commit f32cf8e

File tree

2 files changed

+76
-0
lines changed

2 files changed

+76
-0
lines changed

src/cmd/compile/internal/ssa/prove.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2164,6 +2164,10 @@ func signedAddOverflowsOrUnderflows(a, b int64, t *types.Type) bool {
21642164
}
21652165
}
21662166

2167+
func unsignedSubUnderflows(a, b uint64) bool {
2168+
return a < b
2169+
}
2170+
21672171
func addLocalFacts(ft *factsTable, b *Block) {
21682172
// Propagate constant ranges among values in this block.
21692173
// We do this before the second loop so that we have the
@@ -2226,6 +2230,17 @@ func addLocalFacts(ft *factsTable, b *Block) {
22262230
}
22272231
ft.update(b, v, v.Args[0], signed, r)
22282232
}
2233+
case OpSub64, OpSub32, OpSub16, OpSub8:
2234+
x := ft.limits[v.Args[0].ID]
2235+
y := ft.limits[v.Args[1].ID]
2236+
if !unsignedSubUnderflows(x.umin, y.umax) {
2237+
r := lt
2238+
if !y.nonzero() {
2239+
r |= eq
2240+
}
2241+
ft.update(b, v, v.Args[0], unsigned, r)
2242+
}
2243+
// FIXME: we could also do signed facts but the overflow checks are much trickier and I don't need it yet.
22292244
case OpAnd64, OpAnd32, OpAnd16, OpAnd8:
22302245
ft.update(b, v, v.Args[0], unsigned, lt|eq)
22312246
ft.update(b, v, v.Args[1], unsigned, lt|eq)

test/prove.go

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2241,6 +2241,67 @@ func transitiveProofsThroughOverflowingSignedAddNegative(x, y, z int64) {
22412241
}
22422242
}
22432243

2244+
func transitiveProofsThroughNonOverflowingUnsignedSub(x, y, z uint64) {
2245+
x |= 0xfff
2246+
y &= 0xfff
2247+
2248+
a := x - y
2249+
if a < z {
2250+
return
2251+
}
2252+
2253+
if x < z { // ERROR "Disproved Less64U$"
2254+
return
2255+
}
2256+
if y < z {
2257+
return
2258+
}
2259+
if a == x {
2260+
return
2261+
}
2262+
if a == y {
2263+
return
2264+
}
2265+
2266+
y |= 1
2267+
a = x - y
2268+
if a == x { // ERROR "Disproved Eq64$"
2269+
return
2270+
}
2271+
if a == y {
2272+
return
2273+
}
2274+
}
2275+
2276+
func transitiveProofsThroughOverflowingUnsignedSub(x, y, z uint64) {
2277+
a := x - y
2278+
if a < z {
2279+
return
2280+
}
2281+
2282+
if x < z {
2283+
return
2284+
}
2285+
if y < z {
2286+
return
2287+
}
2288+
if a == x {
2289+
return
2290+
}
2291+
if a == y {
2292+
return
2293+
}
2294+
2295+
y |= 1
2296+
a = x - y
2297+
if a == x {
2298+
return
2299+
}
2300+
if a == y {
2301+
return
2302+
}
2303+
}
2304+
22442305
//go:noinline
22452306
func useInt(a int) {
22462307
}

0 commit comments

Comments
 (0)