Commit 87436805 by Cherry Zhang Committed by Ian Lance Taylor

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
parent 08e113f4
9c8581187b1c1a30036263728370f31cb846a274 3dbf51c01c5d0acbf9ae47f77166fa9935881749
The first line of this file holds the git revision number of the last The first line of this file holds the git revision number of the last
merge done from the gofrontend repository. merge done from the gofrontend repository.
...@@ -12158,6 +12158,13 @@ Map_index_expression::do_flatten(Gogo* gogo, Named_object*, ...@@ -12158,6 +12158,13 @@ Map_index_expression::do_flatten(Gogo* gogo, Named_object*,
return Expression::make_error(loc); 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(), if (!Type::are_identical(mt->key_type(), this->index_->type(),
Type::COMPARE_ERRORS | Type::COMPARE_TAGS, Type::COMPARE_ERRORS | Type::COMPARE_TAGS,
NULL)) NULL))
......
...@@ -1307,6 +1307,13 @@ Tuple_map_assignment_statement::do_lower(Gogo* gogo, Named_object*, ...@@ -1307,6 +1307,13 @@ Tuple_map_assignment_statement::do_lower(Gogo* gogo, Named_object*,
if (map_type == NULL) if (map_type == NULL)
return Statement::make_error_statement(loc); 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); Block* b = new Block(enclosing, loc);
// Move out any subexpressions to make sure that functions are // Move out any subexpressions to make sure that functions are
......
2019-05-09 Cherry Zhang <cherryyz@google.com>
* go.dg/mapstring.go: New test.
2019-05-09 Richard Earnshaw <rearnsha@arm.com> 2019-05-09 Richard Earnshaw <rearnsha@arm.com>
PR target/90405 PR target/90405
......
// { 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
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment