Skip to content

Commit 7e9cc55

Browse files
committed
Ensure that we can constant fold op_Equality and op_Inequality for SIMD
1 parent 31733b9 commit 7e9cc55

File tree

2 files changed

+296
-0
lines changed

2 files changed

+296
-0
lines changed

src/coreclr/jit/gentree.cpp

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31012,6 +31012,32 @@ GenTree* Compiler::gtFoldExprHWIntrinsic(GenTreeHWIntrinsic* tree)
3101231012
}
3101331013
#endif
3101431014

31015+
case NI_Vector128_op_Equality:
31016+
#if defined(TARGET_ARM64)
31017+
case NI_Vector64_op_Equality:
31018+
#elif defined(TARGET_XARCH)
31019+
case NI_Vector256_op_Equality:
31020+
case NI_Vector512_op_Equality:
31021+
#endif // !TARGET_ARM64 && !TARGET_XARCH
31022+
{
31023+
cnsNode->AsVecCon()->EvaluateBinaryInPlace(GT_EQ, isScalar, simdBaseType, otherNode->AsVecCon());
31024+
resultNode = gtNewIconNode(cnsNode->AsVecCon()->IsAllBitsSet() ? 1 : 0, retType);
31025+
break;
31026+
}
31027+
31028+
case NI_Vector128_op_Inequality:
31029+
#if defined(TARGET_ARM64)
31030+
case NI_Vector64_op_Inequality:
31031+
#elif defined(TARGET_XARCH)
31032+
case NI_Vector256_op_Inequality:
31033+
case NI_Vector512_op_Inequality:
31034+
#endif // !TARGET_ARM64 && !TARGET_XARCH
31035+
{
31036+
cnsNode->AsVecCon()->EvaluateBinaryInPlace(GT_NE, isScalar, simdBaseType, otherNode->AsVecCon());
31037+
resultNode = gtNewIconNode(cnsNode->AsVecCon()->IsZero() ? 0 : 1, retType);
31038+
break;
31039+
}
31040+
3101531041
default:
3101631042
{
3101731043
break;
@@ -31452,6 +31478,48 @@ GenTree* Compiler::gtFoldExprHWIntrinsic(GenTreeHWIntrinsic* tree)
3145231478
}
3145331479
#endif
3145431480

31481+
case NI_Vector128_op_Equality:
31482+
#if defined(TARGET_ARM64)
31483+
case NI_Vector64_op_Equality:
31484+
#elif defined(TARGET_XARCH)
31485+
case NI_Vector256_op_Equality:
31486+
case NI_Vector512_op_Equality:
31487+
#endif // !TARGET_ARM64 && !TARGET_XARCH
31488+
{
31489+
if (varTypeIsFloating(simdBaseType))
31490+
{
31491+
// Handle `(x == NaN) == false` and `(NaN == x) == false` for floating-point types
31492+
if (cnsNode->IsVectorNaN(simdBaseType))
31493+
{
31494+
resultNode = gtNewIconNode(0, retType);
31495+
resultNode = gtWrapWithSideEffects(resultNode, otherNode, GTF_ALL_EFFECT);
31496+
break;
31497+
}
31498+
}
31499+
break;
31500+
}
31501+
31502+
case NI_Vector128_op_Inequality:
31503+
#if defined(TARGET_ARM64)
31504+
case NI_Vector64_op_Inequality:
31505+
#elif defined(TARGET_XARCH)
31506+
case NI_Vector256_op_Inequality:
31507+
case NI_Vector512_op_Inequality:
31508+
#endif // !TARGET_ARM64 && !TARGET_XARCH
31509+
{
31510+
if (varTypeIsFloating(simdBaseType))
31511+
{
31512+
// Handle `(x != NaN) == true` and `(NaN != x) == true` for floating-point types
31513+
if (cnsNode->IsVectorNaN(simdBaseType))
31514+
{
31515+
resultNode = gtNewIconNode(1, retType);
31516+
resultNode = gtWrapWithSideEffects(resultNode, otherNode, GTF_ALL_EFFECT);
31517+
break;
31518+
}
31519+
}
31520+
break;
31521+
}
31522+
3145531523
default:
3145631524
{
3145731525
break;

src/coreclr/jit/valuenum.cpp

Lines changed: 228 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8263,6 +8263,111 @@ ValueNum ValueNumStore::EvalHWIntrinsicFunBinary(GenTreeHWIntrinsic* tree,
82638263
break;
82648264
}
82658265

8266+
case GT_EQ:
8267+
{
8268+
if (varTypeIsFloating(baseType))
8269+
{
8270+
// Handle `(x == NaN) == false` and `(NaN == x) == false` for floating-point types
8271+
if (VNIsVectorNaN(type, baseType, cnsVN))
8272+
{
8273+
return VNZeroForType(type);
8274+
}
8275+
}
8276+
break;
8277+
}
8278+
8279+
case GT_GT:
8280+
{
8281+
ValueNum zeroVN = VNZeroForType(type);
8282+
8283+
if (varTypeIsUnsigned(baseType))
8284+
{
8285+
// Handle `(0 > x) == false` for unsigned types.
8286+
if ((cnsVN == arg0VN) && (cnsVN == zeroVN))
8287+
{
8288+
return zeroVN;
8289+
}
8290+
}
8291+
else if (varTypeIsFloating(baseType))
8292+
{
8293+
// Handle `(x > NaN) == false` and `(NaN > x) == false` for floating-point types
8294+
if (VNIsVectorNaN(type, baseType, cnsVN))
8295+
{
8296+
return zeroVN;
8297+
}
8298+
}
8299+
break;
8300+
}
8301+
8302+
case GT_GE:
8303+
{
8304+
ValueNum zeroVN = VNZeroForType(type);
8305+
8306+
if (varTypeIsUnsigned(baseType))
8307+
{
8308+
// Handle `x >= 0 == true` for unsigned types.
8309+
if ((cnsVN == arg1VN) && (cnsVN == zeroVN))
8310+
{
8311+
return VNAllBitsForType(type);
8312+
}
8313+
}
8314+
else if (varTypeIsFloating(baseType))
8315+
{
8316+
// Handle `(x >= NaN) == false` and `(NaN >= x) == false` for floating-point types
8317+
if (VNIsVectorNaN(type, baseType, cnsVN))
8318+
{
8319+
return zeroVN;
8320+
}
8321+
}
8322+
break;
8323+
}
8324+
8325+
case GT_LT:
8326+
{
8327+
ValueNum zeroVN = VNZeroForType(type);
8328+
8329+
if (varTypeIsUnsigned(baseType))
8330+
{
8331+
// Handle `x < 0 == false` for unsigned types.
8332+
if ((cnsVN == arg1VN) && (cnsVN == zeroVN))
8333+
{
8334+
return zeroVN;
8335+
}
8336+
}
8337+
else if (varTypeIsFloating(baseType))
8338+
{
8339+
// Handle `(x < NaN) == false` and `(NaN < x) == false` for floating-point types
8340+
if (VNIsVectorNaN(type, baseType, cnsVN))
8341+
{
8342+
return zeroVN;
8343+
}
8344+
}
8345+
break;
8346+
}
8347+
8348+
case GT_LE:
8349+
{
8350+
ValueNum zeroVN = VNZeroForType(type);
8351+
8352+
if (varTypeIsUnsigned(baseType))
8353+
{
8354+
// Handle `0 <= x == true` for unsigned types.
8355+
if ((cnsVN == arg0VN) && (cnsVN == zeroVN))
8356+
{
8357+
return VNAllBitsForType(type);
8358+
}
8359+
}
8360+
else if (varTypeIsFloating(baseType))
8361+
{
8362+
// Handle `(x <= NaN) == false` and `(NaN <= x) == false` for floating-point types
8363+
if (VNIsVectorNaN(type, baseType, cnsVN))
8364+
{
8365+
return zeroVN;
8366+
}
8367+
}
8368+
break;
8369+
}
8370+
82668371
case GT_MUL:
82678372
{
82688373
if (!varTypeIsFloating(baseType))
@@ -8310,6 +8415,19 @@ ValueNum ValueNumStore::EvalHWIntrinsicFunBinary(GenTreeHWIntrinsic* tree,
83108415
break;
83118416
}
83128417

8418+
case GT_NE:
8419+
{
8420+
if (varTypeIsFloating(baseType))
8421+
{
8422+
// Handle `(x != NaN) == true` and `(NaN != x) == true` for floating-point types
8423+
if (VNIsVectorNaN(type, baseType, cnsVN))
8424+
{
8425+
return VNAllBitsForType(type);
8426+
}
8427+
}
8428+
break;
8429+
}
8430+
83138431
case GT_OR:
83148432
{
83158433
// Handle `x | 0 == x` and `0 | x == x`
@@ -8477,6 +8595,48 @@ ValueNum ValueNumStore::EvalHWIntrinsicFunBinary(GenTreeHWIntrinsic* tree,
84778595
}
84788596
#endif
84798597

8598+
case NI_Vector128_op_Equality:
8599+
#if defined(TARGET_ARM64)
8600+
case NI_Vector64_op_Equality:
8601+
#elif defined(TARGET_XARCH)
8602+
case NI_Vector256_op_Equality:
8603+
case NI_Vector512_op_Equality:
8604+
#endif // !TARGET_ARM64 && !TARGET_XARCH
8605+
{
8606+
if (varTypeIsFloating(baseType))
8607+
{
8608+
// Handle `(x == NaN) == false` and `(NaN == x) == false` for floating-point types
8609+
var_types simdType = Compiler::getSIMDTypeForSize(simdSize);
8610+
8611+
if (VNIsVectorNaN(simdType, baseType, cnsVN))
8612+
{
8613+
return VNZeroForType(type);
8614+
}
8615+
}
8616+
break;
8617+
}
8618+
8619+
case NI_Vector128_op_Inequality:
8620+
#if defined(TARGET_ARM64)
8621+
case NI_Vector64_op_Inequality:
8622+
#elif defined(TARGET_XARCH)
8623+
case NI_Vector256_op_Inequality:
8624+
case NI_Vector512_op_Inequality:
8625+
#endif // !TARGET_ARM64 && !TARGET_XARCH
8626+
{
8627+
if (varTypeIsFloating(baseType))
8628+
{
8629+
// Handle `(x != NaN) == true` and `(NaN != x) == true` for floating-point types
8630+
var_types simdType = Compiler::getSIMDTypeForSize(simdSize);
8631+
8632+
if (VNIsVectorNaN(simdType, baseType, cnsVN))
8633+
{
8634+
return VNOneForType(type);
8635+
}
8636+
}
8637+
break;
8638+
}
8639+
84808640
default:
84818641
{
84828642
break;
@@ -8505,6 +8665,32 @@ ValueNum ValueNumStore::EvalHWIntrinsicFunBinary(GenTreeHWIntrinsic* tree,
85058665
return arg0VN;
85068666
}
85078667

8668+
case GT_EQ:
8669+
case GT_GE:
8670+
case GT_LE:
8671+
{
8672+
// We can't handle floating-point due to NaN
8673+
8674+
if (varTypeIsIntegral(baseType))
8675+
{
8676+
return VNAllBitsForType(type);
8677+
}
8678+
break;
8679+
}
8680+
8681+
case GT_GT:
8682+
case GT_LT:
8683+
case GT_NE:
8684+
{
8685+
// We can't handle floating-point due to NaN
8686+
8687+
if (varTypeIsIntegral(baseType))
8688+
{
8689+
return VNZeroForType(type);
8690+
}
8691+
break;
8692+
}
8693+
85088694
case GT_OR:
85098695
{
85108696
// Handle `x | x == x`
@@ -8532,6 +8718,48 @@ ValueNum ValueNumStore::EvalHWIntrinsicFunBinary(GenTreeHWIntrinsic* tree,
85328718
default:
85338719
break;
85348720
}
8721+
8722+
switch (ni)
8723+
{
8724+
case NI_Vector128_op_Equality:
8725+
#if defined(TARGET_ARM64)
8726+
case NI_Vector64_op_Equality:
8727+
#elif defined(TARGET_XARCH)
8728+
case NI_Vector256_op_Equality:
8729+
case NI_Vector512_op_Equality:
8730+
#endif // !TARGET_ARM64 && !TARGET_XARCH
8731+
{
8732+
// We can't handle floating-point due to NaN
8733+
8734+
if (varTypeIsIntegral(baseType))
8735+
{
8736+
return VNOneForType(type);
8737+
}
8738+
break;
8739+
}
8740+
8741+
case NI_Vector128_op_Inequality:
8742+
#if defined(TARGET_ARM64)
8743+
case NI_Vector64_op_Inequality:
8744+
#elif defined(TARGET_XARCH)
8745+
case NI_Vector256_op_Inequality:
8746+
case NI_Vector512_op_Inequality:
8747+
#endif // !TARGET_ARM64 && !TARGET_XARCH
8748+
{
8749+
// We can't handle floating-point due to NaN
8750+
8751+
if (varTypeIsIntegral(baseType))
8752+
{
8753+
return VNZeroForType(type);
8754+
}
8755+
break;
8756+
}
8757+
8758+
default:
8759+
{
8760+
break;
8761+
}
8762+
}
85358763
}
85368764

85378765
if (encodeResultType)

0 commit comments

Comments
 (0)