Skip to content

Commit

Permalink
[Arm64] Implement ASIMD widening, narrowing, saturating intrinsics (d…
Browse files Browse the repository at this point in the history
…otnet#35612)

* AbsoluteDifferenceWideningLower and AbsoluteDifferenceWideningUpper

* AbsoluteDifferenceWideningLowerAndAdd and AbsoluteDifferenceWideningUpperAndAdd

* AddPairwiseWidening{Scalar}

* AddPairwiseWideningAndAdd{Scalar}

* AddSaturate{Scalar}

* AddWideningLower and AddWideningUpper

* FusedAddHalving

* FusedAddRoundedHalving

* FusedSubtractHalving

* MultiplyWideningLower and MultiplyWideningUpper

* MultiplyWideningLowerAndAdd and MultiplyWideningUpperAndAdd

* MultiplyWideningLowerAndSubtract and MultiplyWideningUpperAndSubtract

* SubtractSaturate{Scalar}

* SubtractWideningLower and SubtractWideningUpper

* AddReturningHighNarrowLower and AddReturningHighNarrowUpper

* AddReturningRoundedHighNarrowLower and AddReturningRoundedHighNarrowUpper

* SubtractReturningHighNarrowLower and SubtractReturningHighNarrowUpper

* SubtractReturningRoundedHighNarrowLower and SubtractReturningRoundedHighNarrowUpper
  • Loading branch information
echesakov authored May 1, 2020
1 parent c614097 commit a156293
Show file tree
Hide file tree
Showing 275 changed files with 146,325 additions and 550 deletions.
7 changes: 7 additions & 0 deletions src/coreclr/src/jit/hwintrinsic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -789,6 +789,13 @@ GenTree* Compiler::impHWIntrinsic(NamedIntrinsic intrinsic,
// to the code generator. May encode the overload info in other way.
retNode->AsHWIntrinsic()->gtSIMDBaseType = JITtype2varType(corType);
}
#ifdef TARGET_ARM64
if ((intrinsic == NI_AdvSimd_AddWideningUpper) || (intrinsic == NI_AdvSimd_SubtractWideningUpper))
{
assert(varTypeIsSIMD(op1->TypeGet()));
retNode->AsHWIntrinsic()->SetOtherBaseType(getBaseTypeOfSIMDType(argClass));
}
#endif
break;
}

Expand Down
71 changes: 65 additions & 6 deletions src/coreclr/src/jit/hwintrinsiccodegenarm64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,11 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node)
emitAttr emitSize;
insOpts opt = INS_OPTS_NONE;

if ((intrin.category == HW_Category_SIMDScalar) || (intrin.category == HW_Category_Scalar))
if (intrin.category == HW_Category_SIMDScalar)
{
emitSize = emitTypeSize(intrin.baseType);
}
else if (intrin.category == HW_Category_Scalar)
{
emitSize = emitActualTypeSize(intrin.baseType);
}
Expand Down Expand Up @@ -242,7 +246,7 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node)

if (targetReg != op1Reg)
{
GetEmitter()->emitIns_R_R(INS_mov, emitSize, targetReg, op1Reg);
GetEmitter()->emitIns_R_R(INS_mov, emitTypeSize(node), targetReg, op1Reg);
}
GetEmitter()->emitIns_R_R(ins, emitSize, targetReg, op2Reg, opt);
}
Expand All @@ -259,7 +263,7 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node)

if (targetReg != op1Reg)
{
GetEmitter()->emitIns_R_R(INS_mov, emitSize, targetReg, op1Reg);
GetEmitter()->emitIns_R_R(INS_mov, emitTypeSize(node), targetReg, op1Reg);
}

GetEmitter()->emitIns_R_R_R(ins, emitSize, targetReg, op2Reg, op3Reg, opt);
Expand Down Expand Up @@ -306,6 +310,56 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node)
ins = INS_crc32cx;
break;

case NI_AdvSimd_AddWideningLower:
assert(varTypeIsIntegral(intrin.baseType));
if (intrin.op1->TypeGet() == TYP_SIMD8)
{
ins = varTypeIsUnsigned(intrin.baseType) ? INS_uaddl : INS_saddl;
}
else
{
assert(intrin.op1->TypeGet() == TYP_SIMD16);
ins = varTypeIsUnsigned(intrin.baseType) ? INS_uaddw : INS_saddw;
}
break;

case NI_AdvSimd_SubtractWideningLower:
assert(varTypeIsIntegral(intrin.baseType));
if (intrin.op1->TypeGet() == TYP_SIMD8)
{
ins = varTypeIsUnsigned(intrin.baseType) ? INS_usubl : INS_ssubl;
}
else
{
assert(intrin.op1->TypeGet() == TYP_SIMD16);
ins = varTypeIsUnsigned(intrin.baseType) ? INS_usubw : INS_ssubw;
}
break;

case NI_AdvSimd_AddWideningUpper:
assert(varTypeIsIntegral(intrin.baseType));
if (node->GetOtherBaseType() == intrin.baseType)
{
ins = varTypeIsUnsigned(intrin.baseType) ? INS_uaddl2 : INS_saddl2;
}
else
{
ins = varTypeIsUnsigned(intrin.baseType) ? INS_uaddw2 : INS_saddw2;
}
break;

case NI_AdvSimd_SubtractWideningUpper:
assert(varTypeIsIntegral(intrin.baseType));
if (node->GetOtherBaseType() == intrin.baseType)
{
ins = varTypeIsUnsigned(intrin.baseType) ? INS_usubl2 : INS_ssubl2;
}
else
{
ins = varTypeIsUnsigned(intrin.baseType) ? INS_usubw2 : INS_ssubw2;
}
break;

default:
ins = HWIntrinsicInfo::lookupIns(intrin.id, intrin.baseType);
break;
Expand Down Expand Up @@ -454,7 +508,6 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node)

case NI_Vector64_CreateScalarUnsafe:
case NI_Vector128_CreateScalarUnsafe:
{
if (intrin.op1->isContainedFltOrDblImmed())
{
// fmov reg, #imm8
Expand Down Expand Up @@ -484,8 +537,14 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node)
INS_OPTS_NONE);
}
}
}
break;
break;

case NI_AdvSimd_AddWideningLower:
case NI_AdvSimd_AddWideningUpper:
case NI_AdvSimd_SubtractWideningLower:
case NI_AdvSimd_SubtractWideningUpper:
GetEmitter()->emitIns_R_R_R(ins, emitSize, targetReg, op1Reg, op2Reg, opt);
break;

// mvni doesn't support the range of element types, so hard code the 'opts' value.
case NI_Vector64_get_Zero:
Expand Down
Loading

0 comments on commit a156293

Please sign in to comment.