From: Kunal Pathak Date: Mon, 27 Apr 2020 23:11:48 +0000 (-0700) Subject: Add support of CreateScalarUnsafe() for arm64 intrinsic in JIT (#34579) X-Git-Tag: submit/tizen/20210909.063632~8333 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=d68342ceeb69adff35d5b3462091d339a700c1a5;p=platform%2Fupstream%2Fdotnet%2Fruntime.git Add support of CreateScalarUnsafe() for arm64 intrinsic in JIT (#34579) * Intrinsify Vector64.CreateScalarUnsafe() for byte, sbyte, short, ushort, int, uint, long, ulong, float * Intrinsify Vector128.CreateScalarUnsafe() for byte, sbyte, short, ushort, int, uint, long, ulong, float, long, ulong, double --- diff --git a/src/coreclr/src/jit/hwintrinsiccodegenarm64.cpp b/src/coreclr/src/jit/hwintrinsiccodegenarm64.cpp index 70fe9c5..9338cc0 100644 --- a/src/coreclr/src/jit/hwintrinsiccodegenarm64.cpp +++ b/src/coreclr/src/jit/hwintrinsiccodegenarm64.cpp @@ -449,6 +449,41 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) } break; + case NI_Vector64_CreateScalarUnsafe: + case NI_Vector128_CreateScalarUnsafe: + { + if (intrin.op1->isContainedFltOrDblImmed()) + { + // fmov reg, #imm8 + const double dataValue = intrin.op1->AsDblCon()->gtDconVal; + GetEmitter()->emitIns_R_F(ins, emitTypeSize(intrin.baseType), targetReg, dataValue, INS_OPTS_NONE); + } + else if (varTypeIsFloating(intrin.baseType)) + { + if (targetReg != op1Reg) + { + // fmov reg1, reg2 + GetEmitter()->emitIns_R_R(ins, emitTypeSize(intrin.baseType), targetReg, op1Reg, INS_OPTS_NONE); + } + } + else + { + if (intrin.op1->isContainedIntOrIImmed()) + { + // movi/movni reg, #imm8 + const ssize_t dataValue = intrin.op1->AsIntCon()->gtIconVal; + GetEmitter()->emitIns_R_I(INS_movi, emitSize, targetReg, dataValue, opt); + } + else + { + // ins reg1[0], reg2 + GetEmitter()->emitIns_R_R_I(ins, emitTypeSize(intrin.baseType), targetReg, op1Reg, 0, + INS_OPTS_NONE); + } + } + } + break; + default: unreached(); } diff --git a/src/coreclr/src/jit/hwintrinsiclistarm64.h b/src/coreclr/src/jit/hwintrinsiclistarm64.h index f210bc0..6a07a01 100644 --- a/src/coreclr/src/jit/hwintrinsiclistarm64.h +++ b/src/coreclr/src/jit/hwintrinsiclistarm64.h @@ -23,6 +23,7 @@ HARDWARE_INTRINSIC(Vector64, AsSByte, HARDWARE_INTRINSIC(Vector64, AsSingle, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector64, AsUInt16, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector64, AsUInt32, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector64, CreateScalarUnsafe, 8, 1, {INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_invalid, INS_invalid, INS_fmov, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SupportsContainment|HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(Vector64, get_Count, 8, 0, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** @@ -41,6 +42,7 @@ HARDWARE_INTRINSIC(Vector128, AsSingle, 1 HARDWARE_INTRINSIC(Vector128, AsUInt16, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector128, AsUInt32, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector128, AsUInt64, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, CreateScalarUnsafe, 16, 1, {INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_fmov, INS_fmov}, HW_Category_SimpleSIMD, HW_Flag_SupportsContainment|HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(Vector128, get_Count, 16, 0, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** diff --git a/src/coreclr/src/jit/lowerarmarch.cpp b/src/coreclr/src/jit/lowerarmarch.cpp index 6eee592..4ae61be 100644 --- a/src/coreclr/src/jit/lowerarmarch.cpp +++ b/src/coreclr/src/jit/lowerarmarch.cpp @@ -914,7 +914,29 @@ void Lowering::ContainCheckHWIntrinsic(GenTreeHWIntrinsic* node) } } break; + case NI_Vector64_CreateScalarUnsafe: + case NI_Vector128_CreateScalarUnsafe: + if (intrin.op1->IsCnsIntOrI()) + { + const ssize_t dataValue = intrin.op1->AsIntCon()->gtIconVal; + + if (comp->GetEmitter()->emitIns_valid_imm_for_movi(dataValue, emitActualTypeSize(intrin.baseType))) + { + MakeSrcContained(node, intrin.op1); + } + } + else if (intrin.op1->IsCnsFltOrDbl()) + { + assert(varTypeIsFloating(intrin.baseType)); + const double dataValue = intrin.op1->AsDblCon()->gtDconVal; + + if (comp->GetEmitter()->emitIns_valid_imm_for_fmov(dataValue)) + { + MakeSrcContained(node, intrin.op1); + } + } + break; default: unreached(); } diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector64.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector64.cs index b1f1645..a4f3fae 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector64.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector64.cs @@ -522,6 +522,7 @@ namespace System.Runtime.Intrinsics /// Creates a new instance with the first element initialized to the specified value and the remaining elements left uninitialized. /// The value that element 0 will be initialized to. /// A new instance with the first element initialized to and the remaining elements left uninitialized. + [Intrinsic] public static unsafe Vector64 CreateScalarUnsafe(byte value) { // This relies on us stripping the "init" flag from the ".locals" @@ -535,6 +536,7 @@ namespace System.Runtime.Intrinsics /// Creates a new instance with the first element initialized to the specified value and the remaining elements left uninitialized. /// The value that element 0 will be initialized to. /// A new instance with the first element initialized to and the remaining elements left uninitialized. + [Intrinsic] public static unsafe Vector64 CreateScalarUnsafe(short value) { // This relies on us stripping the "init" flag from the ".locals" @@ -548,6 +550,7 @@ namespace System.Runtime.Intrinsics /// Creates a new instance with the first element initialized to the specified value and the remaining elements left uninitialized. /// The value that element 0 will be initialized to. /// A new instance with the first element initialized to and the remaining elements left uninitialized. + [Intrinsic] public static unsafe Vector64 CreateScalarUnsafe(int value) { // This relies on us stripping the "init" flag from the ".locals" @@ -562,6 +565,7 @@ namespace System.Runtime.Intrinsics /// The value that element 0 will be initialized to. /// A new instance with the first element initialized to and the remaining elements left uninitialized. [CLSCompliant(false)] + [Intrinsic] public static unsafe Vector64 CreateScalarUnsafe(sbyte value) { // This relies on us stripping the "init" flag from the ".locals" @@ -575,6 +579,7 @@ namespace System.Runtime.Intrinsics /// Creates a new instance with the first element initialized to the specified value and the remaining elements left uninitialized. /// The value that element 0 will be initialized to. /// A new instance with the first element initialized to and the remaining elements left uninitialized. + [Intrinsic] public static unsafe Vector64 CreateScalarUnsafe(float value) { // This relies on us stripping the "init" flag from the ".locals" @@ -589,6 +594,7 @@ namespace System.Runtime.Intrinsics /// The value that element 0 will be initialized to. /// A new instance with the first element initialized to and the remaining elements left uninitialized. [CLSCompliant(false)] + [Intrinsic] public static unsafe Vector64 CreateScalarUnsafe(ushort value) { // This relies on us stripping the "init" flag from the ".locals" @@ -603,6 +609,7 @@ namespace System.Runtime.Intrinsics /// The value that element 0 will be initialized to. /// A new instance with the first element initialized to and the remaining elements left uninitialized. [CLSCompliant(false)] + [Intrinsic] public static unsafe Vector64 CreateScalarUnsafe(uint value) { // This relies on us stripping the "init" flag from the ".locals"