diff options
| author | Jonah Uellenberg <JonahUellenberg@gmail.com> | 2026-01-29 19:45:27 +0000 |
|---|---|---|
| committer | Gopher Robot <gobot@golang.org> | 2026-01-29 14:08:19 -0800 |
| commit | 14a4cb13e389d8dbc1ba3ba0097e208f1436a22a (patch) | |
| tree | cc5cc4779a33f574f50b52e80571590c7ca324b2 /src/cmd | |
| parent | ee7a2119ac17ea2a6bbf12b4c8001bf39c388166 (diff) | |
| download | go-14a4cb13e389d8dbc1ba3ba0097e208f1436a22a.tar.xz | |
cmd/compile: make prove use non-equality in subtraction for a stronger bound
Given:
s := /* slice */
k := /* proved valid index in s (0 <= k < len(s)) */
v := s[k:]
len(v) >= 1, so v[0] needs no bounds check. However, for
len(v) = len(s) - k, we only checked if len(s) >= k and so could only
prove len(v) >= 0, thus the bounds check wasn't removed.
As far as I can tell these checks were commented out for performance,
but after benchmarking prove I see no difference.
Fixes: #76429
Change-Id: I39ba2a18cbabc0559924d4d226dcb99dbe9a06ed
GitHub-Last-Rev: 53f3344d261986cd021c8d7b8435ab89b5438b8f
GitHub-Pull-Request: golang/go#76609
Reviewed-on: https://go-review.googlesource.com/c/go/+/725100
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Keith Randall <khr@google.com>
Auto-Submit: Keith Randall <khr@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Diffstat (limited to 'src/cmd')
| -rw-r--r-- | src/cmd/compile/internal/ssa/prove.go | 24 |
1 files changed, 11 insertions, 13 deletions
diff --git a/src/cmd/compile/internal/ssa/prove.go b/src/cmd/compile/internal/ssa/prove.go index c9f75daa67..1083874100 100644 --- a/src/cmd/compile/internal/ssa/prove.go +++ b/src/cmd/compile/internal/ssa/prove.go @@ -2187,24 +2187,22 @@ func (ft *factsTable) detectSubRelations(v *Value) { return // x-y might overflow } - // Subtracting a positive number only makes - // things smaller. - if yLim.min >= 0 { + // Subtracting a positive non-zero number only makes + // things smaller. If it's positive or zero, it might + // also do nothing (x-0 == v). + if yLim.min > 0 { + ft.update(v.Block, v, x, signed, lt) + } else if yLim.min == 0 { ft.update(v.Block, v, x, signed, lt|eq) - // TODO: is this worth it? - //if yLim.min > 0 { - // ft.update(v.Block, v, x, signed, lt) - //} } // Subtracting a number from a bigger one - // can't go below 0. - if ft.orderS.OrderedOrEqual(y, x) { + // can't go below 1. If the numbers might be + // equal, then it can't go below 0. + if ft.orderS.Ordered(y, x) { + ft.signedMin(v, 1) + } else if ft.orderS.OrderedOrEqual(y, x) { ft.setNonNegative(v) - // TODO: is this worth it? - //if ft.orderS.Ordered(y, x) { - // ft.signedMin(v, 1) - //} } } |
