< prev index next >

src/cpu/aarch64/vm/macroAssembler_aarch64.cpp

Print this page
rev 10285 : 8149733: AArch64: refactor array_equals/string_equals
Summary: combine similar code for string_equals/char_array_equals/byte_array_equals into same implemenation
Reviewed-by: duke


4464   cbz(cnt2, LENGTH_DIFF);
4465 
4466   bind(SHORT_LOOP);
4467   load_unsigned_short(result, Address(post(str1, 2)));
4468   load_unsigned_short(cnt1, Address(post(str2, 2)));
4469   subw(result, result, cnt1);
4470   cbnz(result, DONE);
4471   sub(cnt2, cnt2, 1);
4472   cbnz(cnt2, SHORT_LOOP);
4473 
4474   // Strings are equal up to min length.  Return the length difference.
4475   bind(LENGTH_DIFF);
4476   mov(result, tmp1);
4477 
4478   // That's it
4479   bind(DONE);
4480 
4481   BLOCK_COMMENT("} string_compare");
4482 }
4483 

4484 
4485 void MacroAssembler::string_equals(Register str1, Register str2,
4486                                    Register cnt, Register result,
4487                                    Register tmp1) {
4488   Label SAME_CHARS, DONE, SHORT_LOOP, SHORT_STRING,
4489     NEXT_WORD;
4490 
4491   const Register tmp2 = rscratch1;
4492   assert_different_registers(str1, str2, cnt, result, tmp1, tmp2, rscratch2);
4493 
4494   BLOCK_COMMENT("string_equals {");

4495 
4496   // Start by assuming that the strings are not equal.
4497   mov(result, zr);
4498 
4499   // A very short string
4500   cmpw(cnt, 4);
4501   br(Assembler::LT, SHORT_STRING);

4502 
4503   // Check if the strings start at the same location.
4504   cmp(str1, str2);
4505   br(Assembler::EQ, SAME_CHARS);
4506 
4507   // Compare longwords
4508   {
4509     subw(cnt, cnt, 4); // The last longword is a special case
4510 
4511     // Move both string pointers to the last longword of their
4512     // strings, negate the remaining count, and convert it to bytes.
4513     lea(str1, Address(str1, cnt, Address::uxtw(1)));
4514     lea(str2, Address(str2, cnt, Address::uxtw(1)));
4515     sub(cnt, zr, cnt, LSL, 1);
4516 
4517     // Loop, loading longwords and comparing them into rscratch2.
4518     bind(NEXT_WORD);
4519     ldr(tmp1, Address(str1, cnt));
4520     ldr(tmp2, Address(str2, cnt));
4521     adds(cnt, cnt, wordSize);
4522     eor(rscratch2, tmp1, tmp2);
4523     cbnz(rscratch2, DONE);
4524     br(Assembler::LT, NEXT_WORD);
4525 
4526     // Last longword.  In the case where length == 4 we compare the
4527     // same longword twice, but that's still faster than another
4528     // conditional branch.
4529 
4530     ldr(tmp1, Address(str1));
4531     ldr(tmp2, Address(str2));
4532     eor(rscratch2, tmp1, tmp2);
4533     cbz(rscratch2, SAME_CHARS);
4534     b(DONE);
4535   }
4536 
4537   bind(SHORT_STRING);
4538   // Is the length zero?
4539   cbz(cnt, SAME_CHARS);
4540 
4541   bind(SHORT_LOOP);
4542   load_unsigned_short(tmp1, Address(post(str1, 2)));
4543   load_unsigned_short(tmp2, Address(post(str2, 2)));
4544   subw(tmp1, tmp1, tmp2);
4545   cbnz(tmp1, DONE);
4546   sub(cnt, cnt, 1);
4547   cbnz(cnt, SHORT_LOOP);
4548 
4549   // Strings are equal.
4550   bind(SAME_CHARS);
4551   mov(result, true);
4552 
4553   // That's it
4554   bind(DONE);
4555 
4556   BLOCK_COMMENT("} string_equals");
4557 }
4558 
4559 
4560 void MacroAssembler::byte_arrays_equals(Register ary1, Register ary2,
4561                                         Register result, Register tmp1)
4562 {
4563   Register cnt1 = rscratch1;
4564   Register cnt2 = rscratch2;
4565   Register tmp2 = rscratch2;
4566 
4567   Label SAME, DIFFER, NEXT, TAIL07, TAIL03, TAIL01;
4568 
4569   int length_offset  = arrayOopDesc::length_offset_in_bytes();
4570   int base_offset    = arrayOopDesc::base_offset_in_bytes(T_BYTE);
4571 
4572   BLOCK_COMMENT("byte_arrays_equals  {");
4573 
4574     // different until proven equal
4575     mov(result, false);
4576 
4577     // same array?
4578     cmp(ary1, ary2);
4579     br(Assembler::EQ, SAME);
4580 
4581     // ne if either null
4582     cbz(ary1, DIFFER);
4583     cbz(ary2, DIFFER);
4584 
4585     // lengths ne?
4586     ldrw(cnt1, Address(ary1, length_offset));
4587     ldrw(cnt2, Address(ary2, length_offset));
4588     cmp(cnt1, cnt2);
4589     br(Assembler::NE, DIFFER);
4590 
4591     lea(ary1, Address(ary1, base_offset));
4592     lea(ary2, Address(ary2, base_offset));
4593 
4594     subs(cnt1, cnt1, 8);
4595     br(LT, TAIL07);
4596 
4597   BIND(NEXT);
4598     ldr(tmp1, Address(post(ary1, 8)));
4599     ldr(tmp2, Address(post(ary2, 8)));
4600     subs(cnt1, cnt1, 8);
4601     eor(tmp1, tmp1, tmp2);
4602     cbnz(tmp1, DIFFER);
4603     br(GE, NEXT);
4604 
4605   BIND(TAIL07);  // 0-7 bytes left, cnt1 = #bytes left - 4
4606     tst(cnt1, 0b100);
4607     br(EQ, TAIL03);
4608     ldrw(tmp1, Address(post(ary1, 4)));
4609     ldrw(tmp2, Address(post(ary2, 4)));
4610     cmp(tmp1, tmp2);
4611     br(NE, DIFFER);
4612 
4613   BIND(TAIL03);  // 0-3 bytes left, cnt1 = #bytes left - 4
4614     tst(cnt1, 0b10);
4615     br(EQ, TAIL01);
4616     ldrh(tmp1, Address(post(ary1, 2)));
4617     ldrh(tmp2, Address(post(ary2, 2)));
4618     cmp(tmp1, tmp2);
4619     br(NE, DIFFER);
4620   BIND(TAIL01);  // 0-1 byte left
4621     tst(cnt1, 0b01);
4622     br(EQ, SAME);
4623     ldrb(tmp1, ary1);
4624     ldrb(tmp2, ary2);
4625     cmp(tmp1, tmp2);
4626     br(NE, DIFFER);
4627 
4628   BIND(SAME);
4629     mov(result, true);
4630   BIND(DIFFER); // result already set
4631 
4632   BLOCK_COMMENT("} byte_arrays_equals");
4633 }
4634 
4635 // Compare char[] arrays aligned to 4 bytes
4636 void MacroAssembler::char_arrays_equals(Register ary1, Register ary2,
4637                                         Register result, Register tmp1)
4638 {
4639   Register cnt1 = rscratch1;
4640   Register cnt2 = rscratch2;
4641   Register tmp2 = rscratch2;
4642 
4643   Label SAME, DIFFER, NEXT, TAIL03, TAIL01;
4644 
4645   int length_offset  = arrayOopDesc::length_offset_in_bytes();
4646   int base_offset    = arrayOopDesc::base_offset_in_bytes(T_CHAR);
4647 
4648   BLOCK_COMMENT("char_arrays_equals  {");














4649 
4650     // different until proven equal
4651     mov(result, false);

4652 
4653     // same array?
4654     cmp(ary1, ary2);
4655     br(Assembler::EQ, SAME);
4656 
4657     // ne if either null
4658     cbz(ary1, DIFFER);
4659     cbz(ary2, DIFFER);
4660 
4661     // lengths ne?
4662     ldrw(cnt1, Address(ary1, length_offset));
4663     ldrw(cnt2, Address(ary2, length_offset));
4664     cmp(cnt1, cnt2);
4665     br(Assembler::NE, DIFFER);
4666 
4667     lea(ary1, Address(ary1, base_offset));
4668     lea(ary2, Address(ary2, base_offset));
4669 
4670     subs(cnt1, cnt1, 4);
4671     br(LT, TAIL03);
4672 
4673   BIND(NEXT);
4674     ldr(tmp1, Address(post(ary1, 8)));
4675     ldr(tmp2, Address(post(ary2, 8)));
4676     subs(cnt1, cnt1, 4);
4677     eor(tmp1, tmp1, tmp2);
4678     cbnz(tmp1, DIFFER);
4679     br(GE, NEXT);
4680 
4681   BIND(TAIL03);  // 0-3 chars left, cnt1 = #chars left - 4
4682     tst(cnt1, 0b10);
4683     br(EQ, TAIL01);
4684     ldrw(tmp1, Address(post(ary1, 4)));
4685     ldrw(tmp2, Address(post(ary2, 4)));
4686     cmp(tmp1, tmp2);
4687     br(NE, DIFFER);
4688   BIND(TAIL01);  // 0-1 chars left
4689     tst(cnt1, 0b01);
4690     br(EQ, SAME);
4691     ldrh(tmp1, ary1);
4692     ldrh(tmp2, ary2);
4693     cmp(tmp1, tmp2);
4694     br(NE, DIFFER);
4695 
4696   BIND(SAME);


























4697     mov(result, true);
4698   BIND(DIFFER); // result already set
4699 
4700   BLOCK_COMMENT("} char_arrays_equals");


4701 }

4702 
4703 // encode char[] to byte[] in ISO_8859_1
4704 void MacroAssembler::encode_iso_array(Register src, Register dst,
4705                       Register len, Register result,
4706                       FloatRegister Vtmp1, FloatRegister Vtmp2,
4707                       FloatRegister Vtmp3, FloatRegister Vtmp4)
4708 {
4709     Label DONE, NEXT_32, LOOP_8, NEXT_8, LOOP_1, NEXT_1;
4710     Register tmp1 = rscratch1;
4711 
4712       mov(result, len); // Save initial len
4713 
4714 #ifndef BUILTIN_SIM
4715       subs(len, len, 32);
4716       br(LT, LOOP_8);
4717 
4718 // The following code uses the SIMD 'uqxtn' and 'uqxtn2' instructions
4719 // to convert chars to bytes. These set the 'QC' bit in the FPSR if
4720 // any char could not fit in a byte, so clear the FPSR so we can test it.
4721       clear_fpsr();




4464   cbz(cnt2, LENGTH_DIFF);
4465 
4466   bind(SHORT_LOOP);
4467   load_unsigned_short(result, Address(post(str1, 2)));
4468   load_unsigned_short(cnt1, Address(post(str2, 2)));
4469   subw(result, result, cnt1);
4470   cbnz(result, DONE);
4471   sub(cnt2, cnt2, 1);
4472   cbnz(cnt2, SHORT_LOOP);
4473 
4474   // Strings are equal up to min length.  Return the length difference.
4475   bind(LENGTH_DIFF);
4476   mov(result, tmp1);
4477 
4478   // That's it
4479   bind(DONE);
4480 
4481   BLOCK_COMMENT("} string_compare");
4482 }
4483 
4484 // Compare Strings or char/byte arrays.
4485 
4486 // is_string is true iff this is a string comparison.




4487 
4488 // For Strings we're passed the address of the first characters in a1
4489 // and a2 and the length in cnt1.
4490 
4491 // For byte and char arrays we're passed the arrays themselves and we
4492 // have to extract length fields and do null checks here.
4493 
4494 // elem_size is the element size in bytes: either 1 or 2.

4495 
4496 // There are two implementations.  For arrays >= 8 bytes, all
4497 // comparisons (including the final one, which may overlap) are
4498 // performed 8 bytes at a time.  For arrays < 8 bytes, we compare a
4499 // halfword, then a short, and then a byte.
4500 
4501 void MacroAssembler::arrays_equals(Register a1, Register a2,
4502                                    Register result, Register cnt1,
4503                                    int elem_size, bool is_string)
























































4504 {
4505   Label SAME, DONE, SHORT, NEXT_WORD, ONE;
4506   Register tmp1 = rscratch1;
4507   Register tmp2 = rscratch2;
4508   Register cnt2 = tmp2;  // cnt2 only used in array length compare
4509   int elem_per_word = wordSize/elem_size;
4510   int log_elem_size = exact_log2(elem_size);
4511   int length_offset = arrayOopDesc::length_offset_in_bytes();
4512   int base_offset
4513     = arrayOopDesc::base_offset_in_bytes(elem_size == 2 ? T_CHAR : T_BYTE);
































4514 
4515   assert(elem_size == 1 || elem_size == 2, "must be char or byte");
4516   assert_different_registers(a1, a2, result, cnt1, rscratch1, rscratch2);




















4517 
4518   BLOCK_COMMENT(is_string ? "string_equals {" : "array_equals {");















4519 
4520   mov(result, false);

4521 
4522   if (!is_string) {
4523     // if (a==a2)
4524     //     return true;
4525     eor(rscratch1, a1, a2);
4526     cbz(rscratch1, SAME);
4527     // if (a==null || a2==null)
4528     //     return false;
4529     cbz(a1, DONE);
4530     cbz(a2, DONE);
4531     // if (a1.length != a2.length)
4532     //      return false;
4533     ldrw(cnt1, Address(a1, length_offset));
4534     ldrw(cnt2, Address(a2, length_offset));
4535     eorw(tmp1, cnt1, cnt2);
4536     cbnzw(tmp1, DONE);
4537 
4538     lea(a1, Address(a1, base_offset));
4539     lea(a2, Address(a2, base_offset));
4540   }
4541 
4542   // Check for short strings, i.e. smaller than wordSize.
4543   subs(cnt1, cnt1, elem_per_word);
4544   br(Assembler::LT, SHORT);
4545   // Main 8 byte comparison loop.
4546   bind(NEXT_WORD); {
4547     ldr(tmp1, Address(post(a1, wordSize)));
4548     ldr(tmp2, Address(post(a2, wordSize)));
4549     subs(cnt1, cnt1, elem_per_word);
4550     eor(tmp1, tmp1, tmp2);
4551     cbnz(tmp1, DONE);
4552   } br(GT, NEXT_WORD);
4553   // Last longword.  In the case where length == 4 we compare the
4554   // same longword twice, but that's still faster than another
4555   // conditional branch.
4556   // cnt1 could be 0, -1, -2, -3, -4 for chars; -4 only happens when
4557   // length == 4.
4558   if (log_elem_size > 0)
4559     lsl(cnt1, cnt1, log_elem_size);
4560   ldr(tmp1, Address(a1, cnt1));
4561   ldr(tmp2, Address(a2, cnt1));




4562   eor(tmp1, tmp1, tmp2);
4563   cbnz(tmp1, DONE);
4564   b(SAME);
4565 
4566   bind(SHORT);
4567   Label TAIL03, TAIL01;












4568 
4569   tbz(cnt1, 2 - log_elem_size, TAIL03); // 0-7 bytes left.
4570   {
4571     ldrw(tmp1, Address(post(a1, 4)));
4572     ldrw(tmp2, Address(post(a2, 4)));
4573     eorw(tmp1, tmp1, tmp2);
4574     cbnzw(tmp1, DONE);
4575   }
4576   bind(TAIL03);
4577   tbz(cnt1, 1 - log_elem_size, TAIL01); // 0-3 bytes left.
4578   {
4579     ldrh(tmp1, Address(post(a1, 2)));
4580     ldrh(tmp2, Address(post(a2, 2)));
4581     eorw(tmp1, tmp1, tmp2);
4582     cbnzw(tmp1, DONE);
4583   }
4584   bind(TAIL01);
4585   if (elem_size == 1) { // Only needed when comparing byte arrays.
4586     tbz(cnt1, 0, SAME); // 0-1 bytes left.
4587     {
4588       ldrb(tmp1, a1);
4589       ldrb(tmp2, a2);
4590       eorw(tmp1, tmp1, tmp2);
4591       cbnzw(tmp1, DONE);
4592     }
4593   }
4594   // Arrays are equal.
4595   bind(SAME);
4596   mov(result, true);

4597 
4598   // That's it.
4599   bind(DONE);
4600   BLOCK_COMMENT(is_string ? "} string_equals" : "} array_equals");
4601 }
4602 
4603 
4604 // encode char[] to byte[] in ISO_8859_1
4605 void MacroAssembler::encode_iso_array(Register src, Register dst,
4606                       Register len, Register result,
4607                       FloatRegister Vtmp1, FloatRegister Vtmp2,
4608                       FloatRegister Vtmp3, FloatRegister Vtmp4)
4609 {
4610     Label DONE, NEXT_32, LOOP_8, NEXT_8, LOOP_1, NEXT_1;
4611     Register tmp1 = rscratch1;
4612 
4613       mov(result, len); // Save initial len
4614 
4615 #ifndef BUILTIN_SIM
4616       subs(len, len, 32);
4617       br(LT, LOOP_8);
4618 
4619 // The following code uses the SIMD 'uqxtn' and 'uqxtn2' instructions
4620 // to convert chars to bytes. These set the 'QC' bit in the FPSR if
4621 // any char could not fit in a byte, so clear the FPSR so we can test it.
4622       clear_fpsr();


< prev index next >