]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: improve equality algs for arrays of strings
authorJosh Bleecher Snyder <josharian@gmail.com>
Sat, 25 Apr 2020 22:14:35 +0000 (15:14 -0700)
committerJosh Bleecher Snyder <josharian@gmail.com>
Mon, 27 Apr 2020 17:20:00 +0000 (17:20 +0000)
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>
src/cmd/compile/internal/gc/alg.go

index f6291063a0d0af348478892af4d16cc182c48f54..bda9ab5bff7c53789616eb65ce241736257cc7ab 100644 (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.