Commit 92bf58c2 authored by Josh Bleecher Snyder's avatar Josh Bleecher Snyder

cmd/compile: recognize more memory runs in generated algs

The old implementation assumed that all memory runs
were terminated by non-memory fields.
This isn't necessarily so.
They might be terminated by padding or blank fields.

For example, given

type T struct {
	a int64
	b byte
	c, d, e int64
}

the old implementation did a memory comparison on a+b, on c, and on d+e.

Instead, check for memory runs at the beginning of every round.
This now generates a memory comparison on a+b and on c+d+e.

Also, delete some now-dead code.

Change-Id: I66bffb111420adf6919bd708e4fb3a1e1f07fadd
Reviewed-on: https://go-review.googlesource.com/19841Reviewed-by: 's avatarDavid Crawshaw <crawshaw@golang.org>
parent 0f5d78f6
...@@ -2515,7 +2515,8 @@ func genhash(sym *Sym, t *Type) { ...@@ -2515,7 +2515,8 @@ func genhash(sym *Sym, t *Type) {
var na *Node var na *Node
var hashel *Node var hashel *Node
for t1 := t.Type; ; t1 = t1.Down { t1 := t.Type
for {
first, size, next := memrun(t, t1) first, size, next := memrun(t, t1)
t1 = next t1 = next
...@@ -2539,36 +2540,25 @@ func genhash(sym *Sym, t *Type) { ...@@ -2539,36 +2540,25 @@ func genhash(sym *Sym, t *Type) {
break break
} }
if isblanksym(t1.Sym) { if isblanksym(t1.Sym) {
t1 = t1.Down
continue continue
} }
// Run hash for this field.
if algtype1(t1.Type, nil) == AMEM { if algtype1(t1.Type, nil) == AMEM {
hashel = hashmem(t1.Type) // Our memory run might have been stopped by padding or a blank field.
// If the next field is memory-ish, it could be the start of a new run.
// h = memhash(&p.t1, h, size) continue
call = Nod(OCALL, hashel, nil) }
nx = Nod(OXDOT, np, newname(t1.Sym)) // TODO: fields from other packages?
na = Nod(OADDR, nx, nil)
na.Etype = 1 // no escape to heap
call.List = list(call.List, na)
call.List = list(call.List, nh)
call.List = list(call.List, Nodintconst(t1.Type.Width))
fn.Nbody = list(fn.Nbody, Nod(OAS, nh, call))
} else {
hashel = hashfor(t1.Type)
// h = hashel(&p.t1, h) hashel = hashfor(t1.Type)
call = Nod(OCALL, hashel, nil) call = Nod(OCALL, hashel, nil)
nx = Nod(OXDOT, np, newname(t1.Sym)) // TODO: fields from other packages?
na = Nod(OADDR, nx, nil)
na.Etype = 1 // no escape to heap
call.List = list(call.List, na)
call.List = list(call.List, nh)
fn.Nbody = list(fn.Nbody, Nod(OAS, nh, call))
nx = Nod(OXDOT, np, newname(t1.Sym)) // TODO: fields from other packages? t1 = t1.Down
na = Nod(OADDR, nx, nil)
na.Etype = 1 // no escape to heap
call.List = list(call.List, na)
call.List = list(call.List, nh)
fn.Nbody = list(fn.Nbody, Nod(OAS, nh, call))
}
} }
} }
...@@ -2730,7 +2720,8 @@ func geneq(sym *Sym, t *Type) { ...@@ -2730,7 +2720,8 @@ func geneq(sym *Sym, t *Type) {
case TSTRUCT: case TSTRUCT:
var conjuncts []*Node var conjuncts []*Node
for t1 := t.Type; ; t1 = t1.Down { t1 := t.Type
for {
first, size, next := memrun(t, t1) first, size, next := memrun(t, t1)
t1 = next t1 = next
...@@ -2756,11 +2747,18 @@ func geneq(sym *Sym, t *Type) { ...@@ -2756,11 +2747,18 @@ func geneq(sym *Sym, t *Type) {
break break
} }
if isblanksym(t1.Sym) { if isblanksym(t1.Sym) {
t1 = t1.Down
continue
}
if algtype1(t1.Type, nil) == AMEM {
// Our memory run might have been stopped by padding or a blank field.
// If the next field is memory-ish, it could be the start of a new run.
continue continue
} }
// Check this field, which is not just memory. // Check this field, which is not just memory.
conjuncts = append(conjuncts, eqfield(np, nq, newname(t1.Sym))) conjuncts = append(conjuncts, eqfield(np, nq, newname(t1.Sym)))
t1 = t1.Down
} }
var and *Node var and *Node
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment