NamedIntrinsic lookupNamedIntrinsic(CORINFO_METHOD_HANDLE method);
#ifdef FEATURE_HW_INTRINSICS
- GenTree* impBaseIntrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig);
+ GenTree* impBaseIntrinsic(NamedIntrinsic intrinsic,
+ CORINFO_CLASS_HANDLE clsHnd,
+ CORINFO_METHOD_HANDLE method,
+ CORINFO_SIG_INFO* sig);
GenTree* impHWIntrinsic(NamedIntrinsic intrinsic,
CORINFO_METHOD_HANDLE method,
CORINFO_SIG_INFO* sig,
var_types targetType = node->TypeGet();
var_types baseType = node->gtSIMDBaseType;
- assert(node->gtGetOp1() == nullptr);
+ assert(compiler->compSupports(InstructionSet_SSE));
+ assert((baseType >= TYP_BYTE) && (baseType <= TYP_DOUBLE));
+
+ GenTree* op1 = node->gtGetOp1();
+ regNumber op1Reg = REG_NA;
+
+ if (op1 != nullptr)
+ {
+ assert(!op1->OperIsList());
+ op1Reg = op1->gtRegNum;
+ genConsumeOperands(node);
+ }
+
assert(node->gtGetOp2() == nullptr);
- assert(baseType >= TYP_BYTE && baseType <= TYP_DOUBLE);
- emitter* emit = getEmitter();
- emitAttr attr = EA_ATTR(node->gtSIMDSize);
+ emitter* emit = getEmitter();
+ emitAttr attr = EA_ATTR(node->gtSIMDSize);
+ instruction ins = HWIntrinsicInfo::lookupIns(intrinsicId, baseType);
switch (intrinsicId)
{
- case NI_Base_Vector128_Zero:
+ case NI_Base_Vector128_CreateScalarUnsafe:
+ case NI_Base_Vector256_CreateScalarUnsafe:
{
- // When SSE2 is supported, we generate pxor for integral types otherwise just use xorps
- instruction ins =
- (compiler->compSupports(InstructionSet_SSE2) && varTypeIsIntegral(baseType)) ? INS_pxor : INS_xorps;
- emit->emitIns_SIMD_R_R_R(ins, attr, targetReg, targetReg, targetReg);
+ if (varTypeIsIntegral(baseType))
+ {
+ genHWIntrinsic_R_RM(node, ins, emitActualTypeSize(baseType));
+ }
+ else
+ {
+ assert(varTypeIsFloating(baseType));
+
+ attr = emitTypeSize(baseType);
+
+ if (op1->isContained() || op1->isUsedFromSpillTemp())
+ {
+ genHWIntrinsic_R_RM(node, ins, attr);
+ }
+ else if (targetReg != op1Reg)
+ {
+ // Just use movaps for reg->reg moves as it has zero-latency on modern CPUs
+ emit->emitIns_R_R(INS_movaps, attr, targetReg, op1Reg);
+ }
+ }
break;
}
+ case NI_Base_Vector128_ToScalar:
+ case NI_Base_Vector256_ToScalar:
+ {
+ assert(varTypeIsFloating(baseType));
+
+ attr = emitTypeSize(TYP_SIMD16);
+
+ if (op1->isContained() || op1->isUsedFromSpillTemp())
+ {
+ genHWIntrinsic_R_RM(node, ins, attr);
+ }
+ else if (targetReg != op1Reg)
+ {
+ // Just use movaps for reg->reg moves as it has zero-latency on modern CPUs
+ emit->emitIns_R_R(INS_movaps, attr, targetReg, op1Reg);
+ }
+ break;
+ }
+
+ case NI_Base_Vector128_ToVector256:
+ {
+ // ToVector256 has zero-extend semantics in order to ensure it is deterministic
+ // We always emit a move to the target register, even when op1Reg == targetReg,
+ // in order to ensure that Bits MAXVL-1:128 are zeroed.
+
+ attr = emitTypeSize(TYP_SIMD16);
+
+ if (op1->isContained() || op1->isUsedFromSpillTemp())
+ {
+ genHWIntrinsic_R_RM(node, ins, attr);
+ }
+ else
+ {
+ // Just use movaps for reg->reg moves as it has zero-latency on modern CPUs
+ emit->emitIns_R_R(INS_movaps, attr, targetReg, op1Reg);
+ }
+ break;
+ }
+
+ case NI_Base_Vector128_ToVector256Unsafe:
+ case NI_Base_Vector256_GetLower:
+ {
+ if (op1->isContained() || op1->isUsedFromSpillTemp())
+ {
+ genHWIntrinsic_R_RM(node, ins, attr);
+ }
+ else if (targetReg != op1Reg)
+ {
+ // Just use movaps for reg->reg moves as it has zero-latency on modern CPUs
+ emit->emitIns_R_R(INS_movaps, attr, targetReg, op1Reg);
+ }
+ break;
+ }
+
+ case NI_Base_Vector128_Zero:
case NI_Base_Vector256_Zero:
{
- // When AVX2 is supported, we generate pxor for integral types otherwise just use xorps
- instruction ins =
- (compiler->compSupports(InstructionSet_AVX2) && varTypeIsIntegral(baseType)) ? INS_pxor : INS_xorps;
+ assert(op1 == nullptr);
emit->emitIns_SIMD_R_R_R(ins, attr, targetReg, targetReg, targetReg);
break;
}
HARDWARE_INTRINSIC(Base_Vector128_AsUInt16, "AsUInt16", Base, -1, 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_NoContainment|HW_Flag_NoRMWSemantics)
HARDWARE_INTRINSIC(Base_Vector128_AsUInt32, "AsUInt32", Base, -1, 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_NoContainment|HW_Flag_NoRMWSemantics)
HARDWARE_INTRINSIC(Base_Vector128_AsUInt64, "AsUInt64", Base, -1, 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_NoContainment|HW_Flag_NoRMWSemantics)
-HARDWARE_INTRINSIC(Base_Vector128_Zero, "get_Zero", Base, -1, 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_NoContainment|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(Base_Vector128_CreateScalarUnsafe, "CreateScalarUnsafe", Base, -1, 16, 1, {INS_mov_i2xmm, INS_mov_i2xmm, INS_mov_i2xmm, INS_mov_i2xmm, INS_mov_i2xmm, INS_mov_i2xmm, INS_mov_i2xmm, INS_mov_i2xmm, INS_movss, INS_movsdsse2}, HW_Category_SIMDScalar, HW_Flag_SpecialCodeGen|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(Base_Vector128_ToScalar, "ToScalar", Base, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movss, INS_movsdsse2}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(Base_Vector128_ToVector256, "ToVector256", Base, -1, 16, 1, {INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movups, INS_movupd}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(Base_Vector128_ToVector256Unsafe, "ToVector256Unsafe", Base, -1, 16, 1, {INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movups, INS_movupd}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(Base_Vector128_Zero, "get_Zero", Base, -1, 16, 0, {INS_xorps, INS_xorps, INS_xorps, INS_xorps, INS_xorps, INS_xorps, INS_xorps, INS_xorps, INS_xorps, INS_xorps}, HW_Category_Helper, HW_Flag_NoContainment|HW_Flag_NoRMWSemantics)
HARDWARE_INTRINSIC(Base_Vector256_As, "As`1", Base, -1, 32, 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_NoContainment|HW_Flag_NoRMWSemantics)
HARDWARE_INTRINSIC(Base_Vector256_AsByte, "AsByte", Base, -1, 32, 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_NoContainment|HW_Flag_NoRMWSemantics)
HARDWARE_INTRINSIC(Base_Vector256_AsDouble, "AsDouble", Base, -1, 32, 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_NoContainment|HW_Flag_NoRMWSemantics)
HARDWARE_INTRINSIC(Base_Vector256_AsUInt16, "AsUInt16", Base, -1, 32, 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_NoContainment|HW_Flag_NoRMWSemantics)
HARDWARE_INTRINSIC(Base_Vector256_AsUInt32, "AsUInt32", Base, -1, 32, 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_NoContainment|HW_Flag_NoRMWSemantics)
HARDWARE_INTRINSIC(Base_Vector256_AsUInt64, "AsUInt64", Base, -1, 32, 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_NoContainment|HW_Flag_NoRMWSemantics)
-HARDWARE_INTRINSIC(Base_Vector256_Zero, "get_Zero", Base, -1, 32, 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_NoContainment|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(Base_Vector256_CreateScalarUnsafe, "CreateScalarUnsafe", Base, -1, 32, 1, {INS_mov_i2xmm, INS_mov_i2xmm, INS_mov_i2xmm, INS_mov_i2xmm, INS_mov_i2xmm, INS_mov_i2xmm, INS_mov_i2xmm, INS_mov_i2xmm, INS_movss, INS_movsdsse2}, HW_Category_SIMDScalar, HW_Flag_SpecialCodeGen|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(Base_Vector256_GetLower, "GetLower", Base, -1, 32, 1, {INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movups, INS_movupd}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(Base_Vector256_ToScalar, "ToScalar", Base, -1, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movss, INS_movsdsse2}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(Base_Vector256_Zero, "get_Zero", Base, -1, 32, 0, {INS_xorps, INS_xorps, INS_xorps, INS_xorps, INS_xorps, INS_xorps, INS_xorps, INS_xorps, INS_xorps, INS_xorps}, HW_Category_Helper, HW_Flag_NoContainment|HW_Flag_NoRMWSemantics)
// ***************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
// Intrinsic ID Function name ISA ival SIMD size NumArg instructions Category Flags
case NI_Base_Vector128_AsUInt32:
case NI_Base_Vector128_AsUInt64:
#if defined(_TARGET_XARCH_)
+ case NI_Base_Vector128_CreateScalarUnsafe:
+ case NI_Base_Vector128_ToScalar:
+ case NI_Base_Vector128_ToVector256:
+ case NI_Base_Vector128_ToVector256Unsafe:
case NI_Base_Vector128_Zero:
case NI_Base_Vector256_As:
case NI_Base_Vector256_AsByte:
case NI_Base_Vector256_AsUInt16:
case NI_Base_Vector256_AsUInt32:
case NI_Base_Vector256_AsUInt64:
+ case NI_Base_Vector256_CreateScalarUnsafe:
+ case NI_Base_Vector256_GetLower:
+ case NI_Base_Vector256_ToScalar:
case NI_Base_Vector256_Zero:
#endif // _TARGET_XARCH_
{
- return impBaseIntrinsic(ni, method, sig);
+ return impBaseIntrinsic(ni, clsHnd, method, sig);
}
default:
//
// Arguments:
// intrinsic -- id of the intrinsic function.
+// clsHnd -- handle for the intrinsic method's class
// method -- method handle of the intrinsic function.
// sig -- signature of the intrinsic call
//
// Return Value:
// the expanded intrinsic.
//
-GenTree* Compiler::impBaseIntrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig)
+GenTree* Compiler::impBaseIntrinsic(NamedIntrinsic intrinsic,
+ CORINFO_CLASS_HANDLE clsHnd,
+ CORINFO_METHOD_HANDLE method,
+ CORINFO_SIG_INFO* sig)
{
GenTree* retNode = nullptr;
+ GenTree* op1 = nullptr;
if (!featureSIMD)
{
}
unsigned simdSize = 0;
- var_types baseType = getBaseTypeAndSizeOfSIMDType(sig->retTypeClass, &simdSize);
- var_types retType = getSIMDTypeForSize(simdSize);
+ var_types baseType = TYP_UNKNOWN;
+ var_types retType = JITtype2varType(sig->retType);
if (sig->hasThis())
{
- CORINFO_CLASS_HANDLE thisClass = info.compCompHnd->getArgClass(sig, sig->args);
- var_types thisType = getBaseTypeOfSIMDType(thisClass);
+ baseType = getBaseTypeAndSizeOfSIMDType(clsHnd, &simdSize);
- if (!varTypeIsArithmetic(thisType))
+ if (retType == TYP_STRUCT)
{
- return nullptr;
+ unsigned retSimdSize = 0;
+ getBaseTypeAndSizeOfSIMDType(sig->retTypeClass, &retSimdSize);
+ retType = getSIMDTypeForSize(retSimdSize);
}
}
+ else
+ {
+ assert(retType == TYP_STRUCT);
+ baseType = getBaseTypeAndSizeOfSIMDType(sig->retTypeClass, &simdSize);
+ retType = getSIMDTypeForSize(simdSize);
+ }
if (!varTypeIsArithmetic(baseType))
{
}
#ifdef _TARGET_XARCH_
+ case NI_Base_Vector128_CreateScalarUnsafe:
+ {
+ assert(sig->numArgs == 1);
+
+#ifdef _TARGET_X86_
+ if (varTypeIsLong(baseType))
+ {
+ // TODO-XARCH-CQ: It may be beneficial to emit the movq
+ // instruction, which takes a 64-bit memory address and
+ // works on 32-bit x86 systems.
+ break;
+ }
+#endif // _TARGET_X86_
+
+ if (compSupports(InstructionSet_SSE2) || (compSupports(InstructionSet_SSE) && (baseType == TYP_FLOAT)))
+ {
+ op1 = impPopStack().val;
+ retNode = gtNewSimdHWIntrinsicNode(retType, op1, intrinsic, baseType, simdSize);
+ }
+ break;
+ }
+
+ case NI_Base_Vector128_ToScalar:
+ {
+ assert(sig->numArgs == 0);
+ assert(sig->hasThis());
+
+ if (compSupports(InstructionSet_SSE) && varTypeIsFloating(baseType))
+ {
+ op1 = impSIMDPopStack(getSIMDTypeForSize(simdSize), true, clsHnd);
+ retNode = gtNewSimdHWIntrinsicNode(retType, op1, intrinsic, baseType, 16);
+ }
+ break;
+ }
+
+ case NI_Base_Vector128_ToVector256:
+ case NI_Base_Vector128_ToVector256Unsafe:
+ case NI_Base_Vector256_GetLower:
+ {
+ assert(sig->numArgs == 0);
+ assert(sig->hasThis());
+
+ if (compSupports(InstructionSet_AVX))
+ {
+ op1 = impSIMDPopStack(getSIMDTypeForSize(simdSize), true, clsHnd);
+ retNode = gtNewSimdHWIntrinsicNode(retType, op1, intrinsic, baseType, simdSize);
+ }
+ break;
+ }
+
case NI_Base_Vector128_Zero:
{
assert(sig->numArgs == 0);
break;
}
+ case NI_Base_Vector256_CreateScalarUnsafe:
+ {
+ assert(sig->numArgs == 1);
+
+#ifdef _TARGET_X86_
+ if (varTypeIsLong(baseType))
+ {
+ // TODO-XARCH-CQ: It may be beneficial to emit the movq
+ // instruction, which takes a 64-bit memory address and
+ // works on 32-bit x86 systems.
+ break;
+ }
+#endif // _TARGET_X86_
+
+ if (compSupports(InstructionSet_AVX))
+ {
+ op1 = impPopStack().val;
+ retNode = gtNewSimdHWIntrinsicNode(retType, op1, intrinsic, baseType, simdSize);
+ }
+ break;
+ }
+
+ case NI_Base_Vector256_ToScalar:
+ {
+ assert(sig->numArgs == 0);
+ assert(sig->hasThis());
+
+ if (compSupports(InstructionSet_AVX) && varTypeIsFloating(baseType))
+ {
+ op1 = impSIMDPopStack(getSIMDTypeForSize(simdSize), true, clsHnd);
+ retNode = gtNewSimdHWIntrinsicNode(retType, op1, intrinsic, baseType, 32);
+ }
+ break;
+ }
+
case NI_Base_Vector256_Zero:
{
assert(sig->numArgs == 0);
{
className += 3;
- if (strcmp(className, "`1") == 0)
+#if defined(_TARGET_XARCH_)
+ if (className[0] == '\0')
+ {
+ if (strcmp(methodName, "CreateScalarUnsafe") == 0)
+ {
+ result = NI_Base_Vector128_CreateScalarUnsafe;
+ }
+ }
+ else
+#endif // _TARGET_XARCH_
+ if (strcmp(className, "`1") == 0)
{
if (strncmp(methodName, "As", 2) == 0)
{
{
result = NI_Base_Vector128_Zero;
}
+ else if (strncmp(methodName, "To", 2) == 0)
+ {
+ methodName += 2;
+
+ if (strcmp(methodName, "Scalar") == 0)
+ {
+ result = NI_Base_Vector128_ToScalar;
+ }
+ else if (strncmp(methodName, "Vector256", 9) == 0)
+ {
+ methodName += 9;
+
+ if (methodName[0] == '\0')
+ {
+ result = NI_Base_Vector128_ToVector256;
+ }
+ else if (strcmp(methodName, "Unsafe") == 0)
+ {
+ result = NI_Base_Vector128_ToVector256Unsafe;
+ }
+ }
+ }
#endif // _TARGET_XARCH_
}
}
{
className += 3;
- if (strcmp(className, "`1") == 0)
+ if (className[0] == '\0')
+ {
+ if (strcmp(methodName, "CreateScalarUnsafe") == 0)
+ {
+ result = NI_Base_Vector256_CreateScalarUnsafe;
+ }
+ }
+ else if (strcmp(className, "`1") == 0)
{
if (strncmp(methodName, "As", 2) == 0)
{
{
result = NI_Base_Vector256_Zero;
}
+ else if (strcmp(methodName, "GetLower") == 0)
+ {
+ result = NI_Base_Vector256_GetLower;
+ }
+ else if (strcmp(methodName, "ToScalar") == 0)
+ {
+ result = NI_Base_Vector256_ToScalar;
+ }
}
}
#endif // _TARGET_XARCH_
// must be handled within the case.
switch (intrinsicId)
{
+ case NI_Base_Vector128_CreateScalarUnsafe:
+ case NI_Base_Vector128_ToScalar:
+ case NI_Base_Vector256_CreateScalarUnsafe:
+ case NI_Base_Vector256_ToScalar:
+ {
+ assert(numArgs == 1);
+
+ if (varTypeIsFloating(baseType))
+ {
+ if (op1->isContained())
+ {
+ srcCount += BuildOperandUses(op1);
+ }
+ else
+ {
+ // We will either be in memory and need to be moved
+ // into a register of the appropriate size or we
+ // are already in an XMM/YMM register and can stay
+ // where we are.
+
+ tgtPrefUse = BuildUse(op1);
+ srcCount += 1;
+ }
+
+ buildUses = false;
+ }
+ break;
+ }
+
+ case NI_Base_Vector128_ToVector256:
+ case NI_Base_Vector128_ToVector256Unsafe:
+ case NI_Base_Vector256_GetLower:
+ {
+ assert(numArgs == 1);
+
+ if (op1->isContained())
+ {
+ srcCount += BuildOperandUses(op1);
+ }
+ else
+ {
+ // We will either be in memory and need to be moved
+ // into a register of the appropriate size or we
+ // are already in an XMM/YMM register and can stay
+ // where we are.
+
+ tgtPrefUse = BuildUse(op1);
+ srcCount += 1;
+ }
+
+ buildUses = false;
+ break;
+ }
+
case NI_SSE_CompareEqualOrderedScalar:
case NI_SSE_CompareEqualUnorderedScalar:
case NI_SSE_CompareNotEqualOrderedScalar:
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
+using System.Runtime.CompilerServices;
using Internal.Runtime.CompilerServices;
namespace System.Runtime.Intrinsics
/// <summary>Creates a new <see cref="Vector128{Byte}" /> instance with the first element initialized to the specified value and the remaining elements left uninitialized.</summary>
/// <param name="value">The value that element 0 will be initialized to.</param>
/// <returns>A new <see cref="Vector128{Byte}" /> instance with the first element initialized to <paramref name="value" /> and the remaining elements left uninitialized.</returns>
+ [Intrinsic]
public static unsafe Vector128<byte> CreateScalarUnsafe(byte value)
{
// This relies on us stripping the "init" flag from the ".locals"
/// <summary>Creates a new <see cref="Vector128{Double}" /> instance with the first element initialized to the specified value and the remaining elements left uninitialized.</summary>
/// <param name="value">The value that element 0 will be initialized to.</param>
/// <returns>A new <see cref="Vector128{Double}" /> instance with the first element initialized to <paramref name="value" /> and the remaining elements left uninitialized.</returns>
+ [Intrinsic]
public static unsafe Vector128<double> CreateScalarUnsafe(double value)
{
// This relies on us stripping the "init" flag from the ".locals"
/// <summary>Creates a new <see cref="Vector128{Int16}" /> instance with the first element initialized to the specified value and the remaining elements left uninitialized.</summary>
/// <param name="value">The value that element 0 will be initialized to.</param>
/// <returns>A new <see cref="Vector128{Int16}" /> instance with the first element initialized to <paramref name="value" /> and the remaining elements left uninitialized.</returns>
+ [Intrinsic]
public static unsafe Vector128<short> CreateScalarUnsafe(short value)
{
// This relies on us stripping the "init" flag from the ".locals"
/// <summary>Creates a new <see cref="Vector128{Int32}" /> instance with the first element initialized to the specified value and the remaining elements left uninitialized.</summary>
/// <param name="value">The value that element 0 will be initialized to.</param>
/// <returns>A new <see cref="Vector128{Int32}" /> instance with the first element initialized to <paramref name="value" /> and the remaining elements left uninitialized.</returns>
+ [Intrinsic]
public static unsafe Vector128<int> CreateScalarUnsafe(int value)
{
// This relies on us stripping the "init" flag from the ".locals"
/// <summary>Creates a new <see cref="Vector128{Int64}" /> instance with the first element initialized to the specified value and the remaining elements left uninitialized.</summary>
/// <param name="value">The value that element 0 will be initialized to.</param>
/// <returns>A new <see cref="Vector128{Int64}" /> instance with the first element initialized to <paramref name="value" /> and the remaining elements left uninitialized.</returns>
+ [Intrinsic]
public static unsafe Vector128<long> CreateScalarUnsafe(long value)
{
// This relies on us stripping the "init" flag from the ".locals"
/// <summary>Creates a new <see cref="Vector128{SByte}" /> instance with the first element initialized to the specified value and the remaining elements left uninitialized.</summary>
/// <param name="value">The value that element 0 will be initialized to.</param>
/// <returns>A new <see cref="Vector128{SByte}" /> instance with the first element initialized to <paramref name="value" /> and the remaining elements left uninitialized.</returns>
+ [Intrinsic]
[CLSCompliant(false)]
public static unsafe Vector128<sbyte> CreateScalarUnsafe(sbyte value)
{
/// <summary>Creates a new <see cref="Vector128{Single}" /> instance with the first element initialized to the specified value and the remaining elements left uninitialized.</summary>
/// <param name="value">The value that element 0 will be initialized to.</param>
/// <returns>A new <see cref="Vector128{Single}" /> instance with the first element initialized to <paramref name="value" /> and the remaining elements left uninitialized.</returns>
+ [Intrinsic]
public static unsafe Vector128<float> CreateScalarUnsafe(float value)
{
// This relies on us stripping the "init" flag from the ".locals"
/// <summary>Creates a new <see cref="Vector128{UInt16}" /> instance with the first element initialized to the specified value and the remaining elements left uninitialized.</summary>
/// <param name="value">The value that element 0 will be initialized to.</param>
/// <returns>A new <see cref="Vector128{UInt16}" /> instance with the first element initialized to <paramref name="value" /> and the remaining elements left uninitialized.</returns>
+ [Intrinsic]
[CLSCompliant(false)]
public static unsafe Vector128<ushort> CreateScalarUnsafe(ushort value)
{
/// <summary>Creates a new <see cref="Vector128{UInt32}" /> instance with the first element initialized to the specified value and the remaining elements left uninitialized.</summary>
/// <param name="value">The value that element 0 will be initialized to.</param>
/// <returns>A new <see cref="Vector128{UInt32}" /> instance with the first element initialized to <paramref name="value" /> and the remaining elements left uninitialized.</returns>
+ [Intrinsic]
[CLSCompliant(false)]
public static unsafe Vector128<uint> CreateScalarUnsafe(uint value)
{
/// <summary>Creates a new <see cref="Vector128{UInt64}" /> instance with the first element initialized to the specified value and the remaining elements left uninitialized.</summary>
/// <param name="value">The value that element 0 will be initialized to.</param>
/// <returns>A new <see cref="Vector128{UInt64}" /> instance with the first element initialized to <paramref name="value" /> and the remaining elements left uninitialized.</returns>
+ [Intrinsic]
[CLSCompliant(false)]
public static unsafe Vector128<ulong> CreateScalarUnsafe(ulong value)
{
/// <summary>Converts the current instance to a scalar containing the value of the first element.</summary>
/// <returns>A scalar <typeparamref name="T" /> containing the value of the first element.</returns>
/// <exception cref="NotSupportedException">The type of the current instance (<typeparamref name="T" />) is not supported.</exception>
+ [Intrinsic]
public T ToScalar()
{
ThrowIfUnsupportedType();
/// <summary>Converts the current instance to a new <see cref="Vector256{T}" /> with the lower 128-bits set to the value of the current instance and the upper 128-bits initialized to zero.</summary>
/// <returns>A new <see cref="Vector256{T}" /> with the lower 128-bits set to the value of the current instance and the upper 128-bits initialized to zero.</returns>
/// <exception cref="NotSupportedException">The type of the current instance (<typeparamref name="T" />) is not supported.</exception>
+ [Intrinsic]
public Vector256<T> ToVector256()
{
ThrowIfUnsupportedType();
/// <summary>Converts the current instance to a new <see cref="Vector256{T}" /> with the lower 128-bits set to the value of the current instance and the upper 128-bits left uninitialized.</summary>
/// <returns>A new <see cref="Vector256{T}" /> with the lower 128-bits set to the value of the current instance and the upper 128-bits left uninitialized.</returns>
/// <exception cref="NotSupportedException">The type of the current instance (<typeparamref name="T" />) is not supported.</exception>
+ [Intrinsic]
public unsafe Vector256<T> ToVector256Unsafe()
{
ThrowIfUnsupportedType();
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
+using System.Runtime.CompilerServices;
using Internal.Runtime.CompilerServices;
namespace System.Runtime.Intrinsics
/// <summary>Creates a new <see cref="Vector256{Byte}" /> instance with the first element initialized to the specified value and the remaining elements left uninitialized.</summary>
/// <param name="value">The value that element 0 will be initialized to.</param>
/// <returns>A new <see cref="Vector256{Byte}" /> instance with the first element initialized to <paramref name="value" /> and the remaining elements left uninitialized.</returns>
+ [Intrinsic]
public static unsafe Vector256<byte> CreateScalarUnsafe(byte value)
{
// This relies on us stripping the "init" flag from the ".locals"
/// <summary>Creates a new <see cref="Vector256{Double}" /> instance with the first element initialized to the specified value and the remaining elements left uninitialized.</summary>
/// <param name="value">The value that element 0 will be initialized to.</param>
/// <returns>A new <see cref="Vector256{Double}" /> instance with the first element initialized to <paramref name="value" /> and the remaining elements left uninitialized.</returns>
+ [Intrinsic]
public static unsafe Vector256<double> CreateScalarUnsafe(double value)
{
// This relies on us stripping the "init" flag from the ".locals"
/// <summary>Creates a new <see cref="Vector256{Int16}" /> instance with the first element initialized to the specified value and the remaining elements left uninitialized.</summary>
/// <param name="value">The value that element 0 will be initialized to.</param>
/// <returns>A new <see cref="Vector256{Int16}" /> instance with the first element initialized to <paramref name="value" /> and the remaining elements left uninitialized.</returns>
+ [Intrinsic]
public static unsafe Vector256<short> CreateScalarUnsafe(short value)
{
// This relies on us stripping the "init" flag from the ".locals"
/// <summary>Creates a new <see cref="Vector256{Int32}" /> instance with the first element initialized to the specified value and the remaining elements left uninitialized.</summary>
/// <param name="value">The value that element 0 will be initialized to.</param>
/// <returns>A new <see cref="Vector256{Int32}" /> instance with the first element initialized to <paramref name="value" /> and the remaining elements left uninitialized.</returns>
+ [Intrinsic]
public static unsafe Vector256<int> CreateScalarUnsafe(int value)
{
// This relies on us stripping the "init" flag from the ".locals"
/// <summary>Creates a new <see cref="Vector256{Int64}" /> instance with the first element initialized to the specified value and the remaining elements left uninitialized.</summary>
/// <param name="value">The value that element 0 will be initialized to.</param>
/// <returns>A new <see cref="Vector256{Int64}" /> instance with the first element initialized to <paramref name="value" /> and the remaining elements left uninitialized.</returns>
+ [Intrinsic]
public static unsafe Vector256<long> CreateScalarUnsafe(long value)
{
// This relies on us stripping the "init" flag from the ".locals"
/// <summary>Creates a new <see cref="Vector256{SByte}" /> instance with the first element initialized to the specified value and the remaining elements left uninitialized.</summary>
/// <param name="value">The value that element 0 will be initialized to.</param>
/// <returns>A new <see cref="Vector256{SByte}" /> instance with the first element initialized to <paramref name="value" /> and the remaining elements left uninitialized.</returns>
+ [Intrinsic]
[CLSCompliant(false)]
public static unsafe Vector256<sbyte> CreateScalarUnsafe(sbyte value)
{
/// <summary>Creates a new <see cref="Vector256{Single}" /> instance with the first element initialized to the specified value and the remaining elements left uninitialized.</summary>
/// <param name="value">The value that element 0 will be initialized to.</param>
/// <returns>A new <see cref="Vector256{Single}" /> instance with the first element initialized to <paramref name="value" /> and the remaining elements left uninitialized.</returns>
+ [Intrinsic]
public static unsafe Vector256<float> CreateScalarUnsafe(float value)
{
// This relies on us stripping the "init" flag from the ".locals"
/// <summary>Creates a new <see cref="Vector256{UInt16}" /> instance with the first element initialized to the specified value and the remaining elements left uninitialized.</summary>
/// <param name="value">The value that element 0 will be initialized to.</param>
/// <returns>A new <see cref="Vector256{UInt16}" /> instance with the first element initialized to <paramref name="value" /> and the remaining elements left uninitialized.</returns>
+ [Intrinsic]
[CLSCompliant(false)]
public static unsafe Vector256<ushort> CreateScalarUnsafe(ushort value)
{
/// <summary>Creates a new <see cref="Vector256{UInt32}" /> instance with the first element initialized to the specified value and the remaining elements left uninitialized.</summary>
/// <param name="value">The value that element 0 will be initialized to.</param>
/// <returns>A new <see cref="Vector256{UInt32}" /> instance with the first element initialized to <paramref name="value" /> and the remaining elements left uninitialized.</returns>
+ [Intrinsic]
[CLSCompliant(false)]
public static unsafe Vector256<uint> CreateScalarUnsafe(uint value)
{
/// <summary>Creates a new <see cref="Vector256{UInt64}" /> instance with the first element initialized to the specified value and the remaining elements left uninitialized.</summary>
/// <param name="value">The value that element 0 will be initialized to.</param>
/// <returns>A new <see cref="Vector256{UInt64}" /> instance with the first element initialized to <paramref name="value" /> and the remaining elements left uninitialized.</returns>
+ [Intrinsic]
[CLSCompliant(false)]
public static unsafe Vector256<ulong> CreateScalarUnsafe(ulong value)
{
/// <summary>Gets the value of the lower 128-bits as a new <see cref="Vector128{T}" />.</summary>
/// <returns>The value of the lower 128-bits as a new <see cref="Vector128{T}" />.</returns>
/// <exception cref="NotSupportedException">The type of the current instance (<typeparamref name="T" />) is not supported.</exception>
+ [Intrinsic]
public Vector128<T> GetLower()
{
ThrowIfUnsupportedType();
/// <summary>Converts the current instance to a scalar containing the value of the first element.</summary>
/// <returns>A scalar <typeparamref name="T" /> containing the value of the first element.</returns>
/// <exception cref="NotSupportedException">The type of the current instance (<typeparamref name="T" />) is not supported.</exception>
+ [Intrinsic]
public T ToScalar()
{
ThrowIfUnsupportedType();