diff options
| author | Jorropo <jorropo.pgm@gmail.com> | 2025-07-04 09:23:21 +0200 |
|---|---|---|
| committer | Gopher Robot <gobot@golang.org> | 2025-07-24 13:48:59 -0700 |
| commit | 1a72920f0907259ca9c8fa73679242ca9774e353 (patch) | |
| tree | a599821b20511ebdf837c652ec0eb0f9ecdadce3 /src/cmd/compile | |
| parent | e5f202bb60b246a7aee2a14b95ca399fd243accd (diff) | |
| download | go-1a72920f0907259ca9c8fa73679242ca9774e353.tar.xz | |
cmd/compile: learn transitive proofs for safe positive signed adds
I've split this into it's own CL to make git bisect more effective.
Change-Id: I3fbb42ec7d29169a29f7f55ef2c188317512f532
Reviewed-on: https://go-review.googlesource.com/c/go/+/685819
Auto-Submit: Michael Knyszek <mknyszek@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Keith Randall <khr@google.com>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Diffstat (limited to 'src/cmd/compile')
| -rw-r--r-- | src/cmd/compile/internal/ssa/prove.go | 30 |
1 files changed, 30 insertions, 0 deletions
diff --git a/src/cmd/compile/internal/ssa/prove.go b/src/cmd/compile/internal/ssa/prove.go index 8fe1bb7050..da42a675bf 100644 --- a/src/cmd/compile/internal/ssa/prove.go +++ b/src/cmd/compile/internal/ssa/prove.go @@ -2148,6 +2148,22 @@ func unsignedAddOverflows(a, b uint64, t *types.Type) bool { } } +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 @@ -2182,6 +2198,20 @@ func addLocalFacts(ft *factsTable, b *Block) { } 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) |
