aboutsummaryrefslogtreecommitdiff
path: root/gcc/go
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2018-01-09 23:21:38 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2018-01-09 23:21:38 +0000
commite732b4248592cc992eddcd00d37c6457d99381e7 (patch)
treef67e2b7279b92512a19b582799ce951bbc70d1ee /gcc/go
parent9ac55031c41077b7465c64ac80587587709acbba (diff)
downloadgcc-e732b4248592cc992eddcd00d37c6457d99381e7.zip
gcc-e732b4248592cc992eddcd00d37c6457d99381e7.tar.gz
gcc-e732b4248592cc992eddcd00d37c6457d99381e7.tar.bz2
compiler: stack allocate non-escaping makeslice
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
Diffstat (limited to 'gcc/go')
-rw-r--r--gcc/go/gofrontend/MERGE2
-rw-r--r--gcc/go/gofrontend/expressions.cc32
-rw-r--r--gcc/go/gofrontend/wb.cc41
3 files changed, 61 insertions, 14 deletions
diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE
index 23d2d3a..6dbbf0f 100644
--- a/gcc/go/gofrontend/MERGE
+++ b/gcc/go/gofrontend/MERGE
@@ -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.
diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc
index 4ba1168..2e0a143 100644
--- a/gcc/go/gofrontend/expressions.cc
+++ b/gcc/go/gofrontend/expressions.cc
@@ -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;
diff --git a/gcc/go/gofrontend/wb.cc b/gcc/go/gofrontend/wb.cc
index c672bf3..a3f71a4 100644
--- a/gcc/go/gofrontend/wb.cc
+++ b/gcc/go/gofrontend/wb.cc
@@ -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;
}