aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile
diff options
context:
space:
mode:
authorJorropo <jorropo.pgm@gmail.com>2025-07-04 09:23:21 +0200
committerGopher Robot <gobot@golang.org>2025-07-24 13:48:59 -0700
commit1a72920f0907259ca9c8fa73679242ca9774e353 (patch)
treea599821b20511ebdf837c652ec0eb0f9ecdadce3 /src/cmd/compile
parente5f202bb60b246a7aee2a14b95ca399fd243accd (diff)
downloadgo-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.go30
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)