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