< prev index next >
src/cpu/aarch64/vm/macroAssembler_aarch64.cpp
Print this page
rev 11237 : 8156943: aarch64: string compare does not support CompactStrings
Summary: Implement LL encoding for StrComp intrinsic
Reviewed-by: aph
@@ -4475,40 +4475,50 @@
BIND(MATCH);
add(result, result_tmp, cnt2_neg, ASR, 1);
BIND(DONE);
}
+typedef void (MacroAssembler::* chr_insn)(Register Rt, const Address &adr);
+typedef void (MacroAssembler::* uxt_insn)(Register Rd, Register Rn);
+
// Compare strings.
void MacroAssembler::string_compare(Register str1, Register str2,
Register cnt1, Register cnt2, Register result,
- Register tmp1) {
+ Register tmp1, int ae) {
Label LENGTH_DIFF, DONE, SHORT_LOOP, SHORT_STRING,
NEXT_WORD, DIFFERENCE;
+ guarantee(ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::UU, "unhandled argument encoding");
+ bool isL = ae == StrIntrinsicNode::LL;
+ int chr_shift = isL ? 0:1;
+ int chr_size = isL ? 1:2;
+ chr_insn load_chr = isL ? (chr_insn)&MacroAssembler::ldrb : (chr_insn)&MacroAssembler::ldrh;
+ uxt_insn ext_chr = isL ? (uxt_insn)&MacroAssembler::uxtbw : (uxt_insn)&MacroAssembler::uxthw;
+
BLOCK_COMMENT("string_compare {");
// Compute the minimum of the string lengths and save the difference.
subsw(tmp1, cnt1, cnt2);
cselw(cnt2, cnt1, cnt2, Assembler::LE); // min
// A very short string
- cmpw(cnt2, 4);
+ cmpw(cnt2, 8/chr_size);
br(Assembler::LT, SHORT_STRING);
// Check if the strings start at the same location.
cmp(str1, str2);
br(Assembler::EQ, LENGTH_DIFF);
// Compare longwords
{
- subw(cnt2, cnt2, 4); // The last longword is a special case
+ subw(cnt2, cnt2, 8/chr_size); // 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, cnt2, Address::uxtw(1)));
- lea(str2, Address(str2, cnt2, Address::uxtw(1)));
- sub(cnt2, zr, cnt2, LSL, 1);
+ lea(str1, Address(str1, cnt2, Address::uxtw(chr_shift)));
+ lea(str2, Address(str2, cnt2, Address::uxtw(chr_shift)));
+ sub(cnt2, zr, cnt2, LSL, chr_shift);
// Loop, loading longwords and comparing them into rscratch2.
bind(NEXT_WORD);
ldr(result, Address(str1, cnt2));
ldr(cnt1, Address(str2, cnt2));
@@ -4529,26 +4539,26 @@
// Find the first different characters in the longwords and
// compute their difference.
bind(DIFFERENCE);
rev(rscratch2, rscratch2);
clz(rscratch2, rscratch2);
- andr(rscratch2, rscratch2, -16);
+ andr(rscratch2, rscratch2, isL ? -8 : -16);
lsrv(result, result, rscratch2);
- uxthw(result, result);
+ (this->*ext_chr)(result, result);
lsrv(cnt1, cnt1, rscratch2);
- uxthw(cnt1, cnt1);
+ (this->*ext_chr)(cnt1, cnt1);
subw(result, result, cnt1);
b(DONE);
}
bind(SHORT_STRING);
// Is the minimum length zero?
cbz(cnt2, LENGTH_DIFF);
bind(SHORT_LOOP);
- load_unsigned_short(result, Address(post(str1, 2)));
- load_unsigned_short(cnt1, Address(post(str2, 2)));
+ (this->*load_chr)(result, Address(post(str1, chr_size)));
+ (this->*load_chr)(cnt1, Address(post(str2, chr_size)));
subw(result, result, cnt1);
cbnz(result, DONE);
sub(cnt2, cnt2, 1);
cbnz(cnt2, SHORT_LOOP);
< prev index next >