Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
7835f72
Arm64 SVE: Fix conditionalselect with constant arguments
a74nh Jun 18, 2025
18340c8
Make masked EvaluateBinaryInPlace() Arm64 only
a74nh Jun 23, 2025
0d60a5e
Check significantBit in EvaluateSimdVectorToPattern()
a74nh Jun 23, 2025
0a36025
fix set checks in EvaluateSimdVectorToPattern
a74nh Jun 23, 2025
59107d0
Use masks in EvalHWIntrinsicFunTernary() for SVE conditionalselect
a74nh Jun 24, 2025
b923b28
Check all of a vector lane when converting to mask
a74nh Jun 24, 2025
c01bc22
Add testing for EvalHWIntrinsicFunTernary changes
a74nh Jun 24, 2025
f9c6dd6
whitespace
a74nh Jun 24, 2025
802ae0d
Revert "Check all of a vector lane when converting to mask"
a74nh Jun 24, 2025
3c3cb8f
rename significantBit to leastSignificantBit
a74nh Jun 24, 2025
c96e38c
Use LSB of vector when converting from vector to mask
a74nh Jun 25, 2025
9d2cebd
Add LowerCnsMask
a74nh Jun 27, 2025
70d601d
Add testcase
a74nh Jun 27, 2025
5428e1d
Remove EvaluateSimdMaskToPattern
a74nh Jun 27, 2025
a2d7aea
Revert "Use LSB of vector when converting from vector to mask"
a74nh Jun 27, 2025
c65fd38
formatting
a74nh Jun 27, 2025
f513c84
fix assert check
a74nh Jun 27, 2025
3bf4d1e
GenTree for gtNewSimdCvtVectorToMaskNode()
a74nh Jun 30, 2025
cd27a7c
Split NI_Sve_ConditionalSelect into it's own case
a74nh Jun 30, 2025
7856b87
Remove mask version of EvaluateBinaryInPlace
a74nh Jun 30, 2025
84d0408
remove assert
a74nh Jun 30, 2025
ed633f3
Check all bits in EvaluateSimdCvtVectorToMask
a74nh Jul 1, 2025
a53e4d1
Add ConstantVectors test
a74nh Jul 1, 2025
860ff75
merge main
a74nh Jul 2, 2025
cd52ec1
No need for DOTNET_EnableHWIntrinsic in csproj
a74nh Jul 2, 2025
748d297
Use IsMaskZero
a74nh Jul 2, 2025
090523a
Remove EvaluateBinarySimdAndMask
a74nh Jul 2, 2025
e7034bd
In lowering, default the mask type to byte
a74nh Jul 2, 2025
f14fc8e
In lowering, convert mask using byte basetype
a74nh Jul 2, 2025
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/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -3205,7 +3205,7 @@ class Compiler
unsigned simdSize);

#if defined(FEATURE_MASKED_HW_INTRINSICS)
GenTreeHWIntrinsic* gtNewSimdCvtVectorToMaskNode(var_types type, GenTree* op1, CorInfoType simdBaseJitType, unsigned simdSize);
GenTree* gtNewSimdCvtVectorToMaskNode(var_types type, GenTree* op1, CorInfoType simdBaseJitType, unsigned simdSize);
#endif // FEATURE_MASKED_HW_INTRINSICS

GenTree* gtNewSimdCreateBroadcastNode(
Expand Down
120 changes: 66 additions & 54 deletions src/coreclr/jit/gentree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18608,30 +18608,6 @@ void GenTreeVecCon::EvaluateBinaryInPlace(genTreeOps oper, bool scalar, var_type
}
}

#if defined(TARGET_ARM64)
//------------------------------------------------------------------------
// GenTreeVecCon::EvaluateUnaryInPlace: Evaluates this constant using the given operation, when the other
// operand is a constant mask
//
// Arguments:
// oper - the operation to use in the evaluation
// scalar - true if this is a scalar operation; otherwise, false
// baseType - the base type of the constant being checked
// other - the mask constant to use in the evaluation
//
void GenTreeVecCon::EvaluateBinaryInPlace(genTreeOps oper, bool scalar, var_types baseType, GenTreeMskCon* other)
{
assert(gtType == TYP_SIMD16);

simd16_t otherSimdVal;
EvaluateSimdCvtMaskToVector<simd16_t>(baseType, &otherSimdVal, other->gtSimdMaskVal);

simd16_t result = {};
EvaluateBinarySimd<simd16_t>(oper, scalar, baseType, &result, gtSimd16Val, otherSimdVal);
gtSimd16Val = result;
}
#endif // TARGET_ARM64

//------------------------------------------------------------------------
// GenTreeVecCon::EvaluateBroadcastInPlace: Evaluates this constant using a broadcast
//
Expand Down Expand Up @@ -21971,10 +21947,10 @@ GenTree* Compiler::gtNewSimdCvtNativeNode(var_types type,
// Return Value:
// The node converted to the a mask type
//
GenTreeHWIntrinsic* Compiler::gtNewSimdCvtVectorToMaskNode(var_types type,
GenTree* op1,
CorInfoType simdBaseJitType,
unsigned simdSize)
GenTree* Compiler::gtNewSimdCvtVectorToMaskNode(var_types type,
GenTree* op1,
CorInfoType simdBaseJitType,
unsigned simdSize)
{
assert(varTypeIsMask(type));
assert(varTypeIsSIMD(op1));
Expand Down Expand Up @@ -32820,28 +32796,65 @@ GenTree* Compiler::gtFoldExprHWIntrinsic(GenTreeHWIntrinsic* tree)
case NI_Vector512_ConditionalSelect:
#elif defined(TARGET_ARM64)
case NI_AdvSimd_BitwiseSelect:
case NI_Sve_ConditionalSelect:
#endif
{
assert(!varTypeIsMask(retType));
assert(!varTypeIsMask(op1));

if (cnsNode != op1)
{
break;
}

#if defined(TARGET_ARM64)
if (ni == NI_Sve_ConditionalSelect)
if (op1->IsVectorAllBitsSet())
{
assert(!op1->IsVectorAllBitsSet() && !op1->IsVectorZero());
if ((op3->gtFlags & GTF_SIDE_EFFECT) != 0)
{
// op3 has side effects, this would require us to append a new statement
// to ensure that it isn't lost, which isn't safe to do from the general
// purpose handler here. We'll recognize this and mark it in VN instead
break;
}

// op3 has no side effects, so we can return op2 directly
return op2;
}
else

if (op1->IsVectorZero())
{
return gtWrapWithSideEffects(op3, op2, GTF_ALL_EFFECT);
}

if (op2->IsCnsVec() && op3->IsCnsVec())
{
assert(!op1->IsTrueMask(simdBaseType) && !op1->IsFalseMask());
// op2 = op2 & op1
op2->AsVecCon()->EvaluateBinaryInPlace(GT_AND, false, simdBaseType, op1->AsVecCon());

// op3 = op2 & ~op1
op3->AsVecCon()->EvaluateBinaryInPlace(GT_AND_NOT, false, simdBaseType, op1->AsVecCon());

// op2 = op2 | op3
op2->AsVecCon()->EvaluateBinaryInPlace(GT_OR, false, simdBaseType, op3->AsVecCon());

resultNode = op2;
}
#endif
break;
}

#if defined(TARGET_ARM64)
case NI_Sve_ConditionalSelect:
{
assert(!varTypeIsMask(retType));
assert(varTypeIsMask(op1));

if (cnsNode != op1)
{
break;
}

assert(!op1->IsVectorAllBitsSet() && !op1->IsVectorZero());

if (op1->IsVectorAllBitsSet() || op1->IsTrueMask(simdBaseType))
if (op1->IsTrueMask(simdBaseType))
{
if ((op3->gtFlags & GTF_SIDE_EFFECT) != 0)
{
Expand All @@ -32855,40 +32868,39 @@ GenTree* Compiler::gtFoldExprHWIntrinsic(GenTreeHWIntrinsic* tree)
return op2;
}

if (op1->IsVectorZero() || op1->IsFalseMask())
if (op1->IsFalseMask())
{
return gtWrapWithSideEffects(op3, op2, GTF_ALL_EFFECT);
}

if (op2->IsCnsVec() && op3->IsCnsVec())
{
if (op1->IsCnsVec())
{
// op2 = op2 & op1
op2->AsVecCon()->EvaluateBinaryInPlace(GT_AND, false, simdBaseType, op1->AsVecCon());
assert(op2->gtType == TYP_SIMD16);
assert(op3->gtType == TYP_SIMD16);

// op3 = op2 & ~op1
op3->AsVecCon()->EvaluateBinaryInPlace(GT_AND_NOT, false, simdBaseType, op1->AsVecCon());
}
#if defined(TARGET_ARM64)
else if (op1->IsCnsMsk())
{
assert(ni == NI_Sve_ConditionalSelect);
simd16_t op1SimdVal;
EvaluateSimdCvtMaskToVector<simd16_t>(simdBaseType, &op1SimdVal, op1->AsMskCon()->gtSimdMaskVal);

// op2 = op2 & op1
op2->AsVecCon()->EvaluateBinaryInPlace(GT_AND, false, simdBaseType, op1->AsMskCon());
// op2 = op2 & op1
simd16_t result = {};
EvaluateBinarySimd<simd16_t>(GT_AND, false, simdBaseType, &result, op2->AsVecCon()->gtSimd16Val,
op1SimdVal);
op2->AsVecCon()->gtSimd16Val = result;

// op3 = op2 & ~op1
result = {};
EvaluateBinarySimd<simd16_t>(GT_AND_NOT, false, simdBaseType, &result, op3->AsVecCon()->gtSimd16Val,
op1SimdVal);
op3->AsVecCon()->gtSimd16Val = result;

// op3 = op2 & ~op1
op3->AsVecCon()->EvaluateBinaryInPlace(GT_AND_NOT, false, simdBaseType, op1->AsMskCon());
}
#endif
// op2 = op2 | op3
op2->AsVecCon()->EvaluateBinaryInPlace(GT_OR, false, simdBaseType, op3->AsVecCon());

resultNode = op2;
}
break;
}
#endif // TARGET_ARM64

default:
{
Expand Down
3 changes: 0 additions & 3 deletions src/coreclr/jit/gentree.h
Original file line number Diff line number Diff line change
Expand Up @@ -6851,9 +6851,6 @@ struct GenTreeVecCon : public GenTree

void EvaluateUnaryInPlace(genTreeOps oper, bool scalar, var_types baseType);
void EvaluateBinaryInPlace(genTreeOps oper, bool scalar, var_types baseType, GenTreeVecCon* other);
#if defined(TARGET_ARM64)
void EvaluateBinaryInPlace(genTreeOps oper, bool scalar, var_types baseType, GenTreeMskCon* other);
#endif

template <typename TBase>
void EvaluateBroadcastInPlace(TBase scalar)
Expand Down
5 changes: 2 additions & 3 deletions src/coreclr/jit/lowerarmarch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1193,9 +1193,8 @@ GenTree* Lowering::LowerCnsMask(GenTreeMskCon* mask)
EvaluateSimdCvtMaskToVector<simd16_t>(parentBaseType, &vecCon->gtSimdVal, mask->gtSimdMaskVal);
BlockRange().InsertBefore(mask, vecCon);

GenTreeHWIntrinsic* convertedVec =
comp->gtNewSimdCvtVectorToMaskNode(TYP_MASK, vecCon, parentSimdBaseJitType, parentSimdSize);
BlockRange().InsertBefore(mask, convertedVec->Op(1));
GenTree* convertedVec = comp->gtNewSimdCvtVectorToMaskNode(TYP_MASK, vecCon, parentSimdBaseJitType, parentSimdSize);
BlockRange().InsertBefore(mask, convertedVec->AsHWIntrinsic()->Op(1));
BlockRange().InsertBefore(mask, convertedVec);

use.ReplaceWith(convertedVec);
Expand Down
Loading