]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.simd] cmd/compile: enhance the chunked indexing case to include reslicing
authorDavid Chase <drchase@google.com>
Wed, 17 Sep 2025 18:25:16 +0000 (14:25 -0400)
committerDavid Chase <drchase@google.com>
Fri, 19 Sep 2025 14:21:03 +0000 (07:21 -0700)
this helps SIMD, but also helps plain old Go

Change-Id: Idcdacd54b6776f5c32b497bc94485052611cfa8d
Reviewed-on: https://go-review.googlesource.com/c/go/+/704756
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Keith Randall <khr@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>

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

index 7b860a6f9ea2b0a6fe5400fccf70f8e1cc6ad46a..b1d49812c7d353177528c9224b67eb543efded49 100644 (file)
@@ -2177,10 +2177,18 @@ func unsignedSubUnderflows(a, b uint64) bool {
 // checkForChunkedIndexBounds looks for index expressions of the form
 // A[i+delta] where delta < K and i <= len(A)-K.  That is, this is a chunked
 // iteration where the index is not directly compared to the length.
-func checkForChunkedIndexBounds(ft *factsTable, b *Block, index, bound *Value) bool {
-       if bound.Op != OpSliceLen {
+// if isReslice, then delta can be equal to K.
+func checkForChunkedIndexBounds(ft *factsTable, b *Block, index, bound *Value, isReslice bool) bool {
+       if bound.Op != OpSliceLen && bound.Op != OpSliceCap {
                return false
        }
+
+       // this is a slice bounds check against len or capacity,
+       // and refers back to a prior check against length, which
+       // will also work for the cap since that is not smaller
+       // than the length.
+
+       slice := bound.Args[0]
        lim := ft.limits[index.ID]
        if lim.min < 0 {
                return false
@@ -2206,9 +2214,9 @@ func checkForChunkedIndexBounds(ft *factsTable, b *Block, index, bound *Value) b
                }
                if ow := o.w; ow.Op == OpAdd64 {
                        var lenOffset *Value
-                       if ow.Args[0] == bound {
+                       if bound := ow.Args[0]; bound.Op == OpSliceLen && bound.Args[0] == slice {
                                lenOffset = ow.Args[1]
-                       } else if ow.Args[1] == bound {
+                       } else if bound := ow.Args[1]; bound.Op == OpSliceLen && bound.Args[0] == slice {
                                lenOffset = ow.Args[0]
                        }
                        if lenOffset == nil || lenOffset.Op != OpConst64 {
@@ -2216,12 +2224,15 @@ func checkForChunkedIndexBounds(ft *factsTable, b *Block, index, bound *Value) b
                        }
                        if K := -lenOffset.AuxInt; K >= 0 {
                                or := o.r
+                               if isReslice {
+                                       K++
+                               }
                                if or == lt {
                                        or = lt | eq
                                        K++
-                                       if K < 0 {
-                                               continue
-                                       }
+                               }
+                               if K < 0 { // We hate thinking about overflow
+                                       continue
                                }
 
                                if delta < K && or == lt|eq {
@@ -2345,12 +2356,19 @@ func addLocalFacts(ft *factsTable, b *Block) {
                                ft.update(b, v, v.Args[0].Args[2], signed, eq)
                        }
                case OpIsInBounds:
-                       if checkForChunkedIndexBounds(ft, b, v.Args[0], v.Args[1]) {
+                       if checkForChunkedIndexBounds(ft, b, v.Args[0], v.Args[1], false) {
                                if b.Func.pass.debug > 0 {
                                        b.Func.Warnl(v.Pos, "Proved %s for blocked indexing", v.Op)
                                }
                                ft.booleanTrue(v)
                        }
+               case OpIsSliceInBounds:
+                       if checkForChunkedIndexBounds(ft, b, v.Args[0], v.Args[1], true) {
+                               if b.Func.pass.debug > 0 {
+                                       b.Func.Warnl(v.Pos, "Proved %s for blocked reslicing", v.Op)
+                               }
+                               ft.booleanTrue(v)
+                       }
                case OpPhi:
                        addLocalFactsPhi(ft, v)
                }