comparison src/cpu/x86/vm/assembler_x86.cpp @ 986:62001a362ce9

6827605: new String intrinsics may prevent EA scalar replacement 6875866: Intrinsic for String.indexOf() is broken on x86 with SSE4.2 Summary: Modify String intrinsic methods to pass char[] pointers instead of string oops. Reviewed-by: never
author kvn
date Mon, 14 Sep 2009 12:14:20 -0700
parents 60fea60a6db5
children d40f03b57795
comparison
equal deleted inserted replaced
985:685e959d09ea 986:62001a362ce9
8402 movptr(r12_heapbase, ExternalAddress((address)Universe::narrow_oop_base_addr())); 8402 movptr(r12_heapbase, ExternalAddress((address)Universe::narrow_oop_base_addr()));
8403 } 8403 }
8404 } 8404 }
8405 #endif // _LP64 8405 #endif // _LP64
8406 8406
8407 // IndexOf substring.
8408 void MacroAssembler::string_indexof(Register str1, Register str2,
8409 Register cnt1, Register cnt2, Register result,
8410 XMMRegister vec, Register tmp) {
8411 assert(UseSSE42Intrinsics, "SSE4.2 is required");
8412
8413 Label RELOAD_SUBSTR, PREP_FOR_SCAN, SCAN_TO_SUBSTR,
8414 SCAN_SUBSTR, RET_NOT_FOUND, CLEANUP;
8415
8416 push(str1); // string addr
8417 push(str2); // substr addr
8418 push(cnt2); // substr count
8419 jmpb(PREP_FOR_SCAN);
8420
8421 // Substr count saved at sp
8422 // Substr saved at sp+1*wordSize
8423 // String saved at sp+2*wordSize
8424
8425 // Reload substr for rescan
8426 bind(RELOAD_SUBSTR);
8427 movl(cnt2, Address(rsp, 0));
8428 movptr(str2, Address(rsp, wordSize));
8429 // We came here after the beginninig of the substring was
8430 // matched but the rest of it was not so we need to search
8431 // again. Start from the next element after the previous match.
8432 subptr(str1, result); // Restore counter
8433 shrl(str1, 1);
8434 addl(cnt1, str1);
8435 lea(str1, Address(result, 2)); // Reload string
8436
8437 // Load substr
8438 bind(PREP_FOR_SCAN);
8439 movdqu(vec, Address(str2, 0));
8440 addl(cnt1, 8); // prime the loop
8441 subptr(str1, 16);
8442
8443 // Scan string for substr in 16-byte vectors
8444 bind(SCAN_TO_SUBSTR);
8445 subl(cnt1, 8);
8446 addptr(str1, 16);
8447
8448 // pcmpestri
8449 // inputs:
8450 // xmm - substring
8451 // rax - substring length (elements count)
8452 // mem - scaned string
8453 // rdx - string length (elements count)
8454 // 0xd - mode: 1100 (substring search) + 01 (unsigned shorts)
8455 // outputs:
8456 // rcx - matched index in string
8457 assert(cnt1 == rdx && cnt2 == rax && tmp == rcx, "pcmpestri");
8458
8459 pcmpestri(vec, Address(str1, 0), 0x0d);
8460 jcc(Assembler::above, SCAN_TO_SUBSTR); // CF == 0 && ZF == 0
8461 jccb(Assembler::aboveEqual, RET_NOT_FOUND); // CF == 0
8462
8463 // Fallthrough: found a potential substr
8464
8465 // Make sure string is still long enough
8466 subl(cnt1, tmp);
8467 cmpl(cnt1, cnt2);
8468 jccb(Assembler::negative, RET_NOT_FOUND);
8469 // Compute start addr of substr
8470 lea(str1, Address(str1, tmp, Address::times_2));
8471 movptr(result, str1); // save
8472
8473 // Compare potential substr
8474 addl(cnt1, 8); // prime the loop
8475 addl(cnt2, 8);
8476 subptr(str1, 16);
8477 subptr(str2, 16);
8478
8479 // Scan 16-byte vectors of string and substr
8480 bind(SCAN_SUBSTR);
8481 subl(cnt1, 8);
8482 subl(cnt2, 8);
8483 addptr(str1, 16);
8484 addptr(str2, 16);
8485 movdqu(vec, Address(str2, 0));
8486 pcmpestri(vec, Address(str1, 0), 0x0d);
8487 jcc(Assembler::noOverflow, RELOAD_SUBSTR); // OF == 0
8488 jcc(Assembler::positive, SCAN_SUBSTR); // SF == 0
8489
8490 // Compute substr offset
8491 subptr(result, Address(rsp, 2*wordSize));
8492 shrl(result, 1); // index
8493 jmpb(CLEANUP);
8494
8495 bind(RET_NOT_FOUND);
8496 movl(result, -1);
8497
8498 bind(CLEANUP);
8499 addptr(rsp, 3*wordSize);
8500 }
8501
8502 // Compare strings.
8503 void MacroAssembler::string_compare(Register str1, Register str2,
8504 Register cnt1, Register cnt2, Register result,
8505 XMMRegister vec1, XMMRegister vec2) {
8506 Label LENGTH_DIFF_LABEL, POP_LABEL, DONE_LABEL, WHILE_HEAD_LABEL;
8507
8508 // Compute the minimum of the string lengths and the
8509 // difference of the string lengths (stack).
8510 // Do the conditional move stuff
8511 movl(result, cnt1);
8512 subl(cnt1, cnt2);
8513 push(cnt1);
8514 if (VM_Version::supports_cmov()) {
8515 cmovl(Assembler::lessEqual, cnt2, result);
8516 } else {
8517 Label GT_LABEL;
8518 jccb(Assembler::greater, GT_LABEL);
8519 movl(cnt2, result);
8520 bind(GT_LABEL);
8521 }
8522
8523 // Is the minimum length zero?
8524 testl(cnt2, cnt2);
8525 jcc(Assembler::zero, LENGTH_DIFF_LABEL);
8526
8527 // Load first characters
8528 load_unsigned_short(result, Address(str1, 0));
8529 load_unsigned_short(cnt1, Address(str2, 0));
8530
8531 // Compare first characters
8532 subl(result, cnt1);
8533 jcc(Assembler::notZero, POP_LABEL);
8534 decrementl(cnt2);
8535 jcc(Assembler::zero, LENGTH_DIFF_LABEL);
8536
8537 {
8538 // Check after comparing first character to see if strings are equivalent
8539 Label LSkip2;
8540 // Check if the strings start at same location
8541 cmpptr(str1, str2);
8542 jccb(Assembler::notEqual, LSkip2);
8543
8544 // Check if the length difference is zero (from stack)
8545 cmpl(Address(rsp, 0), 0x0);
8546 jcc(Assembler::equal, LENGTH_DIFF_LABEL);
8547
8548 // Strings might not be equivalent
8549 bind(LSkip2);
8550 }
8551
8552 // Advance to next character
8553 addptr(str1, 2);
8554 addptr(str2, 2);
8555
8556 if (UseSSE42Intrinsics) {
8557 // With SSE4.2, use double quad vector compare
8558 Label COMPARE_VECTORS, VECTOR_NOT_EQUAL, COMPARE_TAIL;
8559 // Setup to compare 16-byte vectors
8560 movl(cnt1, cnt2);
8561 andl(cnt2, 0xfffffff8); // cnt2 holds the vector count
8562 andl(cnt1, 0x00000007); // cnt1 holds the tail count
8563 testl(cnt2, cnt2);
8564 jccb(Assembler::zero, COMPARE_TAIL);
8565
8566 lea(str2, Address(str2, cnt2, Address::times_2));
8567 lea(str1, Address(str1, cnt2, Address::times_2));
8568 negptr(cnt2);
8569
8570 bind(COMPARE_VECTORS);
8571 movdqu(vec1, Address(str1, cnt2, Address::times_2));
8572 movdqu(vec2, Address(str2, cnt2, Address::times_2));
8573 pxor(vec1, vec2);
8574 ptest(vec1, vec1);
8575 jccb(Assembler::notZero, VECTOR_NOT_EQUAL);
8576 addptr(cnt2, 8);
8577 jcc(Assembler::notZero, COMPARE_VECTORS);
8578 jmpb(COMPARE_TAIL);
8579
8580 // Mismatched characters in the vectors
8581 bind(VECTOR_NOT_EQUAL);
8582 lea(str1, Address(str1, cnt2, Address::times_2));
8583 lea(str2, Address(str2, cnt2, Address::times_2));
8584 movl(cnt1, 8);
8585
8586 // Compare tail (< 8 chars), or rescan last vectors to
8587 // find 1st mismatched characters
8588 bind(COMPARE_TAIL);
8589 testl(cnt1, cnt1);
8590 jccb(Assembler::zero, LENGTH_DIFF_LABEL);
8591 movl(cnt2, cnt1);
8592 // Fallthru to tail compare
8593 }
8594
8595 // Shift str2 and str1 to the end of the arrays, negate min
8596 lea(str1, Address(str1, cnt2, Address::times_2, 0));
8597 lea(str2, Address(str2, cnt2, Address::times_2, 0));
8598 negptr(cnt2);
8599
8600 // Compare the rest of the characters
8601 bind(WHILE_HEAD_LABEL);
8602 load_unsigned_short(result, Address(str1, cnt2, Address::times_2, 0));
8603 load_unsigned_short(cnt1, Address(str2, cnt2, Address::times_2, 0));
8604 subl(result, cnt1);
8605 jccb(Assembler::notZero, POP_LABEL);
8606 increment(cnt2);
8607 jcc(Assembler::notZero, WHILE_HEAD_LABEL);
8608
8609 // Strings are equal up to min length. Return the length difference.
8610 bind(LENGTH_DIFF_LABEL);
8611 pop(result);
8612 jmpb(DONE_LABEL);
8613
8614 // Discard the stored length difference
8615 bind(POP_LABEL);
8616 addptr(rsp, wordSize);
8617
8618 // That's it
8619 bind(DONE_LABEL);
8620 }
8621
8622 // Compare char[] arrays aligned to 4 bytes or substrings.
8623 void MacroAssembler::char_arrays_equals(bool is_array_equ, Register ary1, Register ary2,
8624 Register limit, Register result, Register chr,
8625 XMMRegister vec1, XMMRegister vec2) {
8626 Label TRUE_LABEL, FALSE_LABEL, DONE, COMPARE_VECTORS, COMPARE_CHAR;
8627
8628 int length_offset = arrayOopDesc::length_offset_in_bytes();
8629 int base_offset = arrayOopDesc::base_offset_in_bytes(T_CHAR);
8630
8631 // Check the input args
8632 cmpptr(ary1, ary2);
8633 jcc(Assembler::equal, TRUE_LABEL);
8634
8635 if (is_array_equ) {
8636 // Need additional checks for arrays_equals.
8637 andptr(ary1, ary2);
8638 jcc(Assembler::zero, FALSE_LABEL); // One pointer is NULL
8639
8640 // Check the lengths
8641 movl(limit, Address(ary1, length_offset));
8642 cmpl(limit, Address(ary2, length_offset));
8643 jcc(Assembler::notEqual, FALSE_LABEL);
8644 }
8645
8646 // count == 0
8647 testl(limit, limit);
8648 jcc(Assembler::zero, TRUE_LABEL);
8649
8650 if (is_array_equ) {
8651 // Load array address
8652 lea(ary1, Address(ary1, base_offset));
8653 lea(ary2, Address(ary2, base_offset));
8654 }
8655
8656 shll(limit, 1); // byte count != 0
8657 movl(result, limit); // copy
8658
8659 if (UseSSE42Intrinsics) {
8660 // With SSE4.2, use double quad vector compare
8661 Label COMPARE_WIDE_VECTORS, COMPARE_TAIL;
8662 // Compare 16-byte vectors
8663 andl(result, 0x0000000e); // tail count (in bytes)
8664 andl(limit, 0xfffffff0); // vector count (in bytes)
8665 jccb(Assembler::zero, COMPARE_TAIL);
8666
8667 lea(ary1, Address(ary1, limit, Address::times_1));
8668 lea(ary2, Address(ary2, limit, Address::times_1));
8669 negptr(limit);
8670
8671 bind(COMPARE_WIDE_VECTORS);
8672 movdqu(vec1, Address(ary1, limit, Address::times_1));
8673 movdqu(vec2, Address(ary2, limit, Address::times_1));
8674 pxor(vec1, vec2);
8675 ptest(vec1, vec1);
8676 jccb(Assembler::notZero, FALSE_LABEL);
8677 addptr(limit, 16);
8678 jcc(Assembler::notZero, COMPARE_WIDE_VECTORS);
8679
8680 bind(COMPARE_TAIL); // limit is zero
8681 movl(limit, result);
8682 // Fallthru to tail compare
8683 }
8684
8685 // Compare 4-byte vectors
8686 andl(limit, 0xfffffffc); // vector count (in bytes)
8687 jccb(Assembler::zero, COMPARE_CHAR);
8688
8689 lea(ary1, Address(ary1, limit, Address::times_1));
8690 lea(ary2, Address(ary2, limit, Address::times_1));
8691 negptr(limit);
8692
8693 bind(COMPARE_VECTORS);
8694 movl(chr, Address(ary1, limit, Address::times_1));
8695 cmpl(chr, Address(ary2, limit, Address::times_1));
8696 jccb(Assembler::notEqual, FALSE_LABEL);
8697 addptr(limit, 4);
8698 jcc(Assembler::notZero, COMPARE_VECTORS);
8699
8700 // Compare trailing char (final 2 bytes), if any
8701 bind(COMPARE_CHAR);
8702 testl(result, 0x2); // tail char
8703 jccb(Assembler::zero, TRUE_LABEL);
8704 load_unsigned_short(chr, Address(ary1, 0));
8705 load_unsigned_short(limit, Address(ary2, 0));
8706 cmpl(chr, limit);
8707 jccb(Assembler::notEqual, FALSE_LABEL);
8708
8709 bind(TRUE_LABEL);
8710 movl(result, 1); // return true
8711 jmpb(DONE);
8712
8713 bind(FALSE_LABEL);
8714 xorl(result, result); // return false
8715
8716 // That's it
8717 bind(DONE);
8718 }
8719
8407 Assembler::Condition MacroAssembler::negate_condition(Assembler::Condition cond) { 8720 Assembler::Condition MacroAssembler::negate_condition(Assembler::Condition cond) {
8408 switch (cond) { 8721 switch (cond) {
8409 // Note some conditions are synonyms for others 8722 // Note some conditions are synonyms for others
8410 case Assembler::zero: return Assembler::notZero; 8723 case Assembler::zero: return Assembler::notZero;
8411 case Assembler::notZero: return Assembler::zero; 8724 case Assembler::notZero: return Assembler::zero;