summaryrefslogtreecommitdiff
path: root/src/cmd/gc/walk.c
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2014-04-01 20:02:54 -0400
committerRuss Cox <rsc@golang.org>2014-04-01 20:02:54 -0400
commit0c3905a26e145d937c92a7f57ea6e7f395b1d3ad (patch)
tree12890967ffde0a24de6c78a53031fe24e088804c /src/cmd/gc/walk.c
parent279e8ce8518d2d6430c47e995ebbb890b650e835 (diff)
downloadgo-0c3905a26e145d937c92a7f57ea6e7f395b1d3ad.tar.gz
cmd/gc: shorten more temporary lifetimes
1. In functions with heap-allocated result variables or with defer statements, the return sequence requires more than just a single RET instruction. There is an optimization that arranges for all returns to jump to a single copy of the return epilogue in this case. Unfortunately, that optimization is fundamentally incompatible with PC-based liveness information: it takes PCs at many different points in the function and makes them all land at one PC, making the combined liveness information at that target PC a mess. Disable this optimization, so that each return site gets its own copy of the 'call deferreturn' and the copying of result variables back from the heap. This removes quite a few spurious 'ambiguously live' variables. 2. Let orderexpr allocate temporaries that are passed by address to a function call and then die on return, so that we can arrange an appropriate VARKILL. 2a. Do this for ... slices. 2b. Do this for closure structs. 2c. Do this for runtime.concatstring, which is the implementation of large string additions. Change representation of OADDSTR to an explicit list in typecheck to avoid reconstructing list in both walk and order. 3. Let orderexpr allocate the temporary variable copies used for range loops, so that they can be killed when the loop is over. Similarly, let it allocate the temporary holding the map iterator. CL 81940043 reduced the number of ambiguously live temps in the godoc binary from 860 to 711. This CL reduces the number to 121. Still more to do, but another good checkpoint. Update issue 7345 LGTM=khr R=khr CC=golang-codereviews https://codereview.appspot.com/83090046
Diffstat (limited to 'src/cmd/gc/walk.c')
-rw-r--r--src/cmd/gc/walk.c49
1 files changed, 26 insertions, 23 deletions
diff --git a/src/cmd/gc/walk.c b/src/cmd/gc/walk.c
index c9cff289b..876d95530 100644
--- a/src/cmd/gc/walk.c
+++ b/src/cmd/gc/walk.c
@@ -1190,9 +1190,10 @@ walkexpr(Node **np, NodeList **init)
// s + "badgerbadgerbadger" == "badgerbadgerbadger"
if((n->etype == OEQ || n->etype == ONE) &&
isconst(n->right, CTSTR) &&
- n->left->op == OADDSTR && isconst(n->left->right, CTSTR) &&
- cmpslit(n->right, n->left->right) == 0) {
- r = nod(n->etype, nod(OLEN, n->left->left, N), nodintconst(0));
+ n->left->op == OADDSTR && count(n->left->list) == 2 &&
+ isconst(n->left->list->next->n, CTSTR) &&
+ cmpslit(n->right, n->left->list->next->n) == 0) {
+ r = nod(n->etype, nod(OLEN, n->left->list->n, N), nodintconst(0));
typecheck(&r, Erv);
walkexpr(&r, init);
r->type = n->type;
@@ -1535,11 +1536,16 @@ ascompatet(int op, NodeList *nl, Type **nr, int fp, NodeList **init)
* package all the arguments that match a ... T parameter into a []T.
*/
static NodeList*
-mkdotargslice(NodeList *lr0, NodeList *nn, Type *l, int fp, NodeList **init, int esc)
+mkdotargslice(NodeList *lr0, NodeList *nn, Type *l, int fp, NodeList **init, Node *ddd)
{
Node *a, *n;
Type *tslice;
-
+ int esc;
+
+ esc = EscUnknown;
+ if(ddd != nil)
+ esc = ddd->esc;
+
tslice = typ(TARRAY);
tslice->type = l->type->type;
tslice->bound = -1;
@@ -1549,6 +1555,8 @@ mkdotargslice(NodeList *lr0, NodeList *nn, Type *l, int fp, NodeList **init, int
n->type = tslice;
} else {
n = nod(OCOMPLIT, N, typenod(tslice));
+ if(ddd != nil)
+ n->left = ddd->left; // temporary to use
n->list = lr0;
n->esc = esc;
typecheck(&n, Erv);
@@ -1620,7 +1628,6 @@ dumpnodetypes(NodeList *l, char *what)
static NodeList*
ascompatte(int op, Node *call, int isddd, Type **nl, NodeList *lr, int fp, NodeList **init)
{
- int esc;
Type *l, *ll;
Node *r, *a;
NodeList *nn, *lr0, *alist;
@@ -1683,10 +1690,7 @@ loop:
// normal case -- make a slice of all
// remaining arguments and pass it to
// the ddd parameter.
- esc = EscUnknown;
- if(call->right)
- esc = call->right->esc;
- nn = mkdotargslice(lr, nn, l, fp, init, esc);
+ nn = mkdotargslice(lr, nn, l, fp, init, call->right);
goto ret;
}
@@ -2504,26 +2508,24 @@ static Node*
addstr(Node *n, NodeList **init)
{
Node *r, *cat, *slice;
- NodeList *args;
- int count;
+ NodeList *args, *l;
+ int c;
Type *t;
- count = 0;
- for(r=n; r->op == OADDSTR; r=r->left)
- count++; // r->right
- count++; // r
- if(count < 2)
- yyerror("addstr count %d too small", count);
+ // orderexpr rewrote OADDSTR to have a list of strings.
+ c = count(n->list);
+ if(c < 2)
+ yyerror("addstr count %d too small", c);
// build list of string arguments
args = nil;
- for(r=n; r->op == OADDSTR; r=r->left)
- args = concat(list1(conv(r->right, types[TSTRING])), args);
- args = concat(list1(conv(r, types[TSTRING])), args);
+ for(l=n->list; l != nil; l=l->next)
+ args = list(args, conv(l->n, types[TSTRING]));
- if(count <= 5) {
+ if(c <= 5) {
// small numbers of strings use direct runtime helpers.
- snprint(namebuf, sizeof(namebuf), "concatstring%d", count);
+ // note: orderexpr knows this cutoff too.
+ snprint(namebuf, sizeof(namebuf), "concatstring%d", c);
} else {
// large numbers of strings are passed to the runtime as a slice.
strcpy(namebuf, "concatstrings");
@@ -2531,6 +2533,7 @@ addstr(Node *n, NodeList **init)
t->type = types[TSTRING];
t->bound = -1;
slice = nod(OCOMPLIT, N, typenod(t));
+ slice->left = n->left;
slice->list = args;
slice->esc = EscNone;
args = list1(slice);