aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2019-03-19 18:42:43 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2019-03-19 18:42:43 +0000
commitea5ac5a69b4b474bb221051e705f98d8599253fa (patch)
tree96913ddcd86133f8a48bb74399326f954e503841 /gcc
parente0748030863e158ced48802ea42b27e5ec26995f (diff)
downloadgcc-ea5ac5a69b4b474bb221051e705f98d8599253fa.zip
gcc-ea5ac5a69b4b474bb221051e705f98d8599253fa.tar.gz
gcc-ea5ac5a69b4b474bb221051e705f98d8599253fa.tar.bz2
compiler,runtime: pass old slice's ptr/len/cap by value to growslice
In the C calling convention, on AMD64, and probably a number of other architectures, a 3-word struct argument is passed on stack. This is less efficient than passing in three registers. Further, this may affect the code generation in other part of the program, even if the function is not actually called. Slices are common in Go and append is a common slice operation, which calls growslice in the growing path. To improve the code generation, pass the slice header's three fields as separate values, instead of a struct, to growslice. The drawback is that this makes the runtime implementation slightly diverges from the gc runtime. Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/168277 From-SVN: r269811
Diffstat (limited to 'gcc')
-rw-r--r--gcc/go/gofrontend/MERGE2
-rw-r--r--gcc/go/gofrontend/expressions.cc24
-rw-r--r--gcc/go/gofrontend/runtime.def3
3 files changed, 20 insertions, 9 deletions
diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE
index 006da8c..4a9853a 100644
--- a/gcc/go/gofrontend/MERGE
+++ b/gcc/go/gofrontend/MERGE
@@ -1,4 +1,4 @@
-069afe85f38c099660c5d81950d65248ed4fc516
+6e5ff227d4e77d340e86bd2c5e045d5532c2d7d7
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 f41647a..018fdbb 100644
--- a/gcc/go/gofrontend/expressions.cc
+++ b/gcc/go/gofrontend/expressions.cc
@@ -7986,23 +7986,33 @@ Builtin_call_expression::flatten_append(Gogo* gogo, Named_object* function,
// Using uint here means that if the computation of ntmp overflowed,
// we will call growslice which will panic.
- Expression* left = Expression::make_temporary_reference(ntmp, loc);
- left = Expression::make_cast(uint_type, left, loc);
-
Named_object* capfn = gogo->lookup_global("cap");
Expression* capref = Expression::make_func_reference(capfn, NULL, loc);
call_args = new Expression_list();
call_args->push_back(Expression::make_temporary_reference(s1tmp, loc));
- Expression* right = Expression::make_call(capref, call_args, false, loc);
+ Expression* cap = Expression::make_call(capref, call_args, false, loc);
+ gogo->lower_expression(function, inserter, &cap);
+ gogo->flatten_expression(function, inserter, &cap);
+ Temporary_statement* c1tmp = Statement::make_temporary(int_type, cap, loc);
+ inserter->insert(c1tmp);
+
+ Expression* left = Expression::make_temporary_reference(ntmp, loc);
+ left = Expression::make_cast(uint_type, left, loc);
+ Expression* right = Expression::make_temporary_reference(c1tmp, loc);
right = Expression::make_cast(uint_type, right, loc);
Expression* cond = Expression::make_binary(OPERATOR_GT, left, right, loc);
+ Type* unsafe_ptr_type = Type::make_pointer_type(Type::make_void_type());
Expression* a1 = Expression::make_type_descriptor(element_type, loc);
Expression* a2 = Expression::make_temporary_reference(s1tmp, loc);
- Expression* a3 = Expression::make_temporary_reference(ntmp, loc);
- Expression* call = Runtime::make_call(Runtime::GROWSLICE, loc, 3,
- a1, a2, a3);
+ a2 = slice_type->array_type()->get_value_pointer(gogo, a2, false);
+ a2 = Expression::make_cast(unsafe_ptr_type, a2, loc);
+ Expression* a3 = Expression::make_temporary_reference(l1tmp, loc);
+ Expression* a4 = Expression::make_temporary_reference(c1tmp, loc);
+ Expression* a5 = Expression::make_temporary_reference(ntmp, loc);
+ Expression* call = Runtime::make_call(Runtime::GROWSLICE, loc, 5,
+ a1, a2, a3, a4, a5);
call = Expression::make_unsafe_cast(slice_type, call, loc);
ref = Expression::make_temporary_reference(s1tmp, loc);
diff --git a/gcc/go/gofrontend/runtime.def b/gcc/go/gofrontend/runtime.def
index 273c860..83a7152 100644
--- a/gcc/go/gofrontend/runtime.def
+++ b/gcc/go/gofrontend/runtime.def
@@ -202,7 +202,8 @@ DEF_GO_RUNTIME(TYPEDSLICECOPY, "runtime.typedslicecopy",
// Grow a slice for append.
-DEF_GO_RUNTIME(GROWSLICE, "runtime.growslice", P3(TYPE, SLICE, INT), R1(SLICE))
+DEF_GO_RUNTIME(GROWSLICE, "runtime.growslice",
+ P5(TYPE, POINTER, INT, INT, INT), R1(SLICE))
// Register roots (global variables) for the garbage collector.