* Go patch committed: Fix escape analysis for multi-result calls
@ 2015-04-29 23:18 Ian Lance Taylor
0 siblings, 0 replies; only message in thread
From: Ian Lance Taylor @ 2015-04-29 23:18 UTC (permalink / raw)
To: gcc-patches, gofrontend-dev
[-- Attachment #1: Type: text/plain, Size: 185 bytes --]
This patch from Chris Manghane fixes the handling of multi-result
calls in escape analysis. Bootstrapped and ran Go testsuite on
x86_64-unknown-linux-gnu. Committed to mainline.
Ian
[-- Attachment #2: foo.txt --]
[-- Type: text/plain, Size: 7554 bytes --]
diff -r 76359c093067 go/escape.cc
--- a/go/escape.cc Wed Apr 29 15:09:15 2015 -0700
+++ b/go/escape.cc Wed Apr 29 15:27:38 2015 -0700
@@ -989,21 +989,21 @@
Named_object* lhs_no = this->resolve_var_reference(assn->lhs());
Named_object* rhs_no = this->resolve_var_reference(assn->rhs());
- if (assn->rhs()->is_composite_literal()
- || assn->rhs()->heap_expression() != NULL)
- this->handle_composite_literal(var, assn->rhs());
- else if (assn->rhs()->call_result_expression() != NULL)
+ Expression* rhs = assn->rhs();
+ if (rhs->is_composite_literal()
+ || rhs->heap_expression() != NULL)
+ this->handle_composite_literal(var, rhs);
+
+ if (rhs->call_result_expression() != NULL)
{
// V's initialization will be a call result if
// V, V1 := call(VAR).
// There are no useful edges to make from V, but we want
// to make sure we handle the call that references VAR.
- Expression* call =
- assn->rhs()->call_result_expression()->call();
- this->handle_call(var, call);
+ rhs = rhs->call_result_expression()->call();
}
- else if (assn->rhs()->call_expression() != NULL)
- this->handle_call(var, assn->rhs());
+ if (rhs->call_expression() != NULL)
+ this->handle_call(var, rhs);
// If there is no standalone variable on the rhs, this could be a
// binary expression, which isn't interesting for analysis or a
@@ -1038,8 +1038,12 @@
break;
case Statement::STATEMENT_EXPRESSION:
- this->handle_call(var,
- p->statement->expression_statement()->expr());
+ {
+ Expression* call = p->statement->expression_statement()->expr();
+ if (call->call_result_expression() != NULL)
+ call = call->call_result_expression()->call();
+ this->handle_call(var, call);
+ }
break;
case Statement::STATEMENT_GO:
@@ -1064,10 +1068,17 @@
else if (cond->binary_expression() != NULL)
{
Binary_expression* comp = cond->binary_expression();
- if (comp->left()->call_expression() != NULL)
- this->handle_call(var, comp->left());
- if (comp->right()->call_expression() != NULL)
- this->handle_call(var, comp->right());
+ Expression* left = comp->left();
+ Expression* right = comp->right();
+
+ if (left->call_result_expression() != NULL)
+ left = left->call_result_expression()->call();
+ if (left->call_expression() != NULL)
+ this->handle_call(var, left);
+ if (right->call_result_expression() != NULL)
+ right = right->call_result_expression()->call();
+ if (right->call_expression() != NULL)
+ this->handle_call(var, right);
}
}
break;
@@ -1092,16 +1103,10 @@
// composite literal.
this->handle_composite_literal(decl_no, init);
}
- else if (init->call_result_expression() != NULL)
- {
- // V's initialization will be a call result if
- // V, V1 := call(VAR).
- // There's no useful edges to make from V or V1, but we want
- // to make sure we handle the call that references VAR.
- Expression* call = init->call_result_expression()->call();
- this->handle_call(var, call);
- }
- else if (init->call_expression() != NULL)
+
+ if (init->call_result_expression() != NULL)
+ init = init->call_result_expression()->call();
+ if (init->call_expression() != NULL)
this->handle_call(var, init);
}
break;
@@ -1148,18 +1153,46 @@
if (lhs_no == NULL)
break;
- if (assn->rhs()->func_expression() != NULL)
+ Expression* rhs = assn->rhs();
+ if (rhs->temporary_reference_expression() != NULL)
+ rhs = rhs->temporary_reference_expression()->statement()->init();
+ if (rhs == NULL)
+ break;
+
+ if (rhs->call_result_expression() != NULL)
+ rhs = rhs->call_result_expression()->call();
+ if (rhs->call_expression() != NULL)
+ {
+ // It's not clear what variables we are trying to find references to
+ // so just use the arguments to this call.
+ Expression_list* args = rhs->call_expression()->args();
+ if (args == NULL)
+ break;
+
+ for (Expression_list::const_iterator p = args->begin();
+ p != args->end();
+ ++p)
+ {
+ Named_object* no = this->resolve_var_reference(*p);
+ if (no != NULL) {
+ Node* lhs_node = this->gogo_->add_connection_node(lhs_no);
+ Node* rhs_node = this->gogo_->add_connection_node(no);
+ lhs_node->add_edge(rhs_node);
+ }
+ }
+
+ this->handle_call(lhs_no, rhs);
+ }
+ else if (rhs->func_expression() != NULL)
{
Node* lhs_node = this->gogo_->add_connection_node(lhs_no);
- Named_object* fn = assn->rhs()->func_expression()->named_object();
+ Named_object* fn = rhs->func_expression()->named_object();
Node* fn_node = this->gogo_->add_connection_node(fn);
lhs_node->add_edge(fn_node);
}
- else if (assn->rhs()->call_expression() != NULL)
- this->handle_call(lhs_no, assn->rhs()->call_expression());
else
{
- Named_object* rhs_no = this->resolve_var_reference(assn->rhs());
+ Named_object* rhs_no = this->resolve_var_reference(rhs);
if (rhs_no != NULL)
{
Node* lhs_node = this->gogo_->add_connection_node(lhs_no);
@@ -1188,6 +1221,8 @@
case Statement::STATEMENT_EXPRESSION:
{
Expression* expr = s->expression_statement()->expr();
+ if (expr->call_result_expression() != NULL)
+ expr = expr->call_result_expression()->call();
if (expr->call_expression() != NULL)
{
// It's not clear what variables we are trying to find references to
@@ -1208,6 +1243,73 @@
}
break;
+ case Statement::STATEMENT_GO:
+ case Statement::STATEMENT_DEFER:
+ {
+ // Any variable referenced via a go or defer statement escapes to
+ // a different goroutine.
+ Expression* call = s->thunk_statement()->call();
+ if (call->call_expression() != NULL)
+ {
+ // It's not clear what variables we are trying to find references to
+ // so just use the arguments to this call.
+ Expression_list* args = call->call_expression()->args();
+ if (args == NULL)
+ break;
+
+ for (Expression_list::const_iterator p = args->begin();
+ p != args->end();
+ ++p)
+ {
+ Named_object* no = this->resolve_var_reference(*p);
+ if (no != NULL)
+ this->handle_call(no, call);
+ }
+ }
+ }
+ break;
+
+ case Statement::STATEMENT_VARIABLE_DECLARATION:
+ {
+ Variable_declaration_statement* decl =
+ s->variable_declaration_statement();
+ Named_object* decl_no = decl->var();
+ Variable* v = decl_no->var_value();
+
+ Expression* init = v->init();
+ if (init == NULL)
+ break;
+
+ if (init->is_composite_literal()
+ || init->heap_expression() != NULL)
+ {
+ // Create edges between DECL_NO and each named object in the
+ // composite literal.
+ this->handle_composite_literal(decl_no, init);
+ }
+
+ if (init->call_result_expression() != NULL)
+ init = init->call_result_expression()->call();
+ if (init->call_expression() != NULL)
+ {
+ // It's not clear what variables we are trying to find references to
+ // so just use the arguments to this call.
+ Expression_list* args = init->call_expression()->args();
+ if (args == NULL)
+ break;
+
+ for (Expression_list::const_iterator p = args->begin();
+ p != args->end();
+ ++p)
+ {
+ Named_object* no = this->resolve_var_reference(*p);
+ if (no != NULL)
+ this->handle_call(no, init);
+ }
+ }
+ }
+ break;
+
default:
break;
}
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2015-04-29 22:40 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-04-29 23:18 Go patch committed: Fix escape analysis for multi-result calls Ian Lance Taylor
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).