diff options
author | Ian Lance Taylor <ian@gcc.gnu.org> | 2019-03-19 18:42:43 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2019-03-19 18:42:43 +0000 |
commit | ea5ac5a69b4b474bb221051e705f98d8599253fa (patch) | |
tree | 96913ddcd86133f8a48bb74399326f954e503841 /gcc | |
parent | e0748030863e158ced48802ea42b27e5ec26995f (diff) | |
download | gcc-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/MERGE | 2 | ||||
-rw-r--r-- | gcc/go/gofrontend/expressions.cc | 24 | ||||
-rw-r--r-- | gcc/go/gofrontend/runtime.def | 3 |
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. |