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:
parent
08e113f4ae
commit
8743680541
@ -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.
|
||||
|
@ -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))
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
11
gcc/testsuite/go.dg/mapstring.go
Normal file
11
gcc/testsuite/go.dg/mapstring.go
Normal 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
|
||||
}
|
Loading…
Reference in New Issue
Block a user