Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/coreclr/src/jit/emitarm64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5161,6 +5161,14 @@ void emitter::emitIns_R_R_R(
case INS_lsrv:
case INS_asrv:
case INS_rorv:
case INS_crc32b:
case INS_crc32h:
case INS_crc32w:
case INS_crc32x:
case INS_crc32cb:
case INS_crc32ch:
case INS_crc32cw:
case INS_crc32cx:
assert(insOptsNone(opt));
assert(isValidGeneralDatasize(size));
assert(isGeneralRegister(reg1));
Expand Down
39 changes: 38 additions & 1 deletion src/coreclr/src/jit/hwintrinsicarm64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ static InstructionSet Arm64VersionOfIsa(InstructionSet isa)
return InstructionSet_AdvSimd_Arm64;
case InstructionSet_ArmBase:
return InstructionSet_ArmBase_Arm64;
case InstructionSet_Crc32:
return InstructionSet_Crc32_Arm64;
default:
unreached();
}
Expand Down Expand Up @@ -55,6 +57,13 @@ static InstructionSet lookupInstructionSet(const char* className)
return InstructionSet_ArmBase;
}
}
else if (className[0] == 'C')
{
if (strcmp(className, "Crc32") == 0)
{
return InstructionSet_Crc32;
}
}
else if (className[0] == 'S')
{
if (strcmp(className, "Sha1") == 0)
Expand Down Expand Up @@ -154,6 +163,8 @@ bool HWIntrinsicInfo::isFullyImplementedIsa(InstructionSet isa)
case InstructionSet_Aes:
case InstructionSet_ArmBase:
case InstructionSet_ArmBase_Arm64:
case InstructionSet_Crc32:
case InstructionSet_Crc32_Arm64:
case InstructionSet_Sha1:
case InstructionSet_Sha256:
case InstructionSet_Vector64:
Expand Down Expand Up @@ -183,6 +194,8 @@ bool HWIntrinsicInfo::isScalarIsa(InstructionSet isa)
{
case InstructionSet_ArmBase:
case InstructionSet_ArmBase_Arm64:
case InstructionSet_Crc32:
case InstructionSet_Crc32_Arm64:
{
return true;
}
Expand Down Expand Up @@ -247,10 +260,15 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic,
}
}

if (HWIntrinsicInfo::BaseTypeFromFirstArg(intrinsic))
if (HWIntrinsicInfo::BaseTypeFromFirstArg(intrinsic) || HWIntrinsicInfo::BaseTypeFromSecondArg(intrinsic))
{
CORINFO_ARG_LIST_HANDLE arg = sig->args;

if (HWIntrinsicInfo::BaseTypeFromSecondArg(intrinsic))
{
arg = info.compCompHnd->getArgNext(arg);
}

CORINFO_CLASS_HANDLE argClass = info.compCompHnd->getArgClass(sig, arg);
baseType = getBaseTypeAndSizeOfSIMDType(argClass);

Expand Down Expand Up @@ -359,6 +377,25 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic,
return gtNewScalarHWIntrinsicNode(baseType, op1, intrinsic);
}

case NI_Crc32_ComputeCrc32:
case NI_Crc32_ComputeCrc32C:
case NI_Crc32_Arm64_ComputeCrc32:
case NI_Crc32_Arm64_ComputeCrc32C:
{
assert(numArgs == 2);

argType = JITtype2varType(
strip(info.compCompHnd->getArgType(sig, info.compCompHnd->getArgNext(argList), &argClass)));
op2 = getArgForHWIntrinsic(argType, argClass);

argType = JITtype2varType(strip(info.compCompHnd->getArgType(sig, argList, &argClass)));
op1 = getArgForHWIntrinsic(argType, argClass);

retNode = gtNewScalarHWIntrinsicNode(retType, op1, op2, intrinsic);
retNode->AsHWIntrinsic()->gtSIMDBaseType = baseType;
break;
}

default:
{
unreached();
Expand Down
60 changes: 59 additions & 1 deletion src/coreclr/src/jit/hwintrinsiccodegenarm64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,51 @@ void CodeGen::genSpecialIntrinsic(GenTreeHWIntrinsic* node)
GenTree* op2 = node->gtGetOp2();
regNumber targetReg = node->GetRegNum();
var_types targetType = node->TypeGet();
var_types baseType = (category == HW_Category_Scalar) ? op1->TypeGet() : node->gtSIMDBaseType;
var_types baseType = node->gtSIMDBaseType;

if (baseType == TYP_UNKNOWN)
{
assert(category == HW_Category_Scalar);

if (HWIntrinsicInfo::BaseTypeFromFirstArg(intrinsicId))
{
assert(op1 != nullptr);
baseType = op1->TypeGet();
}
else if (HWIntrinsicInfo::BaseTypeFromSecondArg(intrinsicId))
{
assert(op2 != nullptr);
baseType = op2->TypeGet();
}
else
{
baseType = targetType;
}
}

switch (intrinsicId)
{
case NI_Crc32_ComputeCrc32:
case NI_Crc32_ComputeCrc32C:
{
if (baseType == TYP_INT)
{
baseType = TYP_UINT;
}
break;
}

case NI_Crc32_Arm64_ComputeCrc32:
case NI_Crc32_Arm64_ComputeCrc32C:
{
assert(baseType == TYP_LONG);
baseType = TYP_ULONG;
break;
}

default:
break;
}

instruction ins = HWIntrinsicInfo::lookupIns(intrinsicId, baseType);
assert(ins != INS_invalid);
Expand Down Expand Up @@ -215,6 +259,20 @@ void CodeGen::genSpecialIntrinsic(GenTreeHWIntrinsic* node)
break;
}

case NI_Crc32_ComputeCrc32:
case NI_Crc32_ComputeCrc32C:
case NI_Crc32_Arm64_ComputeCrc32:
case NI_Crc32_Arm64_ComputeCrc32C:
{
assert(op1 != nullptr);
assert(op2 != nullptr);

op1Reg = op1->GetRegNum();
op2Reg = op2->GetRegNum();
emit->emitIns_R_R_R(ins, emitSize, targetReg, op1Reg, op2Reg);
break;
}

default:
{
unreached();
Expand Down
22 changes: 19 additions & 3 deletions src/coreclr/src/jit/hwintrinsiclistarm64.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,15 +82,31 @@ HARDWARE_INTRINSIC(Aes, MixColumns, -
// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE}
// ***************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
// Base Intrinsics
HARDWARE_INTRINSIC(ArmBase, LeadingZeroCount, -1, 0, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_clz, INS_clz, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoContainment)
HARDWARE_INTRINSIC(ArmBase, LeadingZeroCount, -1, 0, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_clz, INS_clz, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg)

// ***************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
// ISA Function name ival SIMD size NumArg instructions Category Flags
// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE}
// ***************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
// Base 64-bit only Intrinsics
HARDWARE_INTRINSIC(ArmBase_Arm64, LeadingSignCount, -1, 0, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cls, INS_invalid, INS_cls, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoContainment)
HARDWARE_INTRINSIC(ArmBase_Arm64, LeadingZeroCount, -1, 0, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_clz, INS_clz, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoContainment)
HARDWARE_INTRINSIC(ArmBase_Arm64, LeadingSignCount, -1, 0, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cls, INS_invalid, INS_cls, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg)
HARDWARE_INTRINSIC(ArmBase_Arm64, LeadingZeroCount, -1, 0, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_clz, INS_clz, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg)

// ***************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
// ISA Function name ival SIMD size NumArg instructions Category Flags
// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE}
// ***************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
// CRC32 Intrinsics
HARDWARE_INTRINSIC(Crc32, ComputeCrc32, -1, 0, 2, {INS_invalid, INS_crc32b, INS_invalid, INS_crc32h, INS_invalid, INS_crc32w, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_SpecialImport|HW_Flag_NoContainment|HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromSecondArg)
HARDWARE_INTRINSIC(Crc32, ComputeCrc32C, -1, 0, 2, {INS_invalid, INS_crc32cb, INS_invalid, INS_crc32ch, INS_invalid, INS_crc32cw, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_SpecialImport|HW_Flag_NoContainment|HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromSecondArg)

// ***************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
// ISA Function name ival SIMD size NumArg instructions Category Flags
// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE}
// ***************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
// CRC32 64-bit only Intrinsics
HARDWARE_INTRINSIC(Crc32_Arm64, ComputeCrc32, -1, 0, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_crc32x, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_SpecialImport|HW_Flag_NoContainment|HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromSecondArg)
HARDWARE_INTRINSIC(Crc32_Arm64, ComputeCrc32C, -1, 0, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_crc32cx, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_SpecialImport|HW_Flag_NoContainment|HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromSecondArg)

// ***************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
// ISA Function name ival SIMD size NumArg instructions Category Flags
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/src/jit/instr.h
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,7 @@ enum InstructionSet
InstructionSet_ArmBase_Arm64,
InstructionSet_Atomics, // ID_AA64ISAR0_EL1.Atomic is 2 or better
InstructionSet_Crc32, // ID_AA64ISAR0_EL1.CRC32 is 1 or better
InstructionSet_Crc32_Arm64,
InstructionSet_Dcpop, // ID_AA64ISAR1_EL1.DPB is 1 or better
InstructionSet_Dp, // ID_AA64ISAR0_EL1.DP is 1 or better
InstructionSet_Fcma, // ID_AA64ISAR1_EL1.FCMA is 1 or better
Expand Down
24 changes: 24 additions & 0 deletions src/coreclr/src/jit/instrsarm64.h
Original file line number Diff line number Diff line change
Expand Up @@ -1051,6 +1051,30 @@ INST1(asrv, "asrv", 0, 0, IF_DR_3A, 0x1AC02800)
INST1(rorv, "rorv", 0, 0, IF_DR_3A, 0x1AC02C00)
// rorv Rd,Rn,Rm DR_3A X0011010110mmmmm 001011nnnnnddddd 1AC0 2C00

INST1(crc32b, "crc32b", 0, 0, IF_DR_3A, 0x1AC04000)
// crc32b Rd,Rn,Rm DR_3A 00011010110mmmmm 010000nnnnnddddd 1AC0 4000

INST1(crc32h, "crc32h", 0, 0, IF_DR_3A, 0x1AC04400)
// crc32h Rd,Rn,Rm DR_3A 00011010110mmmmm 010001nnnnnddddd 1AC0 4400

INST1(crc32w, "crc32w", 0, 0, IF_DR_3A, 0x1AC04800)
// crc32w Rd,Rn,Rm DR_3A 00011010110mmmmm 010010nnnnnddddd 1AC0 4800

INST1(crc32x, "crc32x", 0, 0, IF_DR_3A, 0x9AC04C00)
// crc32x Rd,Rn,Xm DR_3A 10011010110mmmmm 010011nnnnnddddd 9AC0 4C00

INST1(crc32cb, "crc32cb",0, 0, IF_DR_3A, 0x1AC05000)
// crc32cb Rd,Rn,Rm DR_3A 00011010110mmmmm 010100nnnnnddddd 1AC0 5000

INST1(crc32ch, "crc32ch",0, 0, IF_DR_3A, 0x1AC05400)
// crc32ch Rd,Rn,Rm DR_3A 00011010110mmmmm 010101nnnnnddddd 1AC0 5400

INST1(crc32cw, "crc32cw",0, 0, IF_DR_3A, 0x1AC05800)
// crc32cw Rd,Rn,Rm DR_3A 00011010110mmmmm 010110nnnnnddddd 1AC0 5800

INST1(crc32cx, "crc32cx",0, 0, IF_DR_3A, 0x9AC05C00)
// crc32cx Rd,Rn,Xm DR_3A 10011010110mmmmm 010111nnnnnddddd 9AC0 5C00

INST1(sha1c, "sha1c", 0, 0, IF_DV_3F, 0x5E000000)
// sha1c Qd, Sn Vm.4S DV_3F 01011110000mmmmm 000000nnnnnddddd 5E00 0000 Qd Sn Vm.4S (vector)

Expand Down
Loading