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: default avatarDavid Crawshaw <crawshaw@golang.org>
parent 0f5d78f6
......@@ -2515,7 +2515,8 @@ func genhash(sym *Sym, t *Type) {
var na *Node
var hashel *Node
for t1 := t.Type; ; t1 = t1.Down {
t1 := t.Type
for {
first, size, next := memrun(t, t1)
t1 = next
......@@ -2539,36 +2540,25 @@ func genhash(sym *Sym, t *Type) {
break
}
if isblanksym(t1.Sym) {
t1 = t1.Down
continue
}
// Run hash for this field.
if algtype1(t1.Type, nil) == AMEM {
hashel = hashmem(t1.Type)
// h = memhash(&p.t1, h, size)
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)
// 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
}
// h = hashel(&p.t1, h)
call = Nod(OCALL, hashel, nil)
hashel = hashfor(t1.Type)
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?
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))
}
t1 = t1.Down
}
}
......@@ -2730,7 +2720,8 @@ func geneq(sym *Sym, t *Type) {
case TSTRUCT:
var conjuncts []*Node
for t1 := t.Type; ; t1 = t1.Down {
t1 := t.Type
for {
first, size, next := memrun(t, t1)
t1 = next
......@@ -2756,11 +2747,18 @@ func geneq(sym *Sym, t *Type) {
break
}
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
}
// Check this field, which is not just memory.
conjuncts = append(conjuncts, eqfield(np, nq, newname(t1.Sym)))
t1 = t1.Down
}
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