//
void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node)
{
- NamedIntrinsic intrinsicID = node->gtHWIntrinsicId;
- InstructionSet isa = Compiler::isaOfHWIntrinsic(intrinsicID);
- HWIntrinsicCategory category = Compiler::categoryOfHWIntrinsic(intrinsicID);
- HWIntrinsicFlag flags = Compiler::flagsOfHWIntrinsic(intrinsicID);
- int ival = Compiler::ivalOfHWIntrinsic(intrinsicID);
+ NamedIntrinsic intrinsicId = node->gtHWIntrinsicId;
+ InstructionSet isa = HWIntrinsicInfo::lookupIsa(intrinsicId);
+ HWIntrinsicCategory category = HWIntrinsicInfo::lookupCategory(intrinsicId);
+ HWIntrinsicFlag flags = HWIntrinsicInfo::lookupFlags(intrinsicId);
+ int ival = HWIntrinsicInfo::lookupIval(intrinsicId);
int numArgs = Compiler::numArgsOfHWIntrinsic(node);
assert((flags & HW_Flag_NoCodeGen) == 0);
emitter* emit = getEmitter();
assert(numArgs >= 0);
- instruction ins = Compiler::insOfHWIntrinsic(intrinsicID, baseType);
+ instruction ins = HWIntrinsicInfo::lookupIns(intrinsicId, baseType);
assert(ins != INS_invalid);
emitAttr simdSize = EA_ATTR(node->gtSIMDSize);
assert(simdSize != 0);
}
else if (category == HW_Category_MemoryLoad)
{
- if (intrinsicID == NI_AVX_MaskLoad)
+ if (intrinsicId == NI_AVX_MaskLoad)
{
emit->emitIns_SIMD_R_R_AR(ins, simdSize, targetReg, op2Reg, op1Reg);
}
emit->emitIns_SIMD_R_R_AR(ins, simdSize, targetReg, op1Reg, op2Reg);
}
}
- else if (Compiler::isImmHWIntrinsic(intrinsicID, op2))
+ else if (Compiler::isImmHWIntrinsic(intrinsicId, op2))
{
assert(ival == -1);
- if (intrinsicID == NI_SSE2_Extract)
+ if (intrinsicId == NI_SSE2_Extract)
{
// extract instructions return to GP-registers, so it needs int size as the emitsize
simdSize = emitTypeSize(TYP_INT);
// can also occur if the consumer calls it directly and just doesn't pass a constant value.
regNumber baseReg = node->ExtractTempReg();
regNumber offsReg = node->GetSingleTempReg();
- genHWIntrinsicJumpTableFallback(intrinsicID, op2Reg, baseReg, offsReg, emitSwCase);
+ genHWIntrinsicJumpTableFallback(intrinsicId, op2Reg, baseReg, offsReg, emitSwCase);
}
}
else
genConsumeRegs(op3);
regNumber op3Reg = op3->gtRegNum;
- if (Compiler::isImmHWIntrinsic(intrinsicID, op3))
+ if (Compiler::isImmHWIntrinsic(intrinsicId, op3))
{
assert(ival == -1);
// can also occur if the consumer calls it directly and just doesn't pass a constant value.
regNumber baseReg = node->ExtractTempReg();
regNumber offsReg = node->GetSingleTempReg();
- genHWIntrinsicJumpTableFallback(intrinsicID, op3Reg, baseReg, offsReg, emitSwCase);
+ genHWIntrinsicJumpTableFallback(intrinsicId, op3Reg, baseReg, offsReg, emitSwCase);
}
}
else if (category == HW_Category_MemoryStore)
{
- assert(intrinsicID == NI_SSE2_MaskMove);
+ assert(intrinsicId == NI_SSE2_MaskMove);
assert(targetReg == REG_NA);
// SSE2 MaskMove hardcodes the destination (op3) in DI/EDI/RDI
if (op2->isContained() || op2->isUsedFromSpillTemp())
{
- assert((Compiler::flagsOfHWIntrinsic(node->gtHWIntrinsicId) & HW_Flag_NoContainment) == 0);
+ assert((HWIntrinsicInfo::lookupFlags(node->gtHWIntrinsicId) & HW_Flag_NoContainment) == 0);
#if DEBUG
bool supportsRegOptional = false;
emitAttr simdSize = EA_ATTR(node->gtSIMDSize);
emitter* emit = getEmitter();
- int ival = Compiler::ivalOfHWIntrinsic(node->gtHWIntrinsicId);
+ int ival = HWIntrinsicInfo::lookupIval(node->gtHWIntrinsicId);
assert((ival >= 0) && (ival <= 127));
// TODO-XArch-CQ: Commutative operations can have op1 be contained
if (op2->isContained() || op2->isUsedFromSpillTemp())
{
- assert((Compiler::flagsOfHWIntrinsic(node->gtHWIntrinsicId) & HW_Flag_NoContainment) == 0);
+ assert((HWIntrinsicInfo::lookupFlags(node->gtHWIntrinsicId) & HW_Flag_NoContainment) == 0);
#if DEBUG
bool supportsRegOptional = false;
//
void CodeGen::genSSEIntrinsic(GenTreeHWIntrinsic* node)
{
- NamedIntrinsic intrinsicID = node->gtHWIntrinsicId;
+ NamedIntrinsic intrinsicId = node->gtHWIntrinsicId;
GenTree* op1 = node->gtGetOp1();
GenTree* op2 = node->gtGetOp2();
GenTree* op3 = nullptr;
genConsumeOperands(node);
}
- switch (intrinsicID)
+ switch (intrinsicId)
{
case NI_SSE_CompareEqualOrderedScalar:
case NI_SSE_CompareEqualUnorderedScalar:
assert(baseType == TYP_FLOAT);
op2Reg = op2->gtRegNum;
regNumber tmpReg = node->GetSingleTempReg();
- instruction ins = Compiler::insOfHWIntrinsic(intrinsicID, node->gtSIMDBaseType);
+ instruction ins = HWIntrinsicInfo::lookupIns(intrinsicId, node->gtSIMDBaseType);
// Ensure we aren't overwriting targetReg
assert(tmpReg != targetReg);
assert(baseType == TYP_FLOAT);
op2Reg = op2->gtRegNum;
- instruction ins = Compiler::insOfHWIntrinsic(intrinsicID, node->gtSIMDBaseType);
+ instruction ins = HWIntrinsicInfo::lookupIns(intrinsicId, node->gtSIMDBaseType);
emit->emitIns_R_R(ins, emitTypeSize(TYP_SIMD16), op1Reg, op2Reg);
emit->emitIns_R(INS_seta, EA_1BYTE, targetReg);
emit->emitIns_R_R(INS_movzx, EA_1BYTE, targetReg, targetReg);
assert(baseType == TYP_FLOAT);
op2Reg = op2->gtRegNum;
- instruction ins = Compiler::insOfHWIntrinsic(intrinsicID, node->gtSIMDBaseType);
+ instruction ins = HWIntrinsicInfo::lookupIns(intrinsicId, node->gtSIMDBaseType);
emit->emitIns_R_R(ins, emitTypeSize(TYP_SIMD16), op1Reg, op2Reg);
emit->emitIns_R(INS_setae, EA_1BYTE, targetReg);
emit->emitIns_R_R(INS_movzx, EA_1BYTE, targetReg, targetReg);
assert(baseType == TYP_FLOAT);
op2Reg = op2->gtRegNum;
- instruction ins = Compiler::insOfHWIntrinsic(intrinsicID, node->gtSIMDBaseType);
+ instruction ins = HWIntrinsicInfo::lookupIns(intrinsicId, node->gtSIMDBaseType);
emit->emitIns_R_R(ins, emitTypeSize(TYP_SIMD16), op2Reg, op1Reg);
emit->emitIns_R(INS_seta, EA_1BYTE, targetReg);
emit->emitIns_R_R(INS_movzx, EA_1BYTE, targetReg, targetReg);
assert(baseType == TYP_FLOAT);
op2Reg = op2->gtRegNum;
- instruction ins = Compiler::insOfHWIntrinsic(intrinsicID, node->gtSIMDBaseType);
+ instruction ins = HWIntrinsicInfo::lookupIns(intrinsicId, node->gtSIMDBaseType);
emit->emitIns_R_R(ins, emitTypeSize(TYP_SIMD16), op2Reg, op1Reg);
emit->emitIns_R(INS_setae, EA_1BYTE, targetReg);
emit->emitIns_R_R(INS_movzx, EA_1BYTE, targetReg, targetReg);
assert(baseType == TYP_FLOAT);
op2Reg = op2->gtRegNum;
regNumber tmpReg = node->GetSingleTempReg();
- instruction ins = Compiler::insOfHWIntrinsic(intrinsicID, node->gtSIMDBaseType);
+ instruction ins = HWIntrinsicInfo::lookupIns(intrinsicId, node->gtSIMDBaseType);
// Ensure we aren't overwriting targetReg
assert(tmpReg != targetReg);
assert(op2 == nullptr);
if (op1Reg != targetReg)
{
- instruction ins = Compiler::insOfHWIntrinsic(intrinsicID, node->gtSIMDBaseType);
+ instruction ins = HWIntrinsicInfo::lookupIns(intrinsicId, node->gtSIMDBaseType);
emit->emitIns_R_R(ins, emitTypeSize(TYP_SIMD16), targetReg, op1Reg);
}
break;
assert(baseType == TYP_FLOAT);
assert(op2 == nullptr);
- instruction ins = Compiler::insOfHWIntrinsic(intrinsicID, node->gtSIMDBaseType);
+ instruction ins = HWIntrinsicInfo::lookupIns(intrinsicId, node->gtSIMDBaseType);
emit->emitIns_R_R(ins, emitTypeSize(TYP_INT), targetReg, op1Reg);
break;
}
assert(baseType == TYP_UBYTE);
assert(op2 == nullptr);
- instruction ins = Compiler::insOfHWIntrinsic(intrinsicID, node->gtSIMDBaseType);
+ instruction ins = HWIntrinsicInfo::lookupIns(intrinsicId, node->gtSIMDBaseType);
emit->emitIns_AR(ins, emitTypeSize(baseType), op1Reg, 0);
break;
}
//
void CodeGen::genSSE2Intrinsic(GenTreeHWIntrinsic* node)
{
- NamedIntrinsic intrinsicID = node->gtHWIntrinsicId;
+ NamedIntrinsic intrinsicId = node->gtHWIntrinsicId;
GenTree* op1 = node->gtGetOp1();
GenTree* op2 = node->gtGetOp2();
regNumber targetReg = node->gtRegNum;
genConsumeOperands(node);
}
- switch (intrinsicID)
+ switch (intrinsicId)
{
// All integer overloads are handled by table codegen
case NI_SSE2_CompareLessThan:
assert(baseType == TYP_DOUBLE);
- int ival = Compiler::ivalOfHWIntrinsic(intrinsicID);
+ int ival = HWIntrinsicInfo::lookupIval(intrinsicId);
assert((ival >= 0) && (ival <= 127));
- instruction ins = Compiler::insOfHWIntrinsic(intrinsicID, baseType);
+ instruction ins = HWIntrinsicInfo::lookupIns(intrinsicId, baseType);
op2Reg = op2->gtRegNum;
emit->emitIns_SIMD_R_R_R_I(ins, emitTypeSize(TYP_SIMD16), targetReg, op1Reg, op2Reg, ival);
assert(baseType == TYP_DOUBLE);
op2Reg = op2->gtRegNum;
regNumber tmpReg = node->GetSingleTempReg();
- instruction ins = Compiler::insOfHWIntrinsic(intrinsicID, baseType);
+ instruction ins = HWIntrinsicInfo::lookupIns(intrinsicId, baseType);
// Ensure we aren't overwriting targetReg
assert(tmpReg != targetReg);
{
assert(baseType == TYP_DOUBLE);
op2Reg = op2->gtRegNum;
- instruction ins = Compiler::insOfHWIntrinsic(intrinsicID, baseType);
+ instruction ins = HWIntrinsicInfo::lookupIns(intrinsicId, baseType);
emit->emitIns_R_R(ins, emitTypeSize(TYP_SIMD16), op1Reg, op2Reg);
emit->emitIns_R(INS_seta, EA_1BYTE, targetReg);
{
assert(baseType == TYP_DOUBLE);
op2Reg = op2->gtRegNum;
- instruction ins = Compiler::insOfHWIntrinsic(intrinsicID, baseType);
+ instruction ins = HWIntrinsicInfo::lookupIns(intrinsicId, baseType);
emit->emitIns_R_R(ins, emitTypeSize(TYP_SIMD16), op1Reg, op2Reg);
emit->emitIns_R(INS_setae, EA_1BYTE, targetReg);
{
assert(baseType == TYP_DOUBLE);
op2Reg = op2->gtRegNum;
- instruction ins = Compiler::insOfHWIntrinsic(intrinsicID, baseType);
+ instruction ins = HWIntrinsicInfo::lookupIns(intrinsicId, baseType);
emit->emitIns_R_R(ins, emitTypeSize(TYP_SIMD16), op2Reg, op1Reg);
emit->emitIns_R(INS_seta, EA_1BYTE, targetReg);
{
assert(baseType == TYP_DOUBLE);
op2Reg = op2->gtRegNum;
- instruction ins = Compiler::insOfHWIntrinsic(intrinsicID, baseType);
+ instruction ins = HWIntrinsicInfo::lookupIns(intrinsicId, baseType);
emit->emitIns_R_R(ins, emitTypeSize(TYP_SIMD16), op2Reg, op1Reg);
emit->emitIns_R(INS_setae, EA_1BYTE, targetReg);
{
assert(baseType == TYP_DOUBLE);
op2Reg = op2->gtRegNum;
- instruction ins = Compiler::insOfHWIntrinsic(intrinsicID, baseType);
+ instruction ins = HWIntrinsicInfo::lookupIns(intrinsicId, baseType);
regNumber tmpReg = node->GetSingleTempReg();
// Ensure we aren't overwriting targetReg
assert(baseType == TYP_INT || baseType == TYP_LONG || baseType == TYP_FLOAT || baseType == TYP_DOUBLE);
assert(op1 != nullptr);
assert(op2 != nullptr);
- instruction ins = Compiler::insOfHWIntrinsic(intrinsicID, baseType);
+ instruction ins = HWIntrinsicInfo::lookupIns(intrinsicId, baseType);
genHWIntrinsic_R_R_RM(node, ins);
break;
}
assert(baseType == TYP_LONG || baseType == TYP_ULONG);
assert(op1 != nullptr);
assert(op2 == nullptr);
- instruction ins = Compiler::insOfHWIntrinsic(intrinsicID, baseType);
+ instruction ins = HWIntrinsicInfo::lookupIns(intrinsicId, baseType);
emit->emitIns_R_R(ins, emitTypeSize(baseType), targetReg, op1Reg);
break;
}
assert(op2 == nullptr);
if (op1Reg != targetReg)
{
- instruction ins = Compiler::insOfHWIntrinsic(intrinsicID, baseType);
+ instruction ins = HWIntrinsicInfo::lookupIns(intrinsicId, baseType);
emit->emitIns_R_R(ins, emitTypeSize(targetType), targetReg, op1Reg);
}
break;
assert(op2 == nullptr);
assert(baseType == TYP_DOUBLE || baseType == TYP_FLOAT || baseType == TYP_INT || baseType == TYP_UINT ||
baseType == TYP_LONG || baseType == TYP_ULONG);
- instruction ins = Compiler::insOfHWIntrinsic(intrinsicID, baseType);
+ instruction ins = HWIntrinsicInfo::lookupIns(intrinsicId, baseType);
if (baseType == TYP_DOUBLE || baseType == TYP_FLOAT)
{
emit->emitIns_R_R(ins, emitTypeSize(targetType), targetReg, op1Reg);
assert(op2 == nullptr);
assert(baseType == TYP_BYTE || baseType == TYP_UBYTE || baseType == TYP_DOUBLE);
- instruction ins = Compiler::insOfHWIntrinsic(intrinsicID, baseType);
+ instruction ins = HWIntrinsicInfo::lookupIns(intrinsicId, baseType);
emit->emitIns_R_R(ins, emitTypeSize(TYP_INT), targetReg, op1Reg);
break;
}
assert(baseType == TYP_DOUBLE);
assert(op2 == nullptr);
- instruction ins = Compiler::insOfHWIntrinsic(intrinsicID, node->gtSIMDBaseType);
+ instruction ins = HWIntrinsicInfo::lookupIns(intrinsicId, node->gtSIMDBaseType);
if (op1Reg == targetReg)
{
regNumber tmpReg = node->GetSingleTempReg();
assert(op1 == nullptr);
assert(op2 == nullptr);
- instruction ins = Compiler::insOfHWIntrinsic(intrinsicID, baseType);
+ instruction ins = HWIntrinsicInfo::lookupIns(intrinsicId, baseType);
emit->emitIns_SIMD_R_R_R(ins, emitTypeSize(TYP_SIMD16), targetReg, targetReg, targetReg);
break;
}
assert(op2 != nullptr);
op2Reg = op2->gtRegNum;
- instruction ins = Compiler::insOfHWIntrinsic(intrinsicID, baseType);
+ instruction ins = HWIntrinsicInfo::lookupIns(intrinsicId, baseType);
emit->emitIns_AR_R(ins, emitTypeSize(baseType), op2Reg, op1Reg, 0);
break;
}
//
void CodeGen::genSSE41Intrinsic(GenTreeHWIntrinsic* node)
{
- NamedIntrinsic intrinsicID = node->gtHWIntrinsicId;
+ NamedIntrinsic intrinsicId = node->gtHWIntrinsicId;
GenTree* op1 = node->gtGetOp1();
GenTree* op2 = node->gtGetOp2();
GenTree* op3 = nullptr;
genConsumeOperands(node);
}
- switch (intrinsicID)
+ switch (intrinsicId)
{
case NI_SSE41_TestAllOnes:
{
regNumber tmpReg = node->GetSingleTempReg();
- assert(Compiler::insOfHWIntrinsic(intrinsicID, node->gtSIMDBaseType) == INS_ptest);
+ assert(HWIntrinsicInfo::lookupIns(intrinsicId, node->gtSIMDBaseType) == INS_ptest);
emit->emitIns_SIMD_R_R_R(INS_pcmpeqd, emitTypeSize(TYP_SIMD16), tmpReg, tmpReg, tmpReg);
emit->emitIns_R_R(INS_xor, EA_4BYTE, targetReg, targetReg);
emit->emitIns_R_R(INS_ptest, emitTypeSize(TYP_SIMD16), op1Reg, tmpReg);
case NI_SSE41_TestAllZeros:
case NI_SSE41_TestZ:
{
- assert(Compiler::insOfHWIntrinsic(intrinsicID, node->gtSIMDBaseType) == INS_ptest);
+ assert(HWIntrinsicInfo::lookupIns(intrinsicId, node->gtSIMDBaseType) == INS_ptest);
emit->emitIns_R_R(INS_xor, EA_4BYTE, targetReg, targetReg);
emit->emitIns_R_R(INS_ptest, emitTypeSize(TYP_SIMD16), op1Reg, op2->gtRegNum);
emit->emitIns_R(INS_sete, EA_1BYTE, targetReg);
case NI_SSE41_TestC:
{
- assert(Compiler::insOfHWIntrinsic(intrinsicID, node->gtSIMDBaseType) == INS_ptest);
+ assert(HWIntrinsicInfo::lookupIns(intrinsicId, node->gtSIMDBaseType) == INS_ptest);
emit->emitIns_R_R(INS_xor, EA_4BYTE, targetReg, targetReg);
emit->emitIns_R_R(INS_ptest, emitTypeSize(TYP_SIMD16), op1Reg, op2->gtRegNum);
emit->emitIns_R(INS_setb, EA_1BYTE, targetReg);
case NI_SSE41_TestMixOnesZeros:
case NI_SSE41_TestNotZAndNotC:
{
- assert(Compiler::insOfHWIntrinsic(intrinsicID, node->gtSIMDBaseType) == INS_ptest);
+ assert(HWIntrinsicInfo::lookupIns(intrinsicId, node->gtSIMDBaseType) == INS_ptest);
emit->emitIns_R_R(INS_xor, EA_4BYTE, targetReg, targetReg);
emit->emitIns_R_R(INS_ptest, emitTypeSize(TYP_SIMD16), op1Reg, op2->gtRegNum);
emit->emitIns_R(INS_seta, EA_1BYTE, targetReg);
case NI_SSE41_Extract:
{
regNumber tmpTargetReg = REG_NA;
- instruction ins = Compiler::insOfHWIntrinsic(intrinsicID, baseType);
+ instruction ins = HWIntrinsicInfo::lookupIns(intrinsicId, baseType);
if (baseType == TYP_FLOAT)
{
tmpTargetReg = node->ExtractTempReg();
// can also occur if the consumer calls it directly and just doesn't pass a constant value.
regNumber baseReg = node->ExtractTempReg();
regNumber offsReg = node->GetSingleTempReg();
- genHWIntrinsicJumpTableFallback(intrinsicID, op2->gtRegNum, baseReg, offsReg, emitSwCase);
+ genHWIntrinsicJumpTableFallback(intrinsicId, op2->gtRegNum, baseReg, offsReg, emitSwCase);
}
break;
}
//
void CodeGen::genSSE42Intrinsic(GenTreeHWIntrinsic* node)
{
- NamedIntrinsic intrinsicID = node->gtHWIntrinsicId;
+ NamedIntrinsic intrinsicId = node->gtHWIntrinsicId;
GenTree* op1 = node->gtGetOp1();
GenTree* op2 = node->gtGetOp2();
regNumber targetReg = node->gtRegNum;
regNumber op2Reg = op2->gtRegNum;
genConsumeOperands(node);
- switch (intrinsicID)
+ switch (intrinsicId)
{
case NI_SSE42_Crc32:
if (op1Reg != targetReg)
//
void CodeGen::genAvxOrAvx2Intrinsic(GenTreeHWIntrinsic* node)
{
- NamedIntrinsic intrinsicID = node->gtHWIntrinsicId;
+ NamedIntrinsic intrinsicId = node->gtHWIntrinsicId;
var_types baseType = node->gtSIMDBaseType;
emitAttr attr = EA_ATTR(node->gtSIMDSize);
var_types targetType = node->TypeGet();
- instruction ins = Compiler::insOfHWIntrinsic(intrinsicID, baseType);
+ instruction ins = HWIntrinsicInfo::lookupIns(intrinsicId, baseType);
int numArgs = Compiler::numArgsOfHWIntrinsic(node);
GenTree* op1 = node->gtGetOp1();
GenTree* op2 = node->gtGetOp2();
genConsumeOperands(node);
}
- switch (intrinsicID)
+ switch (intrinsicId)
{
case NI_AVX_SetZeroVector256:
{
GenTree* lastOp = nullptr;
if (numArgs == 2)
{
- assert(intrinsicID == NI_AVX_ExtractVector128 || NI_AVX_ExtractVector128);
+ assert(intrinsicId == NI_AVX_ExtractVector128 || NI_AVX_ExtractVector128);
op1Reg = op1->gtRegNum;
op2Reg = op2->gtRegNum;
lastOp = op2;
auto emitSwCase = [&](int8_t i) {
if (numArgs == 3)
{
- if (intrinsicID == NI_AVX_ExtractVector128 || intrinsicID == NI_AVX2_ExtractVector128)
+ if (intrinsicId == NI_AVX_ExtractVector128 || intrinsicId == NI_AVX2_ExtractVector128)
{
emit->emitIns_AR_R_I(ins, attr, op1Reg, 0, op2Reg, i);
}
else
{
assert(numArgs == 2);
- assert(intrinsicID == NI_AVX_ExtractVector128 || intrinsicID == NI_AVX2_ExtractVector128);
+ assert(intrinsicId == NI_AVX_ExtractVector128 || intrinsicId == NI_AVX2_ExtractVector128);
emit->emitIns_SIMD_R_R_I(ins, attr, targetReg, op1Reg, i);
}
};
// can also occur if the consumer calls it directly and just doesn't pass a constant value.
regNumber baseReg = node->ExtractTempReg();
regNumber offsReg = node->GetSingleTempReg();
- genHWIntrinsicJumpTableFallback(intrinsicID, op3Reg, baseReg, offsReg, emitSwCase);
+ genHWIntrinsicJumpTableFallback(intrinsicId, op3Reg, baseReg, offsReg, emitSwCase);
}
break;
}
//
void CodeGen::genFMAIntrinsic(GenTreeHWIntrinsic* node)
{
- NamedIntrinsic intrinsicID = node->gtHWIntrinsicId;
+ NamedIntrinsic intrinsicId = node->gtHWIntrinsicId;
var_types baseType = node->gtSIMDBaseType;
- HWIntrinsicFlag flags = Compiler::flagsOfHWIntrinsic(intrinsicID);
+ HWIntrinsicFlag flags = HWIntrinsicInfo::lookupFlags(intrinsicId);
emitAttr attr = EA_ATTR(node->gtSIMDSize);
- instruction ins = Compiler::insOfHWIntrinsic(intrinsicID, baseType);
+ instruction ins = HWIntrinsicInfo::lookupIns(intrinsicId, baseType);
GenTree* op1 = node->gtGetOp1();
regNumber targetReg = node->gtRegNum;
//
void CodeGen::genLZCNTIntrinsic(GenTreeHWIntrinsic* node)
{
- NamedIntrinsic intrinsicID = node->gtHWIntrinsicId;
+ NamedIntrinsic intrinsicId = node->gtHWIntrinsicId;
GenTree* op1 = node->gtGetOp1();
regNumber targetReg = node->gtRegNum;
assert(targetReg != REG_NA);
regNumber op1Reg = op1->gtRegNum;
genConsumeOperands(node);
- assert(intrinsicID == NI_LZCNT_LeadingZeroCount);
+ assert(intrinsicId == NI_LZCNT_LeadingZeroCount);
inst_RV_RV(INS_lzcnt, targetReg, op1Reg, targetType, emitTypeSize(targetType));
//
void CodeGen::genPOPCNTIntrinsic(GenTreeHWIntrinsic* node)
{
- NamedIntrinsic intrinsicID = node->gtHWIntrinsicId;
+ NamedIntrinsic intrinsicId = node->gtHWIntrinsicId;
GenTree* op1 = node->gtGetOp1();
regNumber targetReg = node->gtRegNum;
assert(targetReg != REG_NA);
regNumber op1Reg = op1->gtRegNum;
genConsumeOperands(node);
- assert(intrinsicID == NI_POPCNT_PopCount);
+ assert(intrinsicId == NI_POPCNT_PopCount);
inst_RV_RV(INS_popcnt, targetReg, op1Reg, targetType, emitTypeSize(targetType));
return InstructionSet_ILLEGAL;
}
-//------------------------------------------------------------------------
-// isaOfHWIntrinsic: map named intrinsic value to its instruction set
-//
-// Arguments:
-// intrinsic -- id of the intrinsic function.
-//
-// Return Value:
-// instruction set of the intrinsic.
-//
-InstructionSet Compiler::isaOfHWIntrinsic(NamedIntrinsic intrinsic)
-{
- assert(intrinsic != NI_Illegal);
- assert(intrinsic > NI_HW_INTRINSIC_START && intrinsic < NI_HW_INTRINSIC_END);
- return hwIntrinsicInfoArray[intrinsic - NI_HW_INTRINSIC_START - 1].isa;
-}
-
-//------------------------------------------------------------------------
-// ivalOfHWIntrinsic: get the imm8 value of this intrinsic from the hwIntrinsicInfoArray table
-//
-// Arguments:
-// intrinsic -- id of the intrinsic function.
-//
-// Return Value:
-// The imm8 value that is implicit for this intrinsic, or -1 for intrinsics that do not take an immediate, or for
-// which the immediate is an explicit argument.
-//
-int Compiler::ivalOfHWIntrinsic(NamedIntrinsic intrinsic)
-{
- assert(intrinsic != NI_Illegal);
- assert(intrinsic > NI_HW_INTRINSIC_START && intrinsic < NI_HW_INTRINSIC_END);
- return hwIntrinsicInfoArray[intrinsic - NI_HW_INTRINSIC_START - 1].ival;
-}
-
//------------------------------------------------------------------------
// simdSizeOfHWIntrinsic: get the SIMD size of this intrinsic
//
{
assert(intrinsic > NI_HW_INTRINSIC_START && intrinsic < NI_HW_INTRINSIC_END);
- HWIntrinsicFlag flags = flagsOfHWIntrinsic(intrinsic);
+ HWIntrinsicFlag flags = HWIntrinsicInfo::lookupFlags(intrinsic);
if ((flags & HW_Flag_UnfixedSIMDSize) == 0)
{
}
}
-//------------------------------------------------------------------------
-// insOfHWIntrinsic: get the instruction of the given intrinsic
-//
-// Arguments:
-// intrinsic -- id of the intrinsic function.
-// type -- vector base type of this intrinsic
-//
-// Return Value:
-// the instruction of the given intrinsic on the base type
-// return INS_invalid for unsupported base types
-//
-instruction Compiler::insOfHWIntrinsic(NamedIntrinsic intrinsic, var_types type)
-{
- assert(intrinsic != NI_Illegal);
- assert(intrinsic > NI_HW_INTRINSIC_START && intrinsic < NI_HW_INTRINSIC_END);
- assert(type >= TYP_BYTE && type <= TYP_DOUBLE);
- return hwIntrinsicInfoArray[intrinsic - NI_HW_INTRINSIC_START - 1].ins[type - TYP_BYTE];
-}
-
-//------------------------------------------------------------------------
-// categoryOfHWIntrinsic: get the category of the given intrinsic
-//
-// Arguments:
-// intrinsic -- id of the intrinsic function.
-//
-// Return Value:
-// the category of the given intrinsic
-//
-HWIntrinsicCategory Compiler::categoryOfHWIntrinsic(NamedIntrinsic intrinsic)
-{
- assert(intrinsic != NI_Illegal);
- assert(intrinsic > NI_HW_INTRINSIC_START && intrinsic < NI_HW_INTRINSIC_END);
- return hwIntrinsicInfoArray[intrinsic - NI_HW_INTRINSIC_START - 1].category;
-}
-
-//------------------------------------------------------------------------
-// HWIntrinsicFlag: get the flags of the given intrinsic
-//
-// Arguments:
-// intrinsic -- id of the intrinsic function.
-//
-// Return Value:
-// the flags of the given intrinsic
-//
-HWIntrinsicFlag Compiler::flagsOfHWIntrinsic(NamedIntrinsic intrinsic)
-{
- assert(intrinsic != NI_Illegal);
- assert(intrinsic > NI_HW_INTRINSIC_START && intrinsic < NI_HW_INTRINSIC_END);
- return hwIntrinsicInfoArray[intrinsic - NI_HW_INTRINSIC_START - 1].flags;
-}
-
//------------------------------------------------------------------------
// getArgForHWIntrinsic: get the argument from the stack and match the signature
//
//
int Compiler::immUpperBoundOfHWIntrinsic(NamedIntrinsic intrinsic)
{
- assert(categoryOfHWIntrinsic(intrinsic) == HW_Category_IMM);
+ assert(HWIntrinsicInfo::lookupCategory(intrinsic) == HW_Category_IMM);
switch (intrinsic)
{
case NI_AVX_Compare:
return 31; // enum FloatComparisonMode has 32 values
default:
- assert((flagsOfHWIntrinsic(intrinsic) & HW_Flag_FullRangeIMM) != 0);
+ assert((HWIntrinsicInfo::lookupFlags(intrinsic) & HW_Flag_FullRangeIMM) != 0);
return 255;
}
}
//
GenTree* Compiler::impNonConstFallback(NamedIntrinsic intrinsic, var_types simdType, var_types baseType)
{
- assert((flagsOfHWIntrinsic(intrinsic) & HW_Flag_NoJmpTableIMM) != 0);
+ assert((HWIntrinsicInfo::lookupFlags(intrinsic) & HW_Flag_NoJmpTableIMM) != 0);
switch (intrinsic)
{
case NI_SSE2_ShiftLeftLogical:
//
bool Compiler::isImmHWIntrinsic(NamedIntrinsic intrinsic, GenTree* lastOp)
{
- if (categoryOfHWIntrinsic(intrinsic) != HW_Category_IMM)
+ if (HWIntrinsicInfo::lookupCategory(intrinsic) != HW_Category_IMM)
{
return false;
}
- if ((flagsOfHWIntrinsic(intrinsic) & HW_Flag_MaybeIMM) != 0 && genActualType(lastOp->TypeGet()) != TYP_INT)
+ if ((HWIntrinsicInfo::lookupFlags(intrinsic) & HW_Flag_MaybeIMM) != 0 && genActualType(lastOp->TypeGet()) != TYP_INT)
{
return false;
}
assert(lastOp != nullptr);
// Full-range imm-intrinsics do not need the range-check
// because the imm-parameter of the intrinsic method is a byte.
- if (mustExpand && ((flagsOfHWIntrinsic(intrinsic) & HW_Flag_FullRangeIMM) == 0) &&
+ if (mustExpand && ((HWIntrinsicInfo::lookupFlags(intrinsic) & HW_Flag_FullRangeIMM) == 0) &&
isImmHWIntrinsic(intrinsic, lastOp))
{
assert(!lastOp->IsCnsIntOrI());
CORINFO_SIG_INFO* sig,
bool mustExpand)
{
- InstructionSet isa = isaOfHWIntrinsic(intrinsic);
- HWIntrinsicCategory category = categoryOfHWIntrinsic(intrinsic);
- HWIntrinsicFlag flags = flagsOfHWIntrinsic(intrinsic);
+ InstructionSet isa = HWIntrinsicInfo::lookupIsa(intrinsic);
+ HWIntrinsicCategory category = HWIntrinsicInfo::lookupCategory(intrinsic);
+ HWIntrinsicFlag flags = HWIntrinsicInfo::lookupFlags(intrinsic);
int numArgs = sig->numArgs;
var_types retType = JITtype2varType(sig->retType);
var_types baseType = TYP_UNKNOWN;
var_types argType = TYP_UNKNOWN;
assert(numArgs >= 0);
- assert(insOfHWIntrinsic(intrinsic, baseType) != INS_invalid);
+ assert(HWIntrinsicInfo::lookupIns(intrinsic, baseType) != INS_invalid);
assert(simdSize == 32 || simdSize == 16);
GenTreeHWIntrinsic* retNode = nullptr;