From 4c5956d7481e043c35f5dc78f095516288a00a2e Mon Sep 17 00:00:00 2001 From: David Linus Briemann Date: Thu, 13 Mar 2025 11:14:52 +0000 Subject: [PATCH] 8350866: [x86] Add C1 intrinsics for CRC32-C Reviewed-by: mdoerr, kvn --- src/hotspot/cpu/x86/c1_LIRGenerator_x86.cpp | 69 ++++++++++++++++++++- src/hotspot/share/c1/c1_Compiler.cpp | 2 +- src/hotspot/share/opto/library_call.cpp | 6 +- 3 files changed, 71 insertions(+), 6 deletions(-) diff --git a/src/hotspot/cpu/x86/c1_LIRGenerator_x86.cpp b/src/hotspot/cpu/x86/c1_LIRGenerator_x86.cpp index 7e28b288f71..d0064b62dd8 100644 --- a/src/hotspot/cpu/x86/c1_LIRGenerator_x86.cpp +++ b/src/hotspot/cpu/x86/c1_LIRGenerator_x86.cpp @@ -1054,7 +1054,7 @@ void LIRGenerator::do_ArrayCopy(Intrinsic* x) { } void LIRGenerator::do_update_CRC32(Intrinsic* x) { - assert(UseCRC32Intrinsics, "need AVX and LCMUL instructions support"); + assert(UseCRC32Intrinsics, "need AVX and CLMUL instructions support"); // Make all state_for calls early since they can emit code LIR_Opr result = rlock_result(x); int flags = 0; @@ -1131,7 +1131,72 @@ void LIRGenerator::do_update_CRC32(Intrinsic* x) { } void LIRGenerator::do_update_CRC32C(Intrinsic* x) { - Unimplemented(); + assert(UseCRC32CIntrinsics, "need AVX and CLMUL instructions support"); + LIR_Opr result = rlock_result(x); + + switch (x->id()) { + case vmIntrinsics::_updateBytesCRC32C: + case vmIntrinsics::_updateDirectByteBufferCRC32C: { + bool is_updateBytes = (x->id() == vmIntrinsics::_updateBytesCRC32C); + + LIRItem crc(x->argument_at(0), this); + LIRItem buf(x->argument_at(1), this); + LIRItem off(x->argument_at(2), this); + LIRItem end(x->argument_at(3), this); + buf.load_item(); + off.load_nonconstant(); + end.load_nonconstant(); + + // len = end - off + LIR_Opr len = end.result(); + LIR_Opr tmpA = new_register(T_INT); + LIR_Opr tmpB = new_register(T_INT); + __ move(end.result(), tmpA); + __ move(off.result(), tmpB); + __ sub(tmpA, tmpB, tmpA); + len = tmpA; + + LIR_Opr index = off.result(); + int offset = is_updateBytes ? arrayOopDesc::base_offset_in_bytes(T_BYTE) : 0; + if (off.result()->is_constant()) { + index = LIR_OprFact::illegalOpr; + offset += off.result()->as_jint(); + } + LIR_Opr base_op = buf.result(); + LIR_Address* a = nullptr; + + if (index->is_valid()) { + LIR_Opr tmp = new_register(T_LONG); + __ convert(Bytecodes::_i2l, index, tmp); + index = tmp; + a = new LIR_Address(base_op, index, offset, T_BYTE); + } else { + a = new LIR_Address(base_op, offset, T_BYTE); + } + + BasicTypeList signature(3); + signature.append(T_INT); + signature.append(T_ADDRESS); + signature.append(T_INT); + CallingConvention* cc = frame_map()->c_calling_convention(&signature); + const LIR_Opr result_reg = result_register_for(x->type()); + + LIR_Opr arg1 = cc->at(0), + arg2 = cc->at(1), + arg3 = cc->at(2); + + crc.load_item_force(arg1); + __ leal(LIR_OprFact::address(a), arg2); + __ move(len, arg3); + + __ call_runtime_leaf(StubRoutines::updateBytesCRC32C(), getThreadTemp(), result_reg, cc->args()); + __ move(result_reg, result); + break; + } + default: { + ShouldNotReachHere(); + } + } } void LIRGenerator::do_vectorizedMismatch(Intrinsic* x) { diff --git a/src/hotspot/share/c1/c1_Compiler.cpp b/src/hotspot/share/c1/c1_Compiler.cpp index eb7c42e4576..1024b903550 100644 --- a/src/hotspot/share/c1/c1_Compiler.cpp +++ b/src/hotspot/share/c1/c1_Compiler.cpp @@ -222,7 +222,7 @@ bool Compiler::is_intrinsic_supported(vmIntrinsics::ID id) { case vmIntrinsics::_updateCRC32: case vmIntrinsics::_updateBytesCRC32: case vmIntrinsics::_updateByteBufferCRC32: -#if defined(S390) || defined(PPC64) || defined(AARCH64) +#if defined(S390) || defined(PPC64) || defined(AARCH64) || defined(AMD64) case vmIntrinsics::_updateBytesCRC32C: case vmIntrinsics::_updateDirectByteBufferCRC32C: #endif diff --git a/src/hotspot/share/opto/library_call.cpp b/src/hotspot/share/opto/library_call.cpp index 05efda3c64b..80a4f4e3503 100644 --- a/src/hotspot/share/opto/library_call.cpp +++ b/src/hotspot/share/opto/library_call.cpp @@ -6564,7 +6564,7 @@ bool LibraryCallKit::inline_vectorizedHashCode() { * int java.util.zip.CRC32.update(int crc, int b) */ bool LibraryCallKit::inline_updateCRC32() { - assert(UseCRC32Intrinsics, "need AVX and LCMUL instructions support"); + assert(UseCRC32Intrinsics, "need AVX and CLMUL instructions support"); assert(callee()->signature()->size() == 2, "update has 2 parameters"); // no receiver since it is static method Node* crc = argument(0); // type: int @@ -6599,7 +6599,7 @@ bool LibraryCallKit::inline_updateCRC32() { * int java.util.zip.CRC32.updateBytes(int crc, byte[] buf, int off, int len) */ bool LibraryCallKit::inline_updateBytesCRC32() { - assert(UseCRC32Intrinsics, "need AVX and LCMUL instructions support"); + assert(UseCRC32Intrinsics, "need AVX and CLMUL instructions support"); assert(callee()->signature()->size() == 4, "updateBytes has 4 parameters"); // no receiver since it is static method Node* crc = argument(0); // type: int @@ -6643,7 +6643,7 @@ bool LibraryCallKit::inline_updateBytesCRC32() { * int java.util.zip.CRC32.updateByteBuffer(int crc, long buf, int off, int len) */ bool LibraryCallKit::inline_updateByteBufferCRC32() { - assert(UseCRC32Intrinsics, "need AVX and LCMUL instructions support"); + assert(UseCRC32Intrinsics, "need AVX and CLMUL instructions support"); assert(callee()->signature()->size() == 5, "updateByteBuffer has 4 parameters and one is long"); // no receiver since it is static method Node* crc = argument(0); // type: int