compiler: avoid copy for string([]byte) conversion used in map keys

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
This commit is contained in:
Cherry Zhang 2019-05-09 21:24:56 +00:00 committed by Ian Lance Taylor
parent 08e113f4ae
commit 8743680541
5 changed files with 30 additions and 1 deletions

View 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.

View 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))

View 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

View 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

View File

@ -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
}