Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
07e72ed
Update Vector<T> to implement ISimdVector<TSelf, T>
tannergooding Jun 20, 2024
383cc66
Expose various constants for Vector2/3/4
tannergooding Jun 19, 2024
845978c
Expose Exp, Log, and Log2 on the other vector types
tannergooding Jun 19, 2024
10ed01f
Expose CopySign on the vector types
tannergooding Jun 19, 2024
a450767
Expose DegreesToRadians and RadiansToDegrees on the vector types
tannergooding Jun 20, 2024
87e13a0
Expose Hypot on the vector types
tannergooding Jun 20, 2024
5bad72d
Expose Lerp on the vector types
tannergooding Jun 20, 2024
34879f6
Expose Truncate and Round on the vector types
tannergooding Jun 20, 2024
3e304c2
Cleanup some of the implementations to use helper functions where pos…
tannergooding Jun 21, 2024
43d4696
Expose Max, MaxMagnitude, MaxMagnitudeNumber, MaxNumber, Min, MinMagn…
tannergooding Jun 21, 2024
283301d
Expose Clamp on the various vector types
tannergooding Jun 19, 2024
b513e5c
Ensure mono handles the various zero and low-cost vector conversions
tannergooding Jun 21, 2024
0816d54
Apply formatting patch
tannergooding Jun 21, 2024
8e211ce
Ensure that TensorPrimitives uses the in-box vector operations on .NE…
tannergooding Jun 21, 2024
16e27d8
Fix some build failures
tannergooding Jun 21, 2024
753df42
Workaround a MonoJIT assertion
tannergooding Jun 22, 2024
574c15c
Ensure Hypot for double handles insignificant results
tannergooding Jun 22, 2024
d7bf16b
Merge remote-tracking branch 'dotnet/main' into fix-93513
tannergooding Jun 24, 2024
284ad12
Merge remote-tracking branch 'dotnet/main' into fix-93513
tannergooding Jun 27, 2024
79b225a
Remove part of the mono changes that were extracted to a separate PR
tannergooding Jun 27, 2024
50434a6
Apply suggestions from code review
tannergooding Jun 29, 2024
f1bf9b9
Merge remote-tracking branch 'dotnet/main' into fix-93513
tannergooding Jun 29, 2024
3f9bd35
Ensure tests are added for the new vector APIs
tannergooding Jun 29, 2024
dcffeb8
Fix the mono handling for IsNaN, IsNegative, and IsPositive
tannergooding Jun 29, 2024
6804456
Use the right op for WASM
tannergooding Jun 29, 2024
72d2dd6
Fix a round test to correctly expect -0
tannergooding Jun 29, 2024
aaa71b2
Fix some tests where the wrong parameter counts were being passed
tannergooding Jun 30, 2024
304324d
Ensure APIs are correctly handled for Vector<T>
tannergooding Jun 30, 2024
c722402
Fix the mono handling for OP_XCOMPARE_FP
tannergooding Jun 30, 2024
f5f7a31
Have Mono use the proper klass for IsPositive/IsNegative since we're …
tannergooding Jun 30, 2024
b34be17
Ensure Mono looks up the class namespace
tannergooding Jun 30, 2024
10b1513
Ensure mono inserts xcast where required and handles MultiplyAddEstimate
tannergooding Jul 1, 2024
bf3bc42
Add missing underscores to fix the mono build
tannergooding Jul 1, 2024
f114721
Add the if is_element_type_primitive check to MultiplyAddEstimate for…
tannergooding Jul 1, 2024
cbafcb5
Pass the right klass on Mono
tannergooding Jul 1, 2024
6ea941c
Ensure mono sets the metadata for add_ins
tannergooding Jul 1, 2024
5728b80
Ensure mono passes down the cast arg0
tannergooding Jul 1, 2024
a47ea2a
Fix the lerp for Mono to match the managed impl
tannergooding Jul 2, 2024
414b00a
Ensure mono lerp uses ins_amount for scaling y
tannergooding Jul 2, 2024
ea072a7
Merge branch 'main' into fix-93513
tannergooding Jul 3, 2024
3c3ef36
Use gtCloneExpr after the first fgMakeMultiUse if we need another copy
tannergooding Jul 4, 2024
a180caf
Merge branch 'main' into fix-93513
tannergooding Jul 7, 2024
4eabf81
Combine the SN_IsNegative and SN_IsPositive logic
tannergooding Jul 8, 2024
73fda9a
Update src/mono/mono/mini/simd-intrinsics.c
tannergooding Jul 9, 2024
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
Prev Previous commit
Next Next commit
Expose various constants for Vector2/3/4
  • Loading branch information
tannergooding committed Jun 21, 2024
commit 383cc66c317d869585e359c8db2f0eb74cf63260
25 changes: 25 additions & 0 deletions src/coreclr/jit/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -3289,6 +3289,31 @@ class Compiler
CorInfoType simdBaseJitType,
unsigned simdSize);

GenTree* gtNewSimdIsNaNNode(var_types type,
GenTree* op1,
CorInfoType simdBaseJitType,
unsigned simdSize);

GenTree* gtNewSimdIsNegativeNode(var_types type,
GenTree* op1,
CorInfoType simdBaseJitType,
unsigned simdSize);

GenTree* gtNewSimdIsPositiveNode(var_types type,
GenTree* op1,
CorInfoType simdBaseJitType,
unsigned simdSize);

GenTree* gtNewSimdIsPositiveInfinityNode(var_types type,
GenTree* op1,
CorInfoType simdBaseJitType,
unsigned simdSize);

GenTree* gtNewSimdIsZeroNode(var_types type,
GenTree* op1,
CorInfoType simdBaseJitType,
unsigned simdSize);

GenTree* gtNewSimdLoadNode(
var_types type, GenTree* op1, CorInfoType simdBaseJitType, unsigned simdSize);

Expand Down
247 changes: 238 additions & 9 deletions src/coreclr/jit/gentree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20856,13 +20856,11 @@ GenTree* Compiler::gtNewSimdAbsNode(var_types type, GenTree* op1, CorInfoType si
GenTree* op1Dup1 = fgMakeMultiUse(&op1);
GenTree* op1Dup2 = fgMakeMultiUse(&op1Dup1);

// op1 = op1 < Zero
tmp = gtNewZeroConNode(type);
op1 = gtNewSimdCmpOpNode(GT_LT, type, op1, tmp, simdBaseJitType, simdSize);
// op1 = IsNegative(op1)
op1 = gtNewSimdIsPositiveInfinityNode(type, op1, simdBaseJitType, simdSize);

// tmp = Zero - op1Dup1
tmp = gtNewZeroConNode(type);
tmp = gtNewSimdBinOpNode(GT_SUB, type, tmp, op1Dup1, simdBaseJitType, simdSize);
// tmp = -op1Dup1
tmp = gtNewSimdUnOpNode(GT_NEG, type, op1Dup1, simdBaseJitType, simdSize);

// result = ConditionalSelect(op1, tmp, op1Dup2)
return gtNewSimdCndSelNode(type, op1, tmp, op1Dup2, simdBaseJitType, simdSize);
Expand Down Expand Up @@ -22222,9 +22220,8 @@ GenTree* Compiler::gtNewSimdCvtNode(var_types type,
// mask1 contains the output either 0xFFFFFFFF or 0.
// FixupVal zeros out any NaN values in the input by ANDing input with mask1.
GenTree* op1Clone1 = fgMakeMultiUse(&op1);
GenTree* op1Clone2 = fgMakeMultiUse(&op1);
GenTree* mask1 = gtNewSimdCmpOpNode(GT_EQ, type, op1, op1Clone1, simdSourceBaseJitType, simdSize);
fixupVal = gtNewSimdBinOpNode(GT_AND, type, op1Clone2, mask1, simdSourceBaseJitType, simdSize);
GenTree* mask1 = gtNewSimdIsNaNNode(type, op1, simdSourceBaseJitType, simdSize);
fixupVal = gtNewSimdBinOpNode(GT_AND_NOT, type, op1Clone1, mask1, simdSourceBaseJitType, simdSize);
}

if (varTypeIsSigned(simdTargetBaseType))
Expand Down Expand Up @@ -23138,6 +23135,39 @@ GenTree* Compiler::gtNewSimdCmpOpNode(
}
break;
}

case GT_NE:
{
if (!varTypeIsFloating(simdBaseType) && (simdSize != 64))
{
GenTree* result = gtNewSimdCmpOpNode(GT_EQ, type, op1, op2, simdBaseJitType, simdSize);
return gtNewSimdUnOpNode(GT_NEG, type, result, simdBaseJitType, simdSize);
}

if (simdSize == 64)
{
assert(canUseEvexEncodingDebugOnly());
intrinsic = NI_EVEX_CompareNotEqualMask;
needsConvertMaskToVector = true;
}
else if (simdSize == 32)
{
assert(compIsaSupportedDebugOnly(InstructionSet_AVX));
intrinsic = NI_AVX_CompareNotEqual;
}
else if (simdBaseType == TYP_FLOAT)
{
assert((simdSize == 8) || (simdSize == 12) || (simdSize == 16));
intrinsic = NI_SSE_CompareNotEqual;
}
else
{
assert(simdSize == 16);
assert(simdBaseType == TYP_DOUBLE);
intrinsic = NI_SSE2_CompareNotEqual;
}
break;
}
#elif defined(TARGET_ARM64)
case GT_EQ:
{
Expand Down Expand Up @@ -23206,6 +23236,12 @@ GenTree* Compiler::gtNewSimdCmpOpNode(
}
break;
}

case GT_NE:
{
GenTree* result = gtNewSimdCmpOpNode(GT_EQ, type, op1, op2, simdBaseJitType, simdSize);
return gtNewSimdUnOpNode(GT_NEG, type, result, simdBaseJitType, simdSize);
}
#else
#error Unsupported platform
#endif // !TARGET_XARCH && !TARGET_ARM64
Expand Down Expand Up @@ -24523,6 +24559,199 @@ GenTree* Compiler::gtNewSimdGetUpperNode(var_types type, GenTree* op1, CorInfoTy
return gtNewSimdHWIntrinsicNode(type, op1, intrinsicId, simdBaseJitType, simdSize);
}

//----------------------------------------------------------------------------------------------
// Compiler::gtNewSimdIsNaNNode: Creates a new simd IsNaN node
//
// Arguments:
// type - The return type of SIMD node being created
// op1 - The vector to check for NaNs
// simdBaseJitType - The base JIT type of SIMD type of the intrinsic
// simdSize - The size of the SIMD type of the intrinsic
//
// Returns:
// The created IsNaN node
//
GenTree* Compiler::gtNewSimdIsNaNNode(var_types type,
GenTree* op1,
CorInfoType simdBaseJitType,
unsigned simdSize)
{
assert(IsBaselineSimdIsaSupportedDebugOnly());

assert(varTypeIsSIMD(type));
assert(getSIMDTypeForSize(simdSize) == type);

assert(op1 != nullptr);
assert(op1->TypeIs(type));

var_types simdBaseType = JitType2PreciseVarType(simdBaseJitType);
assert(varTypeIsArithmetic(simdBaseType));

if (varTypeIsFloating(simdBaseType))
{
GenTree* op1Dup = fgMakeMultiUse(&op1);
return gtNewSimdCmpOpNode(GT_NE, type, op1, op1Dup, simdBaseJitType, simdSize);
}
return gtNewZeroConNode(type);
}

//----------------------------------------------------------------------------------------------
// Compiler::gtNewSimdIsNegativeNode: Creates a new simd IsNegative node
//
// Arguments:
// type - The return type of SIMD node being created
// op1 - The vector to check for Negatives
// simdBaseJitType - The base JIT type of SIMD type of the intrinsic
// simdSize - The size of the SIMD type of the intrinsic
//
// Returns:
// The created IsNegative node
//
GenTree* Compiler::gtNewSimdIsNegativeNode(var_types type,
GenTree* op1,
CorInfoType simdBaseJitType,
unsigned simdSize)
{
assert(IsBaselineSimdIsaSupportedDebugOnly());

assert(varTypeIsSIMD(type));
assert(getSIMDTypeForSize(simdSize) == type);

assert(op1 != nullptr);
assert(op1->TypeIs(type));

if (simdBaseJitType == CORINFO_TYPE_FLOAT)
{
simdBaseJitType = CORINFO_TYPE_INT;
}
else if (simdBaseJitType == CORINFO_TYPE_DOUBLE)
{
simdBaseJitType = CORINFO_TYPE_LONG;
}

var_types simdBaseType = JitType2PreciseVarType(simdBaseJitType);
assert(varTypeIsIntegral(simdBaseType));

if (varTypeIsUnsigned(simdBaseType))
{
return gtNewZeroConNode(type);
}
return gtNewSimdCmpOpNode(GT_LT, type, op1, gtNewZeroConNode(type), simdBaseJitType, simdSize);
}

//----------------------------------------------------------------------------------------------
// Compiler::gtNewSimdIsPositiveNode: Creates a new simd IsPositive node
//
// Arguments:
// type - The return type of SIMD node being created
// op1 - The vector to check for Positives
// simdBaseJitType - The base JIT type of SIMD type of the intrinsic
// simdSize - The size of the SIMD type of the intrinsic
//
// Returns:
// The created IsPositive node
//
GenTree* Compiler::gtNewSimdIsPositiveNode(var_types type,
GenTree* op1,
CorInfoType simdBaseJitType,
unsigned simdSize)
{
assert(IsBaselineSimdIsaSupportedDebugOnly());

assert(varTypeIsSIMD(type));
assert(getSIMDTypeForSize(simdSize) == type);

assert(op1 != nullptr);
assert(op1->TypeIs(type));

if (simdBaseJitType == CORINFO_TYPE_FLOAT)
{
simdBaseJitType = CORINFO_TYPE_INT;
}
else if (simdBaseJitType == CORINFO_TYPE_DOUBLE)
{
simdBaseJitType = CORINFO_TYPE_LONG;
}

var_types simdBaseType = JitType2PreciseVarType(simdBaseJitType);
assert(varTypeIsIntegral(simdBaseType));

if (varTypeIsUnsigned(simdBaseType))
{
return gtNewAllBitsSetConNode(type);
}
return gtNewSimdCmpOpNode(GT_GE, type, op1, gtNewZeroConNode(type), simdBaseJitType, simdSize);
}

//----------------------------------------------------------------------------------------------
// Compiler::gtNewSimdIsPositiveInfinityNode: Creates a new simd IsPositiveInfinity node
//
// Arguments:
// type - The return type of SIMD node being created
// op1 - The vector to check for PositiveInfinities
// simdBaseJitType - The base JIT type of SIMD type of the intrinsic
// simdSize - The size of the SIMD type of the intrinsic
//
// Returns:
// The created IsPositiveInfinity node
//
GenTree* Compiler::gtNewSimdIsPositiveInfinityNode(var_types type,
GenTree* op1,
CorInfoType simdBaseJitType,
unsigned simdSize)
{
assert(IsBaselineSimdIsaSupportedDebugOnly());

assert(varTypeIsSIMD(type));
assert(getSIMDTypeForSize(simdSize) == type);

assert(op1 != nullptr);
assert(op1->TypeIs(type));

var_types simdBaseType = JitType2PreciseVarType(simdBaseJitType);
assert(varTypeIsArithmetic(simdBaseType));

if (varTypeIsFloating(simdBaseType))
{
double infinity = FloatingPointUtils::convertUInt64ToDouble(0x7FF0000000000000);
GenTree* cnsNode = gtNewDconNode(infinity, simdBaseType);
cnsNode = gtNewSimdCreateBroadcastNode(type, cnsNode, simdBaseJitType, simdSize);
return gtNewSimdCmpOpNode(GT_EQ, type, op1, cnsNode, simdBaseJitType, simdSize);
}
return gtNewZeroConNode(type);
}

//----------------------------------------------------------------------------------------------
// Compiler::gtNewSimdIsPositiveInfinityNode: Creates a new simd IsZero node
//
// Arguments:
// type - The return type of SIMD node being created
// op1 - The vector to check for Zeroes
// simdBaseJitType - The base JIT type of SIMD type of the intrinsic
// simdSize - The size of the SIMD type of the intrinsic
//
// Returns:
// The created IsZero node
//
GenTree* Compiler::gtNewSimdIsZeroNode(var_types type,
GenTree* op1,
CorInfoType simdBaseJitType,
unsigned simdSize)
{
assert(IsBaselineSimdIsaSupportedDebugOnly());

assert(varTypeIsSIMD(type));
assert(getSIMDTypeForSize(simdSize) == type);

assert(op1 != nullptr);
assert(op1->TypeIs(type));

var_types simdBaseType = JitType2PreciseVarType(simdBaseJitType);
assert(varTypeIsArithmetic(simdBaseType));

return gtNewSimdCmpOpNode(GT_EQ, type, op1, gtNewZeroConNode(type), simdBaseJitType, simdSize);
}

//----------------------------------------------------------------------------------------------
// Compiler::gtNewSimdLoadNode: Creates a new simd Load node
//
Expand Down
55 changes: 55 additions & 0 deletions src/coreclr/jit/hwintrinsicarm64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1523,6 +1523,61 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic,
break;
}

case NI_Vector64_IsNaN:
case NI_Vector128_IsNaN:
{
assert(sig->numArgs == 1);
var_types simdType = getSIMDTypeForSize(simdSize);

op1 = impSIMDPopStack();
retNode = gtNewSimdIsNaNNode(retType, op1, simdBaseJitType, simdSize);
break;
}

case NI_Vector64_IsNegative:
case NI_Vector128_IsNegative:
{
assert(sig->numArgs == 1);
var_types simdType = getSIMDTypeForSize(simdSize);

op1 = impSIMDPopStack();
retNode = gtNewSimdIsNegativeNode(retType, op1, simdBaseJitType, simdSize);
break;
}

case NI_Vector64_IsPositive:
case NI_Vector128_IsPositive:
{
assert(sig->numArgs == 1);
var_types simdType = getSIMDTypeForSize(simdSize);

op1 = impSIMDPopStack();
retNode = gtNewSimdIsPositiveNode(retType, op1, simdBaseJitType, simdSize);
break;
}

case NI_Vector64_IsPositiveInfinity:
case NI_Vector128_IsPositiveInfinity:
{
assert(sig->numArgs == 1);
var_types simdType = getSIMDTypeForSize(simdSize);

op1 = impSIMDPopStack();
retNode = gtNewSimdIsPositiveInfinityNode(retType, op1, simdBaseJitType, simdSize);
break;
}

case NI_Vector64_IsZero:
case NI_Vector128_IsZero:
{
assert(sig->numArgs == 1);
var_types simdType = getSIMDTypeForSize(simdSize);

op1 = impSIMDPopStack();
retNode = gtNewSimdIsZeroNode(retType, op1, simdBaseJitType, simdSize);
break;
}

case NI_Vector64_LessThan:
case NI_Vector128_LessThan:
{
Expand Down
Loading