Go patch committed: stack allocate non-escaping expressions

Ian Lance Taylor iant@golang.org
Wed Aug 3 16:32:00 GMT 2016


This patch by Chris Manghane allocates expressions that do not escape
on the stack.  This only happens when doing escape analysis, which is
still not enabled by default.  Bootstrapped and ran Go testsuite on
x86_64-pc-linux-gnu.  Committed to mainline.

Ian
-------------- next part --------------
Index: gcc/go/gofrontend/MERGE
===================================================================
--- gcc/go/gofrontend/MERGE	(revision 239002)
+++ gcc/go/gofrontend/MERGE	(working copy)
@@ -1,4 +1,4 @@
-89a0b3a04f80df388242166b8835f12e82ceb194
+7d6c53910e52b7db2a77c1c1c3bc2c170283a1fa
 
 The first line of this file holds the git revision number of the last
 merge done from the gofrontend repository.
Index: gcc/go/gofrontend/expressions.cc
===================================================================
--- gcc/go/gofrontend/expressions.cc	(revision 238653)
+++ gcc/go/gofrontend/expressions.cc	(working copy)
@@ -252,7 +252,9 @@ Expression::convert_type_to_interface(Ty
   else
     {
       // We are assigning a non-pointer value to the interface; the
-      // interface gets a copy of the value in the heap.
+      // interface gets a copy of the value in the heap if it escapes.
+      // TODO(cmang): Associate escape state state of RHS with newly
+      // created OBJ.
       obj = Expression::make_heap_expression(rhs, location);
     }
 
@@ -729,6 +731,13 @@ Var_expression::do_address_taken(bool es
       else
 	go_unreachable();
     }
+
+  if (this->variable_->is_variable()
+      && this->variable_->var_value()->is_in_heap())
+    {
+      Node::make_node(this)->set_encoding(Node::ESCAPE_HEAP);
+      Node::make_node(this->variable_)->set_encoding(Node::ESCAPE_HEAP);
+    }
 }
 
 // Get the backend representation for a reference to a variable.
@@ -831,6 +840,10 @@ Enclosed_var_expression::do_address_take
       else
 	go_unreachable();
     }
+
+  if (this->variable_->is_variable()
+      && this->variable_->var_value()->is_in_heap())
+    Node::make_node(this->variable_)->set_encoding(Node::ESCAPE_HEAP);
 }
 
 // Ast dump for enclosed variable expression.
@@ -3769,9 +3782,18 @@ Unary_expression::do_flatten(Gogo* gogo,
       // value does not escape.  If this->escapes_ is true, we may be
       // able to set it to false if taking the address of a variable
       // that does not escape.
-      if (this->escapes_ && this->expr_->var_expression() != NULL)
+      Node* n = Node::make_node(this);
+      if ((n->encoding() & ESCAPE_MASK) == int(Node::ESCAPE_NONE))
+	this->escapes_ = false;
+
+      Named_object* var = NULL;
+      if (this->expr_->var_expression() != NULL)
+	var = this->expr_->var_expression()->named_object();
+      else if (this->expr_->enclosed_var_expression() != NULL)
+	var = this->expr_->enclosed_var_expression()->variable();
+
+      if (this->escapes_ && var != NULL)
 	{
-	  Named_object* var = this->expr_->var_expression()->named_object();
 	  if (var->is_variable())
 	    this->escapes_ = var->var_value()->escapes();
 	  if (var->is_result_variable())
@@ -11658,7 +11680,9 @@ Allocation_expression::do_get_backend(Tr
   Gogo* gogo = context->gogo();
   Location loc = this->location();
 
-  if (this->allocate_on_stack_)
+  Node* n = Node::make_node(this);
+  if (this->allocate_on_stack_
+      || (n->encoding() & ESCAPE_MASK) == int(Node::ESCAPE_NONE))
     {
       int64_t size;
       bool ok = this->type_->backend_type_size(gogo, &size);
@@ -12344,7 +12368,15 @@ Slice_construction_expression::do_get_ba
       space->unary_expression()->set_is_slice_init();
     }
   else
-    space = Expression::make_heap_expression(array_val, loc);
+    {
+      space = Expression::make_heap_expression(array_val, loc);
+      Node* n = Node::make_node(this);
+      if ((n->encoding() & ESCAPE_MASK) == int(Node::ESCAPE_NONE))
+	{
+	  n = Node::make_node(space);
+	  n->set_encoding(Node::ESCAPE_NONE);
+	}
+    }
 
   // Build a constructor for the slice.
 
@@ -13417,8 +13449,12 @@ Heap_expression::do_get_backend(Translat
   Location loc = this->location();
   Gogo* gogo = context->gogo();
   Btype* btype = this->type()->get_backend(gogo);
-  Bexpression* space = Expression::make_allocation(this->expr_->type(),
-						   loc)->get_backend(context);
+
+  Expression* alloc = Expression::make_allocation(this->expr_->type(), loc);
+  Node* n = Node::make_node(this);
+  if ((n->encoding() & ESCAPE_MASK) == int(Node::ESCAPE_NONE))
+    alloc->allocation_expression()->set_allocate_on_stack();
+  Bexpression* space = alloc->get_backend(context);
 
   Bstatement* decl;
   Named_object* fn = context->function();


More information about the Gcc-patches mailing list