mirror of
https://github.com/golang/go.git
synced 2025-10-19 11:03:18 +00:00
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 <khr@golang.org> Reviewed-by: Keith Randall <khr@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-on: https://go-review.googlesource.com/c/go/+/708862 Reviewed-by: David Chase <drchase@google.com>
This commit is contained in:
parent
ad3db2562e
commit
20c9377e47
1 changed files with 26 additions and 8 deletions
|
@ -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)
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue