< 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 >