]> Cypherpunks repositories - gostls13.git/commit
cmd/compile: improve equality algs for arrays of interfaces
authorJosh Bleecher Snyder <josharian@gmail.com>
Fri, 24 Apr 2020 22:59:17 +0000 (15:59 -0700)
committerJosh Bleecher Snyder <josharian@gmail.com>
Mon, 27 Apr 2020 17:19:48 +0000 (17:19 +0000)
commit7eab9506c92562fe49861597e7bf1fcb28f2fd40
tree0a3a9728bd88bb3e26041feeb3243a958064def1
parent1cc7be89a94951cbd1b6db669cb5a278e7aea545
cmd/compile: improve equality algs for arrays of interfaces

type T [8]interface{}

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

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

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

We now generate:

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

The use of a named return value and a bare return is to work
around some typechecking problems that stymied me.

The structure of using equals and else (instead of not equals and then)
was for implementation convenience and clarity. As a bonus,
it generates slightly shorter code on AMD64, because zeroing a register
to return is cheaper than writing $1 to it.

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: I5b2c8dd3384852f085c4f3e1f6ad20bc5ae59062
Reviewed-on: https://go-review.googlesource.com/c/go/+/230208
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