[aarch64-port-dev ] String.equals()
Andrew Haley
aph at redhat.com
Thu Jul 3 09:44:29 UTC 2014
As before.
I tried to combine the logic for String.equals() and String.compare()
because they should be very similar, but the result was a mess. Ths
is better, even at the expense of some code duplication.
Andrew.
# HG changeset patch
# User aph
# Date 1404310864 14400
# Wed Jul 02 10:21:04 2014 -0400
# Node ID fd73d7b8ba5d7b51da2289cc4239108382cf52a3
# Parent 1f7e1e16a5341f557a58c20fab339b874089da82
Fast String.equals
diff -r 1f7e1e16a534 -r fd73d7b8ba5d src/cpu/aarch64/vm/aarch64.ad
--- a/src/cpu/aarch64/vm/aarch64.ad Fri Jun 27 06:13:30 2014 -0400
+++ b/src/cpu/aarch64/vm/aarch64.ad Wed Jul 02 10:21:04 2014 -0400
@@ -11348,6 +11348,21 @@
ins_pipe(pipe_class_memory);
%}
+instruct string_equals(iRegP_R1 str1, iRegP_R3 str2, iRegI_R4 cnt,
+ iRegI_R0 result, iRegP tmp, rFlagsReg cr)
+%{
+ match(Set result (StrEquals (Binary str1 str2) cnt));
+ effect(TEMP tmp, USE_KILL str1, USE_KILL str2, USE_KILL cnt, KILL cr);
+
+ format %{ "String Equals $str1,$str2,$cnt -> $result // KILL $tmp" %}
+ ins_encode %{
+ __ string_equals($str1$$Register, $str2$$Register,
+ $cnt$$Register, $result$$Register,
+ $tmp$$Register);
+ %}
+ ins_pipe(pipe_class_memory);
+%}
+
// ============================================================================
// This name is KNOWN by the ADLC and cannot be changed.
// The ADLC forces a 'TypeRawPtr::BOTTOM' output type
diff -r 1f7e1e16a534 -r fd73d7b8ba5d src/cpu/aarch64/vm/macroAssembler_aarch64.cpp
--- a/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp Fri Jun 27 06:13:30 2014 -0400
+++ b/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp Wed Jul 02 10:21:04 2014 -0400
@@ -3436,3 +3436,78 @@
BLOCK_COMMENT("} string_compare");
}
+
+
+void MacroAssembler::string_equals(Register str1, Register str2,
+ Register cnt, Register result,
+ Register tmp1) {
+ Label SAME_CHARS, DONE, SHORT_LOOP, SHORT_STRING,
+ NEXT_WORD;
+
+ const Register tmp2 = rscratch1;
+ assert_different_registers(str1, str2, cnt, result, tmp1, tmp2, rscratch2);
+
+ BLOCK_COMMENT("string_equals {");
+
+ // Start by assuming that the strings are not equal.
+ mov(result, zr);
+
+ // A very short string
+ cmpw(cnt, 4);
+ br(Assembler::LT, SHORT_STRING);
+
+ // Check if the strings start at the same location.
+ cmp(str1, str2);
+ br(Assembler::EQ, SAME_CHARS);
+
+ // Compare longwords
+ {
+ subw(cnt, cnt, 4); // The last longword is a special case
+
+ // Move both string pointers to the last longword of their
+ // strings, negate the remaining count, and convert it to bytes.
+ lea(str1, Address(str1, cnt, Address::uxtw(1)));
+ lea(str2, Address(str2, cnt, Address::uxtw(1)));
+ sub(cnt, zr, cnt, LSL, 1);
+
+ // Loop, loading longwords and comparing them into rscratch2.
+ bind(NEXT_WORD);
+ ldr(tmp1, Address(str1, cnt));
+ ldr(tmp2, Address(str2, cnt));
+ adds(cnt, cnt, wordSize);
+ eor(rscratch2, tmp1, tmp2);
+ cbnz(rscratch2, DONE);
+ br(Assembler::LT, NEXT_WORD);
+
+ // Last longword. In the case where length == 4 we compare the
+ // same longword twice, but that's still faster than another
+ // conditional branch.
+
+ ldr(tmp1, Address(str1));
+ ldr(tmp2, Address(str2));
+ eor(rscratch2, tmp1, tmp2);
+ cbz(rscratch2, SAME_CHARS);
+ b(DONE);
+ }
+
+ bind(SHORT_STRING);
+ // Is the length zero?
+ cbz(cnt, SAME_CHARS);
+
+ bind(SHORT_LOOP);
+ load_unsigned_short(tmp1, Address(post(str1, 2)));
+ load_unsigned_short(tmp2, Address(post(str2, 2)));
+ subw(tmp1, tmp1, tmp2);
+ cbnz(tmp1, DONE);
+ sub(cnt, cnt, 1);
+ cbnz(cnt, SHORT_LOOP);
+
+ // Strings are equal.
+ bind(SAME_CHARS);
+ mov(result, true);
+
+ // That's it
+ bind(DONE);
+
+ BLOCK_COMMENT("} string_equals");
+}
diff -r 1f7e1e16a534 -r fd73d7b8ba5d src/cpu/aarch64/vm/macroAssembler_aarch64.hpp
--- a/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp Fri Jun 27 06:13:30 2014 -0400
+++ b/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp Wed Jul 02 10:21:04 2014 -0400
@@ -1292,8 +1292,11 @@
bool upper = false);
void string_compare(Register str1, Register str2,
- Register cnt1, Register cnt2, Register result,
- Register vec1);
+ Register cnt1, Register cnt2, Register result,
+ Register vec1);
+ void string_equals(Register str1, Register str2,
+ Register cnt, Register result,
+ Register tmp1);
};
// Used by aarch64.ad to control code generation
More information about the aarch64-port-dev
mailing list