diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index c45a6268a5a5a5..bc1bd821b6488d 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -8228,6 +8228,23 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */ + bool IsBaselineSimdIsaSupported() + { +#ifdef FEATURE_SIMD +#if defined(TARGET_XARCH) + CORINFO_InstructionSet minimumIsa = InstructionSet_SSE2; +#elif defined(TARGET_ARM64) + CORINFO_InstructionSet minimumIsa = InstructionSet_AdvSimd; +#else +#error Unsupported platform +#endif // !TARGET_XARCH && !TARGET_ARM64 + + return compOpportunisticallyDependsOn(minimumIsa) && JitConfig.EnableHWIntrinsic(); +#else + return false; +#endif + } + // Get highest available level for SIMD codegen SIMDLevel getSIMDSupportLevel() { diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp index 0440c879480760..8c3a669d3568b5 100644 --- a/src/coreclr/jit/gentree.cpp +++ b/src/coreclr/jit/gentree.cpp @@ -6507,7 +6507,13 @@ GenTree* Compiler::gtNewLclvNode(unsigned lnum, var_types type DEBUGARG(IL_OFFSE // should be able to remove this exception and handle the assignment mismatch in // Lowering. LclVarDsc* varDsc = lvaGetDesc(lnum); - assert((type == varDsc->lvType) || + + bool simd12ToSimd16Widening = false; +#if FEATURE_SIMD + // We can additionally have a SIMD12 that was widened to a SIMD16, generally as part of lowering + simd12ToSimd16Widening = (type == TYP_SIMD16) && (varDsc->lvType == TYP_SIMD12); +#endif + assert((type == varDsc->lvType) || simd12ToSimd16Widening || (lvaIsImplicitByRefLocal(lnum) && fgGlobalMorph && (varDsc->lvType == TYP_BYREF)) || ((varDsc->lvType == TYP_STRUCT) && (genTypeSize(type) == varDsc->lvExactSize))); } diff --git a/src/coreclr/jit/lir.cpp b/src/coreclr/jit/lir.cpp index beac0b069e2142..6bcc97b3ea2ea9 100644 --- a/src/coreclr/jit/lir.cpp +++ b/src/coreclr/jit/lir.cpp @@ -246,10 +246,11 @@ void LIR::Use::ReplaceWith(Compiler* compiler, GenTree* replacement) // lclNum - The local to use for temporary storage. If BAD_VAR_NUM (the // default) is provided, this method will create and use a new // local var. +// assign - On return, if non null, contains the created assignment node // // Return Value: The number of the local var used for temporary storage. // -unsigned LIR::Use::ReplaceWithLclVar(Compiler* compiler, unsigned lclNum) +unsigned LIR::Use::ReplaceWithLclVar(Compiler* compiler, unsigned lclNum, GenTree** assign) { assert(IsInitialized()); assert(compiler != nullptr); @@ -277,6 +278,10 @@ unsigned LIR::Use::ReplaceWithLclVar(Compiler* compiler, unsigned lclNum) JITDUMP("ReplaceWithLclVar created store :\n"); DISPNODE(store); + if (assign != nullptr) + { + *assign = store; + } return lclNum; } diff --git a/src/coreclr/jit/lir.h b/src/coreclr/jit/lir.h index 5348b9ed920e9b..e174482be6b36e 100644 --- a/src/coreclr/jit/lir.h +++ b/src/coreclr/jit/lir.h @@ -74,7 +74,7 @@ class LIR final bool IsDummyUse() const; void ReplaceWith(Compiler* compiler, GenTree* replacement); - unsigned ReplaceWithLclVar(Compiler* compiler, unsigned lclNum = BAD_VAR_NUM); + unsigned ReplaceWithLclVar(Compiler* compiler, unsigned lclNum = BAD_VAR_NUM, GenTree** assign = nullptr); }; //------------------------------------------------------------------------ diff --git a/src/coreclr/jit/lower.h b/src/coreclr/jit/lower.h index bc061bf7548f06..7f7c9d3760aa14 100644 --- a/src/coreclr/jit/lower.h +++ b/src/coreclr/jit/lower.h @@ -217,9 +217,18 @@ class Lowering final : public Phase GenTree* oldUseNode = use.Def(); if ((oldUseNode->gtOper != GT_LCL_VAR) || (tempNum != BAD_VAR_NUM)) { - use.ReplaceWithLclVar(comp, tempNum); + GenTree* assign; + use.ReplaceWithLclVar(comp, tempNum, &assign); + GenTree* newUseNode = use.Def(); ContainCheckRange(oldUseNode->gtNext, newUseNode); + + // We need to lower the LclVar and assignment since there may be certain + // types or scenarios, such as TYP_SIMD12, that need special handling + + LowerNode(assign); + LowerNode(newUseNode); + return newUseNode->AsLclVar(); } return oldUseNode->AsLclVar(); diff --git a/src/coreclr/jit/lowerxarch.cpp b/src/coreclr/jit/lowerxarch.cpp index 09cd7c02159cf9..d7e7746c292524 100644 --- a/src/coreclr/jit/lowerxarch.cpp +++ b/src/coreclr/jit/lowerxarch.cpp @@ -3007,15 +3007,16 @@ void Lowering::LowerHWIntrinsicWithElement(GenTreeHWIntrinsic* node) NamedIntrinsic resIntrinsic = NI_Illegal; - idx = comp->gtNewIconNode(imm8); - BlockRange().InsertBefore(node, idx); - switch (simdBaseType) { case TYP_LONG: case TYP_ULONG: { - op2 = idx; + idx = comp->gtNewIconNode(imm8); + BlockRange().InsertBefore(node, idx); + + op1 = comp->gtNewArgList(op1, op3, idx); + op2 = nullptr; resIntrinsic = NI_SSE41_X64_Insert; break; } @@ -3033,7 +3034,7 @@ void Lowering::LowerHWIntrinsicWithElement(GenTreeHWIntrinsic* node) tmp1 = comp->gtNewSimdHWIntrinsicNode(TYP_SIMD16, op3, NI_Vector128_CreateScalarUnsafe, CORINFO_TYPE_FLOAT, 16); - BlockRange().InsertBefore(idx, tmp1); + BlockRange().InsertBefore(node, tmp1); LowerNode(tmp1); if (!comp->compOpportunisticallyDependsOn(InstructionSet_SSE41)) @@ -3088,26 +3089,36 @@ void Lowering::LowerHWIntrinsicWithElement(GenTreeHWIntrinsic* node) ssize_t controlBits1; ssize_t controlBits2; + // The comments beside the control bits below are listed using the managed API operands + // + // In practice, for the first step the value being inserted (op3) is in tmp1 + // while the other elements of the result (op1) are in tmp2. The result ends + // up containing the value being inserted and its immediate neighbor. + // + // The second step takes that result (which is in op1) plus the other elements + // from op2 (a clone of op1/tmp2 from the previous step) and combines them to + // create the final result. + switch (imm8) { case 1: { - controlBits1 = 0; - controlBits2 = 226; + controlBits1 = 0; // 00 00 00 00; op1 = { X = op3, Y = op3, Z = op1.X, W = op1.X } + controlBits2 = 226; // 11 10 00 10; node = { X = op1.X, Y = op3, Z = op1.Z, W = op1.W } break; } case 2: { - controlBits1 = 48; - controlBits2 = 132; + controlBits1 = 15; // 00 00 11 11; op1 = { X = op1.W, Y = op1.W, Z = op3, W = op3 } + controlBits2 = 36; // 00 10 01 00; node = { X = op1.X, Y = op1.Y, Z = op3, W = op1.W } break; } case 3: { - controlBits1 = 32; - controlBits2 = 36; + controlBits1 = 10; // 00 00 10 10; op1 = { X = op1.Z, Y = op1.Z, Z = op3, W = op3 } + controlBits2 = 132; // 10 00 01 00; node = { X = op1.X, Y = op1.Y, Z = op1.Z, W = op3 } break; } @@ -3118,12 +3129,12 @@ void Lowering::LowerHWIntrinsicWithElement(GenTreeHWIntrinsic* node) idx = comp->gtNewIconNode(controlBits1); BlockRange().InsertAfter(tmp2, idx); - if (imm8 == 1) + if (imm8 != 1) { std::swap(tmp1, tmp2); } - op1 = comp->gtNewSimdHWIntrinsicNode(TYP_SIMD16, tmp2, tmp1, idx, NI_SSE_Shuffle, + op1 = comp->gtNewSimdHWIntrinsicNode(TYP_SIMD16, tmp1, tmp2, idx, NI_SSE_Shuffle, CORINFO_TYPE_FLOAT, 16); BlockRange().InsertAfter(idx, op1); LowerNode(op1); @@ -3131,6 +3142,11 @@ void Lowering::LowerHWIntrinsicWithElement(GenTreeHWIntrinsic* node) idx = comp->gtNewIconNode(controlBits2); BlockRange().InsertAfter(op1, idx); + if (imm8 != 1) + { + std::swap(op1, op2); + } + op1 = comp->gtNewArgList(op1, op2, idx); op2 = nullptr; resIntrinsic = NI_SSE_Shuffle; @@ -3139,8 +3155,8 @@ void Lowering::LowerHWIntrinsicWithElement(GenTreeHWIntrinsic* node) } else { - op3 = tmp1; - idx->AsIntCon()->SetIconValue(imm8 * 16); + imm8 = imm8 * 16; + op3 = tmp1; FALLTHROUGH; } } @@ -3150,6 +3166,9 @@ void Lowering::LowerHWIntrinsicWithElement(GenTreeHWIntrinsic* node) case TYP_INT: case TYP_UINT: { + idx = comp->gtNewIconNode(imm8); + BlockRange().InsertBefore(node, idx); + op1 = comp->gtNewArgList(op1, op3, idx); op2 = nullptr; resIntrinsic = NI_SSE41_Insert; @@ -3159,6 +3178,9 @@ void Lowering::LowerHWIntrinsicWithElement(GenTreeHWIntrinsic* node) case TYP_SHORT: case TYP_USHORT: { + idx = comp->gtNewIconNode(imm8); + BlockRange().InsertBefore(node, idx); + op1 = comp->gtNewArgList(op1, op3, idx); op2 = nullptr; resIntrinsic = NI_SSE2_Insert; @@ -3178,7 +3200,7 @@ void Lowering::LowerHWIntrinsicWithElement(GenTreeHWIntrinsic* node) tmp1 = comp->gtNewSimdHWIntrinsicNode(TYP_SIMD16, op3, NI_Vector128_CreateScalarUnsafe, CORINFO_TYPE_DOUBLE, 16); - BlockRange().InsertBefore(idx, tmp1); + BlockRange().InsertBefore(node, tmp1); LowerNode(tmp1); op2 = tmp1; @@ -5474,8 +5496,11 @@ bool Lowering::IsContainableHWIntrinsicOp(GenTreeHWIntrinsic* containingNode, Ge default: { - // These intrinsics only expect 16 or 32-byte nodes for containment - assert((genTypeSize(node->TypeGet()) == 16) || (genTypeSize(node->TypeGet()) == 32)); + if ((genTypeSize(node->TypeGet()) != 16) && (genTypeSize(node->TypeGet()) != 32)) + { + // These intrinsics only expect 16 or 32-byte nodes for containment + break; + } if (!comp->canUseVexEncoding()) { @@ -5535,9 +5560,12 @@ bool Lowering::IsContainableHWIntrinsicOp(GenTreeHWIntrinsic* containingNode, Ge case NI_AVX2_ShuffleHigh: case NI_AVX2_ShuffleLow: { - // These intrinsics only expect 16 or 32-byte nodes for containment - assert((genTypeSize(node->TypeGet()) == 16) || (genTypeSize(node->TypeGet()) == 32)); - assert(supportsSIMDScalarLoads == false); + if ((genTypeSize(node->TypeGet()) != 16) && (genTypeSize(node->TypeGet()) != 32)) + { + // These intrinsics only expect 16 or 32-byte nodes for containment + break; + } + assert(!supportsSIMDScalarLoads); supportsAlignedSIMDLoads = !comp->canUseVexEncoding() || !comp->opts.MinOpts(); supportsUnalignedSIMDLoads = comp->canUseVexEncoding(); @@ -5553,7 +5581,12 @@ bool Lowering::IsContainableHWIntrinsicOp(GenTreeHWIntrinsic* containingNode, Ge if (containingNode->GetSimdBaseType() == TYP_FLOAT) { assert(containingIntrinsicId == NI_SSE41_Insert); - assert(genTypeSize(node->TypeGet()) == 16); + + if (genTypeSize(node->TypeGet()) != 16) + { + // These intrinsics only expect 16-byte nodes for containment + break; + } // Sse41.Insert(V128, V128, byte) is a bit special // in that it has different behavior depending on whether the @@ -5620,8 +5653,11 @@ bool Lowering::IsContainableHWIntrinsicOp(GenTreeHWIntrinsic* containingNode, Ge case NI_AVX_CompareScalar: { - // These intrinsics only expect 16 or 32-byte nodes for containment - assert((genTypeSize(node->TypeGet()) == 16) || (genTypeSize(node->TypeGet()) == 32)); + if ((genTypeSize(node->TypeGet()) != 16) && (genTypeSize(node->TypeGet()) != 32)) + { + // These intrinsics only expect 16 or 32-byte nodes for containment + break; + } assert(supportsAlignedSIMDLoads == false); assert(supportsUnalignedSIMDLoads == false); @@ -5700,8 +5736,11 @@ bool Lowering::IsContainableHWIntrinsicOp(GenTreeHWIntrinsic* containingNode, Ge default: { - // These intrinsics only expect 16 or 32-byte nodes for containment - assert((genTypeSize(node->TypeGet()) == 16) || (genTypeSize(node->TypeGet()) == 32)); + if ((genTypeSize(node->TypeGet()) != 16) && (genTypeSize(node->TypeGet()) != 32)) + { + // These intrinsics only expect 16 or 32-byte nodes for containment + break; + } supportsSIMDScalarLoads = true; supportsGeneralLoads = supportsSIMDScalarLoads; diff --git a/src/coreclr/jit/morph.cpp b/src/coreclr/jit/morph.cpp index 9fe30eea23e102..b6e1f808ea9094 100644 --- a/src/coreclr/jit/morph.cpp +++ b/src/coreclr/jit/morph.cpp @@ -6009,11 +6009,14 @@ GenTree* Compiler::fgMorphField(GenTree* tree, MorphAddrContext* mac) // if this field belongs to simd struct, translate it to simd intrinsic. if (mac == nullptr) { - GenTree* newTree = fgMorphFieldToSimdGetElement(tree); - if (newTree != tree) + if (IsBaselineSimdIsaSupported()) { - newTree = fgMorphSmpOp(newTree); - return newTree; + GenTree* newTree = fgMorphFieldToSimdGetElement(tree); + if (newTree != tree) + { + newTree = fgMorphSmpOp(newTree); + return newTree; + } } } else if ((objRef != nullptr) && (objRef->OperGet() == GT_ADDR) && varTypeIsSIMD(objRef->gtGetOp1())) @@ -12238,6 +12241,7 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac) op2 = tree->AsOp()->gtOp2; #ifdef FEATURE_SIMD + if (IsBaselineSimdIsaSupported()) { // We should check whether op2 should be assigned to a SIMD field or not. // If it is, we should tranlate the tree to simd intrinsic. diff --git a/src/coreclr/jit/simd.cpp b/src/coreclr/jit/simd.cpp index 0cb2947cff0de3..2eb0fca532ca85 100644 --- a/src/coreclr/jit/simd.cpp +++ b/src/coreclr/jit/simd.cpp @@ -1901,15 +1901,7 @@ GenTree* Compiler::impSIMDIntrinsic(OPCODE opcode, return nullptr; } -#if defined(TARGET_XARCH) - CORINFO_InstructionSet minimumIsa = InstructionSet_SSE2; -#elif defined(TARGET_ARM64) - CORINFO_InstructionSet minimumIsa = InstructionSet_AdvSimd; -#else -#error Unsupported platform -#endif // !TARGET_XARCH && !TARGET_ARM64 - - if (!compOpportunisticallyDependsOn(minimumIsa) || !JitConfig.EnableHWIntrinsic()) + if (!IsBaselineSimdIsaSupported()) { // The user disabled support for the baseline ISA so // don't emit any SIMD intrinsics as they all require diff --git a/src/coreclr/jit/simdashwintrinsic.cpp b/src/coreclr/jit/simdashwintrinsic.cpp index 7369172c5c989c..e8f742cfc78a9a 100644 --- a/src/coreclr/jit/simdashwintrinsic.cpp +++ b/src/coreclr/jit/simdashwintrinsic.cpp @@ -176,15 +176,7 @@ GenTree* Compiler::impSimdAsHWIntrinsic(NamedIntrinsic intrinsic, return nullptr; } -#if defined(TARGET_XARCH) - CORINFO_InstructionSet minimumIsa = InstructionSet_SSE2; -#elif defined(TARGET_ARM64) - CORINFO_InstructionSet minimumIsa = InstructionSet_AdvSimd; -#else -#error Unsupported platform -#endif // !TARGET_XARCH && !TARGET_ARM64 - - if (!compOpportunisticallyDependsOn(minimumIsa) || !JitConfig.EnableHWIntrinsic()) + if (!IsBaselineSimdIsaSupported()) { // The user disabled support for the baseline ISA so // don't emit any SIMD intrinsics as they all require diff --git a/src/tests/JIT/Directed/StructABI/structreturn.cs b/src/tests/JIT/Directed/StructABI/structreturn.cs index 72f54b306d8c36..cbcdd70a1e2184 100644 --- a/src/tests/JIT/Directed/StructABI/structreturn.cs +++ b/src/tests/JIT/Directed/StructABI/structreturn.cs @@ -1332,7 +1332,7 @@ private static void TestReturnViaThrowing() where T : struct T value = vector[Vector.Count]; System.Diagnostics.Debug.Assert(false); } - catch (IndexOutOfRangeException) + catch (ArgumentOutOfRangeException) { return; } diff --git a/src/tests/JIT/SIMD/VectorArray.cs b/src/tests/JIT/SIMD/VectorArray.cs index 505743a7e8c72e..4de968286287f1 100644 --- a/src/tests/JIT/SIMD/VectorArray.cs +++ b/src/tests/JIT/SIMD/VectorArray.cs @@ -4,7 +4,8 @@ using System; using System.Numerics; - +using System.Runtime.Intrinsics.Arm; +using System.Runtime.Intrinsics.X86; internal partial class VectorTest { @@ -161,44 +162,46 @@ private static int Main() if (VectorArrayTest.VectorArray(1) != Pass) returnVal = Fail; if (VectorArrayTest.VectorArray(1) != Pass) returnVal = Fail; - JitLog jitLog = new JitLog(); - if (!jitLog.Check("get_Item", "Single")) returnVal = Fail; - if (!jitLog.Check("System.Numerics.Vector`1[Single][System.Single]:.ctor(float)")) returnVal = Fail; - if (!jitLog.Check("get_Item", "Double")) returnVal = Fail; - if (!jitLog.Check("System.Numerics.Vector`1[Double][System.Double]:.ctor(double)")) returnVal = Fail; - if (!jitLog.Check("get_Item", "Int32")) returnVal = Fail; - if (!jitLog.Check("System.Numerics.Vector`1[Int32][System.Int32]:.ctor(int)")) returnVal = Fail; - if (!jitLog.Check("get_Item", "Int64")) returnVal = Fail; - if (!jitLog.Check("System.Numerics.Vector`1[Int64][System.Int64]:.ctor(long)")) returnVal = Fail; - if (!jitLog.Check("System.Numerics.Vector4:.ctor(float)")) returnVal = Fail; - if (!jitLog.Check("System.Numerics.Vector3:.ctor(float)")) returnVal = Fail; - if (!jitLog.Check("System.Numerics.Vector2:.ctor(float)")) returnVal = Fail; - if (!jitLog.Check("get_Item", "UInt16")) returnVal = Fail; - // We are not currently recognizing the Vector constructor. - if (!Vector.IsHardwareAccelerated) - if (!jitLog.Check("System.Numerics.Vector`1[UInt16][System.UInt16]:.ctor(char)")) returnVal = Fail; - if (!jitLog.Check("get_Item", "Byte")) returnVal = Fail; - // We are not currently recognizing the Vector constructor. - if (!Vector.IsHardwareAccelerated) - if (!jitLog.Check("System.Numerics.Vector`1[Byte][System.Byte]:.ctor(ubyte)")) returnVal = Fail; - if (!jitLog.Check("get_Item", "Int16")) returnVal = Fail; - // We are not currently recognizing the Vector constructor. - if (!Vector.IsHardwareAccelerated) - if (!jitLog.Check("System.Numerics.Vector`1[Int16][System.Int16]:.ctor(short)")) returnVal = Fail; - if (!jitLog.Check("get_Item", "SByte")) returnVal = Fail; - // We are not currently recognizing the Vector constructor. - if (!Vector.IsHardwareAccelerated) - if (!jitLog.Check("System.Numerics.Vector`1[SByte][System.SByte]:.ctor(byte)")) returnVal = Fail; - if (!jitLog.Check("get_Item", "UInt32")) returnVal = Fail; - if (!jitLog.Check("System.Numerics.Vector`1[UInt32][System.UInt32]:.ctor(int)")) returnVal = Fail; - if (!jitLog.Check("get_Item", "UInt64")) returnVal = Fail; - if (!jitLog.Check("System.Numerics.Vector`1[UInt64][System.UInt64]:.ctor(long)")) returnVal = Fail; - if (!jitLog.Check("get_Item", "IntPtr")) returnVal = Fail; - if (!jitLog.Check("System.Numerics.Vector`1[IntPtr][System.UIntPtr]:.ctor(nuint)")) returnVal = Fail; - if (!jitLog.Check("get_Item", "UIntPtr")) returnVal = Fail; - if (!jitLog.Check("System.Numerics.Vector`1[UIntPtr][System.IntPtr]:.ctor(nint)")) returnVal = Fail; - jitLog.Dispose(); - + if (Sse41.IsSupported || AdvSimd.IsSupported) + { + JitLog jitLog = new JitLog(); + if (!jitLog.Check("get_Item", "Single")) returnVal = Fail; + if (!jitLog.Check("System.Numerics.Vector`1[Single][System.Single]:.ctor(float)")) returnVal = Fail; + if (!jitLog.Check("get_Item", "Double")) returnVal = Fail; + if (!jitLog.Check("System.Numerics.Vector`1[Double][System.Double]:.ctor(double)")) returnVal = Fail; + if (!jitLog.Check("get_Item", "Int32")) returnVal = Fail; + if (!jitLog.Check("System.Numerics.Vector`1[Int32][System.Int32]:.ctor(int)")) returnVal = Fail; + if (!jitLog.Check("get_Item", "Int64")) returnVal = Fail; + if (!jitLog.Check("System.Numerics.Vector`1[Int64][System.Int64]:.ctor(long)")) returnVal = Fail; + if (!jitLog.Check("System.Numerics.Vector4:.ctor(float)")) returnVal = Fail; + if (!jitLog.Check("System.Numerics.Vector3:.ctor(float)")) returnVal = Fail; + if (!jitLog.Check("System.Numerics.Vector2:.ctor(float)")) returnVal = Fail; + if (!jitLog.Check("get_Item", "UInt16")) returnVal = Fail; + // We are not currently recognizing the Vector constructor. + if (!Vector.IsHardwareAccelerated) + if (!jitLog.Check("System.Numerics.Vector`1[UInt16][System.UInt16]:.ctor(char)")) returnVal = Fail; + if (!jitLog.Check("get_Item", "Byte")) returnVal = Fail; + // We are not currently recognizing the Vector constructor. + if (!Vector.IsHardwareAccelerated) + if (!jitLog.Check("System.Numerics.Vector`1[Byte][System.Byte]:.ctor(ubyte)")) returnVal = Fail; + if (!jitLog.Check("get_Item", "Int16")) returnVal = Fail; + // We are not currently recognizing the Vector constructor. + if (!Vector.IsHardwareAccelerated) + if (!jitLog.Check("System.Numerics.Vector`1[Int16][System.Int16]:.ctor(short)")) returnVal = Fail; + if (!jitLog.Check("get_Item", "SByte")) returnVal = Fail; + // We are not currently recognizing the Vector constructor. + if (!Vector.IsHardwareAccelerated) + if (!jitLog.Check("System.Numerics.Vector`1[SByte][System.SByte]:.ctor(byte)")) returnVal = Fail; + if (!jitLog.Check("get_Item", "UInt32")) returnVal = Fail; + if (!jitLog.Check("System.Numerics.Vector`1[UInt32][System.UInt32]:.ctor(int)")) returnVal = Fail; + if (!jitLog.Check("get_Item", "UInt64")) returnVal = Fail; + if (!jitLog.Check("System.Numerics.Vector`1[UInt64][System.UInt64]:.ctor(long)")) returnVal = Fail; + if (!jitLog.Check("get_Item", "IntPtr")) returnVal = Fail; + if (!jitLog.Check("System.Numerics.Vector`1[IntPtr][System.UIntPtr]:.ctor(nuint)")) returnVal = Fail; + if (!jitLog.Check("get_Item", "UIntPtr")) returnVal = Fail; + if (!jitLog.Check("System.Numerics.Vector`1[UIntPtr][System.IntPtr]:.ctor(nint)")) returnVal = Fail; + jitLog.Dispose(); + } } catch (ArgumentException ex) { diff --git a/src/tests/JIT/SIMD/VectorGet.cs b/src/tests/JIT/SIMD/VectorGet.cs index d46e98c6533ac9..aa9fb118eb2ba1 100644 --- a/src/tests/JIT/SIMD/VectorGet.cs +++ b/src/tests/JIT/SIMD/VectorGet.cs @@ -5,6 +5,8 @@ using System; using System.Numerics; using System.Runtime.CompilerServices; +using System.Runtime.Intrinsics.Arm; +using System.Runtime.Intrinsics.X86; internal partial class VectorTest { @@ -206,33 +208,35 @@ private static int Main() if (VectorGetTest.VectorGet(100, 1) == Fail) returnVal = Fail; if (VectorGetTest.VectorGetIndexerOutOfRange(100, 1) == Fail) returnVal = Fail; - JitLog jitLog = new JitLog(); - if (!jitLog.Check("get_Item", "Double")) returnVal = Fail; - if (!jitLog.Check("get_Count", "Double")) returnVal = Fail; - if (!jitLog.Check("get_Item", "Single")) returnVal = Fail; - if (!jitLog.Check("get_Count", "Single")) returnVal = Fail; - if (!jitLog.Check("get_Item", "Int32")) returnVal = Fail; - if (!jitLog.Check("get_Count", "Int32")) returnVal = Fail; - if (!jitLog.Check("get_Item", "Int64")) returnVal = Fail; - if (!jitLog.Check("get_Count", "Int64")) returnVal = Fail; - if (!jitLog.Check("get_Item", "UInt16")) returnVal = Fail; - if (!jitLog.Check("get_Count", "UInt16")) returnVal = Fail; - if (!jitLog.Check("get_Item", "Byte")) returnVal = Fail; - if (!jitLog.Check("get_Count", "Byte")) returnVal = Fail; - if (!jitLog.Check("get_Item", "Int16")) returnVal = Fail; - if (!jitLog.Check("get_Count", "Int16")) returnVal = Fail; - if (!jitLog.Check("get_Item", "SByte")) returnVal = Fail; - if (!jitLog.Check("get_Count", "SByte")) returnVal = Fail; - if (!jitLog.Check("get_Item", "UInt32")) returnVal = Fail; - if (!jitLog.Check("get_Count", "UInt32")) returnVal = Fail; - if (!jitLog.Check("get_Item", "UInt64")) returnVal = Fail; - if (!jitLog.Check("get_Count", "UInt64")) returnVal = Fail; - if (!jitLog.Check("get_Item", "IntPtr")) returnVal = Fail; - if (!jitLog.Check("get_Count", "IntPtr")) returnVal = Fail; - if (!jitLog.Check("get_Item", "UIntPtr")) returnVal = Fail; - if (!jitLog.Check("get_Count", "UIntPtr")) returnVal = Fail; - jitLog.Dispose(); - + if (Sse41.IsSupported || AdvSimd.IsSupported) + { + JitLog jitLog = new JitLog(); + if (!jitLog.Check("get_Item", "Double")) returnVal = Fail; + if (!jitLog.Check("get_Count", "Double")) returnVal = Fail; + if (!jitLog.Check("get_Item", "Single")) returnVal = Fail; + if (!jitLog.Check("get_Count", "Single")) returnVal = Fail; + if (!jitLog.Check("get_Item", "Int32")) returnVal = Fail; + if (!jitLog.Check("get_Count", "Int32")) returnVal = Fail; + if (!jitLog.Check("get_Item", "Int64")) returnVal = Fail; + if (!jitLog.Check("get_Count", "Int64")) returnVal = Fail; + if (!jitLog.Check("get_Item", "UInt16")) returnVal = Fail; + if (!jitLog.Check("get_Count", "UInt16")) returnVal = Fail; + if (!jitLog.Check("get_Item", "Byte")) returnVal = Fail; + if (!jitLog.Check("get_Count", "Byte")) returnVal = Fail; + if (!jitLog.Check("get_Item", "Int16")) returnVal = Fail; + if (!jitLog.Check("get_Count", "Int16")) returnVal = Fail; + if (!jitLog.Check("get_Item", "SByte")) returnVal = Fail; + if (!jitLog.Check("get_Count", "SByte")) returnVal = Fail; + if (!jitLog.Check("get_Item", "UInt32")) returnVal = Fail; + if (!jitLog.Check("get_Count", "UInt32")) returnVal = Fail; + if (!jitLog.Check("get_Item", "UInt64")) returnVal = Fail; + if (!jitLog.Check("get_Count", "UInt64")) returnVal = Fail; + if (!jitLog.Check("get_Item", "IntPtr")) returnVal = Fail; + if (!jitLog.Check("get_Count", "IntPtr")) returnVal = Fail; + if (!jitLog.Check("get_Item", "UIntPtr")) returnVal = Fail; + if (!jitLog.Check("get_Count", "UIntPtr")) returnVal = Fail; + jitLog.Dispose(); + } return returnVal; } }