{
case HW_Category_SimpleSIMD:
{
+ // These intrinsics only expect 16 or 32-byte nodes for containment
+ assert((genTypeSize(node->TypeGet()) == 16) || (genTypeSize(node->TypeGet()) == 32));
assert(supportsSIMDScalarLoads == false);
supportsAlignedSIMDLoads =
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);
supportsAlignedSIMDLoads = !comp->canUseVexEncoding();
break;
}
+ case NI_SSE2_Insert:
case NI_SSE41_Insert:
case NI_SSE41_X64_Insert:
{
if (containingNode->gtSIMDBaseType == TYP_FLOAT)
{
+ assert(containingIntrinsicId == NI_SSE41_Insert);
+ assert(genTypeSize(node->TypeGet()) == 16);
+
+ // Sse41.Insert(V128<float>, V128<float>, byte) is a bit special
+ // in that it has different behavior depending on whether the
+ // second operand is coming from a register or memory. When coming
+ // from a register, all 4 elements of the vector can be used and it
+ // is effectively a regular `SimpleSIMD` operation; but when loading
+ // from memory, it only works with the lowest element and is effectively
+ // a `SIMDScalar`.
+
+ assert(supportsAlignedSIMDLoads == false);
+ assert(supportsUnalignedSIMDLoads == false);
+ assert(supportsGeneralLoads == false);
assert(supportsSIMDScalarLoads == false);
GenTree* op1 = containingNode->gtGetOp1();
- GenTree* op2 = containingNode->gtGetOp2();
+ GenTree* op2 = nullptr;
GenTree* op3 = nullptr;
assert(op1->OperIsList());
ssize_t ival = op3->AsIntCon()->IconValue();
assert((ival >= 0) && (ival <= 255));
- if (ival <= 0x3F)
- {
- supportsAlignedSIMDLoads = !comp->canUseVexEncoding();
- supportsUnalignedSIMDLoads = !supportsAlignedSIMDLoads;
- supportsGeneralLoads = supportsUnalignedSIMDLoads;
-
- break;
- }
+ supportsSIMDScalarLoads = (ival <= 0x3F);
+ supportsGeneralLoads = supportsSIMDScalarLoads;
}
-
- assert(supportsAlignedSIMDLoads == false);
- assert(supportsUnalignedSIMDLoads == false);
- assert(supportsGeneralLoads == false);
+ break;
}
- else
- {
- assert(supportsAlignedSIMDLoads == false);
- assert(supportsUnalignedSIMDLoads == false);
- supportsSIMDScalarLoads = true;
- supportsGeneralLoads = supportsSIMDScalarLoads;
- }
+ // We should only get here for integral nodes.
+ assert(varTypeIsIntegral(node->TypeGet()));
+
+ assert(supportsAlignedSIMDLoads == false);
+ assert(supportsUnalignedSIMDLoads == false);
+ assert(supportsSIMDScalarLoads == false);
+ const unsigned expectedSize = genTypeSize(containingNode->gtSIMDBaseType);
+ const unsigned operandSize = genTypeSize(node->TypeGet());
+
+ supportsGeneralLoads = (operandSize >= expectedSize);
break;
}
- case NI_SSE2_Insert:
case NI_AVX_CompareScalar:
{
+ // These intrinsics only expect 16 or 32-byte nodes for containment
+ assert((genTypeSize(node->TypeGet()) == 16) || (genTypeSize(node->TypeGet()) == 32));
+
assert(supportsAlignedSIMDLoads == false);
assert(supportsUnalignedSIMDLoads == false);
supportsSIMDScalarLoads = true;
supportsGeneralLoads = supportsSIMDScalarLoads;
-
break;
}
assert(supportsAlignedSIMDLoads == false);
assert(supportsUnalignedSIMDLoads == false);
- supportsSIMDScalarLoads = true;
- supportsGeneralLoads = supportsSIMDScalarLoads;
+ switch (containingIntrinsicId)
+ {
+ case NI_Base_Vector128_CreateScalarUnsafe:
+ case NI_Base_Vector256_CreateScalarUnsafe:
+ {
+ assert(supportsSIMDScalarLoads == false);
+
+ const unsigned expectedSize = genTypeSize(genActualType(containingNode->gtSIMDBaseType));
+ const unsigned operandSize = genTypeSize(node->TypeGet());
+
+ supportsGeneralLoads = (operandSize == expectedSize);
+ break;
+ }
+
+ case NI_SSE_ConvertScalarToVector128Single:
+ case NI_SSE2_ConvertScalarToVector128Double:
+ case NI_SSE2_ConvertScalarToVector128Int32:
+ case NI_SSE2_ConvertScalarToVector128UInt32:
+ case NI_SSE_X64_ConvertScalarToVector128Single:
+ case NI_SSE2_X64_ConvertScalarToVector128Double:
+ case NI_SSE2_X64_ConvertScalarToVector128Int64:
+ case NI_SSE2_X64_ConvertScalarToVector128UInt64:
+ {
+ if (!varTypeIsIntegral(node->TypeGet()))
+ {
+ // The floating-point overload doesn't require any special semantics
+ assert(containingIntrinsicId == NI_SSE2_ConvertScalarToVector128Double);
+ supportsSIMDScalarLoads = true;
+ supportsGeneralLoads = supportsSIMDScalarLoads;
+ break;
+ }
+
+ assert(supportsSIMDScalarLoads == false);
+
+ const unsigned expectedSize = genTypeSize(genActualType(containingNode->gtSIMDBaseType));
+ const unsigned operandSize = genTypeSize(node->TypeGet());
+ supportsGeneralLoads = (operandSize == expectedSize);
+ break;
+ }
+
+ default:
+ {
+ // These intrinsics only expect 16 or 32-byte nodes for containment
+ assert((genTypeSize(node->TypeGet()) == 16) || (genTypeSize(node->TypeGet()) == 32));
+
+ supportsSIMDScalarLoads = true;
+ supportsGeneralLoads = supportsSIMDScalarLoads;
+ break;
+ }
+ }
break;
}
case HW_Category_Scalar:
{
+ // We should only get here for integral nodes.
+ assert(varTypeIsIntegral(node->TypeGet()));
+
assert(supportsAlignedSIMDLoads == false);
- assert(supportsSIMDScalarLoads == false);
assert(supportsUnalignedSIMDLoads == false);
+ assert(supportsSIMDScalarLoads == false);
+
+ const unsigned expectedSize = genTypeSize(containingNode->TypeGet());
+ const unsigned operandSize = genTypeSize(node->TypeGet());
- supportsGeneralLoads = true;
+ supportsGeneralLoads = (operandSize >= expectedSize);
break;
}
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{2649FAFE-07BF-4F93-8120-BA9A69285ABB}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+ <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "></PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "></PropertyGroup>
+ <PropertyGroup>
+ <DebugType>None</DebugType>
+ <Optimize>True</Optimize>
+ </PropertyGroup>
+ <ItemGroup>
+ <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
+ <Visible>False</Visible>
+ </CodeAnalysisDependentAssemblyPaths>
+ </ItemGroup>
+ <ItemGroup>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="$(MSBuildProjectName).cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="$(SourceDir)Common/CoreCLRTestLibrary/CoreCLRTestLibrary.csproj" />
+ </ItemGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+ <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' "></PropertyGroup>
+</Project>