diff --git a/src/coreclr/jit/codegenlinear.cpp b/src/coreclr/jit/codegenlinear.cpp
index 145c074b8fc68..d099fe192fc38 100644
--- a/src/coreclr/jit/codegenlinear.cpp
+++ b/src/coreclr/jit/codegenlinear.cpp
@@ -1648,7 +1648,6 @@ void CodeGen::genConsumeRegs(GenTree* tree)
// Update the life of the lcl var.
genUpdateLife(tree);
}
-#ifdef TARGET_XARCH
#ifdef FEATURE_HW_INTRINSICS
else if (tree->OperIs(GT_HWINTRINSIC))
{
@@ -1656,7 +1655,6 @@ void CodeGen::genConsumeRegs(GenTree* tree)
genConsumeMultiOpOperands(hwintrinsic);
}
#endif // FEATURE_HW_INTRINSICS
-#endif // TARGET_XARCH
else if (tree->OperIs(GT_BITCAST, GT_NEG, GT_CAST, GT_LSH, GT_RSH, GT_RSZ, GT_ROR, GT_BSWAP, GT_BSWAP16))
{
genConsumeRegs(tree->gtGetOp1());
diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h
index 3c19969d0c90d..474ade28e07ed 100644
--- a/src/coreclr/jit/compiler.h
+++ b/src/coreclr/jit/compiler.h
@@ -3473,6 +3473,7 @@ class Compiler
#if defined(TARGET_ARM64)
GenTree* gtNewSimdConvertVectorToMaskNode(var_types type, GenTree* node, CorInfoType simdBaseJitType, unsigned simdSize);
GenTree* gtNewSimdConvertMaskToVectorNode(GenTreeHWIntrinsic* node, var_types type);
+ GenTree* gtNewSimdAllTrueMaskNode(CorInfoType simdBaseJitType, unsigned simdSize);
#endif
//------------------------------------------------------------------------
diff --git a/src/coreclr/jit/emitloongarch64.h b/src/coreclr/jit/emitloongarch64.h
index 135f9cf400673..afaca5b2ba04b 100644
--- a/src/coreclr/jit/emitloongarch64.h
+++ b/src/coreclr/jit/emitloongarch64.h
@@ -333,7 +333,7 @@ enum EmitCallType
EC_FUNC_TOKEN, // Direct call to a helper/static/nonvirtual/global method
// EC_FUNC_TOKEN_INDIR, // Indirect call to a helper/static/nonvirtual/global method
- // EC_FUNC_ADDR, // Direct call to an absolute address
+ // EC_FUNC_ADDR, // Direct call to an absolute address
EC_INDIR_R, // Indirect call via register
diff --git a/src/coreclr/jit/emitriscv64.h b/src/coreclr/jit/emitriscv64.h
index 07e603a70afb7..262f44c9ac4bb 100644
--- a/src/coreclr/jit/emitriscv64.h
+++ b/src/coreclr/jit/emitriscv64.h
@@ -310,7 +310,7 @@ enum EmitCallType
EC_FUNC_TOKEN, // Direct call to a helper/static/nonvirtual/global method
// EC_FUNC_TOKEN_INDIR, // Indirect call to a helper/static/nonvirtual/global method
- // EC_FUNC_ADDR, // Direct call to an absolute address
+ // EC_FUNC_ADDR, // Direct call to an absolute address
// EC_FUNC_VIRTUAL, // Call to a virtual method (using the vtable)
EC_INDIR_R, // Indirect call via register
diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp
index 878c02ac1603d..5a6dc9a856f86 100644
--- a/src/coreclr/jit/gentree.cpp
+++ b/src/coreclr/jit/gentree.cpp
@@ -18012,7 +18012,7 @@ bool GenTree::canBeContained() const
}
else if (OperIsHWIntrinsic() && !isContainableHWIntrinsic())
{
- return isEvexEmbeddedMaskingCompatibleHWIntrinsic();
+ return isEmbeddedMaskingCompatibleHWIntrinsic();
}
return true;
@@ -19909,24 +19909,26 @@ bool GenTree::isEvexCompatibleHWIntrinsic() const
}
//------------------------------------------------------------------------
-// isEvexEmbeddedMaskingCompatibleHWIntrinsic: Checks if the intrinsic is compatible
+// isEmbeddedMaskingCompatibleHWIntrinsic : Checks if the intrinsic is compatible
// with the EVEX embedded masking form for its intended lowering instruction.
//
// Return Value:
// true if the intrisic node lowering instruction has an EVEX embedded masking
//
-bool GenTree::isEvexEmbeddedMaskingCompatibleHWIntrinsic() const
+bool GenTree::isEmbeddedMaskingCompatibleHWIntrinsic() const
{
-#if defined(TARGET_XARCH)
if (OperIsHWIntrinsic())
{
+#if defined(TARGET_XARCH)
// TODO-AVX512F-CQ: Expand this to the full set of APIs and make it table driven
// using IsEmbMaskingCompatible. For now, however, limit it to some explicit ids
// for prototyping purposes.
return (AsHWIntrinsic()->GetHWIntrinsicId() == NI_AVX512F_Add);
+#elif defined(TARGET_ARM64)
+ return HWIntrinsicInfo::IsEmbeddedMaskedOperation(AsHWIntrinsic()->GetHWIntrinsicId()) ||
+ HWIntrinsicInfo::IsOptionalEmbeddedMaskedOperation(AsHWIntrinsic()->GetHWIntrinsicId());
+#endif
}
-#endif // TARGET_XARCH
-
return false;
}
diff --git a/src/coreclr/jit/gentree.h b/src/coreclr/jit/gentree.h
index c636912180952..079174f67e939 100644
--- a/src/coreclr/jit/gentree.h
+++ b/src/coreclr/jit/gentree.h
@@ -557,9 +557,9 @@ enum GenTreeFlags : unsigned int
GTF_MDARRLOWERBOUND_NONFAULTING = 0x20000000, // GT_MDARR_LOWER_BOUND -- An MD array lower bound operation that cannot fault. Same as GT_IND_NONFAULTING.
-#if defined(TARGET_XARCH) && defined(FEATURE_HW_INTRINSICS)
+#ifdef FEATURE_HW_INTRINSICS
GTF_HW_EM_OP = 0x10000000, // GT_HWINTRINSIC -- node is used as an operand to an embedded mask
-#endif // TARGET_XARCH && FEATURE_HW_INTRINSICS
+#endif // FEATURE_HW_INTRINSICS
};
inline constexpr GenTreeFlags operator ~(GenTreeFlags a)
@@ -1465,7 +1465,7 @@ struct GenTree
bool isContainableHWIntrinsic() const;
bool isRMWHWIntrinsic(Compiler* comp);
bool isEvexCompatibleHWIntrinsic() const;
- bool isEvexEmbeddedMaskingCompatibleHWIntrinsic() const;
+ bool isEmbeddedMaskingCompatibleHWIntrinsic() const;
#else
bool isCommutativeHWIntrinsic() const
{
@@ -1487,7 +1487,7 @@ struct GenTree
return false;
}
- bool isEvexEmbeddedMaskingCompatibleHWIntrinsic() const
+ bool isEmbeddedMaskingCompatibleHWIntrinsic() const
{
return false;
}
@@ -2226,7 +2226,7 @@ struct GenTree
gtFlags &= ~GTF_ICON_HDL_MASK;
}
-#if defined(TARGET_XARCH) && defined(FEATURE_HW_INTRINSICS)
+#ifdef FEATURE_HW_INTRINSICS
bool IsEmbMaskOp()
{
@@ -2240,7 +2240,7 @@ struct GenTree
gtFlags |= GTF_HW_EM_OP;
}
-#endif // TARGET_XARCH && FEATURE_HW_INTRINSICS
+#endif // FEATURE_HW_INTRINSICS
static bool HandleKindDataIsInvariant(GenTreeFlags flags);
diff --git a/src/coreclr/jit/hwintrinsic.cpp b/src/coreclr/jit/hwintrinsic.cpp
index 53970ef4a7460..402cae99b3f63 100644
--- a/src/coreclr/jit/hwintrinsic.cpp
+++ b/src/coreclr/jit/hwintrinsic.cpp
@@ -1396,6 +1396,36 @@ GenTree* Compiler::impHWIntrinsic(NamedIntrinsic intrinsic,
GenTree* op3 = nullptr;
GenTree* op4 = nullptr;
+ switch (numArgs)
+ {
+ case 4:
+ op4 = getArgForHWIntrinsic(sigReader.GetOp4Type(), sigReader.op4ClsHnd);
+ op4 = addRangeCheckIfNeeded(intrinsic, op4, mustExpand, immLowerBound, immUpperBound);
+ op3 = getArgForHWIntrinsic(sigReader.GetOp3Type(), sigReader.op3ClsHnd);
+ op2 = getArgForHWIntrinsic(sigReader.GetOp2Type(), sigReader.op2ClsHnd);
+ op1 = getArgForHWIntrinsic(sigReader.GetOp1Type(), sigReader.op1ClsHnd);
+ break;
+
+ case 3:
+ op3 = getArgForHWIntrinsic(sigReader.GetOp3Type(), sigReader.op3ClsHnd);
+ op2 = getArgForHWIntrinsic(sigReader.GetOp2Type(), sigReader.op2ClsHnd);
+ op1 = getArgForHWIntrinsic(sigReader.GetOp1Type(), sigReader.op1ClsHnd);
+ break;
+
+ case 2:
+ op2 = getArgForHWIntrinsic(sigReader.GetOp2Type(), sigReader.op2ClsHnd);
+ op2 = addRangeCheckIfNeeded(intrinsic, op2, mustExpand, immLowerBound, immUpperBound);
+ op1 = getArgForHWIntrinsic(sigReader.GetOp1Type(), sigReader.op1ClsHnd);
+ break;
+
+ case 1:
+ op1 = getArgForHWIntrinsic(sigReader.GetOp1Type(), sigReader.op1ClsHnd);
+ break;
+
+ default:
+ break;
+ }
+
switch (numArgs)
{
case 0:
@@ -1407,8 +1437,6 @@ GenTree* Compiler::impHWIntrinsic(NamedIntrinsic intrinsic,
case 1:
{
- op1 = getArgForHWIntrinsic(sigReader.GetOp1Type(), sigReader.op1ClsHnd);
-
if ((category == HW_Category_MemoryLoad) && op1->OperIs(GT_CAST))
{
// Although the API specifies a pointer, if what we have is a BYREF, that's what
@@ -1467,10 +1495,6 @@ GenTree* Compiler::impHWIntrinsic(NamedIntrinsic intrinsic,
case 2:
{
- op2 = getArgForHWIntrinsic(sigReader.GetOp2Type(), sigReader.op2ClsHnd);
- op2 = addRangeCheckIfNeeded(intrinsic, op2, mustExpand, immLowerBound, immUpperBound);
- op1 = getArgForHWIntrinsic(sigReader.GetOp1Type(), sigReader.op1ClsHnd);
-
retNode = isScalar
? gtNewScalarHWIntrinsicNode(nodeRetType, op1, op2, intrinsic)
: gtNewSimdHWIntrinsicNode(nodeRetType, op1, op2, intrinsic, simdBaseJitType, simdSize);
@@ -1524,10 +1548,6 @@ GenTree* Compiler::impHWIntrinsic(NamedIntrinsic intrinsic,
case 3:
{
- op3 = getArgForHWIntrinsic(sigReader.GetOp3Type(), sigReader.op3ClsHnd);
- op2 = getArgForHWIntrinsic(sigReader.GetOp2Type(), sigReader.op2ClsHnd);
- op1 = getArgForHWIntrinsic(sigReader.GetOp1Type(), sigReader.op1ClsHnd);
-
#ifdef TARGET_ARM64
if (intrinsic == NI_AdvSimd_LoadAndInsertScalar)
{
@@ -1569,12 +1589,6 @@ GenTree* Compiler::impHWIntrinsic(NamedIntrinsic intrinsic,
case 4:
{
- op4 = getArgForHWIntrinsic(sigReader.GetOp4Type(), sigReader.op4ClsHnd);
- op4 = addRangeCheckIfNeeded(intrinsic, op4, mustExpand, immLowerBound, immUpperBound);
- op3 = getArgForHWIntrinsic(sigReader.GetOp3Type(), sigReader.op3ClsHnd);
- op2 = getArgForHWIntrinsic(sigReader.GetOp2Type(), sigReader.op2ClsHnd);
- op1 = getArgForHWIntrinsic(sigReader.GetOp1Type(), sigReader.op1ClsHnd);
-
assert(!isScalar);
retNode =
gtNewSimdHWIntrinsicNode(nodeRetType, op1, op2, op3, op4, intrinsic, simdBaseJitType, simdSize);
@@ -1591,10 +1605,22 @@ GenTree* Compiler::impHWIntrinsic(NamedIntrinsic intrinsic,
}
#if defined(TARGET_ARM64)
- if (HWIntrinsicInfo::IsMaskedOperation(intrinsic))
+ if (HWIntrinsicInfo::IsExplicitMaskedOperation(intrinsic))
{
assert(numArgs > 0);
GenTree* op1 = retNode->AsHWIntrinsic()->Op(1);
+ if (intrinsic == NI_Sve_ConditionalSelect)
+ {
+ if (op1->IsVectorAllBitsSet())
+ {
+ return retNode->AsHWIntrinsic()->Op(2);
+ }
+ else if (op1->IsVectorZero())
+ {
+ return retNode->AsHWIntrinsic()->Op(3);
+ }
+ }
+
if (!varTypeIsMask(op1))
{
// Op1 input is a vector. HWInstrinsic requires a mask.
diff --git a/src/coreclr/jit/hwintrinsic.h b/src/coreclr/jit/hwintrinsic.h
index 5ca302e126f32..e7bd08d5cb33d 100644
--- a/src/coreclr/jit/hwintrinsic.h
+++ b/src/coreclr/jit/hwintrinsic.h
@@ -186,11 +186,18 @@ enum HWIntrinsicFlag : unsigned int
HW_Flag_ReturnsPerElementMask = 0x10000,
// The intrinsic uses a mask in arg1 to select elements present in the result
- HW_Flag_MaskedOperation = 0x20000,
+ HW_Flag_ExplicitMaskedOperation = 0x20000,
// The intrinsic uses a mask in arg1 to select elements present in the result, and must use a low register.
HW_Flag_LowMaskedOperation = 0x40000,
+ // The intrinsic can optionally use a mask in arg1 to select elements present in the result, which is not present in
+ // the API call
+ HW_Flag_OptionalEmbeddedMaskedOperation = 0x80000,
+
+ // The intrinsic uses a mask in arg1 to select elements present in the result, which is not present in the API call
+ HW_Flag_EmbeddedMaskedOperation = 0x100000,
+
#else
#error Unsupported platform
#endif
@@ -872,7 +879,7 @@ struct HWIntrinsicInfo
static bool IsMaskedOperation(NamedIntrinsic id)
{
const HWIntrinsicFlag flags = lookupFlags(id);
- return ((flags & HW_Flag_MaskedOperation) != 0) || IsLowMaskedOperation(id);
+ return IsLowMaskedOperation(id) || IsOptionalEmbeddedMaskedOperation(id) || IsExplicitMaskedOperation(id);
}
static bool IsLowMaskedOperation(NamedIntrinsic id)
@@ -881,6 +888,24 @@ struct HWIntrinsicInfo
return (flags & HW_Flag_LowMaskedOperation) != 0;
}
+ static bool IsOptionalEmbeddedMaskedOperation(NamedIntrinsic id)
+ {
+ const HWIntrinsicFlag flags = lookupFlags(id);
+ return (flags & HW_Flag_OptionalEmbeddedMaskedOperation) != 0;
+ }
+
+ static bool IsEmbeddedMaskedOperation(NamedIntrinsic id)
+ {
+ const HWIntrinsicFlag flags = lookupFlags(id);
+ return (flags & HW_Flag_EmbeddedMaskedOperation) != 0;
+ }
+
+ static bool IsExplicitMaskedOperation(NamedIntrinsic id)
+ {
+ const HWIntrinsicFlag flags = lookupFlags(id);
+ return (flags & HW_Flag_ExplicitMaskedOperation) != 0;
+ }
+
#endif // TARGET_ARM64
static bool HasSpecialSideEffect(NamedIntrinsic id)
diff --git a/src/coreclr/jit/hwintrinsicarm64.cpp b/src/coreclr/jit/hwintrinsicarm64.cpp
index 8e3288f75d709..205102abc9b0b 100644
--- a/src/coreclr/jit/hwintrinsicarm64.cpp
+++ b/src/coreclr/jit/hwintrinsicarm64.cpp
@@ -2222,9 +2222,8 @@ GenTree* Compiler::gtNewSimdConvertVectorToMaskNode(var_types type,
assert(varTypeIsSIMD(node));
// ConvertVectorToMask uses cmpne which requires an embedded mask.
- GenTree* embeddedMask = gtNewSimdHWIntrinsicNode(TYP_MASK, NI_Sve_CreateTrueMaskAll, simdBaseJitType, simdSize);
- return gtNewSimdHWIntrinsicNode(TYP_MASK, embeddedMask, node, NI_Sve_ConvertVectorToMask, simdBaseJitType,
- simdSize);
+ GenTree* trueMask = gtNewSimdAllTrueMaskNode(simdBaseJitType, simdSize);
+ return gtNewSimdHWIntrinsicNode(TYP_MASK, trueMask, node, NI_Sve_ConvertVectorToMask, simdBaseJitType, simdSize);
}
//------------------------------------------------------------------------
@@ -2246,4 +2245,19 @@ GenTree* Compiler::gtNewSimdConvertMaskToVectorNode(GenTreeHWIntrinsic* node, va
node->GetSimdSize());
}
+//------------------------------------------------------------------------
+// gtNewSimdEmbeddedMaskNode: Create an embedded mask
+//
+// Arguments:
+// simdBaseJitType -- the base jit type of the nodes being masked
+// simdSize -- the simd size of the nodes being masked
+//
+// Return Value:
+// The mask
+//
+GenTree* Compiler::gtNewSimdAllTrueMaskNode(CorInfoType simdBaseJitType, unsigned simdSize)
+{
+ return gtNewSimdHWIntrinsicNode(TYP_MASK, NI_Sve_CreateTrueMaskAll, simdBaseJitType, simdSize);
+}
+
#endif // FEATURE_HW_INTRINSICS
diff --git a/src/coreclr/jit/hwintrinsiccodegenarm64.cpp b/src/coreclr/jit/hwintrinsiccodegenarm64.cpp
index 9a3a98e087a27..c5ea702c1c4be 100644
--- a/src/coreclr/jit/hwintrinsiccodegenarm64.cpp
+++ b/src/coreclr/jit/hwintrinsiccodegenarm64.cpp
@@ -401,6 +401,100 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node)
unreached();
}
}
+ else if (intrin.numOperands >= 2 && intrin.op2->IsEmbMaskOp())
+ {
+ // Handle case where op2 is operation that needs embedded mask
+ GenTree* op2 = intrin.op2;
+ assert(intrin.id == NI_Sve_ConditionalSelect);
+ assert(op2->isContained());
+ assert(op2->OperIsHWIntrinsic());
+
+ // Get the registers and intrinsics that needs embedded mask
+ const HWIntrinsic intrinEmbMask(op2->AsHWIntrinsic());
+ instruction insEmbMask = HWIntrinsicInfo::lookupIns(intrinEmbMask.id, intrinEmbMask.baseType);
+ const bool instrIsRMW = op2->isRMWHWIntrinsic(compiler);
+
+ regNumber maskReg = op1Reg;
+ regNumber embMaskOp1Reg = REG_NA;
+ regNumber embMaskOp2Reg = REG_NA;
+ regNumber falseReg = op3Reg;
+
+ switch (intrinEmbMask.numOperands)
+ {
+ case 2:
+ assert(intrinEmbMask.op2 != nullptr);
+ embMaskOp2Reg = intrinEmbMask.op2->GetRegNum();
+ FALLTHROUGH;
+
+ case 1:
+ assert(intrinEmbMask.op1 != nullptr);
+ embMaskOp1Reg = intrinEmbMask.op1->GetRegNum();
+ break;
+
+ default:
+ unreached();
+ }
+
+ switch (intrinEmbMask.numOperands)
+ {
+ case 1:
+ assert(!instrIsRMW);
+ if (targetReg != falseReg)
+ {
+ GetEmitter()->emitIns_R_R(INS_sve_movprfx, EA_SCALABLE, targetReg, falseReg);
+ }
+ GetEmitter()->emitIns_R_R_R(insEmbMask, emitSize, targetReg, maskReg, embMaskOp1Reg, opt);
+ break;
+
+ case 2:
+
+ assert(instrIsRMW);
+
+ if (intrin.op3->IsVectorZero())
+ {
+ // If `falseReg` is zero, then move the first operand of `intrinEmbMask` in the
+ // destination using /Z.
+ GetEmitter()->emitIns_R_R_R(INS_sve_movprfx, emitSize, targetReg, maskReg, embMaskOp1Reg, opt);
+
+ // Finally, perform the actual "predicated" operation so that `targetReg` is the first operand
+ // and `embMaskOp2Reg` is the second operand.
+ GetEmitter()->emitIns_R_R_R(insEmbMask, emitSize, targetReg, maskReg, embMaskOp2Reg, opt);
+ }
+ else if (targetReg != falseReg)
+ {
+ // If `targetReg` and `falseReg` are not same, then we need to move it to `targetReg` first
+ // so the `insEmbMask` operation can be merged on top of it.
+
+ if (falseReg != embMaskOp1Reg)
+ {
+ // None of targetReg, embMaskOp1Reg and falseReg are same. In such case, use the
+ // "unpredicated" version of the instruction and then use "sel" to select the active lanes.
+
+ GetEmitter()->emitIns_R_R_R(insEmbMask, emitSize, targetReg, embMaskOp1Reg, embMaskOp2Reg,
+ opt, INS_SCALABLE_OPTS_UNPREDICATED);
+ GetEmitter()->emitIns_R_R_R_R(INS_sve_sel, emitSize, targetReg, maskReg, targetReg,
+ falseReg, opt, INS_SCALABLE_OPTS_UNPREDICATED);
+ break;
+ }
+ else if (targetReg != embMaskOp1Reg)
+ {
+ // embMaskOp1Reg is same as `falseReg`, but not same as `targetReg`. Move the
+ // `embMaskOp1Reg` i.e. `falseReg` in `targetReg`, using "unpredicated movprfx", so the
+ // subsequent `insEmbMask` operation can be merged on top of it.
+ GetEmitter()->emitIns_R_R(INS_sve_movprfx, EA_SCALABLE, targetReg, falseReg, opt);
+ }
+
+ // Finally, perform the actual "predicated" operation so that `targetReg` is the first operand
+ // and `embMaskOp2Reg` is the second operand.
+ GetEmitter()->emitIns_R_R_R(insEmbMask, emitSize, targetReg, maskReg, embMaskOp2Reg, opt);
+ }
+
+ break;
+
+ default:
+ unreached();
+ }
+ }
else
{
assert(!hasImmediateOperand);
@@ -419,6 +513,14 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node)
{
GetEmitter()->emitIns_R_R(ins, emitSize, targetReg, op1Reg, opt);
}
+ else if (HWIntrinsicInfo::IsScalable(intrin.id))
+ {
+ assert(!node->IsEmbMaskOp());
+ // This generates an unpredicated version
+ // Predicated should be taken care above `intrin.op2->IsEmbMaskOp()`
+ GetEmitter()->emitIns_R_R_R(ins, emitSize, targetReg, op1Reg, op2Reg, opt,
+ INS_SCALABLE_OPTS_UNPREDICATED);
+ }
else if (isRMW)
{
if (targetReg != op1Reg)
@@ -437,17 +539,24 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node)
break;
case 3:
- assert(isRMW);
- if (targetReg != op1Reg)
+ if (isRMW)
{
- assert(targetReg != op2Reg);
- assert(targetReg != op3Reg);
+ if (targetReg != op1Reg)
+ {
+ assert(targetReg != op2Reg);
+ assert(targetReg != op3Reg);
- GetEmitter()->emitIns_Mov(INS_mov, emitTypeSize(node), targetReg, op1Reg, /* canSkip */ true);
+ GetEmitter()->emitIns_Mov(INS_mov, emitTypeSize(node), targetReg, op1Reg,
+ /* canSkip */ true);
+ }
+ GetEmitter()->emitIns_R_R_R(ins, emitSize, targetReg, op2Reg, op3Reg, opt);
+ }
+ else
+ {
+ GetEmitter()->emitIns_R_R_R_R(ins, emitSize, targetReg, op1Reg, op2Reg, op3Reg, opt,
+ INS_SCALABLE_OPTS_UNPREDICATED);
}
- GetEmitter()->emitIns_R_R_R(ins, emitSize, targetReg, op2Reg, op3Reg, opt);
break;
-
default:
unreached();
}
diff --git a/src/coreclr/jit/hwintrinsiclistarm64sve.h b/src/coreclr/jit/hwintrinsiclistarm64sve.h
index ac110c2a0e1b5..14b880c8e570e 100644
--- a/src/coreclr/jit/hwintrinsiclistarm64sve.h
+++ b/src/coreclr/jit/hwintrinsiclistarm64sve.h
@@ -17,6 +17,9 @@
// SVE Intrinsics
// Sve
+HARDWARE_INTRINSIC(Sve, Abs, -1, -1, false, {INS_sve_abs, INS_invalid, INS_sve_abs, INS_invalid, INS_sve_abs, INS_invalid, INS_sve_abs, INS_invalid, INS_sve_fabs, INS_sve_fabs}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation)
+HARDWARE_INTRINSIC(Sve, Add, -1, -1, false, {INS_sve_add, INS_sve_add, INS_sve_add, INS_sve_add, INS_sve_add, INS_sve_add, INS_sve_add, INS_sve_add, INS_sve_fadd, INS_sve_fadd}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_OptionalEmbeddedMaskedOperation|HW_Flag_HasRMWSemantics|HW_Flag_LowMaskedOperation)
+HARDWARE_INTRINSIC(Sve, ConditionalSelect, -1, 3, true, {INS_sve_sel, INS_sve_sel, INS_sve_sel, INS_sve_sel, INS_sve_sel, INS_sve_sel, INS_sve_sel, INS_sve_sel, INS_sve_sel, INS_sve_sel}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_SupportsContainment)
HARDWARE_INTRINSIC(Sve, CreateTrueMaskByte, -1, 1, false, {INS_invalid, INS_sve_ptrue, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_EnumPattern, HW_Flag_Scalable|HW_Flag_HasImmediateOperand|HW_Flag_ReturnsPerElementMask)
HARDWARE_INTRINSIC(Sve, CreateTrueMaskDouble, -1, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ptrue}, HW_Category_EnumPattern, HW_Flag_Scalable|HW_Flag_HasImmediateOperand|HW_Flag_ReturnsPerElementMask)
HARDWARE_INTRINSIC(Sve, CreateTrueMaskInt16, -1, 1, false, {INS_invalid, INS_invalid, INS_sve_ptrue, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_EnumPattern, HW_Flag_Scalable|HW_Flag_HasImmediateOperand|HW_Flag_ReturnsPerElementMask)
@@ -28,7 +31,7 @@ HARDWARE_INTRINSIC(Sve, CreateTrueMaskUInt16,
HARDWARE_INTRINSIC(Sve, CreateTrueMaskUInt32, -1, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ptrue, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_EnumPattern, HW_Flag_Scalable|HW_Flag_HasImmediateOperand|HW_Flag_ReturnsPerElementMask)
HARDWARE_INTRINSIC(Sve, CreateTrueMaskUInt64, -1, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_ptrue, INS_invalid, INS_invalid}, HW_Category_EnumPattern, HW_Flag_Scalable|HW_Flag_HasImmediateOperand|HW_Flag_ReturnsPerElementMask)
-HARDWARE_INTRINSIC(Sve, LoadVector, -1, 2, true, {INS_sve_ld1b, INS_sve_ld1b, INS_sve_ld1h, INS_sve_ld1h, INS_sve_ld1w, INS_sve_ld1w, INS_sve_ld1d, INS_sve_ld1d, INS_sve_ld1w, INS_sve_ld1d}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_LowMaskedOperation)
+HARDWARE_INTRINSIC(Sve, LoadVector, -1, 2, true, {INS_sve_ld1b, INS_sve_ld1b, INS_sve_ld1h, INS_sve_ld1h, INS_sve_ld1w, INS_sve_ld1w, INS_sve_ld1d, INS_sve_ld1d, INS_sve_ld1w, INS_sve_ld1d}, HW_Category_MemoryLoad, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation|HW_Flag_LowMaskedOperation)
@@ -38,11 +41,11 @@ HARDWARE_INTRINSIC(Sve, LoadVector,
// ***************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
// Special intrinsics that are generated during importing or lowering
-HARDWARE_INTRINSIC(Sve, ConvertMaskToVector, -1, 1, true, {INS_sve_mov, INS_sve_mov, INS_sve_mov, INS_sve_mov, INS_sve_mov, INS_sve_mov, INS_sve_mov, INS_sve_mov, INS_sve_mov, INS_sve_mov}, HW_Category_Helper, HW_Flag_Scalable|HW_Flag_MaskedOperation)
+HARDWARE_INTRINSIC(Sve, ConvertMaskToVector, -1, 1, true, {INS_sve_mov, INS_sve_mov, INS_sve_mov, INS_sve_mov, INS_sve_mov, INS_sve_mov, INS_sve_mov, INS_sve_mov, INS_sve_mov, INS_sve_mov}, HW_Category_Helper, HW_Flag_Scalable|HW_Flag_ExplicitMaskedOperation)
HARDWARE_INTRINSIC(Sve, ConvertVectorToMask, -1, 2, true, {INS_sve_cmpne, INS_sve_cmpne, INS_sve_cmpne, INS_sve_cmpne, INS_sve_cmpne, INS_sve_cmpne, INS_sve_cmpne, INS_sve_cmpne, INS_sve_cmpne, INS_sve_cmpne}, HW_Category_Helper, HW_Flag_Scalable|HW_Flag_ReturnsPerElementMask|HW_Flag_LowMaskedOperation)
-
HARDWARE_INTRINSIC(Sve, CreateTrueMaskAll, -1, -1, false, {INS_sve_ptrue, INS_sve_ptrue, INS_sve_ptrue, INS_sve_ptrue, INS_sve_ptrue, INS_sve_ptrue, INS_sve_ptrue, INS_sve_ptrue, INS_sve_ptrue, INS_sve_ptrue}, HW_Category_Helper, HW_Flag_Scalable|HW_Flag_ReturnsPerElementMask)
+
#endif // FEATURE_HW_INTRINSIC
#undef HARDWARE_INTRINSIC
diff --git a/src/coreclr/jit/liveness.cpp b/src/coreclr/jit/liveness.cpp
index 521e989133433..ef3fedf5b31d3 100644
--- a/src/coreclr/jit/liveness.cpp
+++ b/src/coreclr/jit/liveness.cpp
@@ -1762,8 +1762,8 @@ void Compiler::fgComputeLifeLIR(VARSET_TP& life, BasicBlock* block, VARSET_VALAR
operand->SetUnusedValue();
}
- // Special-case PUTARG_STK: since this operator is not considered a value, DCE will not remove
- // these nodes.
+ // Special-case PUTARG_STK: since this operator is not considered a value, DCE will not
+ // remove these nodes.
if (operand->OperIs(GT_PUTARG_STK))
{
operand->AsPutArgStk()->gtOp1->SetUnusedValue();
diff --git a/src/coreclr/jit/lowerarmarch.cpp b/src/coreclr/jit/lowerarmarch.cpp
index cbdc886ee2802..7ea9a90d62343 100644
--- a/src/coreclr/jit/lowerarmarch.cpp
+++ b/src/coreclr/jit/lowerarmarch.cpp
@@ -1280,6 +1280,34 @@ GenTree* Lowering::LowerHWIntrinsic(GenTreeHWIntrinsic* node)
break;
}
+ if (HWIntrinsicInfo::IsEmbeddedMaskedOperation(intrinsicId))
+ {
+ LIR::Use use;
+ if (BlockRange().TryGetUse(node, &use))
+ {
+ GenTree* user = use.User();
+ // Wrap the intrinsic in ConditionalSelect only if it is not already inside another ConditionalSelect
+ if (!user->OperIsHWIntrinsic() || (user->AsHWIntrinsic()->GetHWIntrinsicId() != NI_Sve_ConditionalSelect))
+ {
+ CorInfoType simdBaseJitType = node->GetSimdBaseJitType();
+ unsigned simdSize = node->GetSimdSize();
+ var_types simdType = Compiler::getSIMDTypeForSize(simdSize);
+ GenTree* trueMask = comp->gtNewSimdAllTrueMaskNode(simdBaseJitType, simdSize);
+ GenTree* trueVal = node;
+ GenTree* falseVal = comp->gtNewZeroConNode(simdType);
+
+ GenTreeHWIntrinsic* condSelNode =
+ comp->gtNewSimdHWIntrinsicNode(simdType, trueMask, trueVal, falseVal, NI_Sve_ConditionalSelect,
+ simdBaseJitType, simdSize);
+
+ BlockRange().InsertBefore(node, trueMask);
+ BlockRange().InsertBefore(node, falseVal);
+ BlockRange().InsertAfter(node, condSelNode);
+ use.ReplaceWith(condSelNode);
+ }
+ }
+ }
+
ContainCheckHWIntrinsic(node);
return node->gtNext;
}
@@ -3275,6 +3303,45 @@ void Lowering::ContainCheckHWIntrinsic(GenTreeHWIntrinsic* node)
}
break;
+ case NI_Sve_ConditionalSelect:
+ {
+ assert(intrin.numOperands == 3);
+ GenTree* op1 = intrin.op1;
+ GenTree* op2 = intrin.op2;
+ GenTree* op3 = intrin.op3;
+
+ // Handle op1
+ if (op1->IsVectorZero())
+ {
+ // When we are merging with zero, we can specialize
+ // and avoid instantiating the vector constant.
+ MakeSrcContained(node, op1);
+ }
+
+ // Handle op2
+ if (op2->OperIsHWIntrinsic())
+ {
+ uint32_t maskSize = genTypeSize(node->GetSimdBaseType());
+ uint32_t operSize = genTypeSize(op2->AsHWIntrinsic()->GetSimdBaseType());
+
+ if ((maskSize == operSize) && IsInvariantInRange(op2, node))
+ {
+ MakeSrcContained(node, op2);
+ op2->MakeEmbMaskOp();
+ }
+ }
+
+ // Handle op3
+ if (op3->IsVectorZero())
+ {
+ // When we are merging with zero, we can specialize
+ // and avoid instantiating the vector constant.
+ MakeSrcContained(node, op3);
+ }
+
+ break;
+ }
+
default:
unreached();
}
diff --git a/src/coreclr/jit/lowerxarch.cpp b/src/coreclr/jit/lowerxarch.cpp
index 5a9b12ca4aa27..0e18c5685066f 100644
--- a/src/coreclr/jit/lowerxarch.cpp
+++ b/src/coreclr/jit/lowerxarch.cpp
@@ -2970,7 +2970,7 @@ GenTree* Lowering::LowerHWIntrinsicCndSel(GenTreeHWIntrinsic* node)
}
//----------------------------------------------------------------------------------------------
-// Lowering::LowerHWIntrinsicCndSel: Lowers an AVX512 TernaryLogic call
+// Lowering::LowerHWIntrinsicTernaryLogic: Lowers an AVX512 TernaryLogic call
//
// Arguments:
// node - The hardware intrinsic node.
@@ -10137,7 +10137,7 @@ void Lowering::ContainCheckHWIntrinsic(GenTreeHWIntrinsic* node)
// contained and not a memory operand and know to invoke the special handling
// so that the embedded masking can work as expected.
- if (op2->isEvexEmbeddedMaskingCompatibleHWIntrinsic())
+ if (op2->isEmbeddedMaskingCompatibleHWIntrinsic())
{
uint32_t maskSize = genTypeSize(simdBaseType);
uint32_t operSize = genTypeSize(op2->AsHWIntrinsic()->GetSimdBaseType());
diff --git a/src/coreclr/jit/lsrabuild.cpp b/src/coreclr/jit/lsrabuild.cpp
index 3ee0f88ee2214..37fa4320cc691 100644
--- a/src/coreclr/jit/lsrabuild.cpp
+++ b/src/coreclr/jit/lsrabuild.cpp
@@ -3489,6 +3489,16 @@ int LinearScan::BuildOperandUses(GenTree* node, regMaskTP candidates)
if (numArgs != 1)
{
+#ifdef TARGET_ARM64
+ if (HWIntrinsicInfo::IsScalable(hwintrinsic->GetHWIntrinsicId()))
+ {
+ for (size_t argNum = 1; argNum <= numArgs; argNum++)
+ {
+ BuildOperandUses(hwintrinsic->Op(argNum), candidates);
+ }
+ return (int)numArgs;
+ }
+#endif
assert(numArgs == 2);
assert(hwintrinsic->Op(2)->isContained());
assert(hwintrinsic->Op(2)->IsCnsIntOrI());
diff --git a/src/coreclr/jit/ssabuilder.cpp b/src/coreclr/jit/ssabuilder.cpp
index caba13f3536ab..0a5229e32b8b7 100644
--- a/src/coreclr/jit/ssabuilder.cpp
+++ b/src/coreclr/jit/ssabuilder.cpp
@@ -965,8 +965,8 @@ void SsaBuilder::AddPhiArgsToSuccessors(BasicBlock* block)
// Walk the statements for phi nodes.
for (Statement* const stmt : succ->Statements())
{
- // A prefix of the statements of the block are phi definition nodes. If we complete processing
- // that prefix, exit.
+ // A prefix of the statements of the block are phi definition nodes. If we complete
+ // processing that prefix, exit.
if (!stmt->IsPhiDefnStmt())
{
break;
@@ -988,8 +988,9 @@ void SsaBuilder::AddPhiArgsToSuccessors(BasicBlock* block)
{
if ((memoryKind == GcHeap) && m_pCompiler->byrefStatesMatchGcHeapStates)
{
- // We've already propagated the "out" number to the phi shared with ByrefExposed,
- // but still need to update bbMemorySsaPhiFunc to be in sync between GcHeap and ByrefExposed.
+ // We've already propagated the "out" number to the phi shared with
+ // ByrefExposed, but still need to update bbMemorySsaPhiFunc to be in sync
+ // between GcHeap and ByrefExposed.
assert(memoryKind > ByrefExposed);
assert(block->bbMemorySsaNumOut[memoryKind] == block->bbMemorySsaNumOut[ByrefExposed]);
assert((succ->bbMemorySsaPhiFunc[ByrefExposed] == succMemoryPhi) ||
@@ -1009,8 +1010,9 @@ void SsaBuilder::AddPhiArgsToSuccessors(BasicBlock* block)
BasicBlock::MemoryPhiArg* curArg = succMemoryPhi;
unsigned ssaNum = block->bbMemorySsaNumOut[memoryKind];
bool found = false;
- // This is a quadratic algorithm. We might need to consider some switch over to a hash table
- // representation for the arguments of a phi node, to make this linear.
+ // This is a quadratic algorithm. We might need to consider some switch over
+ // to a hash table representation for the arguments of a phi node, to make this
+ // linear.
while (curArg != nullptr)
{
if (curArg->m_ssaNum == ssaNum)
diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.PlatformNotSupported.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.PlatformNotSupported.cs
index fbd5ee65ca748..8d56e32fc863c 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.PlatformNotSupported.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.PlatformNotSupported.cs
@@ -31,6 +31,125 @@ internal Arm64() { }
public static new bool IsSupported { [Intrinsic] get { return false; } }
}
+
+ /// Abs : Absolute value
+
+ ///
+ /// svint8_t svabs[_s8]_m(svint8_t inactive, svbool_t pg, svint8_t op)
+ /// svint8_t svabs[_s8]_x(svbool_t pg, svint8_t op)
+ /// svint8_t svabs[_s8]_z(svbool_t pg, svint8_t op)
+ ///
+ public static unsafe Vector Abs(Vector value) { throw new PlatformNotSupportedException(); }
+
+ ///
+ /// svint16_t svabs[_s16]_m(svint16_t inactive, svbool_t pg, svint16_t op)
+ /// svint16_t svabs[_s16]_x(svbool_t pg, svint16_t op)
+ /// svint16_t svabs[_s16]_z(svbool_t pg, svint16_t op)
+ ///
+ public static unsafe Vector Abs(Vector value) { throw new PlatformNotSupportedException(); }
+
+ ///
+ /// svint32_t svabs[_s32]_m(svint32_t inactive, svbool_t pg, svint32_t op)
+ /// svint32_t svabs[_s32]_x(svbool_t pg, svint32_t op)
+ /// svint32_t svabs[_s32]_z(svbool_t pg, svint32_t op)
+ ///
+ public static unsafe Vector Abs(Vector value) { throw new PlatformNotSupportedException(); }
+
+ ///
+ /// svint64_t svabs[_s64]_m(svint64_t inactive, svbool_t pg, svint64_t op)
+ /// svint64_t svabs[_s64]_x(svbool_t pg, svint64_t op)
+ /// svint64_t svabs[_s64]_z(svbool_t pg, svint64_t op)
+ ///
+ public static unsafe Vector Abs(Vector value) { throw new PlatformNotSupportedException(); }
+
+ ///
+ /// svfloat32_t svabs[_f32]_m(svfloat32_t inactive, svbool_t pg, svfloat32_t op)
+ /// svfloat32_t svabs[_f32]_x(svbool_t pg, svfloat32_t op)
+ /// svfloat32_t svabs[_f32]_z(svbool_t pg, svfloat32_t op)
+ ///
+ public static unsafe Vector Abs(Vector value) { throw new PlatformNotSupportedException(); }
+
+ ///
+ /// svfloat64_t svabs[_f64]_m(svfloat64_t inactive, svbool_t pg, svfloat64_t op)
+ /// svfloat64_t svabs[_f64]_x(svbool_t pg, svfloat64_t op)
+ /// svfloat64_t svabs[_f64]_z(svbool_t pg, svfloat64_t op)
+ ///
+ public static unsafe Vector Abs(Vector value) { throw new PlatformNotSupportedException(); }
+
+
+ /// Add : Add
+
+ ///
+ /// svint8_t svadd[_s8]_m(svbool_t pg, svint8_t op1, svint8_t op2)
+ /// svint8_t svadd[_s8]_x(svbool_t pg, svint8_t op1, svint8_t op2)
+ /// svint8_t svadd[_s8]_z(svbool_t pg, svint8_t op1, svint8_t op2)
+ ///
+ public static unsafe Vector Add(Vector left, Vector right) { throw new PlatformNotSupportedException(); }
+
+ ///
+ /// svint16_t svadd[_s16]_m(svbool_t pg, svint16_t op1, svint16_t op2)
+ /// svint16_t svadd[_s16]_x(svbool_t pg, svint16_t op1, svint16_t op2)
+ /// svint16_t svadd[_s16]_z(svbool_t pg, svint16_t op1, svint16_t op2)
+ ///
+ public static unsafe Vector Add(Vector left, Vector right) { throw new PlatformNotSupportedException(); }
+
+ ///
+ /// svint32_t svadd[_s32]_m(svbool_t pg, svint32_t op1, svint32_t op2)
+ /// svint32_t svadd[_s32]_x(svbool_t pg, svint32_t op1, svint32_t op2)
+ /// svint32_t svadd[_s32]_z(svbool_t pg, svint32_t op1, svint32_t op2)
+ ///
+ public static unsafe Vector Add(Vector left, Vector right) { throw new PlatformNotSupportedException(); }
+
+ ///
+ /// svint64_t svadd[_s64]_m(svbool_t pg, svint64_t op1, svint64_t op2)
+ /// svint64_t svadd[_s64]_x(svbool_t pg, svint64_t op1, svint64_t op2)
+ /// svint64_t svadd[_s64]_z(svbool_t pg, svint64_t op1, svint64_t op2)
+ ///
+ public static unsafe Vector Add(Vector left, Vector right) { throw new PlatformNotSupportedException(); }
+
+ ///
+ /// svuint8_t svadd[_u8]_m(svbool_t pg, svuint8_t op1, svuint8_t op2)
+ /// svuint8_t svadd[_u8]_x(svbool_t pg, svuint8_t op1, svuint8_t op2)
+ /// svuint8_t svadd[_u8]_z(svbool_t pg, svuint8_t op1, svuint8_t op2)
+ ///
+ public static unsafe Vector Add(Vector left, Vector right) { throw new PlatformNotSupportedException(); }
+
+ ///
+ /// svuint16_t svadd[_u16]_m(svbool_t pg, svuint16_t op1, svuint16_t op2)
+ /// svuint16_t svadd[_u16]_x(svbool_t pg, svuint16_t op1, svuint16_t op2)
+ /// svuint16_t svadd[_u16]_z(svbool_t pg, svuint16_t op1, svuint16_t op2)
+ ///
+ public static unsafe Vector Add(Vector left, Vector right) { throw new PlatformNotSupportedException(); }
+
+ ///
+ /// svuint32_t svadd[_u32]_m(svbool_t pg, svuint32_t op1, svuint32_t op2)
+ /// svuint32_t svadd[_u32]_x(svbool_t pg, svuint32_t op1, svuint32_t op2)
+ /// svuint32_t svadd[_u32]_z(svbool_t pg, svuint32_t op1, svuint32_t op2)
+ ///
+ public static unsafe Vector Add(Vector left, Vector right) { throw new PlatformNotSupportedException(); }
+
+ ///
+ /// svuint64_t svadd[_u64]_m(svbool_t pg, svuint64_t op1, svuint64_t op2)
+ /// svuint64_t svadd[_u64]_x(svbool_t pg, svuint64_t op1, svuint64_t op2)
+ /// svuint64_t svadd[_u64]_z(svbool_t pg, svuint64_t op1, svuint64_t op2)
+ ///
+ public static unsafe Vector Add(Vector left, Vector right) { throw new PlatformNotSupportedException(); }
+
+ ///
+ /// svfloat32_t svadd[_f32]_m(svbool_t pg, svfloat32_t op1, svfloat32_t op2)
+ /// svfloat32_t svadd[_f32]_x(svbool_t pg, svfloat32_t op1, svfloat32_t op2)
+ /// svfloat32_t svadd[_f32]_z(svbool_t pg, svfloat32_t op1, svfloat32_t op2)
+ ///
+ public static unsafe Vector Add(Vector left, Vector right) { throw new PlatformNotSupportedException(); }
+
+ ///
+ /// svfloat64_t svadd[_f64]_m(svbool_t pg, svfloat64_t op1, svfloat64_t op2)
+ /// svfloat64_t svadd[_f64]_x(svbool_t pg, svfloat64_t op1, svfloat64_t op2)
+ /// svfloat64_t svadd[_f64]_z(svbool_t pg, svfloat64_t op1, svfloat64_t op2)
+ ///
+ public static unsafe Vector Add(Vector left, Vector right) { throw new PlatformNotSupportedException(); }
+
+
/// CreateTrueMaskByte : Set predicate elements to true
///
@@ -120,7 +239,65 @@ internal Arm64() { }
///
public static unsafe Vector CreateTrueMaskUInt64([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) { throw new PlatformNotSupportedException(); }
+ /// ConditionalSelect : Conditionally select elements
+
+ ///
+ /// svint8_t svsel[_s8](svbool_t pg, svint8_t op1, svint8_t op2)
+ /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2)
+ ///
+ public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) { throw new PlatformNotSupportedException(); }
+
+ ///
+ /// svint16_t svsel[_s16](svbool_t pg, svint16_t op1, svint16_t op2)
+ /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2)
+ ///
+ public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) { throw new PlatformNotSupportedException(); }
+
+ ///
+ /// svint32_t svsel[_s32](svbool_t pg, svint32_t op1, svint32_t op2)
+ /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2)
+ ///
+ public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) { throw new PlatformNotSupportedException(); }
+ ///
+ /// svint64_t svsel[_s64](svbool_t pg, svint64_t op1, svint64_t op2)
+ /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2)
+ ///
+ public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) { throw new PlatformNotSupportedException(); }
+
+ ///
+ /// svuint8_t svsel[_u8](svbool_t pg, svuint8_t op1, svuint8_t op2)
+ /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2)
+ ///
+ public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) { throw new PlatformNotSupportedException(); }
+
+ ///
+ /// svuint16_t svsel[_u16](svbool_t pg, svuint16_t op1, svuint16_t op2)
+ /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2)
+ ///
+ public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) { throw new PlatformNotSupportedException(); }
+
+ ///
+ /// svuint32_t svsel[_u32](svbool_t pg, svuint32_t op1, svuint32_t op2)
+ /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2)
+ ///
+ public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) { throw new PlatformNotSupportedException(); }
+
+ ///
+ /// svuint64_t svsel[_u64](svbool_t pg, svuint64_t op1, svuint64_t op2)
+ /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2)
+ ///
+ public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) { throw new PlatformNotSupportedException(); }
+
+ ///
+ /// svfloat32_t svsel[_f32](svbool_t pg, svfloat32_t op1, svfloat32_t op2)
+ ///
+ public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) { throw new PlatformNotSupportedException(); }
+
+ ///
+ /// svfloat64_t svsel[_f64](svbool_t pg, svfloat64_t op1, svfloat64_t op2)
+ ///
+ public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) { throw new PlatformNotSupportedException(); }
/// LoadVector : Unextended load
diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.cs
index 6ba2a2c67bc8a..a13957916f49a 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve.cs
@@ -29,6 +29,154 @@ internal Arm64() { }
}
+ /// Abs : Absolute value
+
+ ///
+ /// svint8_t svabs[_s8]_m(svint8_t inactive, svbool_t pg, svint8_t op)
+ /// ABS Ztied.B, Pg/M, Zop.B
+ /// MOVPRFX Zresult, Zinactive; ABS Zresult.B, Pg/M, Zop.B
+ /// svint8_t svabs[_s8]_x(svbool_t pg, svint8_t op)
+ /// ABS Ztied.B, Pg/M, Ztied.B
+ /// MOVPRFX Zresult, Zop; ABS Zresult.B, Pg/M, Zop.B
+ /// svint8_t svabs[_s8]_z(svbool_t pg, svint8_t op)
+ /// MOVPRFX Zresult.B, Pg/Z, Zop.B; ABS Zresult.B, Pg/M, Zop.B
+ ///
+ public static unsafe Vector Abs(Vector value) => Abs(value);
+
+ ///
+ /// svint16_t svabs[_s16]_m(svint16_t inactive, svbool_t pg, svint16_t op)
+ /// ABS Ztied.H, Pg/M, Zop.H
+ /// MOVPRFX Zresult, Zinactive; ABS Zresult.H, Pg/M, Zop.H
+ /// svint16_t svabs[_s16]_x(svbool_t pg, svint16_t op)
+ /// ABS Ztied.H, Pg/M, Ztied.H
+ /// MOVPRFX Zresult, Zop; ABS Zresult.H, Pg/M, Zop.H
+ /// svint16_t svabs[_s16]_z(svbool_t pg, svint16_t op)
+ /// MOVPRFX Zresult.H, Pg/Z, Zop.H; ABS Zresult.H, Pg/M, Zop.H
+ ///
+ public static unsafe Vector Abs(Vector value) => Abs(value);
+
+ ///
+ /// svint32_t svabs[_s32]_m(svint32_t inactive, svbool_t pg, svint32_t op)
+ /// ABS Ztied.S, Pg/M, Zop.S
+ /// MOVPRFX Zresult, Zinactive; ABS Zresult.S, Pg/M, Zop.S
+ /// svint32_t svabs[_s32]_x(svbool_t pg, svint32_t op)
+ /// ABS Ztied.S, Pg/M, Ztied.S
+ /// MOVPRFX Zresult, Zop; ABS Zresult.S, Pg/M, Zop.S
+ /// svint32_t svabs[_s32]_z(svbool_t pg, svint32_t op)
+ /// MOVPRFX Zresult.S, Pg/Z, Zop.S; ABS Zresult.S, Pg/M, Zop.S
+ ///
+ public static unsafe Vector Abs(Vector value) => Abs(value);
+
+ ///
+ /// svint64_t svabs[_s64]_m(svint64_t inactive, svbool_t pg, svint64_t op)
+ /// ABS Ztied.D, Pg/M, Zop.D
+ /// MOVPRFX Zresult, Zinactive; ABS Zresult.D, Pg/M, Zop.D
+ /// svint64_t svabs[_s64]_x(svbool_t pg, svint64_t op)
+ /// ABS Ztied.D, Pg/M, Ztied.D
+ /// MOVPRFX Zresult, Zop; ABS Zresult.D, Pg/M, Zop.D
+ /// svint64_t svabs[_s64]_z(svbool_t pg, svint64_t op)
+ /// MOVPRFX Zresult.D, Pg/Z, Zop.D; ABS Zresult.D, Pg/M, Zop.D
+ ///
+ public static unsafe Vector Abs(Vector value) => Abs(value);
+
+ ///
+ /// svfloat32_t svabs[_f32]_m(svfloat32_t inactive, svbool_t pg, svfloat32_t op)
+ /// FABS Ztied.S, Pg/M, Zop.S
+ /// MOVPRFX Zresult, Zinactive; FABS Zresult.S, Pg/M, Zop.S
+ /// svfloat32_t svabs[_f32]_x(svbool_t pg, svfloat32_t op)
+ /// FABS Ztied.S, Pg/M, Ztied.S
+ /// MOVPRFX Zresult, Zop; FABS Zresult.S, Pg/M, Zop.S
+ /// svfloat32_t svabs[_f32]_z(svbool_t pg, svfloat32_t op)
+ /// MOVPRFX Zresult.S, Pg/Z, Zop.S; FABS Zresult.S, Pg/M, Zop.S
+ ///
+ public static unsafe Vector Abs(Vector value) => Abs(value);
+
+ ///
+ /// svfloat64_t svabs[_f64]_m(svfloat64_t inactive, svbool_t pg, svfloat64_t op)
+ /// FABS Ztied.D, Pg/M, Zop.D
+ /// MOVPRFX Zresult, Zinactive; FABS Zresult.D, Pg/M, Zop.D
+ /// svfloat64_t svabs[_f64]_x(svbool_t pg, svfloat64_t op)
+ /// FABS Ztied.D, Pg/M, Ztied.D
+ /// MOVPRFX Zresult, Zop; FABS Zresult.D, Pg/M, Zop.D
+ /// svfloat64_t svabs[_f64]_z(svbool_t pg, svfloat64_t op)
+ /// MOVPRFX Zresult.D, Pg/Z, Zop.D; FABS Zresult.D, Pg/M, Zop.D
+ ///
+ public static unsafe Vector Abs(Vector value) => Abs(value);
+
+
+ /// Add : Add
+
+ ///
+ /// svint8_t svadd[_s8]_m(svbool_t pg, svint8_t op1, svint8_t op2)
+ /// svint8_t svadd[_s8]_x(svbool_t pg, svint8_t op1, svint8_t op2)
+ /// svint8_t svadd[_s8]_z(svbool_t pg, svint8_t op1, svint8_t op2)
+ ///
+ public static unsafe Vector Add(Vector left, Vector right) => Add(left, right);
+
+ ///
+ /// svint16_t svadd[_s16]_m(svbool_t pg, svint16_t op1, svint16_t op2)
+ /// svint16_t svadd[_s16]_x(svbool_t pg, svint16_t op1, svint16_t op2)
+ /// svint16_t svadd[_s16]_z(svbool_t pg, svint16_t op1, svint16_t op2)
+ ///
+ public static unsafe Vector Add(Vector left, Vector right) => Add(left, right);
+
+ ///
+ /// svint32_t svadd[_s32]_m(svbool_t pg, svint32_t op1, svint32_t op2)
+ /// svint32_t svadd[_s32]_x(svbool_t pg, svint32_t op1, svint32_t op2)
+ /// svint32_t svadd[_s32]_z(svbool_t pg, svint32_t op1, svint32_t op2)
+ ///
+ public static unsafe Vector Add(Vector left, Vector right) => Add(left, right);
+
+ ///
+ /// svint64_t svadd[_s64]_m(svbool_t pg, svint64_t op1, svint64_t op2)
+ /// svint64_t svadd[_s64]_x(svbool_t pg, svint64_t op1, svint64_t op2)
+ /// svint64_t svadd[_s64]_z(svbool_t pg, svint64_t op1, svint64_t op2)
+ ///
+ public static unsafe Vector Add(Vector left, Vector right) => Add(left, right);
+
+ ///
+ /// svuint8_t svadd[_u8]_m(svbool_t pg, svuint8_t op1, svuint8_t op2)
+ /// svuint8_t svadd[_u8]_x(svbool_t pg, svuint8_t op1, svuint8_t op2)
+ /// svuint8_t svadd[_u8]_z(svbool_t pg, svuint8_t op1, svuint8_t op2)
+ ///
+ public static unsafe Vector Add(Vector left, Vector right) => Add(left, right);
+
+ ///
+ /// svuint16_t svadd[_u16]_m(svbool_t pg, svuint16_t op1, svuint16_t op2)
+ /// svuint16_t svadd[_u16]_x(svbool_t pg, svuint16_t op1, svuint16_t op2)
+ /// svuint16_t svadd[_u16]_z(svbool_t pg, svuint16_t op1, svuint16_t op2)
+ ///
+ public static unsafe Vector Add(Vector left, Vector right) => Add(left, right);
+
+ ///
+ /// svuint32_t svadd[_u32]_m(svbool_t pg, svuint32_t op1, svuint32_t op2)
+ /// svuint32_t svadd[_u32]_x(svbool_t pg, svuint32_t op1, svuint32_t op2)
+ /// svuint32_t svadd[_u32]_z(svbool_t pg, svuint32_t op1, svuint32_t op2)
+ ///
+ public static unsafe Vector Add(Vector left, Vector right) => Add(left, right);
+
+ ///
+ /// svuint64_t svadd[_u64]_m(svbool_t pg, svuint64_t op1, svuint64_t op2)
+ /// svuint64_t svadd[_u64]_x(svbool_t pg, svuint64_t op1, svuint64_t op2)
+ /// svuint64_t svadd[_u64]_z(svbool_t pg, svuint64_t op1, svuint64_t op2)
+ ///
+ public static unsafe Vector Add(Vector left, Vector right) => Add(left, right);
+
+ ///
+ /// svfloat32_t svadd[_f32]_m(svbool_t pg, svfloat32_t op1, svfloat32_t op2)
+ /// svfloat32_t svadd[_f32]_x(svbool_t pg, svfloat32_t op1, svfloat32_t op2)
+ /// svfloat32_t svadd[_f32]_z(svbool_t pg, svfloat32_t op1, svfloat32_t op2)
+ ///
+ public static unsafe Vector Add(Vector left, Vector right) => Add(left, right);
+
+ ///
+ /// svfloat64_t svadd[_f64]_m(svbool_t pg, svfloat64_t op1, svfloat64_t op2)
+ /// svfloat64_t svadd[_f64]_x(svbool_t pg, svfloat64_t op1, svfloat64_t op2)
+ /// svfloat64_t svadd[_f64]_z(svbool_t pg, svfloat64_t op1, svfloat64_t op2)
+ ///
+ public static unsafe Vector Add(Vector left, Vector right) => Add(left, right);
+
+
/// CreateTrueMaskByte : Set predicate elements to true
///
@@ -118,7 +266,93 @@ internal Arm64() { }
///
public static unsafe Vector CreateTrueMaskUInt64([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) => CreateTrueMaskUInt64(pattern);
+ /// ConditionalSelect : Conditionally select elements
+
+ ///
+ /// svint8_t svsel[_s8](svbool_t pg, svint8_t op1, svint8_t op2)
+ /// SEL Zresult.B, Pg, Zop1.B, Zop2.B
+ /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2)
+ /// SEL Presult.B, Pg, Pop1.B, Pop2.B
+ ///
+ ///
+ public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) => ConditionalSelect(mask, left, right);
+
+ ///
+ /// svint16_t svsel[_s16](svbool_t pg, svint16_t op1, svint16_t op2)
+ /// SEL Zresult.H, Pg, Zop1.H, Zop2.H
+ /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2)
+ /// SEL Presult.B, Pg, Pop1.B, Pop2.B
+ ///
+ ///
+ public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) => ConditionalSelect(mask, left, right);
+
+ ///
+ /// svint32_t svsel[_s32](svbool_t pg, svint32_t op1, svint32_t op2)
+ /// SEL Zresult.S, Pg, Zop1.S, Zop2.S
+ /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2)
+ /// SEL Presult.B, Pg, Pop1.B, Pop2.B
+ ///
+ ///
+ public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) => ConditionalSelect(mask, left, right);
+
+ ///
+ /// svint64_t svsel[_s64](svbool_t pg, svint64_t op1, svint64_t op2)
+ /// SEL Zresult.D, Pg, Zop1.D, Zop2.D
+ /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2)
+ /// SEL Presult.B, Pg, Pop1.B, Pop2.B
+ ///
+ ///
+ public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) => ConditionalSelect(mask, left, right);
+
+ ///
+ /// svuint8_t svsel[_u8](svbool_t pg, svuint8_t op1, svuint8_t op2)
+ /// SEL Zresult.B, Pg, Zop1.B, Zop2.B
+ /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2)
+ /// SEL Presult.B, Pg, Pop1.B, Pop2.B
+ ///
+ ///
+ public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) => ConditionalSelect(mask, left, right);
+
+ ///
+ /// svuint16_t svsel[_u16](svbool_t pg, svuint16_t op1, svuint16_t op2)
+ /// SEL Zresult.H, Pg, Zop1.H, Zop2.H
+ /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2)
+ /// SEL Presult.B, Pg, Pop1.B, Pop2.B
+ ///
+ ///
+ public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) => ConditionalSelect(mask, left, right);
+
+ ///
+ /// svuint32_t svsel[_u32](svbool_t pg, svuint32_t op1, svuint32_t op2)
+ /// SEL Zresult.S, Pg, Zop1.S, Zop2.S
+ /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2)
+ /// SEL Presult.B, Pg, Pop1.B, Pop2.B
+ ///
+ ///
+ public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) => ConditionalSelect(mask, left, right);
+
+ ///
+ /// svuint64_t svsel[_u64](svbool_t pg, svuint64_t op1, svuint64_t op2)
+ /// SEL Zresult.D, Pg, Zop1.D, Zop2.D
+ /// svbool_t svsel[_b](svbool_t pg, svbool_t op1, svbool_t op2)
+ /// SEL Presult.B, Pg, Pop1.B, Pop2.B
+ ///
+ ///
+ public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) => ConditionalSelect(mask, left, right);
+ ///
+ /// svfloat32_t svsel[_f32](svbool_t pg, svfloat32_t op1, svfloat32_t op2)
+ /// SEL Zresult.S, Pg, Zop1.S, Zop2.S
+ ///
+ ///
+ public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) => ConditionalSelect(mask, left, right);
+
+ ///
+ /// svfloat64_t svsel[_f64](svbool_t pg, svfloat64_t op1, svfloat64_t op2)
+ /// SEL Zresult.D, Pg, Zop1.D, Zop2.D
+ ///
+ ///
+ public static unsafe Vector ConditionalSelect(Vector mask, Vector left, Vector right) => ConditionalSelect(mask, left, right);
/// LoadVector : Unextended load
diff --git a/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs b/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs
index c34725ba0bae5..a1813dba44719 100644
--- a/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs
+++ b/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs
@@ -4147,7 +4147,22 @@ internal Sve() { }
internal Arm64() { }
public static new bool IsSupported { get { throw null; } }
}
-
+ public static System.Numerics.Vector Abs(System.Numerics.Vector value) { throw null; }
+ public static System.Numerics.Vector Abs(System.Numerics.Vector value) { throw null; }
+ public static System.Numerics.Vector Abs(System.Numerics.Vector value) { throw null; }
+ public static System.Numerics.Vector Abs(System.Numerics.Vector value) { throw null; }
+ public static System.Numerics.Vector Abs(System.Numerics.Vector value) { throw null; }
+ public static System.Numerics.Vector Abs(System.Numerics.Vector value) { throw null; }
+ public static System.Numerics.Vector Add(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; }
+ public static System.Numerics.Vector Add(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; }
+ public static System.Numerics.Vector Add(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; }
+ public static System.Numerics.Vector Add(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; }
+ public static System.Numerics.Vector Add(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; }
+ public static System.Numerics.Vector Add(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; }
+ public static System.Numerics.Vector Add(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; }
+ public static System.Numerics.Vector Add(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; }
+ public static System.Numerics.Vector Add(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; }
+ public static System.Numerics.Vector Add(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; }
public static System.Numerics.Vector CreateTrueMaskByte([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) { throw null; }
public static System.Numerics.Vector CreateTrueMaskDouble([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) { throw null; }
public static System.Numerics.Vector CreateTrueMaskInt16([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) { throw null; }
@@ -4158,7 +4173,16 @@ internal Arm64() { }
public static System.Numerics.Vector CreateTrueMaskUInt16([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) { throw null; }
public static System.Numerics.Vector CreateTrueMaskUInt32([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) { throw null; }
public static System.Numerics.Vector CreateTrueMaskUInt64([ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) { throw null; }
-
+ public static System.Numerics.Vector ConditionalSelect(System.Numerics.Vector mask, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; }
+ public static System.Numerics.Vector ConditionalSelect(System.Numerics.Vector mask, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; }
+ public static System.Numerics.Vector ConditionalSelect(System.Numerics.Vector mask, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; }
+ public static System.Numerics.Vector ConditionalSelect(System.Numerics.Vector mask, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; }
+ public static System.Numerics.Vector ConditionalSelect(System.Numerics.Vector mask, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; }
+ public static System.Numerics.Vector ConditionalSelect(System.Numerics.Vector mask, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; }
+ public static System.Numerics.Vector ConditionalSelect(System.Numerics.Vector mask, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; }
+ public static System.Numerics.Vector ConditionalSelect(System.Numerics.Vector mask, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; }
+ public static System.Numerics.Vector ConditionalSelect(System.Numerics.Vector mask, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; }
+ public static System.Numerics.Vector ConditionalSelect(System.Numerics.Vector mask, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; }
public static unsafe System.Numerics.Vector