src/cpu/sparc/vm/sparc.ad
Index
Unified diffs
Context diffs
Sdiffs
Wdiffs
Patch
New
Old
Previous File
Next File
*** old/src/cpu/sparc/vm/sparc.ad Tue Aug 18 19:06:12 2009
--- new/src/cpu/sparc/vm/sparc.ad Tue Aug 18 19:06:12 2009
*** 2836,2911 ****
--- 2836,2889 ----
__ delayed()-> stx(G0, base_pointer_arg, nof_bytes_tmp);
// %%%% this mini-loop must not cross a cache boundary!
%}
! enc_class enc_String_Compare(o0RegP str1, o1RegP str2, g3RegP tmp1, g4RegP tmp2, notemp_iRegI result) %{
! enc_class enc_String_Compare(o0RegP str1, o1RegP str2, g3RegI cnt1, g4RegI cnt2, notemp_iRegI result) %{
Label Ldone, Lloop;
MacroAssembler _masm(&cbuf);
Register str1_reg = reg_to_register_object($str1$$reg);
Register str2_reg = reg_to_register_object($str2$$reg);
! Register tmp1_reg = reg_to_register_object($tmp1$$reg);
! Register tmp2_reg = reg_to_register_object($tmp2$$reg);
! Register cnt1_reg = reg_to_register_object($cnt1$$reg);
! Register cnt2_reg = reg_to_register_object($cnt2$$reg);
Register result_reg = reg_to_register_object($result$$reg);
// Get the first character position in both strings
// [8] char array, [12] offset, [16] count
int value_offset = java_lang_String:: value_offset_in_bytes();
int offset_offset = java_lang_String::offset_offset_in_bytes();
! int count_offset = java_lang_String:: count_offset_in_bytes();
+ assert(result_reg != str1_reg &&
+ result_reg != str2_reg &&
+ result_reg != cnt1_reg &&
+ result_reg != cnt2_reg ,
! "need different registers");
// load str1 (jchar*) base address into tmp1_reg
__ load_heap_oop(str1_reg, value_offset, tmp1_reg);
__ ld(str1_reg, offset_offset, result_reg);
__ add(tmp1_reg, arrayOopDesc::base_offset_in_bytes(T_CHAR), tmp1_reg);
__ ld(str1_reg, count_offset, str1_reg); // hoisted
__ sll(result_reg, exact_log2(sizeof(jchar)), result_reg);
__ load_heap_oop(str2_reg, value_offset, tmp2_reg); // hoisted
__ add(result_reg, tmp1_reg, tmp1_reg);
// load str2 (jchar*) base address into tmp2_reg
// __ ld_ptr(str2_reg, value_offset, tmp2_reg); // hoisted
__ ld(str2_reg, offset_offset, result_reg);
__ add(tmp2_reg, arrayOopDesc::base_offset_in_bytes(T_CHAR), tmp2_reg);
__ ld(str2_reg, count_offset, str2_reg); // hoisted
__ sll(result_reg, exact_log2(sizeof(jchar)), result_reg);
__ subcc(str1_reg, str2_reg, O7); // hoisted
__ add(result_reg, tmp2_reg, tmp2_reg);
// Compute the minimum of the string lengths(str1_reg) and the
// difference of the string lengths (stack)
// discard string base pointers, after loading up the lengths
// __ ld(str1_reg, count_offset, str1_reg); // hoisted
// __ ld(str2_reg, count_offset, str2_reg); // hoisted
// See if the lengths are different, and calculate min in str1_reg.
// Stash diff in O7 in case we need it for a tie-breaker.
Label Lskip;
// __ subcc(str1_reg, str2_reg, O7); // hoisted
! __ sll(str1_reg, exact_log2(sizeof(jchar)), str1_reg); // scale the limit
+ __ subcc(cnt1_reg, cnt2_reg, O7);
! __ sll(cnt1_reg, exact_log2(sizeof(jchar)), cnt1_reg); // scale the limit
__ br(Assembler::greater, true, Assembler::pt, Lskip);
! // str2 is shorter, so use its count:
! __ delayed()->sll(str2_reg, exact_log2(sizeof(jchar)), str1_reg); // scale the limit
! // cnt2 is shorter, so use its count:
! __ delayed()->sll(cnt2_reg, exact_log2(sizeof(jchar)), cnt1_reg); // scale the limit
__ bind(Lskip);
! // reallocate str1_reg, str2_reg, result_reg
! // reallocate cnt1_reg, cnt2_reg, result_reg
// Note: limit_reg holds the string length pre-scaled by 2
! Register limit_reg = str1_reg;
! Register chr2_reg = str2_reg;
! Register limit_reg = cnt1_reg;
! Register chr2_reg = cnt2_reg;
Register chr1_reg = result_reg;
! // tmp{12} are the base pointers
! // str{12} are the base pointers
// Is the minimum length zero?
__ cmp(limit_reg, (int)(0 * sizeof(jchar))); // use cast to resolve overloading ambiguity
__ br(Assembler::equal, true, Assembler::pn, Ldone);
__ delayed()->mov(O7, result_reg); // result is difference in lengths
// Load first characters
! __ lduh(tmp1_reg, 0, chr1_reg);
! __ lduh(tmp2_reg, 0, chr2_reg);
! __ lduh(str1_reg, 0, chr1_reg);
! __ lduh(str2_reg, 0, chr2_reg);
// Compare first characters
__ subcc(chr1_reg, chr2_reg, chr1_reg);
__ br(Assembler::notZero, false, Assembler::pt, Ldone);
assert(chr1_reg == result_reg, "result must be pre-placed");
*** 2913,2923 ****
--- 2891,2901 ----
{
// Check after comparing first character to see if strings are equivalent
Label LSkip2;
// Check if the strings start at same location
! __ cmp(tmp1_reg, tmp2_reg);
! __ cmp(str1_reg, str2_reg);
__ brx(Assembler::notEqual, true, Assembler::pt, LSkip2);
__ delayed()->nop();
// Check if the length difference is zero (in O7)
__ cmp(G0, O7);
*** 2930,3069 ****
--- 2908,3028 ----
__ subcc(limit_reg, 1 * sizeof(jchar), chr1_reg);
__ br(Assembler::equal, true, Assembler::pn, Ldone);
__ delayed()->mov(O7, result_reg); // result is difference in lengths
! // Shift tmp1_reg and tmp2_reg to the end of the arrays, negate limit
! __ add(tmp1_reg, limit_reg, tmp1_reg);
! __ add(tmp2_reg, limit_reg, tmp2_reg);
! // Shift str1_reg and str2_reg to the end of the arrays, negate limit
! __ add(str1_reg, limit_reg, str1_reg);
! __ add(str2_reg, limit_reg, str2_reg);
__ neg(chr1_reg, limit_reg); // limit = -(limit-2)
// Compare the rest of the characters
! __ lduh(tmp1_reg, limit_reg, chr1_reg);
! __ lduh(str1_reg, limit_reg, chr1_reg);
__ bind(Lloop);
! // __ lduh(tmp1_reg, limit_reg, chr1_reg); // hoisted
! __ lduh(tmp2_reg, limit_reg, chr2_reg);
! // __ lduh(str1_reg, limit_reg, chr1_reg); // hoisted
! __ lduh(str2_reg, limit_reg, chr2_reg);
__ subcc(chr1_reg, chr2_reg, chr1_reg);
__ br(Assembler::notZero, false, Assembler::pt, Ldone);
assert(chr1_reg == result_reg, "result must be pre-placed");
__ delayed()->inccc(limit_reg, sizeof(jchar));
// annul LDUH if branch is not taken to prevent access past end of string
__ br(Assembler::notZero, true, Assembler::pt, Lloop);
! __ delayed()->lduh(tmp1_reg, limit_reg, chr1_reg); // hoisted
! __ delayed()->lduh(str1_reg, limit_reg, chr1_reg); // hoisted
// If strings are equal up to min length, return the length difference.
__ mov(O7, result_reg);
// Otherwise, return the difference between the first mismatched chars.
__ bind(Ldone);
%}
! enc_class enc_String_Equals(o0RegP str1, o1RegP str2, g3RegP tmp1, g4RegP tmp2, notemp_iRegI result) %{
- Label Lword, Lword_loop, Lpost_word, Lchar, Lchar_loop, Ldone;
! enc_class enc_String_Equals(o0RegP str1, o1RegP str2, g3RegI cnt, g4RegI tmp1, notemp_iRegI result) %{
! Label Lword_loop, Lpost_word, Lchar, Lchar_loop, Ldone;
MacroAssembler _masm(&cbuf);
Register str1_reg = reg_to_register_object($str1$$reg);
Register str2_reg = reg_to_register_object($str2$$reg);
+ Register cnt_reg = reg_to_register_object($cnt$$reg);
Register tmp1_reg = reg_to_register_object($tmp1$$reg);
Register tmp2_reg = reg_to_register_object($tmp2$$reg);
Register result_reg = reg_to_register_object($result$$reg);
// Get the first character position in both strings
// [8] char array, [12] offset, [16] count
int value_offset = java_lang_String:: value_offset_in_bytes();
int offset_offset = java_lang_String::offset_offset_in_bytes();
! int count_offset = java_lang_String:: count_offset_in_bytes();
+ assert(result_reg != str1_reg &&
+ result_reg != str2_reg &&
+ result_reg != cnt_reg &&
+ result_reg != tmp1_reg ,
! "need different registers");
// load str1 (jchar*) base address into tmp1_reg
__ load_heap_oop(Address(str1_reg, value_offset), tmp1_reg);
__ ld(Address(str1_reg, offset_offset), result_reg);
__ add(tmp1_reg, arrayOopDesc::base_offset_in_bytes(T_CHAR), tmp1_reg);
__ ld(Address(str1_reg, count_offset), str1_reg); // hoisted
__ sll(result_reg, exact_log2(sizeof(jchar)), result_reg);
__ load_heap_oop(Address(str2_reg, value_offset), tmp2_reg); // hoisted
__ add(result_reg, tmp1_reg, tmp1_reg);
+ __ br_zero(Assembler::equal, true, Assembler::pn, cnt_reg, Ldone);
+ __ delayed()->add(G0, 1, result_reg); // count == 0
+ __ sll(cnt_reg, exact_log2(sizeof(jchar)), cnt_reg); // bytes count
// load str2 (jchar*) base address into tmp2_reg
// __ ld_ptr(Address(str2_reg, value_offset), tmp2_reg); // hoisted
__ ld(Address(str2_reg, offset_offset), result_reg);
__ add(tmp2_reg, arrayOopDesc::base_offset_in_bytes(T_CHAR), tmp2_reg);
__ ld(Address(str2_reg, count_offset), str2_reg); // hoisted
__ sll(result_reg, exact_log2(sizeof(jchar)), result_reg);
__ cmp(str1_reg, str2_reg); // hoisted
__ add(result_reg, tmp2_reg, tmp2_reg);
__ sll(str1_reg, exact_log2(sizeof(jchar)), str1_reg);
__ br(Assembler::notEqual, true, Assembler::pt, Ldone);
__ delayed()->mov(G0, result_reg); // not equal
__ br_zero(Assembler::equal, true, Assembler::pn, str1_reg, Ldone);
__ delayed()->add(G0, 1, result_reg); //equals
__ cmp(tmp1_reg, tmp2_reg); //same string ?
+ __ cmp(str1_reg, str2_reg); //same char[] ?
__ brx(Assembler::equal, true, Assembler::pn, Ldone);
__ delayed()->add(G0, 1, result_reg);
//rename registers
! Register limit_reg = str1_reg;
Register chr2_reg = str2_reg;
! Register limit_reg = cnt_reg;
Register chr1_reg = result_reg;
// tmp{12} are the base pointers
+ Register chr2_reg = tmp1_reg;
//check for alignment and position the pointers to the ends
! __ or3(tmp1_reg, tmp2_reg, chr1_reg);
! __ or3(str1_reg, str2_reg, chr1_reg);
__ andcc(chr1_reg, 0x3, chr1_reg); // notZero means at least one not 4-byte aligned
! __ br(Assembler::notZero, false, Assembler::pn, Lchar); // char by char compare
__ delayed()->nop();
__ bind(Lword);
! __ and3(limit_reg, 0x2, O7); //remember the remainder (either 0 or 2)
+ // word by word compare
! __ and3(limit_reg, 0x2, O7); //remember the remainder (either 0 or 2 bytes)
__ andn(limit_reg, 0x3, limit_reg);
__ br_zero(Assembler::zero, false, Assembler::pn, limit_reg, Lpost_word);
__ delayed()->nop();
! __ add(tmp1_reg, limit_reg, tmp1_reg);
! __ add(tmp2_reg, limit_reg, tmp2_reg);
! __ add(str1_reg, limit_reg, str1_reg);
! __ add(str2_reg, limit_reg, str2_reg);
__ neg(limit_reg);
! __ lduw(tmp1_reg, limit_reg, chr1_reg);
! __ lduw(str1_reg, limit_reg, chr1_reg);
+ // Lword_loop
__ bind(Lword_loop);
! __ lduw(tmp2_reg, limit_reg, chr2_reg);
! __ lduw(str2_reg, limit_reg, chr2_reg);
__ cmp(chr1_reg, chr2_reg);
__ br(Assembler::notEqual, true, Assembler::pt, Ldone);
__ delayed()->mov(G0, result_reg);
__ inccc(limit_reg, 2*sizeof(jchar));
// annul LDUW if branch i s not taken to prevent access past end of string
__ br(Assembler::notZero, true, Assembler::pt, Lword_loop); //annul on taken
! __ delayed()->lduw(tmp1_reg, limit_reg, chr1_reg); // hoisted
! __ delayed()->lduw(str1_reg, limit_reg, chr1_reg); // hoisted
__ bind(Lpost_word);
__ br_zero(Assembler::zero, true, Assembler::pt, O7, Ldone);
__ delayed()->add(G0, 1, result_reg);
! __ lduh(tmp1_reg, 0, chr1_reg);
! __ lduh(tmp2_reg, 0, chr2_reg);
! __ lduh(str1_reg, 0, chr1_reg);
! __ lduh(str2_reg, 0, chr2_reg);
__ cmp (chr1_reg, chr2_reg);
__ br(Assembler::notEqual, true, Assembler::pt, Ldone);
__ delayed()->mov(G0, result_reg);
__ ba(false,Ldone);
__ delayed()->add(G0, 1, result_reg);
+ // char by char compare
__ bind(Lchar);
! __ add(tmp1_reg, limit_reg, tmp1_reg);
! __ add(tmp2_reg, limit_reg, tmp2_reg);
! __ add(str1_reg, limit_reg, str1_reg);
! __ add(str2_reg, limit_reg, str2_reg);
__ neg(limit_reg); //negate count
! __ lduh(tmp1_reg, limit_reg, chr1_reg);
! __ lduh(str1_reg, limit_reg, chr1_reg);
+ // Lchar_loop
__ bind(Lchar_loop);
! __ lduh(tmp2_reg, limit_reg, chr2_reg);
! __ lduh(str2_reg, limit_reg, chr2_reg);
__ cmp(chr1_reg, chr2_reg);
__ br(Assembler::notEqual, true, Assembler::pt, Ldone);
__ delayed()->mov(G0, result_reg); //not equal
__ inccc(limit_reg, sizeof(jchar));
// annul LDUH if branch is not taken to prevent access past end of string
__ br(Assembler::notZero, true, Assembler::pt, Lchar_loop); //annul on taken
! __ delayed()->lduh(tmp1_reg, limit_reg, chr1_reg); // hoisted
! __ delayed()->lduh(str1_reg, limit_reg, chr1_reg); // hoisted
__ add(G0, 1, result_reg); //equal
__ bind(Ldone);
%}
*** 9469,9495 ****
--- 9428,9454 ----
" STX G0,[$base+$temp]\t! delay slot" %}
ins_encode( enc_Clear_Array(cnt, base, temp) );
ins_pipe(long_memory_op);
%}
! instruct string_compare(o0RegP str1, o1RegP str2, g3RegP tmp1, g4RegP tmp2, notemp_iRegI result,
- o7RegI tmp3, flagsReg ccr) %{
! match(Set result (StrComp str1 str2));
! effect(USE_KILL str1, USE_KILL str2, KILL tmp1, KILL tmp2, KILL ccr, KILL tmp3);
! instruct string_compare(o0RegP str1, o1RegP str2, g3RegI cnt1, g4RegI cnt2, notemp_iRegI result,
! o7RegI tmp, flagsReg ccr) %{
! match(Set result (StrComp (Binary str1 str2) (Binary cnt1 cnt2)));
! effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL ccr, KILL tmp);
ins_cost(300);
! format %{ "String Compare $str1,$str2,$cnt1,$cnt2 -> $result // KILL $tmp" %}
! ins_encode( enc_String_Compare(str1, str2, tmp1, tmp2, result) );
! ins_encode( enc_String_Compare(str1, str2, cnt1, cnt2, result) );
ins_pipe(long_memory_op);
%}
! instruct string_equals(o0RegP str1, o1RegP str2, g3RegP tmp1, g4RegP tmp2, notemp_iRegI result,
! o7RegI tmp3, flagsReg ccr) %{
! match(Set result (StrEquals str1 str2));
! effect(USE_KILL str1, USE_KILL str2, KILL tmp1, KILL tmp2, KILL ccr, KILL tmp3);
! instruct string_equals(o0RegP str1, o1RegP str2, g3RegI cnt, g4RegI tmp1, notemp_iRegI result,
! o7RegI tmp2, flagsReg ccr) %{
! match(Set result (StrEquals (Binary str1 str2) cnt));
! effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt, KILL tmp1, KILL tmp2, KILL ccr);
ins_cost(300);
! format %{ "String Equals $str1,$str2,$cnt -> $result // KILL $tmp1, $tmp2" %}
! ins_encode( enc_String_Equals(str1, str2, tmp1, tmp2, result) );
! ins_encode( enc_String_Equals(str1, str2, cnt, tmp1, result) );
ins_pipe(long_memory_op);
%}
instruct array_equals(o0RegP ary1, o1RegP ary2, g3RegP tmp1, g4RegP tmp2, notemp_iRegI result,
flagsReg ccr) %{
src/cpu/sparc/vm/sparc.ad
Index
Unified diffs
Context diffs
Sdiffs
Wdiffs
Patch
New
Old
Previous File
Next File