From 864fcf61a00fa1b73ae32be6f1ee11a6f7362b82 Mon Sep 17 00:00:00 2001 From: Cherry Zhang Date: Tue, 18 Jun 2019 23:55:50 +0000 Subject: compiler: avoid copy for string([]byte) conversion used in string concatenation If a string([]byte) conversion is used immediately in a string concatenation, we don't need to copy the backing store of the byte slice, as the runtime function doesn't hold any reference to it. Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/182437 * go.dg/concatstring.go: New test. From-SVN: r272460 --- gcc/go/gofrontend/MERGE | 2 +- gcc/go/gofrontend/expressions.cc | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) (limited to 'gcc/go') diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE index d89e8e3..16abddf 100644 --- a/gcc/go/gofrontend/MERGE +++ b/gcc/go/gofrontend/MERGE @@ -1,4 +1,4 @@ -b1ae35965cadac235d7d218e689944286cccdd90 +62d1b667f3e85f72a186b04aad36d701160a4611 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 740daec..e5e6ba7 100644 --- a/gcc/go/gofrontend/expressions.cc +++ b/gcc/go/gofrontend/expressions.cc @@ -7408,6 +7408,26 @@ String_concat_expression::do_flatten(Gogo*, Named_object*, return this; Location loc = this->location(); Type* type = this->type(); + + // Mark string([]byte) operands to reuse the backing store. + // runtime.concatstrings does not keep the reference. + // + // Note: in the gc runtime, if all but one inputs are empty, + // concatstrings returns the only nonempty input without copy. + // So it is not safe to reuse the backing store if it is a + // string([]byte) conversion. So the gc compiler does the + // no-copy optimization only when there is at least one + // constant nonempty input. Currently the gccgo runtime + // doesn't do this, so we don't do the check. + for (Expression_list::iterator p = this->exprs_->begin(); + p != this->exprs_->end(); + ++p) + { + Type_conversion_expression* tce = (*p)->conversion_expression(); + if (tce != NULL) + tce->set_no_copy(true); + } + Expression* nil_arg = Expression::make_nil(loc); Expression* call; switch (this->exprs_->size()) -- cgit v1.1