Go patch committed: Stack allocate non-escaping constant make of slice

Ian Lance Taylor iant@golang.org
Tue Jan 9 23:26:00 GMT 2018


This patch to the Go frontend by Cherry Zhang stack allocates a
non-escaping make of a slice type with a constant length and capacity.
Bootstrapped on x86_64-pc-linux-gnu.  Committed to mainline.

Ian
-------------- next part --------------
Index: gcc/go/gofrontend/MERGE
===================================================================
--- gcc/go/gofrontend/MERGE	(revision 256403)
+++ gcc/go/gofrontend/MERGE	(working copy)
@@ -1,4 +1,4 @@
-91169ab206266361624236f0137668162ee8cb9b
+b361bec95927fd6209c286906f98deeedcfe1da3
 
 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 256403)
+++ gcc/go/gofrontend/expressions.cc	(working copy)
@@ -7496,6 +7496,10 @@ Builtin_call_expression::lower_make(Stat
 
   Expression* cap_arg = NULL;
   bool cap_small = false;
+  Numeric_constant nclen;
+  Numeric_constant nccap;
+  unsigned long vlen;
+  unsigned long vcap;
   if (is_slice && parg != args->end())
     {
       cap_arg = *parg;
@@ -7503,10 +7507,6 @@ Builtin_call_expression::lower_make(Stat
       if (!this->check_int_value(cap_arg, false, &cap_small))
 	return Expression::make_error(this->location());
 
-      Numeric_constant nclen;
-      Numeric_constant nccap;
-      unsigned long vlen;
-      unsigned long vcap;
       if (len_arg->numeric_constant_value(&nclen)
 	  && cap_arg->numeric_constant_value(&nccap)
 	  && nclen.to_unsigned_long(&vlen) == Numeric_constant::NC_UL_VALID
@@ -7531,19 +7531,25 @@ Builtin_call_expression::lower_make(Stat
   Expression* call;
   if (is_slice)
     {
-      Type* et = type->array_type()->element_type();
-      Expression* type_arg = Expression::make_type_descriptor(et, type_loc);
       if (cap_arg == NULL)
 	{
-	  Temporary_statement* temp = Statement::make_temporary(NULL,
-								len_arg,
-								loc);
-	  inserter->insert(temp);
-	  len_arg = Expression::make_temporary_reference(temp, loc);
-	  cap_arg = Expression::make_temporary_reference(temp, loc);
-	  cap_small = len_small;
+          cap_small = len_small;
+          if (len_arg->numeric_constant_value(&nclen)
+              && nclen.to_unsigned_long(&vlen) == Numeric_constant::NC_UL_VALID)
+            cap_arg = Expression::make_integer_ul(vlen, len_arg->type(), loc);
+          else
+            {
+              Temporary_statement* temp = Statement::make_temporary(NULL,
+                                                                    len_arg,
+                                                                    loc);
+              inserter->insert(temp);
+              len_arg = Expression::make_temporary_reference(temp, loc);
+              cap_arg = Expression::make_temporary_reference(temp, loc);
+            }
 	}
 
+      Type* et = type->array_type()->element_type();
+      Expression* type_arg = Expression::make_type_descriptor(et, type_loc);
       Runtime::Function code = Runtime::MAKESLICE;
       if (!len_small || !cap_small)
 	code = Runtime::MAKESLICE64;
Index: gcc/go/gofrontend/wb.cc
===================================================================
--- gcc/go/gofrontend/wb.cc	(revision 256403)
+++ gcc/go/gofrontend/wb.cc	(working copy)
@@ -64,6 +64,47 @@ Mark_address_taken::expression(Expressio
         }
       aie->array()->address_taken(escapes);
     }
+
+  // Rewrite non-escaping makeslice with constant size to stack allocation.
+  Unsafe_type_conversion_expression* uce =
+    expr->unsafe_conversion_expression();
+  if (uce != NULL
+      && uce->type()->is_slice_type()
+      && Node::make_node(uce->expr())->encoding() == Node::ESCAPE_NONE
+      && uce->expr()->call_expression() != NULL)
+    {
+      Call_expression* call = uce->expr()->call_expression();
+      if (call->fn()->func_expression() != NULL
+          && call->fn()->func_expression()->runtime_code() == Runtime::MAKESLICE)
+        {
+          Expression* len_arg = call->args()->at(1);
+          Expression* cap_arg = call->args()->at(2);
+          Numeric_constant nclen;
+          Numeric_constant nccap;
+          unsigned long vlen;
+          unsigned long vcap;
+          if (len_arg->numeric_constant_value(&nclen)
+              && cap_arg->numeric_constant_value(&nccap)
+              && nclen.to_unsigned_long(&vlen) == Numeric_constant::NC_UL_VALID
+              && nccap.to_unsigned_long(&vcap) == Numeric_constant::NC_UL_VALID)
+            {
+              // Turn it into a slice expression of an addressable array,
+              // which is allocated on stack.
+              Location loc = expr->location();
+              Type* elmt_type = expr->type()->array_type()->element_type();
+              Expression* len_expr =
+                Expression::make_integer_ul(vcap, cap_arg->type(), loc);
+              Type* array_type = Type::make_array_type(elmt_type, len_expr);
+              Expression* alloc = Expression::make_allocation(array_type, loc);
+              alloc->allocation_expression()->set_allocate_on_stack();
+              Expression* array = Expression::make_unary(OPERATOR_MULT, alloc, loc);
+              Expression* zero = Expression::make_integer_ul(0, len_arg->type(), loc);
+              Expression* slice =
+                Expression::make_array_index(array, zero, len_arg, cap_arg, loc);
+              *pexpr = slice;
+            }
+        }
+    }
   return TRAVERSE_CONTINUE;
 }
 


More information about the Gcc-patches mailing list