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
34 changes: 26 additions & 8 deletions src/coreclr/jit/valuenum.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2518,9 +2518,17 @@ ValueNum ValueNumStore::VNOneForSimdType(var_types simdType, var_types simdBaseT
return VNBroadcastForSimdType(simdType, simdBaseType, oneVN);
}

ValueNum ValueNumStore::VNForSimdType(unsigned simdSize, var_types simdBaseType)
ValueNum ValueNumStore::VNForSimdType(unsigned simdSize, var_types simdBaseType, var_types auxiliaryType)
{
ValueNum baseTypeVN = VNForIntCon(INT32(simdBaseType));
// Both types fit in a byte. Reserve zero in the upper byte for no auxiliary type,
// preserving the base-type constant for the common case.
unsigned encodedTypes = static_cast<unsigned>(simdBaseType);
if (auxiliaryType != TYP_UNKNOWN)
{
encodedTypes |= (static_cast<unsigned>(auxiliaryType) + 1) << SimdTypeBits;
}

ValueNum baseTypeVN = VNForIntCon(encodedTypes);
ValueNum sizeVN = VNForIntCon(simdSize);
ValueNum simdTypeVN = VNForFunc(TYP_REF, VNF_SimdType, sizeVN, baseTypeVN);

Expand Down Expand Up @@ -10932,7 +10940,7 @@ uint32_t ValueNumStore::GetVNHWIntrinsicSizeAndBaseType(const VNFuncApp& funcApp
assert(IsVNConstant(simdType.GetArg(0)));
assert(IsVNConstant(simdType.GetArg(1)));

*simdBaseType = static_cast<var_types>(GetConstantInt32(simdType.GetArg(1)));
*simdBaseType = static_cast<var_types>(GetConstantInt32(simdType.GetArg(1)) & SimdTypeMask);
Comment thread
tannergooding marked this conversation as resolved.
Comment thread
tannergooding marked this conversation as resolved.
return static_cast<uint32_t>(GetConstantInt32(simdType.GetArg(0)));
}
#endif // FEATURE_HW_INTRINSICS
Expand Down Expand Up @@ -11422,11 +11430,19 @@ void ValueNumStore::vnDumpSimdType(Compiler* comp, VNFuncApp* simdType)
assert(IsVNConstant(simdType->GetArg(0)));
assert(IsVNConstant(simdType->GetArg(1)));

int simdSize = ConstantValue<int>(simdType->GetArg(0));
var_types simdBaseType = static_cast<var_types>(ConstantValue<int>(simdType->GetArg(1)));
int simdSize = ConstantValue<int>(simdType->GetArg(0));
unsigned encodedTypes = ConstantValue<unsigned>(simdType->GetArg(1));
var_types simdBaseType = static_cast<var_types>(encodedTypes & SimdTypeMask);
unsigned auxiliaryType = encodedTypes >> SimdTypeBits;

printf("%s(simd%d, %s)", VNFuncName(simdType->GetFunc()), simdSize,
printf("%s(simd%d, %s", VNFuncName(simdType->GetFunc()), simdSize,
(simdBaseType == TYP_UNDEF) ? varTypeName(TYP_UNDEF) : varTypeName(simdBaseType));

if (auxiliaryType != 0)
{
printf(", aux %s", varTypeName(static_cast<var_types>(auxiliaryType - 1)));
}
printf(")");
}
#endif // FEATURE_SIMD

Expand Down Expand Up @@ -14188,8 +14204,10 @@ void Compiler::fgValueNumberHWIntrinsic(GenTreeHWIntrinsic* tree)
}
else
{
VNFunc func = GetVNFuncForNode(tree);
ValueNum simdTypeVN = vnStore->VNForSimdType(tree->GetSimdSize(), tree->GetSimdBaseType());
// The auxiliary type distinguishes overloads with the same operand bits, such as gather index widths.
VNFunc func = GetVNFuncForNode(tree);
ValueNum simdTypeVN =
vnStore->VNForSimdType(tree->GetSimdSize(), tree->GetSimdBaseType(), tree->GetAuxiliaryType());
ValueNumPair resultTypeVNPair(simdTypeVN, simdTypeVN);

JITDUMP(" simdTypeVN is ");
Expand Down
8 changes: 7 additions & 1 deletion src/coreclr/jit/valuenum.h
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,12 @@ class ValueNumStore
VCA_ReservedBits = 0x01, // i.e. (VCA_UnsignedSrc)
};

#ifdef FEATURE_SIMD
static constexpr unsigned SimdTypeBits = 8;
static constexpr unsigned SimdTypeMask = (1 << SimdTypeBits) - 1;
static_assert(TYP_COUNT <= SimdTypeMask);
#endif
Comment thread
tannergooding marked this conversation as resolved.

// Helpers and an array of length GT_COUNT, mapping genTreeOp values to their VNFOpAttrib.
static constexpr uint8_t GetOpAttribsForArity(genTreeOps oper, GenTreeOperKind kind);
static constexpr uint8_t GetOpAttribsForGenTree(genTreeOps oper,
Expand Down Expand Up @@ -792,7 +798,7 @@ class ValueNumStore
ValueNum VNOneForSimdType(var_types simdType, var_types simdBaseType);

// A helper function for constructing VNF_SimdType VNs.
Comment thread
tannergooding marked this conversation as resolved.
ValueNum VNForSimdType(unsigned simdSize, var_types simdBaseType);
ValueNum VNForSimdType(unsigned simdSize, var_types simdBaseType, var_types auxiliaryType);

// Returns if a value number represents NaN in all elements
bool VNIsVectorNaN(var_types simdType, var_types simdBaseType, ValueNum valVN);
Expand Down
43 changes: 43 additions & 0 deletions src/tests/JIT/Regression_ro_2/Runtime_134486.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

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

public class Runtime_134486
{
[ConditionalFact(typeof(Avx2), nameof(Avx2.IsSupported))]
public static unsafe void TestGather()
{
int* data = stackalloc int[] { 10, 11, 12, 13 };
Assert.Equal(2, Gather(data, Vector128.Create(1, 0, 2, 0), Vector128.Create(11, 10, 12, 10)));
}

[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
private static unsafe int Gather(int* data, Vector128<int> indices, Vector128<int> expected)
{
Vector128<int> a = Avx2.GatherVector128(data, indices, 4);
Vector128<int> b = Avx2.GatherVector128(data, indices.AsInt64(), 4);

if (a == expected)
{
return b == expected ? 1 : 2;
}
return 3;
}

[ConditionalFact(typeof(AdvSimd.Arm64), nameof(AdvSimd.Arm64.IsSupported))]
public static void TestAddSaturateScalar()
{
Assert.True(DistinguishAddSaturateScalar(Vector64.CreateScalar(1), Vector64.CreateScalar(-1)));
}

[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
private static bool DistinguishAddSaturateScalar(Vector64<int> left, Vector64<int> right)
{
return AdvSimd.Arm64.AddSaturateScalar(left, right) != AdvSimd.Arm64.AddSaturateScalar(left, right.AsUInt32());
}
}
Loading