-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve the handling of SIMD comparisons #104944
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -31012,6 +31012,32 @@ GenTree* Compiler::gtFoldExprHWIntrinsic(GenTreeHWIntrinsic* tree) | |
} | ||
#endif | ||
|
||
case NI_Vector128_op_Equality: | ||
#if defined(TARGET_ARM64) | ||
case NI_Vector64_op_Equality: | ||
#elif defined(TARGET_XARCH) | ||
case NI_Vector256_op_Equality: | ||
case NI_Vector512_op_Equality: | ||
#endif // !TARGET_ARM64 && !TARGET_XARCH | ||
{ | ||
cnsNode->AsVecCon()->EvaluateBinaryInPlace(GT_EQ, isScalar, simdBaseType, otherNode->AsVecCon()); | ||
resultNode = gtNewIconNode(cnsNode->AsVecCon()->IsAllBitsSet() ? 1 : 0, retType); | ||
break; | ||
} | ||
|
||
case NI_Vector128_op_Inequality: | ||
#if defined(TARGET_ARM64) | ||
case NI_Vector64_op_Inequality: | ||
#elif defined(TARGET_XARCH) | ||
case NI_Vector256_op_Inequality: | ||
case NI_Vector512_op_Inequality: | ||
#endif // !TARGET_ARM64 && !TARGET_XARCH | ||
{ | ||
cnsNode->AsVecCon()->EvaluateBinaryInPlace(GT_NE, isScalar, simdBaseType, otherNode->AsVecCon()); | ||
resultNode = gtNewIconNode(cnsNode->AsVecCon()->IsZero() ? 0 : 1, retType); | ||
break; | ||
} | ||
|
||
default: | ||
{ | ||
break; | ||
|
@@ -31452,6 +31478,48 @@ GenTree* Compiler::gtFoldExprHWIntrinsic(GenTreeHWIntrinsic* tree) | |
} | ||
#endif | ||
|
||
case NI_Vector128_op_Equality: | ||
#if defined(TARGET_ARM64) | ||
case NI_Vector64_op_Equality: | ||
#elif defined(TARGET_XARCH) | ||
case NI_Vector256_op_Equality: | ||
case NI_Vector512_op_Equality: | ||
#endif // !TARGET_ARM64 && !TARGET_XARCH | ||
{ | ||
if (varTypeIsFloating(simdBaseType)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. how is this path different from There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, it's when only one of the operand is constant? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Right, it’s for when one is all nan, which is an optimization we can do for float/double |
||
{ | ||
// Handle `(x == NaN) == false` and `(NaN == x) == false` for floating-point types | ||
if (cnsNode->IsVectorNaN(simdBaseType)) | ||
{ | ||
resultNode = gtNewIconNode(0, retType); | ||
resultNode = gtWrapWithSideEffects(resultNode, otherNode, GTF_ALL_EFFECT); | ||
break; | ||
} | ||
} | ||
break; | ||
} | ||
|
||
case NI_Vector128_op_Inequality: | ||
#if defined(TARGET_ARM64) | ||
case NI_Vector64_op_Inequality: | ||
#elif defined(TARGET_XARCH) | ||
case NI_Vector256_op_Inequality: | ||
case NI_Vector512_op_Inequality: | ||
#endif // !TARGET_ARM64 && !TARGET_XARCH | ||
{ | ||
if (varTypeIsFloating(simdBaseType)) | ||
{ | ||
// Handle `(x != NaN) == true` and `(NaN != x) == true` for floating-point types | ||
if (cnsNode->IsVectorNaN(simdBaseType)) | ||
{ | ||
resultNode = gtNewIconNode(1, retType); | ||
resultNode = gtWrapWithSideEffects(resultNode, otherNode, GTF_ALL_EFFECT); | ||
break; | ||
} | ||
} | ||
break; | ||
} | ||
|
||
default: | ||
{ | ||
break; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is also
NI_VectorX_EqualsAll
(unless they're normalized toop_Equality
somewhere). Btw the last time I tried to constant fold these, you told me that is odd to cover only EQ/NE relation operators ;-) #85584 (comment)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We’ve already added support for all the other comparisons (elementwise eq/ge/gt/le/lt/ne), what was remaining was the ==/!= operators, which this pr covers.
EqualsAll/Any and the other All/Any APIs are then imported as elementwise compare + op ==/!=, so this covers the full set