src/cpu/x86/vm/x86_64.ad
Index
Unified diffs
Context diffs
Sdiffs
Wdiffs
Patch
New
Old
Previous File
Next File
*** old/src/cpu/x86/vm/x86_64.ad Tue Aug 18 19:06:17 2009
--- new/src/cpu/x86/vm/x86_64.ad Tue Aug 18 19:06:17 2009
*** 3699,3763 ****
--- 3699,3747 ----
masm.nop(); // avoid branch to branch
}
}
%}
! enc_class enc_String_Compare(rdi_RegP str1, rsi_RegP str2, regD tmp1, regD tmp2,
! rax_RegI tmp3, rbx_RegI tmp4, rcx_RegI result) %{
! enc_class enc_String_Compare(rdi_RegP str1, rsi_RegP str2, rbx_RegI cnt1, rax_RegI cnt2,
! regD tmp1, regD tmp2, rcx_RegI result) %{
Label RCX_GOOD_LABEL, LENGTH_DIFF_LABEL,
POP_LABEL, DONE_LABEL, CONT_LABEL,
WHILE_HEAD_LABEL;
MacroAssembler masm(&cbuf);
XMMRegister tmp1Reg = as_XMMRegister($tmp1$$reg);
XMMRegister tmp2Reg = as_XMMRegister($tmp2$$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();
int base_offset = arrayOopDesc::base_offset_in_bytes(T_CHAR);
masm.load_heap_oop(rax, Address(rsi, value_offset));
masm.movl(rcx, Address(rsi, offset_offset));
masm.lea(rax, Address(rax, rcx, Address::times_2, base_offset));
masm.load_heap_oop(rbx, Address(rdi, value_offset));
masm.movl(rcx, Address(rdi, offset_offset));
masm.lea(rbx, Address(rbx, rcx, Address::times_2, base_offset));
// Compute the minimum of the string lengths(rsi) and the
// difference of the string lengths (stack)
// do the conditional move stuff
! masm.movl(rdi, Address(rdi, count_offset));
! masm.movl(rsi, Address(rsi, count_offset));
! masm.movl(rcx, rdi);
! masm.subl(rdi, rsi);
masm.push(rdi);
masm.cmov(Assembler::lessEqual, rsi, rcx);
! masm.movl(rcx, rbx);
! masm.subl(rbx, rax);
! masm.push(rbx);
! masm.cmov(Assembler::lessEqual, rax, rcx);
// Is the minimum length zero?
masm.bind(RCX_GOOD_LABEL);
! masm.testl(rsi, rsi);
! masm.testl(rax, rax);
masm.jcc(Assembler::zero, LENGTH_DIFF_LABEL);
// Load first characters
! masm.load_unsigned_short(rcx, Address(rbx, 0));
! masm.load_unsigned_short(rdi, Address(rax, 0));
! masm.load_unsigned_short(rcx, Address(rdi, 0));
! masm.load_unsigned_short(rbx, Address(rsi, 0));
// Compare first characters
! masm.subl(rcx, rdi);
! masm.subl(rcx, rbx);
masm.jcc(Assembler::notZero, POP_LABEL);
! masm.decrementl(rsi);
! masm.decrementl(rax);
masm.jcc(Assembler::zero, LENGTH_DIFF_LABEL);
{
// Check after comparing first character to see if strings are equivalent
Label LSkip2;
// Check if the strings start at same location
! masm.cmpptr(rbx, rax);
! masm.cmpptr(rdi, rsi);
masm.jccb(Assembler::notEqual, LSkip2);
// Check if the length difference is zero (from stack)
masm.cmpl(Address(rsp, 0), 0x0);
masm.jcc(Assembler::equal, LENGTH_DIFF_LABEL);
*** 3765,3828 ****
--- 3749,3812 ----
// Strings might not be equivalent
masm.bind(LSkip2);
}
// Advance to next character
! masm.addptr(rax, 2);
! masm.addptr(rbx, 2);
! masm.addptr(rsi, 2);
! masm.addptr(rdi, 2);
if (UseSSE42Intrinsics) {
// With SSE4.2, use double quad vector compare
Label COMPARE_VECTORS, VECTOR_NOT_EQUAL, COMPARE_TAIL;
// Setup to compare 16-byte vectors
! masm.movl(rdi, rsi);
! masm.andl(rsi, 0xfffffff8); // rsi holds the vector count
! masm.andl(rdi, 0x00000007); // rdi holds the tail count
! masm.testl(rsi, rsi);
! masm.movl(rbx, rax);
! masm.andl(rax, 0xfffffff8); // rax holds the vector count
! masm.andl(rbx, 0x00000007); // rbx holds the tail count
! masm.testl(rax, rax);
masm.jccb(Assembler::zero, COMPARE_TAIL);
! masm.lea(rax, Address(rax, rsi, Address::times_2));
! masm.lea(rbx, Address(rbx, rsi, Address::times_2));
! masm.negptr(rsi);
! masm.lea(rsi, Address(rsi, rax, Address::times_2));
! masm.lea(rdi, Address(rdi, rax, Address::times_2));
! masm.negptr(rax);
masm.bind(COMPARE_VECTORS);
! masm.movdqu(tmp1Reg, Address(rax, rsi, Address::times_2));
! masm.movdqu(tmp2Reg, Address(rbx, rsi, Address::times_2));
! masm.movdqu(tmp1Reg, Address(rsi, rax, Address::times_2));
! masm.movdqu(tmp2Reg, Address(rdi, rax, Address::times_2));
masm.pxor(tmp1Reg, tmp2Reg);
masm.ptest(tmp1Reg, tmp1Reg);
masm.jccb(Assembler::notZero, VECTOR_NOT_EQUAL);
! masm.addptr(rsi, 8);
! masm.addptr(rax, 8);
masm.jcc(Assembler::notZero, COMPARE_VECTORS);
masm.jmpb(COMPARE_TAIL);
// Mismatched characters in the vectors
masm.bind(VECTOR_NOT_EQUAL);
! masm.lea(rax, Address(rax, rsi, Address::times_2));
! masm.lea(rbx, Address(rbx, rsi, Address::times_2));
! masm.movl(rdi, 8);
! masm.lea(rsi, Address(rsi, rax, Address::times_2));
! masm.lea(rdi, Address(rdi, rax, Address::times_2));
! masm.movl(rbx, 8);
// Compare tail (< 8 chars), or rescan last vectors to
// find 1st mismatched characters
masm.bind(COMPARE_TAIL);
! masm.testl(rdi, rdi);
! masm.testl(rbx, rbx);
masm.jccb(Assembler::zero, LENGTH_DIFF_LABEL);
! masm.movl(rsi, rdi);
! masm.movl(rax, rbx);
// Fallthru to tail compare
}
! // Shift RAX and RBX to the end of the arrays, negate min
! masm.lea(rax, Address(rax, rsi, Address::times_2, 0));
! masm.lea(rbx, Address(rbx, rsi, Address::times_2, 0));
! masm.negptr(rsi);
! // Shift rsi and rdi to the end of the arrays, negate min
! masm.lea(rsi, Address(rsi, rax, Address::times_2, 0));
! masm.lea(rdi, Address(rdi, rax, Address::times_2, 0));
! masm.negptr(rax);
// Compare the rest of the characters
masm.bind(WHILE_HEAD_LABEL);
! masm.load_unsigned_short(rcx, Address(rbx, rsi, Address::times_2, 0));
! masm.load_unsigned_short(rdi, Address(rax, rsi, Address::times_2, 0));
! masm.subl(rcx, rdi);
! masm.load_unsigned_short(rcx, Address(rdi, rax, Address::times_2, 0));
! masm.load_unsigned_short(rbx, Address(rsi, rax, Address::times_2, 0));
! masm.subl(rcx, rbx);
masm.jccb(Assembler::notZero, POP_LABEL);
! masm.increment(rsi);
! masm.increment(rax);
masm.jcc(Assembler::notZero, WHILE_HEAD_LABEL);
// Strings are equal up to min length. Return the length difference.
masm.bind(LENGTH_DIFF_LABEL);
masm.pop(rcx);
*** 3834,3877 ****
--- 3818,3841 ----
// That's it
masm.bind(DONE_LABEL);
%}
! enc_class enc_String_IndexOf(rsi_RegP str1, rdi_RegP str2, regD tmp1, rax_RegI tmp2,
! rcx_RegI tmp3, rdx_RegI tmp4, rbx_RegI result) %{
! enc_class enc_String_IndexOf(rsi_RegP str1, rdi_RegP str2, rdx_RegI cnt1, rax_RegI cnt2,
! regD tmp1, rcx_RegI tmp2, rbx_RegI result) %{
// SSE4.2 version
Label LOAD_SUBSTR, PREP_FOR_SCAN, SCAN_TO_SUBSTR,
SCAN_SUBSTR, RET_NEG_ONE, RET_NOT_FOUND, CLEANUP, DONE;
MacroAssembler masm(&cbuf);
XMMRegister tmp1Reg = as_XMMRegister($tmp1$$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();
int base_offset = arrayOopDesc::base_offset_in_bytes(T_CHAR);
// Get counts for string and substr
masm.movl(rdx, Address(rsi, count_offset));
masm.movl(rax, Address(rdi, count_offset));
// Check for substr count > string count
masm.cmpl(rax, rdx);
masm.jcc(Assembler::greater, RET_NEG_ONE);
// Start the indexOf operation
// Get start addr of string
masm.load_heap_oop(rbx, Address(rsi, value_offset));
masm.movl(rcx, Address(rsi, offset_offset));
masm.lea(rsi, Address(rbx, rcx, Address::times_2, base_offset));
masm.push(rsi);
// Get start addr of substr
masm.load_heap_oop(rbx, Address(rdi, value_offset));
masm.movl(rcx, Address(rdi, offset_offset));
masm.lea(rdi, Address(rbx, rcx, Address::times_2, base_offset));
masm.push(rdi);
masm.push(rax);
masm.jmpb(PREP_FOR_SCAN);
// Substr count saved at sp
*** 3891,3907 ****
--- 3855,3879 ----
// Scan string for substr in 16-byte vectors
masm.bind(SCAN_TO_SUBSTR);
masm.subq(rdx, 8);
masm.addptr(rsi, 16);
+ // pcmpestri
+ // inputs:
+ // xmm - substring
+ // rax - substring length (elements count)
+ // mem - scaned string
+ // rdx - string length (elements count)
+ // outputs:
+ // rcx - matched index in string
masm.pcmpestri(tmp1Reg, Address(rsi, 0), 0x0d);
masm.jcc(Assembler::above, SCAN_TO_SUBSTR);
masm.jccb(Assembler::aboveEqual, RET_NOT_FOUND);
// Fallthru: found a potential substr
! // Make sure string is still long enough
masm.subl(rdx, rcx);
masm.cmpl(rdx, rax);
masm.jccb(Assembler::negative, RET_NOT_FOUND);
// Compute start addr of substr
masm.lea(rsi, Address(rsi, rcx, Address::times_2));
*** 3941,3985 ****
--- 3913,3938 ----
masm.addptr(rsp, 24);
masm.bind(DONE);
%}
! enc_class enc_String_Equals(rdi_RegP str1, rsi_RegP str2, regD tmp1, regD tmp2,
! rbx_RegI tmp3, rcx_RegI tmp2, rax_RegI result) %{
! enc_class enc_String_Equals(rdi_RegP str1, rsi_RegP str2, rcx_RegI cnt, regD tmp1,
! regD tmp2, rbx_RegI tmp3, rax_RegI result) %{
Label RET_TRUE, RET_FALSE, DONE, COMPARE_VECTORS, COMPARE_CHAR;
MacroAssembler masm(&cbuf);
XMMRegister tmp1Reg = as_XMMRegister($tmp1$$reg);
XMMRegister tmp2Reg = as_XMMRegister($tmp2$$reg);
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();
int base_offset = arrayOopDesc::base_offset_in_bytes(T_CHAR);
// does source == target string?
+ // does source == target?
masm.cmpptr(rdi, rsi);
masm.jcc(Assembler::equal, RET_TRUE);
// get and compare counts
! masm.movl(rcx, Address(rdi, count_offset));
masm.movl(rax, Address(rsi, count_offset));
masm.cmpl(rcx, rax);
masm.jcc(Assembler::notEqual, RET_FALSE);
masm.testl(rax, rax);
+ // count == 0
! masm.testl(rcx, rcx);
masm.jcc(Assembler::zero, RET_TRUE);
// get source string offset and value
masm.load_heap_oop(rbx, Address(rsi, value_offset));
masm.movl(rax, Address(rsi, offset_offset));
masm.lea(rsi, Address(rbx, rax, Address::times_2, base_offset));
// get compare string offset and value
masm.load_heap_oop(rbx, Address(rdi, value_offset));
masm.movl(rax, Address(rdi, offset_offset));
masm.lea(rdi, Address(rbx, rax, Address::times_2, base_offset));
// Set byte count
masm.shll(rcx, 1);
masm.movl(rax, rcx);
if (UseSSE42Intrinsics) {
*** 12094,12136 ****
--- 12047,12089 ----
ins_encode(opc_reg_reg(0x33, RAX, RAX), // xorl %eax, %eax
Opcode(0xF3), Opcode(0x48), Opcode(0xAB)); // rep REX_W stos
ins_pipe(pipe_slow);
%}
! instruct string_compare(rdi_RegP str1, rsi_RegP str2, regD tmp1, regD tmp2,
! rax_RegI tmp3, rbx_RegI tmp4, rcx_RegI result, rFlagsReg cr)
! instruct string_compare(rdi_RegP str1, rsi_RegP str2, rbx_RegI cnt1, rax_RegI cnt2,
! regD tmp1, regD tmp2, rcx_RegI result, rFlagsReg cr)
%{
! match(Set result (StrComp (Binary str1 str2) (Binary cnt1 cnt2)));
! effect(TEMP tmp1, TEMP tmp2, USE_KILL str1, USE_KILL str2, KILL tmp3, KILL tmp4, KILL cr);
! effect(TEMP tmp1, TEMP tmp2, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr);
//ins_cost(300);
! format %{ "String Compare $str1, $str2 -> $result // XXX KILL RAX, RBX" %}
! ins_encode( enc_String_Compare(str1, str2, tmp1, tmp2, tmp3, tmp4, result) );
! format %{ "String Compare $str1,$str2,$cnt1,$cnt2 -> $result // KILL $tmp1, $tmp2" %}
! ins_encode( enc_String_Compare(str1, str2, cnt1, cnt2, tmp1, tmp2, result) );
ins_pipe( pipe_slow );
%}
! instruct string_indexof(rsi_RegP str1, rdi_RegP str2, regD tmp1, rax_RegI tmp2,
! rcx_RegI tmp3, rdx_RegI tmp4, rbx_RegI result, rFlagsReg cr)
! instruct string_indexof(rsi_RegP str1, rdi_RegP str2, rdx_RegI cnt1, rax_RegI cnt2,
! regD tmp1, rcx_RegI tmp2, rbx_RegI result, rFlagsReg cr)
%{
predicate(UseSSE42Intrinsics);
! match(Set result (StrIndexOf (Binary str1 str2) (Binary cnt1 cnt2)));
! effect(TEMP tmp1, USE_KILL str1, USE_KILL str2, KILL tmp2, KILL tmp3, KILL tmp4, KILL cr);
! effect(TEMP tmp1, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL tmp2, KILL cr);
! format %{ "String IndexOf $str1,$str2 -> $result // KILL RAX, RCX, RDX" %}
! ins_encode( enc_String_IndexOf(str1, str2, tmp1, tmp2, tmp3, tmp4, result) );
! format %{ "String IndexOf $str1,$str2,$cnt1,$cnt2 -> $result // KILL $tmp1, $tmp2" %}
! ins_encode( enc_String_IndexOf(str1, str2, cnt1, cnt2, tmp1, tmp2, result) );
ins_pipe( pipe_slow );
%}
// fast string equals
! instruct string_equals(rdi_RegP str1, rsi_RegP str2, regD tmp1, regD tmp2, rbx_RegI tmp3,
! rcx_RegI tmp4, rax_RegI result, rFlagsReg cr)
! instruct string_equals(rdi_RegP str1, rsi_RegP str2, rcx_RegI cnt, regD tmp1, regD tmp2,
! rbx_RegI tmp3, rax_RegI result, rFlagsReg cr)
%{
! match(Set result (StrEquals (Binary str1 str2) cnt));
! effect(TEMP tmp1, TEMP tmp2, USE_KILL str1, USE_KILL str2, KILL tmp3, KILL tmp4, KILL cr);
! effect(TEMP tmp1, TEMP tmp2, USE_KILL str1, USE_KILL str2, USE_KILL cnt, KILL tmp3, KILL cr);
! format %{ "String Equals $str1,$str2 -> $result // KILL RBX, RCX" %}
! ins_encode( enc_String_Equals(str1, str2, tmp1, tmp2, tmp3, tmp4, result) );
! format %{ "String Equals $str1,$str2,$cnt -> $result // KILL $tmp1, $tmp2, $tmp3" %}
! ins_encode( enc_String_Equals(str1, str2, cnt, tmp1, tmp2, tmp3, result) );
ins_pipe( pipe_slow );
%}
// fast array equals
instruct array_equals(rdi_RegP ary1, rsi_RegP ary2, regD tmp1, regD tmp2, rax_RegI tmp3,
src/cpu/x86/vm/x86_64.ad
Index
Unified diffs
Context diffs
Sdiffs
Wdiffs
Patch
New
Old
Previous File
Next File