@@ -11677,6 +11677,20 @@
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
@@ -3512,3 +3512,71 @@
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");
+}
@@ -1085,6 +1085,8 @@
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