compiler: stack allocate non-escaping makeslice
authorIan Lance Taylor <ian@gcc.gnu.org>
Tue, 9 Jan 2018 23:21:38 +0000 (23:21 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Tue, 9 Jan 2018 23:21:38 +0000 (23:21 +0000)
    If we're making a slice of constant size that does not need to
    escape, allocate it on stack.

    In lower, do not create temporaries for constant size makeslice,
    so that it is easier to detect the slice is constant size later.

    Reviewed-on: https://go-review.googlesource.com/85636

From-SVN: r256404

gcc/go/gofrontend/MERGE
gcc/go/gofrontend/expressions.cc
gcc/go/gofrontend/wb.cc

index 23d2d3ad53147e49a5aa4941a167b4a0dd4bc335..6dbbf0f63c6e06c73ff88d39d1a7ae05aa6ceee8 100644 (file)
@@ -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 4ba116860e1b9ce55c38e6ef80a0a110ed1f90c1..2e0a14302591ed512a96d21589b798a1dad21f0f 100644 (file)
@@ -7496,6 +7496,10 @@ Builtin_call_expression::lower_make(Statement_inserter* inserter)
 
   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(Statement_inserter* inserter)
       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(Statement_inserter* inserter)
   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 c672bf36b26cea639328a82fcf36cae85b641974..a3f71a4a485a33a64784f3d153604a8b60afe8c4 100644 (file)
@@ -64,6 +64,47 @@ Mark_address_taken::expression(Expression** pexpr)
         }
       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;
 }