diff mbox series

Go patch committed: Avoid copy for string([]byte) conversion in string concat

Message ID CAOyqgcV6L_0HH5QgmF=jU2muVXj1ZaYWz3NB8PnGmkOfQx+scA@mail.gmail.com
State New
Headers show
Series Go patch committed: Avoid copy for string([]byte) conversion in string concat | expand

Commit Message

Ian Lance Taylor June 18, 2019, 11:55 p.m. UTC
This patch to the Go frontend by Cherry Zhang avoids a copy for a
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.
Bootstrapped and ran Go testsuite on x86_64-pc-linux-gnu.  Committed
to mainline.

Ian

2019-06-18  Cherry Zhang  <cherryyz@google.com>

* go.dg/concatstring.go: New test.
diff mbox series

Patch

Index: gcc/go/gofrontend/MERGE
===================================================================
--- gcc/go/gofrontend/MERGE	(revision 272133)
+++ gcc/go/gofrontend/MERGE	(working copy)
@@ -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.
Index: gcc/go/gofrontend/expressions.cc
===================================================================
--- gcc/go/gofrontend/expressions.cc	(revision 272133)
+++ gcc/go/gofrontend/expressions.cc	(working copy)
@@ -7408,6 +7408,26 @@  String_concat_expression::do_flatten(Gog
     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())
Index: gcc/testsuite/go.dg/concatstring.go
===================================================================
--- gcc/testsuite/go.dg/concatstring.go	(nonexistent)
+++ gcc/testsuite/go.dg/concatstring.go	(working copy)
@@ -0,0 +1,8 @@ 
+// { dg-do compile }
+// { dg-options "-fgo-debug-optimization" }
+
+package p
+
+func F(b []byte, x string) string {
+	return "hello " + string(b) + x // { dg-error "no copy string\\(\\\[\\\]byte\\)" }
+}