Skip to content

Commit 6359b4e

Browse files
ygaevskyVladimir Kempik
authored andcommitted
8318217: RISC-V: C2 VectorizedHashCode
Reviewed-by: mli, fyang
1 parent ce4b257 commit 6359b4e

File tree

4 files changed

+139
-0
lines changed

4 files changed

+139
-0
lines changed

src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
14621568
typedef void (Assembler::*conditional_branch_insn)(Register op1, Register op2, Label& label, bool is_far);
14631569
typedef void (MacroAssembler::*float_conditional_branch_insn)(FloatRegister op1, FloatRegister op2, Label& label,
14641570
bool is_far, bool is_unordered);

src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.hpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,15 @@
8282
Register result, Register cnt1,
8383
int elem_size);
8484

85+
void arrays_hashcode(Register ary, Register cnt, Register result,
86+
Register tmp1, Register tmp2,
87+
Register tmp3, Register tmp4,
88+
Register tmp5, Register tmp6,
89+
BasicType eltype);
90+
// helper function for arrays_hashcode
91+
int arrays_hashcode_elsize(BasicType eltype);
92+
void arrays_hashcode_elload(Register dst, Address src, BasicType eltype);
93+
8594
void string_equals(Register r1, Register r2,
8695
Register result, Register cnt1,
8796
int elem_size);

src/hotspot/cpu/riscv/riscv.ad

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10371,6 +10371,26 @@ instruct array_equalsC(iRegP_R11 ary1, iRegP_R12 ary2, iRegI_R10 result,
1037110371
ins_pipe(pipe_class_memory);
1037210372
%}
1037310373

10374+
// fast ArraysSupport.vectorizedHashCode
10375+
instruct arrays_hashcode(iRegP_R11 ary, iRegI_R12 cnt, iRegI_R10 result, immI basic_type,
10376+
iRegLNoSp tmp1, iRegLNoSp tmp2,
10377+
iRegLNoSp tmp3, iRegLNoSp tmp4,
10378+
iRegLNoSp tmp5, iRegLNoSp tmp6, rFlagsReg cr)
10379+
%{
10380+
match(Set result (VectorizedHashCode (Binary ary cnt) (Binary result basic_type)));
10381+
effect(TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, TEMP tmp5, TEMP tmp6,
10382+
USE_KILL ary, USE_KILL cnt, USE basic_type, KILL cr);
10383+
10384+
format %{ "Array HashCode array[] $ary,$cnt,$result,$basic_type -> $result // KILL all" %}
10385+
ins_encode %{
10386+
__ arrays_hashcode($ary$$Register, $cnt$$Register, $result$$Register,
10387+
$tmp1$$Register, $tmp2$$Register, $tmp3$$Register,
10388+
$tmp4$$Register, $tmp5$$Register, $tmp6$$Register,
10389+
(BasicType)$basic_type$$constant);
10390+
%}
10391+
ins_pipe(pipe_class_memory);
10392+
%}
10393+
1037410394
// ============================================================================
1037510395
// Safepoint Instructions
1037610396

src/hotspot/cpu/riscv/vm_version_riscv.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,10 @@ void VM_Version::c2_initialize() {
315315
}
316316
}
317317

318+
if (FLAG_IS_DEFAULT(UseVectorizedHashCodeIntrinsic)) {
319+
FLAG_SET_DEFAULT(UseVectorizedHashCodeIntrinsic, true);
320+
}
321+
318322
if (!UseZicbop) {
319323
if (!FLAG_IS_DEFAULT(AllocatePrefetchStyle)) {
320324
warning("Zicbop is not available on this CPU");

0 commit comments

Comments
 (0)