aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2019-06-24 17:54:07 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2019-06-24 17:54:07 +0000
commit609c7da9ab08b009fb7a9cacf68a40b3b39231b3 (patch)
tree35dca03ba85159a6996a182caf07eaaeccfd9728 /gcc
parentd611cec3de1e54091843019a0d02c23493d288ce (diff)
downloadgcc-609c7da9ab08b009fb7a9cacf68a40b3b39231b3.zip
gcc-609c7da9ab08b009fb7a9cacf68a40b3b39231b3.tar.gz
gcc-609c7da9ab08b009fb7a9cacf68a40b3b39231b3.tar.bz2
compiler: open code string equality
Open code string equality with builtin memcmp. This allows further optimizations in the backend. Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/183538 From-SVN: r272624
Diffstat (limited to 'gcc')
-rw-r--r--gcc/go/gofrontend/MERGE2
-rw-r--r--gcc/go/gofrontend/expressions.cc62
-rw-r--r--gcc/go/gofrontend/runtime.def3
3 files changed, 52 insertions, 15 deletions
diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE
index 89d401b..ca68507 100644
--- a/gcc/go/gofrontend/MERGE
+++ b/gcc/go/gofrontend/MERGE
@@ -1,4 +1,4 @@
-338e4baf88a4ae676205dff601dbef2d31b19d2d
+89b442a0100286ee569b8d2562ce1b2ea602f7e7
The first line of this file holds the git revision number of the last
merge done from the gofrontend repository.
diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc
index 050da32..2f33dee 100644
--- a/gcc/go/gofrontend/expressions.cc
+++ b/gcc/go/gofrontend/expressions.cc
@@ -6226,10 +6226,27 @@ Binary_expression::do_flatten(Gogo* gogo, Named_object*,
bool is_idiv_op = ((this->op_ == OPERATOR_DIV &&
left_type->integer_type() != NULL)
|| this->op_ == OPERATOR_MOD);
+ bool is_string_op = (left_type->is_string_type()
+ && this->right_->type()->is_string_type());
+
+ if (is_string_op)
+ {
+ // Mark string([]byte) operands to reuse the backing store.
+ // String comparison does not keep the reference, so it is safe.
+ Type_conversion_expression* lce =
+ this->left_->conversion_expression();
+ if (lce != NULL && lce->expr()->type()->is_slice_type())
+ lce->set_no_copy(true);
+ Type_conversion_expression* rce =
+ this->right_->conversion_expression();
+ if (rce != NULL && rce->expr()->type()->is_slice_type())
+ rce->set_no_copy(true);
+ }
if (is_shift_op
|| (is_idiv_op
- && (gogo->check_divide_by_zero() || gogo->check_divide_overflow())))
+ && (gogo->check_divide_by_zero() || gogo->check_divide_overflow()))
+ || is_string_op)
{
if (!this->left_->is_variable() && !this->left_->is_constant())
{
@@ -7217,19 +7234,42 @@ Expression::comparison(Translate_context* context, Type* result_type,
if (left_type->is_string_type() && right_type->is_string_type())
{
- // Mark string([]byte) operands to reuse the backing store.
- // String comparison does not keep the reference, so it is safe.
- Type_conversion_expression* lce = left->conversion_expression();
- if (lce != NULL && lce->expr()->type()->is_slice_type())
- lce->set_no_copy(true);
- Type_conversion_expression* rce = right->conversion_expression();
- if (rce != NULL && rce->expr()->type()->is_slice_type())
- rce->set_no_copy(true);
+ go_assert(left->is_variable() || left->is_constant());
+ go_assert(right->is_variable() || right->is_constant());
if (op == OPERATOR_EQEQ || op == OPERATOR_NOTEQ)
{
- left = Runtime::make_call(Runtime::EQSTRING, location, 2,
- left, right);
+ // (l.len == r.len
+ // ? (l.ptr == r.ptr ? true : memcmp(l.ptr, r.ptr, r.len) == 0)
+ // : false)
+ Expression* llen = Expression::make_string_info(left,
+ STRING_INFO_LENGTH,
+ location);
+ Expression* rlen = Expression::make_string_info(right,
+ STRING_INFO_LENGTH,
+ location);
+ Expression* leneq = Expression::make_binary(OPERATOR_EQEQ, llen, rlen,
+ location);
+ Expression* lptr = Expression::make_string_info(left->copy(),
+ STRING_INFO_DATA,
+ location);
+ Expression* rptr = Expression::make_string_info(right->copy(),
+ STRING_INFO_DATA,
+ location);
+ Expression* ptreq = Expression::make_binary(OPERATOR_EQEQ, lptr, rptr,
+ location);
+ Expression* btrue = Expression::make_boolean(true, location);
+ Expression* call = Runtime::make_call(Runtime::MEMCMP, location, 3,
+ lptr->copy(), rptr->copy(),
+ rlen->copy());
+ Type* int32_type = Type::lookup_integer_type("int32");
+ Expression* zero = Expression::make_integer_ul(0, int32_type, location);
+ Expression* cmp = Expression::make_binary(OPERATOR_EQEQ, call, zero,
+ location);
+ Expression* cond = Expression::make_conditional(ptreq, btrue, cmp,
+ location);
+ Expression* bfalse = Expression::make_boolean(false, location);
+ left = Expression::make_conditional(leneq, cond, bfalse, location);
right = Expression::make_boolean(true, location);
}
else
diff --git a/gcc/go/gofrontend/runtime.def b/gcc/go/gofrontend/runtime.def
index 7b66b16..ec7ec76 100644
--- a/gcc/go/gofrontend/runtime.def
+++ b/gcc/go/gofrontend/runtime.def
@@ -39,9 +39,6 @@ DEF_GO_RUNTIME(DECODERUNE, "runtime.decoderune", P2(STRING, INT),
DEF_GO_RUNTIME(CONCATSTRINGS, "runtime.concatstrings",
P3(POINTER, POINTER, INT), R1(STRING))
-// Compare two strings for equality.
-DEF_GO_RUNTIME(EQSTRING, "runtime.eqstring", P2(STRING, STRING), R1(BOOL))
-
// Compare two strings.
DEF_GO_RUNTIME(CMPSTRING, "runtime.cmpstring", P2(STRING, STRING), R1(INT))