compiler: avoid copy for string([]byte) conversion used in string concatenation
authorCherry Zhang <cherryyz@google.com>
Tue, 18 Jun 2019 23:55:50 +0000 (23:55 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Tue, 18 Jun 2019 23:55:50 +0000 (23:55 +0000)
    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
gcc/go/gofrontend/expressions.cc
gcc/testsuite/ChangeLog
gcc/testsuite/go.dg/concatstring.go [new file with mode: 0644]

index d89e8e3e2884a11c23529cb9da6ca6aa37ee3d0a..16abddfcdfae03e952aa51cb6fbf61514380f3fb 100644 (file)
@@ -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 740daec5f2178e92ae80ea131d517854e6a71e1e..e5e6ba75635102218f05906211c5767b3f1c6839 100644 (file)
@@ -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())
index 6ff197c8e4dc60f1bf4234ad68d2dfb30756b8a4..6f4834191cf36f3a0b06da14e79c58d5e44369fa 100644 (file)
@@ -1,3 +1,7 @@
+2019-06-18  Cherry Zhang  <cherryyz@google.com>
+
+       * go.dg/concatstring.go: New test.
+
 2019-06-18  Thomas Schwinge  <thomas@codesourcery.com>
 
        PR fortran/90921
diff --git a/gcc/testsuite/go.dg/concatstring.go b/gcc/testsuite/go.dg/concatstring.go
new file mode 100644 (file)
index 0000000..5dc4254
--- /dev/null
@@ -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\\)" }
+}