@@ -1459,6 +1459,112 @@ void C2_MacroAssembler::string_equals(Register a1, Register a2,
14591459 BLOCK_COMMENT (" } string_equals" );
14601460}
14611461
1462+ // jdk.internal.util.ArraysSupport.vectorizedHashCode
1463+ void C2_MacroAssembler::arrays_hashcode (Register ary, Register cnt, Register result,
1464+ Register tmp1, Register tmp2, Register tmp3,
1465+ Register tmp4, Register tmp5, Register tmp6,
1466+ BasicType eltype)
1467+ {
1468+ assert_different_registers (ary, cnt, result, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, t0, t1);
1469+
1470+ const int elsize = arrays_hashcode_elsize (eltype);
1471+ const int chunks_end_shift = exact_log2 (elsize);
1472+
1473+ switch (eltype) {
1474+ case T_BOOLEAN: BLOCK_COMMENT (" arrays_hashcode(unsigned byte) {" ); break ;
1475+ case T_CHAR: BLOCK_COMMENT (" arrays_hashcode(char) {" ); break ;
1476+ case T_BYTE: BLOCK_COMMENT (" arrays_hashcode(byte) {" ); break ;
1477+ case T_SHORT: BLOCK_COMMENT (" arrays_hashcode(short) {" ); break ;
1478+ case T_INT: BLOCK_COMMENT (" arrays_hashcode(int) {" ); break ;
1479+ default :
1480+ ShouldNotReachHere ();
1481+ }
1482+
1483+ const int stride = 4 ;
1484+ const Register pow31_4 = tmp1;
1485+ const Register pow31_3 = tmp2;
1486+ const Register pow31_2 = tmp3;
1487+ const Register chunks = tmp4;
1488+ const Register chunks_end = chunks;
1489+
1490+ Label DONE, TAIL, TAIL_LOOP, WIDE_LOOP;
1491+
1492+ // result has a value initially
1493+
1494+ beqz (cnt, DONE);
1495+
1496+ andi (chunks, cnt, ~(stride-1 ));
1497+ beqz (chunks, TAIL);
1498+
1499+ mv (pow31_4, 923521 ); // [31^^4]
1500+ mv (pow31_3, 29791 ); // [31^^3]
1501+ mv (pow31_2, 961 ); // [31^^2]
1502+
1503+ slli (chunks_end, chunks, chunks_end_shift);
1504+ add (chunks_end, ary, chunks_end);
1505+ andi (cnt, cnt, stride-1 ); // don't forget about tail!
1506+
1507+ bind (WIDE_LOOP);
1508+ mulw (result, result, pow31_4); // 31^^4 * h
1509+ arrays_hashcode_elload (t0, Address (ary, 0 * elsize), eltype);
1510+ arrays_hashcode_elload (t1, Address (ary, 1 * elsize), eltype);
1511+ arrays_hashcode_elload (tmp5, Address (ary, 2 * elsize), eltype);
1512+ arrays_hashcode_elload (tmp6, Address (ary, 3 * elsize), eltype);
1513+ mulw (t0, t0, pow31_3); // 31^^3 * ary[i+0]
1514+ addw (result, result, t0);
1515+ mulw (t1, t1, pow31_2); // 31^^2 * ary[i+1]
1516+ addw (result, result, t1);
1517+ slli (t0, tmp5, 5 ); // optimize 31^^1 * ary[i+2]
1518+ subw (tmp5, t0, tmp5); // with ary[i+2]<<5 - ary[i+2]
1519+ addw (result, result, tmp5);
1520+ addw (result, result, tmp6); // 31^^4 * h + 31^^3 * ary[i+0] + 31^^2 * ary[i+1]
1521+ // + 31^^1 * ary[i+2] + 31^^0 * ary[i+3]
1522+ addi (ary, ary, elsize * stride);
1523+ bne (ary, chunks_end, WIDE_LOOP);
1524+ beqz (cnt, DONE);
1525+
1526+ bind (TAIL);
1527+ slli (chunks_end, cnt, chunks_end_shift);
1528+ add (chunks_end, ary, chunks_end);
1529+
1530+ bind (TAIL_LOOP);
1531+ arrays_hashcode_elload (t0, Address (ary), eltype);
1532+ slli (t1, result, 5 ); // optimize 31 * result
1533+ subw (result, t1, result); // with result<<5 - result
1534+ addw (result, result, t0);
1535+ addi (ary, ary, elsize);
1536+ bne (ary, chunks_end, TAIL_LOOP);
1537+
1538+ bind (DONE);
1539+ BLOCK_COMMENT (" } // arrays_hashcode" );
1540+ }
1541+
1542+ int C2_MacroAssembler::arrays_hashcode_elsize (BasicType eltype) {
1543+ switch (eltype) {
1544+ case T_BOOLEAN: return sizeof (jboolean);
1545+ case T_BYTE: return sizeof (jbyte);
1546+ case T_SHORT: return sizeof (jshort);
1547+ case T_CHAR: return sizeof (jchar);
1548+ case T_INT: return sizeof (jint);
1549+ default :
1550+ ShouldNotReachHere ();
1551+ return -1 ;
1552+ }
1553+ }
1554+
1555+ void C2_MacroAssembler::arrays_hashcode_elload (Register dst, Address src, BasicType eltype) {
1556+ switch (eltype) {
1557+ // T_BOOLEAN used as surrogate for unsigned byte
1558+ case T_BOOLEAN: lbu (dst, src); break ;
1559+ case T_BYTE: lb (dst, src); break ;
1560+ case T_SHORT: lh (dst, src); break ;
1561+ case T_CHAR: lhu (dst, src); break ;
1562+ case T_INT: lw (dst, src); break ;
1563+ default :
1564+ ShouldNotReachHere ();
1565+ }
1566+ }
1567+
14621568typedef void (Assembler::*conditional_branch_insn)(Register op1, Register op2, Label& label, bool is_far);
14631569typedef void (MacroAssembler::*float_conditional_branch_insn)(FloatRegister op1, FloatRegister op2, Label& label,
14641570 bool is_far, bool is_unordered);
0 commit comments