1
0
mirror of https://github.com/golang/go synced 2024-11-18 15:54:42 -07:00

cmd/compile: improve equality algs for arrays of strings

type T [8]string

Prior to this change, we generated this equality algorithm for T:

func eqT(p, q *T) (r bool) {
    for i := range *p {
        if p[i] == q[i] {
		} else {
            return
        }
    }
    return true
}

This change splits this into two loops, so that we can do the
cheap (length) half early and only then do the expensive (contents) half.

We now generate:

func eqT(p, q *T) (r bool) {
    for i := range *p {
        if len(p[i]) == len(q[i]) {
        } else {
            return
        }
    }
    for j := range *p {
        if runtime.memeq(p[j].ptr, q[j].ptr, len(p[j])) {
        } else {
            return
        }
    }
    return true
}

The generated code is typically ~17% larger because it contains
two loops instead of one. In the future, we might want to unroll
the first loop when the array is small.

Change-Id: I26b2793b90ec6aff21766a411b15a4ff1096c03f
Reviewed-on: https://go-review.googlesource.com/c/go/+/230209
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
This commit is contained in:
Josh Bleecher Snyder 2020-04-25 15:14:35 -07:00
parent 7eab9506c9
commit 1c4e9b2eda

View File

@ -574,6 +574,20 @@ func geneq(t *types.Type) *obj.LSym {
_, eqdata := eqinterface(pi, qi)
return eqdata
})
case TSTRING:
// Do two loops. First, check that all the lengths match (cheap).
// Second, check that all the contents match (expensive).
// TODO: when the array size is small, unroll the length match checks.
rangedCheck("i", func(pi, qi *Node) *Node {
// Compare lengths.
eqlen, _ := eqstring(pi, qi)
return eqlen
})
rangedCheck("j", func(pi, qi *Node) *Node {
// Compare contents.
_, eqmem := eqstring(pi, qi)
return eqmem
})
default:
// An array of pure memory would be handled by the standard memequal,
// so the element type must not be pure memory.