compiler: avoid copy for string([]byte) conversion used in map keys
authorCherry Zhang <cherryyz@google.com>
Thu, 9 May 2019 21:24:56 +0000 (21:24 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Thu, 9 May 2019 21:24:56 +0000 (21:24 +0000)
    If a string([]byte) conversion is used immediately as a key for a
    map read, we don't need to copy the backing store of the byte
    slice, as mapaccess does not keep a reference to it.

    The gc compiler does more than this: it also avoids the copy if
    the map key is a composite literal that contains the conversion
    as a field, like, T{ ... { ..., string(b), ... }, ... }. For now,
    we just optimize the simple case, which is probably most common.

    Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/176197

* go.dg/mapstring.go: New test.

From-SVN: r271044

gcc/go/gofrontend/MERGE
gcc/go/gofrontend/expressions.cc
gcc/go/gofrontend/statements.cc
gcc/testsuite/ChangeLog
gcc/testsuite/go.dg/mapstring.go [new file with mode: 0644]

index f6f28a39ee3b144c2dcc63c1dbb7c60bc1cf9d55..b60177085409ba111ea8d650eef9d130544d43dc 100644 (file)
@@ -1,4 +1,4 @@
-9c8581187b1c1a30036263728370f31cb846a274
+3dbf51c01c5d0acbf9ae47f77166fa9935881749
 
 The first line of this file holds the git revision number of the last
 merge done from the gofrontend repository.
index 2c1286cbdb046c96a4c8d5e50b3b407f0f41c94f..929571b29e452ea567105553f2548f7e16b14098 100644 (file)
@@ -12158,6 +12158,13 @@ Map_index_expression::do_flatten(Gogo* gogo, Named_object*,
       return Expression::make_error(loc);
     }
 
+  // Avoid copy for string([]byte) conversions used in map keys.
+  // mapaccess doesn't keep the reference, so this is safe.
+  Type_conversion_expression* ce = this->index_->conversion_expression();
+  if (ce != NULL && ce->type()->is_string_type()
+      && ce->expr()->type()->is_slice_type())
+    ce->set_no_copy(true);
+
   if (!Type::are_identical(mt->key_type(), this->index_->type(),
                           Type::COMPARE_ERRORS | Type::COMPARE_TAGS,
                           NULL))
index 2e2d039afbd99ad68bf31b99898e28bda0f49a93..67ab18469a55a344c18f1dd28dc581f26a8d13f0 100644 (file)
@@ -1307,6 +1307,13 @@ Tuple_map_assignment_statement::do_lower(Gogo* gogo, Named_object*,
   if (map_type == NULL)
     return Statement::make_error_statement(loc);
 
+  // Avoid copy for string([]byte) conversions used in map keys.
+  // mapaccess doesn't keep the reference, so this is safe.
+  Type_conversion_expression* ce = map_index->index()->conversion_expression();
+  if (ce != NULL && ce->type()->is_string_type()
+      && ce->expr()->type()->is_slice_type())
+    ce->set_no_copy(true);
+
   Block* b = new Block(enclosing, loc);
 
   // Move out any subexpressions to make sure that functions are
index f75dbe767840e24a3954c75c1d5fe5373b64c3cd..4959d2abf79a45f63f082da0ef9bb6a8901885f6 100644 (file)
@@ -1,3 +1,7 @@
+2019-05-09  Cherry Zhang  <cherryyz@google.com>
+
+       * go.dg/mapstring.go: New test.
+
 2019-05-09  Richard Earnshaw  <rearnsha@arm.com>
 
        PR target/90405
diff --git a/gcc/testsuite/go.dg/mapstring.go b/gcc/testsuite/go.dg/mapstring.go
new file mode 100644 (file)
index 0000000..8a60e74
--- /dev/null
@@ -0,0 +1,11 @@
+// { dg-do compile }
+// { dg-options "-fgo-debug-optimization" }
+
+package p
+
+func F(m map[string]int, a, b []byte) int {
+       x := m[string(a)]     // { dg-error "no copy string\\(\\\[\\\]byte\\)" }
+       y, ok := m[string(b)] // { dg-error "no copy string\\(\\\[\\\]byte\\)" }
+       _ = ok
+       return x + y
+}