Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/coreclr/jit/hwintrinsicxarch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -934,7 +934,7 @@ GenTree* Compiler::impNonConstFallback(NamedIntrinsic intrinsic, var_types simdT
GenTree* op2 = impPopStack().val;
GenTree* op1 = impSIMDPopStack();

GenTree* tmpOp = gtNewSimdCreateScalarUnsafeNode(TYP_SIMD16, op2, CORINFO_TYPE_INT, 16);
GenTree* tmpOp = gtNewSimdCreateScalarNode(TYP_SIMD16, op2, CORINFO_TYPE_INT, 16);
return gtNewSimdHWIntrinsicNode(simdType, op1, tmpOp, intrinsic, simdBaseJitType, genTypeSize(simdType));
}

Expand Down
54 changes: 51 additions & 3 deletions src/coreclr/jit/simd.h
Original file line number Diff line number Diff line change
Expand Up @@ -453,7 +453,23 @@ void EvaluateUnarySimd(genTreeOps oper, bool scalar, var_types baseType, TSimd*
template <typename TBase>
TBase EvaluateBinaryScalarRSZ(TBase arg0, TBase arg1)
{
return arg0 >> (arg1 & ((sizeof(TBase) * 8) - 1));
#if defined(TARGET_XARCH)
if ((arg1 < 0) || (arg1 >= (sizeof(TBase) * 8)))
{
// For SIMD, xarch allows overshifting and treats
// it as zeroing. So ensure we do the same here.
//
// The xplat APIs ensure the shiftAmount is masked
// to be within range, so we can't hit this for them.

return static_cast<TBase>(0);
}
#else
// Other platforms enforce masking in their encoding
assert((arg1 >= 0) && (arg1 < (sizeof(TBase) * 8)));
#endif

return arg0 >> arg1;
}

template <>
Expand Down Expand Up @@ -513,7 +529,22 @@ TBase EvaluateBinaryScalarSpecialized(genTreeOps oper, TBase arg0, TBase arg1)

case GT_LSH:
{
return arg0 << (arg1 & ((sizeof(TBase) * 8) - 1));
#if defined(TARGET_XARCH)
if ((arg1 < 0) || (arg1 >= (sizeof(TBase) * 8)))
{
// For SIMD, xarch allows overshifting and treats
// it as zeroing. So ensure we do the same here.
//
// The xplat APIs ensure the shiftAmount is masked
// to be within range, so we can't hit this for them.

return static_cast<TBase>(0);
}
#else
// Other platforms enforce masking in their encoding
assert((arg1 >= 0) && (arg1 < (sizeof(TBase) * 8)));
#endif
return arg0 << arg1;
}

case GT_OR:
Expand All @@ -535,7 +566,24 @@ TBase EvaluateBinaryScalarSpecialized(genTreeOps oper, TBase arg0, TBase arg1)

case GT_RSH:
{
return arg0 >> (arg1 & ((sizeof(TBase) * 8) - 1));
#if defined(TARGET_XARCH)
if ((arg1 < 0) || (arg1 >= (sizeof(TBase) * 8)))
{
// For SIMD, xarch allows overshifting and treats
// it as propagating the sign bit (returning Zero
// or AllBitsSet). So ensure we do the same here.
//
// The xplat APIs ensure the shiftAmount is masked
// to be within range, so we can't hit this for them.

arg0 >>= ((sizeof(TBase) * 8) - 1);
arg1 = static_cast<TBase>(1);
}
#else
// Other platforms enforce masking in their encoding
assert((arg1 >= 0) && (arg1 < (sizeof(TBase) * 8)));
#endif
return arg0 >> arg1;
}

case GT_RSZ:
Expand Down
15 changes: 15 additions & 0 deletions src/coreclr/jit/valuenum.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7561,6 +7561,11 @@ ValueNum ValueNumStore::EvalHWIntrinsicFunBinary(var_types type,

if (genTypeSize(baseType) != 8)
{
if (shiftAmount > INT_MAX)
{
// Ensure we don't lose track the the amount is an overshift
shiftAmount = -1;
}
arg1VN = VNForIntCon(static_cast<int32_t>(shiftAmount));
}
else
Expand Down Expand Up @@ -7594,6 +7599,11 @@ ValueNum ValueNumStore::EvalHWIntrinsicFunBinary(var_types type,

if (genTypeSize(baseType) != 8)
{
if (shiftAmount > INT_MAX)
{
// Ensure we don't lose track the the amount is an overshift
shiftAmount = -1;
}
arg1VN = VNForIntCon(static_cast<int32_t>(shiftAmount));
}
else
Expand Down Expand Up @@ -7626,6 +7636,11 @@ ValueNum ValueNumStore::EvalHWIntrinsicFunBinary(var_types type,

if (genTypeSize(baseType) != 8)
{
if (shiftAmount > INT_MAX)
{
// Ensure we don't lose track the the amount is an overshift
shiftAmount = -1;
}
arg1VN = VNForIntCon(static_cast<int32_t>(shiftAmount));
}
else
Expand Down
49 changes: 49 additions & 0 deletions src/tests/JIT/Regression/JitBlue/Runtime_93698/Runtime_93698.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Runtime.Intrinsics;
using System.Runtime.Intrinsics.X86;
using Xunit;

public static class Runtime_93698
{
[Fact]
public static void TestShiftLeftLogicalOvershift()
{
if (Sse2.IsSupported)
{
var result1 = Sse2.ShiftLeftLogical(Vector128.Create(-1, +2, -3, +4), 32);
Assert.Equal(Vector128<int>.Zero, result1);

var result2 = Sse2.ShiftLeftLogical(Vector128.Create(-5, +6, -7, +8), Vector128.Create(0, 32, 0, 0));
Assert.Equal(Vector128<int>.Zero, result2);
}
}

[Fact]
public static void TestShiftRightLogicalOvershift()
{
if (Sse2.IsSupported)
{
var result1 = Sse2.ShiftRightLogical(Vector128.Create(-1, +2, -3, +4), 32);
Assert.Equal(Vector128<int>.Zero, result1);

var result2 = Sse2.ShiftRightLogical(Vector128.Create(-5, +6, -7, +8), Vector128.Create(0, 32, 0, 0));
Assert.Equal(Vector128<int>.Zero, result2);
}
}

[Fact]
public static void TestShiftRightArithmeticOvershift()
{
if (Sse2.IsSupported)
{
var result1 = Sse2.ShiftRightArithmetic(Vector128.Create(-1, +2, -3, +4), 32);
Assert.Equal(Vector128.Create(-1, 0, -1, 0), result1);

var result2 = Sse2.ShiftRightArithmetic(Vector128.Create(-5, +6, -7, +8), Vector128.Create(0, 32, 0, 0));
Assert.Equal(Vector128.Create(-1, 0, -1, 0), result2);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Optimize>True</Optimize>
</PropertyGroup>
<ItemGroup>
<Compile Include="$(MSBuildProjectName).cs" />
</ItemGroup>
</Project>