From 20c9377e47706d558e55a29eb5370ef2407a081b Mon Sep 17 00:00:00 2001 From: David Chase Date: Wed, 17 Sep 2025 14:25:16 -0400 Subject: [PATCH] cmd/compile: enhance the chunked indexing case to include reslicing this helps SIMD, but also helps plain old Go Cherry-picked from the dev.simd branch. This CL is not necessarily SIMD specific. Apply early to reduce risk. Change-Id: Idcdacd54b6776f5c32b497bc94485052611cfa8d Reviewed-on: https://go-review.googlesource.com/c/go/+/704756 Reviewed-by: Keith Randall Reviewed-by: Keith Randall LUCI-TryBot-Result: Go LUCI Reviewed-on: https://go-review.googlesource.com/c/go/+/708862 Reviewed-by: David Chase --- src/cmd/compile/internal/ssa/prove.go | 34 ++++++++++++++++++++------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/src/cmd/compile/internal/ssa/prove.go b/src/cmd/compile/internal/ssa/prove.go index 7b860a6f9e..b1d49812c7 100644 --- a/src/cmd/compile/internal/ssa/prove.go +++ b/src/cmd/compile/internal/ssa/prove.go @@ -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) } -- 2.52.0