aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoraph <none@none>2014-08-04 12:00:05 -0400
committeraph <none@none>2014-08-04 12:00:05 -0400
commit5179fe4960c995b995e084ee173d46e06f4899fc (patch)
tree24353e24bb72e139803eea7af02ae59d49912295
parentc65e11f7f1db5f320caabaf67e8c024e11a24a06 (diff)
parent3713e6f0e012787cf5a0a221e164cf35114ddb80 (diff)
Merge
-rw-r--r--src/cpu/aarch64/vm/aarch64.ad14
-rw-r--r--src/cpu/aarch64/vm/macroAssembler_aarch64.cpp68
-rw-r--r--src/cpu/aarch64/vm/macroAssembler_aarch64.hpp2
3 files changed, 84 insertions, 0 deletions
diff --git a/src/cpu/aarch64/vm/aarch64.ad b/src/cpu/aarch64/vm/aarch64.ad
index 0fc3438ba..e1f5a44f4 100644
--- a/src/cpu/aarch64/vm/aarch64.ad
+++ b/src/cpu/aarch64/vm/aarch64.ad
@@ -11677,6 +11677,20 @@ instruct string_equals(iRegP_R1 str1, iRegP_R3 str2, iRegI_R4 cnt,
ins_pipe(pipe_class_memory);
%}
+instruct array_equals(iRegP_R1 ary1, iRegP_R2 ary2, iRegI_R0 result,
+ iRegP_R10 tmp, rFlagsReg cr)
+%{
+ match(Set result (AryEq ary1 ary2));
+ effect(KILL tmp, USE_KILL ary1, USE_KILL ary2, KILL cr);
+
+ format %{ "Array Equals $ary1,ary2 -> $result // KILL $tmp" %}
+ ins_encode %{
+ __ char_arrays_equals($ary1$$Register, $ary2$$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 --git a/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp b/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp
index 1c0432232..a00726d37 100644
--- a/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp
+++ b/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp
@@ -3545,3 +3545,71 @@ void MacroAssembler::string_equals(Register str1, Register str2,
BLOCK_COMMENT("} string_equals");
}
+
+// Compare char[] arrays aligned to 4 bytes
+void MacroAssembler::char_arrays_equals(Register ary1, Register ary2,
+ Register result, Register tmp1)
+{
+ Register cnt1 = rscratch1;
+ Register cnt2 = rscratch2;
+ Register tmp2 = rscratch2;
+
+ Label SAME, DIFFER, NEXT, TAIL03, TAIL01;
+
+ int length_offset = arrayOopDesc::length_offset_in_bytes();
+ int base_offset = arrayOopDesc::base_offset_in_bytes(T_CHAR);
+
+ BLOCK_COMMENT("char_arrays_equals {");
+
+ // different until proven equal
+ mov(result, false);
+
+ // same array?
+ cmp(ary1, ary2);
+ br(Assembler::EQ, SAME);
+
+ // ne if either null
+ cbz(ary1, DIFFER);
+ cbz(ary2, DIFFER);
+
+ // lengths ne?
+ ldrw(cnt1, Address(ary1, length_offset));
+ ldrw(cnt2, Address(ary2, length_offset));
+ cmp(cnt1, cnt2);
+ br(Assembler::NE, DIFFER);
+
+ lea(ary1, Address(ary1, base_offset));
+ lea(ary2, Address(ary2, base_offset));
+
+ subs(cnt1, cnt1, 4);
+ br(LT, TAIL03);
+
+ BIND(NEXT);
+ ldr(tmp1, Address(post(ary1, 8)));
+ ldr(tmp2, Address(post(ary2, 8)));
+ subs(cnt1, cnt1, 4);
+ eor(tmp1, tmp1, tmp2);
+ cbnz(tmp1, DIFFER);
+ br(GE, NEXT);
+
+ BIND(TAIL03); // 0-3 chars left, cnt1 = #chars left - 4
+ tst(cnt1, 0b10);
+ br(EQ, TAIL01);
+ ldrw(tmp1, Address(post(ary1, 4)));
+ ldrw(tmp2, Address(post(ary2, 4)));
+ cmp(tmp1, tmp2);
+ br(NE, DIFFER);
+ BIND(TAIL01); // 0-1 chars left
+ tst(cnt1, 0b01);
+ br(EQ, SAME);
+ ldrh(tmp1, ary1);
+ ldrh(tmp2, ary2);
+ cmp(tmp1, tmp2);
+ br(NE, DIFFER);
+
+ BIND(SAME);
+ mov(result, true);
+ BIND(DIFFER); // result already set
+
+ BLOCK_COMMENT("} char_arrays_equals");
+}
diff --git a/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp b/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp
index 1caabb8eb..77274d855 100644
--- a/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp
+++ b/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp
@@ -1085,6 +1085,8 @@ public:
void string_equals(Register str1, Register str2,
Register cnt, Register result,
Register tmp1);
+ void char_arrays_equals(Register ary1, Register ary2,
+ Register result, Register tmp1);
};
// Used by aarch64.ad to control code generation