Commit 91b1f7cb authored by Russ Cox's avatar Russ Cox

cmd/gc: handle variable initialization by block move in liveness

Any initialization of a variable by a block copy or block zeroing
or by multiple assignments (componentwise copying or zeroing
of a multiword variable) needs to emit a VARDEF. These cases were not.

Fixes #7205.

TBR=iant
CC=golang-codereviews
https://golang.org/cl/63650044
parent 7addda68
...@@ -1414,6 +1414,7 @@ sgen(Node *n, Node *res, int64 w) ...@@ -1414,6 +1414,7 @@ sgen(Node *n, Node *res, int64 w)
int32 c, odst, osrc; int32 c, odst, osrc;
int dir, align, op; int dir, align, op;
Prog *p, *ploop; Prog *p, *ploop;
NodeList *l;
if(debug['g']) { if(debug['g']) {
print("\nsgen w=%lld\n", w); print("\nsgen w=%lld\n", w);
...@@ -1439,6 +1440,17 @@ sgen(Node *n, Node *res, int64 w) ...@@ -1439,6 +1440,17 @@ sgen(Node *n, Node *res, int64 w)
return; return;
} }
// Record site of definition of ns for liveness analysis.
if(res->op == ONAME && res->class != PEXTERN)
gvardef(res);
// If copying .args, that's all the results, so record definition sites
// for them for the liveness analysis.
if(res->op == ONAME && strcmp(res->sym->name, ".args") == 0)
for(l = curfn->dcl; l != nil; l = l->next)
if(l->n->class == PPARAMOUT)
gvardef(l->n);
// Avoid taking the address for simple enough types. // Avoid taking the address for simple enough types.
if(componentgen(n, res)) if(componentgen(n, res))
return; return;
......
...@@ -1337,6 +1337,7 @@ sgen(Node *n, Node *ns, int64 w) ...@@ -1337,6 +1337,7 @@ sgen(Node *n, Node *ns, int64 w)
{ {
Node nodl, nodr, nodsi, noddi, cx, oldcx, tmp; Node nodl, nodr, nodsi, noddi, cx, oldcx, tmp;
vlong c, q, odst, osrc; vlong c, q, odst, osrc;
NodeList *l;
if(debug['g']) { if(debug['g']) {
print("\nsgen w=%lld\n", w); print("\nsgen w=%lld\n", w);
...@@ -1350,6 +1351,17 @@ sgen(Node *n, Node *ns, int64 w) ...@@ -1350,6 +1351,17 @@ sgen(Node *n, Node *ns, int64 w)
if(w < 0) if(w < 0)
fatal("sgen copy %lld", w); fatal("sgen copy %lld", w);
// Record site of definition of ns for liveness analysis.
if(ns->op == ONAME && ns->class != PEXTERN)
gvardef(ns);
// If copying .args, that's all the results, so record definition sites
// for them for the liveness analysis.
if(ns->op == ONAME && strcmp(ns->sym->name, ".args") == 0)
for(l = curfn->dcl; l != nil; l = l->next)
if(l->n->class == PPARAMOUT)
gvardef(l->n);
// Avoid taking the address for simple enough types. // Avoid taking the address for simple enough types.
if(componentgen(n, ns)) if(componentgen(n, ns))
return; return;
......
...@@ -1203,6 +1203,7 @@ sgen(Node *n, Node *res, int64 w) ...@@ -1203,6 +1203,7 @@ sgen(Node *n, Node *res, int64 w)
{ {
Node dst, src, tdst, tsrc; Node dst, src, tdst, tsrc;
int32 c, q, odst, osrc; int32 c, q, odst, osrc;
NodeList *l;
if(debug['g']) { if(debug['g']) {
print("\nsgen w=%lld\n", w); print("\nsgen w=%lld\n", w);
...@@ -1223,6 +1224,17 @@ sgen(Node *n, Node *res, int64 w) ...@@ -1223,6 +1224,17 @@ sgen(Node *n, Node *res, int64 w)
return; return;
} }
// Record site of definition of ns for liveness analysis.
if(res->op == ONAME && res->class != PEXTERN)
gvardef(res);
// If copying .args, that's all the results, so record definition sites
// for them for the liveness analysis.
if(res->op == ONAME && strcmp(res->sym->name, ".args") == 0)
for(l = curfn->dcl; l != nil; l = l->next)
if(l->n->class == PPARAMOUT)
gvardef(l->n);
// Avoid taking the address for simple enough types. // Avoid taking the address for simple enough types.
if(componentgen(n, res)) if(componentgen(n, res))
return; return;
......
...@@ -34,8 +34,8 @@ makefuncdatasym(char *namefmt, int64 funcdatakind) ...@@ -34,8 +34,8 @@ makefuncdatasym(char *namefmt, int64 funcdatakind)
void void
gvardef(Node *n) gvardef(Node *n)
{ {
if(n == N || !isfat(n->type)) if(n == N)
fatal("gvardef: node is not fat"); fatal("gvardef nil");
switch(n->class) { switch(n->class) {
case PAUTO: case PAUTO:
case PPARAM: case PPARAM:
......
...@@ -621,7 +621,7 @@ freecfg(Array *cfg) ...@@ -621,7 +621,7 @@ freecfg(Array *cfg)
static int static int
isfunny(Node *node) isfunny(Node *node)
{ {
char *names[] = { ".fp", ".args", "_", nil }; char *names[] = { ".fp", ".args", nil };
int i; int i;
if(node->sym != nil && node->sym->name != nil) if(node->sym != nil && node->sym->name != nil)
...@@ -696,8 +696,8 @@ progeffects(Prog *prog, Array *vars, Bvec *uevar, Bvec *varkill, Bvec *avarinit) ...@@ -696,8 +696,8 @@ progeffects(Prog *prog, Array *vars, Bvec *uevar, Bvec *varkill, Bvec *avarinit)
} }
if(info.flags & (LeftRead | LeftWrite | LeftAddr)) { if(info.flags & (LeftRead | LeftWrite | LeftAddr)) {
from = &prog->from; from = &prog->from;
if (from->node != nil && !isfunny(from->node) && from->sym != nil) { if (from->node != nil && from->sym != nil) {
switch(prog->from.node->class & ~PHEAP) { switch(from->node->class & ~PHEAP) {
case PAUTO: case PAUTO:
case PPARAM: case PPARAM:
case PPARAMOUT: case PPARAMOUT:
...@@ -710,7 +710,7 @@ progeffects(Prog *prog, Array *vars, Bvec *uevar, Bvec *varkill, Bvec *avarinit) ...@@ -710,7 +710,7 @@ progeffects(Prog *prog, Array *vars, Bvec *uevar, Bvec *varkill, Bvec *avarinit)
if(info.flags & (LeftRead | LeftAddr)) if(info.flags & (LeftRead | LeftAddr))
bvset(uevar, pos); bvset(uevar, pos);
if(info.flags & LeftWrite) if(info.flags & LeftWrite)
if(from->node != nil && (!isfat(from->node->type) || prog->as == AVARDEF)) if(from->node != nil && !isfat(from->node->type))
bvset(varkill, pos); bvset(varkill, pos);
} }
} }
...@@ -719,8 +719,8 @@ progeffects(Prog *prog, Array *vars, Bvec *uevar, Bvec *varkill, Bvec *avarinit) ...@@ -719,8 +719,8 @@ progeffects(Prog *prog, Array *vars, Bvec *uevar, Bvec *varkill, Bvec *avarinit)
Next: Next:
if(info.flags & (RightRead | RightWrite | RightAddr)) { if(info.flags & (RightRead | RightWrite | RightAddr)) {
to = &prog->to; to = &prog->to;
if (to->node != nil && to->sym != nil && !isfunny(to->node)) { if (to->node != nil && to->sym != nil) {
switch(prog->to.node->class & ~PHEAP) { switch(to->node->class & ~PHEAP) {
case PAUTO: case PAUTO:
case PPARAM: case PPARAM:
case PPARAMOUT: case PPARAMOUT:
...@@ -728,10 +728,9 @@ Next: ...@@ -728,10 +728,9 @@ Next:
if(pos == -1) if(pos == -1)
goto Next1; goto Next1;
if(to->node->addrtaken) { if(to->node->addrtaken) {
//if(prog->as == AKILL)
// bvset(varkill, pos);
//else
bvset(avarinit, pos); bvset(avarinit, pos);
if(prog->as == AVARDEF)
bvset(varkill, pos);
} else { } else {
if(info.flags & (RightRead | RightAddr)) if(info.flags & (RightRead | RightAddr))
bvset(uevar, pos); bvset(uevar, pos);
......
...@@ -95,3 +95,21 @@ func f7() (x string) { ...@@ -95,3 +95,21 @@ func f7() (x string) {
return return
} }
// ignoring block returns used to cause "live at entry to f8: x, y".
func f8() (x, y string) {
return g8()
}
func g8() (string, string)
// ignoring block assignments used to cause "live at entry to f9: x"
// issue 7205
var i9 interface{}
func f9() bool {
g8()
x := i9
return x != 99
}
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