diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h
index 18fce48d72b344..66d53992b70759 100644
--- a/src/coreclr/jit/compiler.h
+++ b/src/coreclr/jit/compiler.h
@@ -3319,6 +3319,7 @@ class Compiler
unsigned simdSize,
bool isSimdAsHWIntrinsic);
+ GenTreeHWIntrinsic* gtNewScalarHWIntrinsicNode(var_types type, NamedIntrinsic hwIntrinsicID);
GenTreeHWIntrinsic* gtNewScalarHWIntrinsicNode(var_types type, GenTree* op1, NamedIntrinsic hwIntrinsicID);
GenTreeHWIntrinsic* gtNewScalarHWIntrinsicNode(var_types type,
GenTree* op1,
diff --git a/src/coreclr/jit/emit.h b/src/coreclr/jit/emit.h
index 3f6607a9966a52..22e9cfd6c79e09 100644
--- a/src/coreclr/jit/emit.h
+++ b/src/coreclr/jit/emit.h
@@ -1240,21 +1240,22 @@ class emitter
#define PERFSCORE_THROUGHPUT_1C 1.0f // Single Issue
-#define PERFSCORE_THROUGHPUT_2C 2.0f // slower - 2 cycles
-#define PERFSCORE_THROUGHPUT_3C 3.0f // slower - 3 cycles
-#define PERFSCORE_THROUGHPUT_4C 4.0f // slower - 4 cycles
-#define PERFSCORE_THROUGHPUT_5C 5.0f // slower - 5 cycles
-#define PERFSCORE_THROUGHPUT_6C 6.0f // slower - 6 cycles
-#define PERFSCORE_THROUGHPUT_7C 7.0f // slower - 7 cycles
-#define PERFSCORE_THROUGHPUT_8C 8.0f // slower - 8 cycles
-#define PERFSCORE_THROUGHPUT_9C 9.0f // slower - 9 cycles
-#define PERFSCORE_THROUGHPUT_10C 10.0f // slower - 10 cycles
-#define PERFSCORE_THROUGHPUT_13C 13.0f // slower - 13 cycles
-#define PERFSCORE_THROUGHPUT_19C 19.0f // slower - 19 cycles
-#define PERFSCORE_THROUGHPUT_25C 25.0f // slower - 25 cycles
-#define PERFSCORE_THROUGHPUT_33C 33.0f // slower - 33 cycles
-#define PERFSCORE_THROUGHPUT_52C 52.0f // slower - 52 cycles
-#define PERFSCORE_THROUGHPUT_57C 57.0f // slower - 57 cycles
+#define PERFSCORE_THROUGHPUT_2C 2.0f // slower - 2 cycles
+#define PERFSCORE_THROUGHPUT_3C 3.0f // slower - 3 cycles
+#define PERFSCORE_THROUGHPUT_4C 4.0f // slower - 4 cycles
+#define PERFSCORE_THROUGHPUT_5C 5.0f // slower - 5 cycles
+#define PERFSCORE_THROUGHPUT_6C 6.0f // slower - 6 cycles
+#define PERFSCORE_THROUGHPUT_7C 7.0f // slower - 7 cycles
+#define PERFSCORE_THROUGHPUT_8C 8.0f // slower - 8 cycles
+#define PERFSCORE_THROUGHPUT_9C 9.0f // slower - 9 cycles
+#define PERFSCORE_THROUGHPUT_10C 10.0f // slower - 10 cycles
+#define PERFSCORE_THROUGHPUT_13C 13.0f // slower - 13 cycles
+#define PERFSCORE_THROUGHPUT_19C 19.0f // slower - 19 cycles
+#define PERFSCORE_THROUGHPUT_25C 25.0f // slower - 25 cycles
+#define PERFSCORE_THROUGHPUT_33C 33.0f // slower - 33 cycles
+#define PERFSCORE_THROUGHPUT_52C 52.0f // slower - 52 cycles
+#define PERFSCORE_THROUGHPUT_57C 57.0f // slower - 57 cycles
+#define PERFSCORE_THROUGHPUT_140C 140.0f // slower - 140 cycles
#define PERFSCORE_LATENCY_ILLEGAL -1024.0f
@@ -1281,6 +1282,7 @@ class emitter
#define PERFSCORE_LATENCY_26C 26.0f
#define PERFSCORE_LATENCY_62C 62.0f
#define PERFSCORE_LATENCY_69C 69.0f
+#define PERFSCORE_LATENCY_140C 140.0f
#define PERFSCORE_LATENCY_400C 400.0f // Intel microcode issue with these instuctions
#define PERFSCORE_LATENCY_BRANCH_DIRECT 1.0f // cost of an unconditional branch
diff --git a/src/coreclr/jit/emitarm64.cpp b/src/coreclr/jit/emitarm64.cpp
index 0e9da02b60cd4e..1ae7aa873a0aef 100644
--- a/src/coreclr/jit/emitarm64.cpp
+++ b/src/coreclr/jit/emitarm64.cpp
@@ -14588,6 +14588,12 @@ emitter::insExecutionCharacteristics emitter::getInsExecutionCharacteristics(ins
result.insThroughput = PERFSCORE_THROUGHPUT_ZERO;
result.insLatency = PERFSCORE_LATENCY_ZERO;
}
+ else if (ins == INS_yield)
+ {
+ // @ToDo - find out the actual latency, match x86/x64 for now
+ result.insThroughput = PERFSCORE_THROUGHPUT_140C;
+ result.insLatency = PERFSCORE_LATENCY_140C;
+ }
else
{
result.insThroughput = PERFSCORE_THROUGHPUT_2X;
diff --git a/src/coreclr/jit/emitxarch.cpp b/src/coreclr/jit/emitxarch.cpp
index fa6d44cda0f4bc..00c403d08768d9 100644
--- a/src/coreclr/jit/emitxarch.cpp
+++ b/src/coreclr/jit/emitxarch.cpp
@@ -2898,7 +2898,8 @@ void emitter::emitIns(instruction ins)
ins == INS_r_movsp || ins == INS_r_stosb || ins == INS_r_stosd || ins == INS_r_stosp || ins == INS_ret ||
ins == INS_sahf || ins == INS_stosb || ins == INS_stosd || ins == INS_stosp
// These instructions take zero operands
- || ins == INS_vzeroupper || ins == INS_lfence || ins == INS_mfence || ins == INS_sfence);
+ || ins == INS_vzeroupper || ins == INS_lfence || ins == INS_mfence || ins == INS_sfence ||
+ ins == INS_pause);
assert(assertCond);
}
@@ -12333,8 +12334,8 @@ BYTE* emitter::emitOutputRR(BYTE* dst, instrDesc* id)
// Due to elided register moves, we can't have the following assert.
// For example, consider:
// t85 = LCL_VAR byref V01 arg1 rdx (last use) REG rdx
- // /--* t85 byref
- // * STORE_LCL_VAR byref V40 tmp31 rdx REG rdx
+ // /--* t85 byref
+ // * STORE_LCL_VAR byref V40 tmp31 rdx REG rdx
// Here, V01 is type `long` on entry, then is stored as a byref. But because
// the register allocator assigned the same register, no instruction was
// generated, and we only (currently) make gcref/byref changes in emitter GC info
@@ -16104,6 +16105,13 @@ emitter::insExecutionCharacteristics emitter::getInsExecutionCharacteristics(ins
result.insThroughput = PERFSCORE_THROUGHPUT_2X;
break;
+ case INS_pause:
+ {
+ result.insLatency = PERFSCORE_LATENCY_140C;
+ result.insThroughput = PERFSCORE_THROUGHPUT_140C;
+ break;
+ }
+
default:
// unhandled instruction insFmt combination
perfScoreUnhandledInstruction(id, &result);
diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp
index e7aded8d92c927..867e2ae9e72c6e 100644
--- a/src/coreclr/jit/gentree.cpp
+++ b/src/coreclr/jit/gentree.cpp
@@ -21948,6 +21948,12 @@ GenTree* Compiler::gtNewSimdZeroNode(var_types type,
return gtNewSimdHWIntrinsicNode(type, intrinsic, simdBaseJitType, simdSize, isSimdAsHWIntrinsic);
}
+GenTreeHWIntrinsic* Compiler::gtNewScalarHWIntrinsicNode(var_types type, NamedIntrinsic hwIntrinsicID)
+{
+ return new (this, GT_HWINTRINSIC)
+ GenTreeHWIntrinsic(type, hwIntrinsicID, CORINFO_TYPE_UNDEF, 0, /* isSimdAsHWIntrinsic */ false);
+}
+
GenTreeHWIntrinsic* Compiler::gtNewScalarHWIntrinsicNode(var_types type, GenTree* op1, NamedIntrinsic hwIntrinsicID)
{
SetOpLclRelatedToSIMDIntrinsic(op1);
diff --git a/src/coreclr/jit/hwintrinsic.h b/src/coreclr/jit/hwintrinsic.h
index 0b35ca719b6e2f..186b64463d820f 100644
--- a/src/coreclr/jit/hwintrinsic.h
+++ b/src/coreclr/jit/hwintrinsic.h
@@ -804,7 +804,7 @@ struct HWIntrinsic final
if (baseType == TYP_UNKNOWN)
{
- assert(category == HW_Category_Scalar);
+ assert((category == HW_Category_Scalar) || (category == HW_Category_Special));
if (HWIntrinsicInfo::BaseTypeFromFirstArg(id))
{
diff --git a/src/coreclr/jit/hwintrinsicarm64.cpp b/src/coreclr/jit/hwintrinsicarm64.cpp
index 8f4d0f0ebf96fd..f72fbaf1df7e1e 100644
--- a/src/coreclr/jit/hwintrinsicarm64.cpp
+++ b/src/coreclr/jit/hwintrinsicarm64.cpp
@@ -308,9 +308,8 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic,
var_types retType,
unsigned simdSize)
{
- HWIntrinsicCategory category = HWIntrinsicInfo::lookupCategory(intrinsic);
- int numArgs = sig->numArgs;
- var_types simdBaseType = JitType2PreciseVarType(simdBaseJitType);
+ HWIntrinsicCategory category = HWIntrinsicInfo::lookupCategory(intrinsic);
+ int numArgs = sig->numArgs;
if (!featureSIMD || !IsBaselineSimdIsaSupported())
{
@@ -318,7 +317,14 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic,
}
assert(numArgs >= 0);
- assert(varTypeIsArithmetic(simdBaseType));
+
+ var_types simdBaseType = TYP_UNKNOWN;
+
+ if (intrinsic != NI_ArmBase_Yield)
+ {
+ simdBaseType = JitType2PreciseVarType(simdBaseJitType);
+ assert(varTypeIsArithmetic(simdBaseType));
+ }
GenTree* retNode = nullptr;
GenTree* op1 = nullptr;
@@ -327,6 +333,16 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic,
switch (intrinsic)
{
+ case NI_ArmBase_Yield:
+ {
+ assert(sig->numArgs == 0);
+ assert(JITtype2varType(sig->retType) == TYP_VOID);
+ assert(simdSize == 0);
+
+ retNode = gtNewScalarHWIntrinsicNode(TYP_VOID, intrinsic);
+ break;
+ }
+
case NI_Vector64_Abs:
case NI_Vector128_Abs:
{
diff --git a/src/coreclr/jit/hwintrinsiccodegenarm64.cpp b/src/coreclr/jit/hwintrinsiccodegenarm64.cpp
index 3352c9ba595710..8604d0db811d2d 100644
--- a/src/coreclr/jit/hwintrinsiccodegenarm64.cpp
+++ b/src/coreclr/jit/hwintrinsiccodegenarm64.cpp
@@ -255,6 +255,13 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node)
emitSize = emitActualTypeSize(intrin.baseType);
opt = INS_OPTS_NONE;
}
+ else if (intrin.category == HW_Category_Special)
+ {
+ assert(intrin.id == NI_ArmBase_Yield);
+
+ emitSize = EA_UNKNOWN;
+ opt = INS_OPTS_NONE;
+ }
else
{
emitSize = emitActualTypeSize(Compiler::getSIMDTypeForSize(node->GetSimdSize()));
@@ -443,6 +450,12 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node)
}
break;
+ case NI_ArmBase_Yield:
+ {
+ ins = INS_yield;
+ break;
+ }
+
default:
ins = HWIntrinsicInfo::lookupIns(intrin.id, intrin.baseType);
break;
@@ -735,6 +748,12 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node)
}
break;
+ case NI_ArmBase_Yield:
+ {
+ GetEmitter()->emitIns(ins);
+ break;
+ }
+
// mvni doesn't support the range of element types, so hard code the 'opts' value.
case NI_Vector64_get_Zero:
case NI_Vector64_get_AllBitsSet:
diff --git a/src/coreclr/jit/hwintrinsiccodegenxarch.cpp b/src/coreclr/jit/hwintrinsiccodegenxarch.cpp
index 8523b529cbec42..0dc565d65575a7 100644
--- a/src/coreclr/jit/hwintrinsiccodegenxarch.cpp
+++ b/src/coreclr/jit/hwintrinsiccodegenxarch.cpp
@@ -1447,6 +1447,8 @@ void CodeGen::genX86BaseIntrinsic(GenTreeHWIntrinsic* node)
{
NamedIntrinsic intrinsicId = node->gtHWIntrinsicId;
+ genConsumeOperands(node);
+
switch (intrinsicId)
{
case NI_X86Base_BitScanForward:
@@ -1459,9 +1461,16 @@ void CodeGen::genX86BaseIntrinsic(GenTreeHWIntrinsic* node)
var_types targetType = node->TypeGet();
instruction ins = HWIntrinsicInfo::lookupIns(intrinsicId, targetType);
- genConsumeOperands(node);
genHWIntrinsic_R_RM(node, ins, emitTypeSize(targetType), targetReg, op1);
- genProduceReg(node);
+ break;
+ }
+
+ case NI_X86Base_Pause:
+ {
+ assert(node->GetSimdBaseType() == TYP_UNKNOWN);
+ assert(node->gtGetOp1() == nullptr);
+ assert(node->gtGetOp2() == nullptr);
+ GetEmitter()->emitIns(INS_pause);
break;
}
@@ -1469,6 +1478,8 @@ void CodeGen::genX86BaseIntrinsic(GenTreeHWIntrinsic* node)
unreached();
break;
}
+
+ genProduceReg(node);
}
//------------------------------------------------------------------------
@@ -1532,7 +1543,7 @@ void CodeGen::genSSEIntrinsic(GenTreeHWIntrinsic* node)
case NI_SSE_StoreFence:
{
- assert(baseType == TYP_VOID);
+ assert(baseType == TYP_UNKNOWN);
assert(op1 == nullptr);
assert(op2 == nullptr);
emit->emitIns(INS_sfence);
@@ -1617,7 +1628,7 @@ void CodeGen::genSSE2Intrinsic(GenTreeHWIntrinsic* node)
case NI_SSE2_LoadFence:
{
- assert(baseType == TYP_VOID);
+ assert(baseType == TYP_UNKNOWN);
assert(op1 == nullptr);
assert(op2 == nullptr);
emit->emitIns(INS_lfence);
@@ -1626,7 +1637,7 @@ void CodeGen::genSSE2Intrinsic(GenTreeHWIntrinsic* node)
case NI_SSE2_MemoryFence:
{
- assert(baseType == TYP_VOID);
+ assert(baseType == TYP_UNKNOWN);
assert(op1 == nullptr);
assert(op2 == nullptr);
emit->emitIns(INS_mfence);
diff --git a/src/coreclr/jit/hwintrinsiclistarm64.h b/src/coreclr/jit/hwintrinsiclistarm64.h
index 3f6c90a1315f87..c7e49b91a05be8 100644
--- a/src/coreclr/jit/hwintrinsiclistarm64.h
+++ b/src/coreclr/jit/hwintrinsiclistarm64.h
@@ -627,6 +627,7 @@ HARDWARE_INTRINSIC(Aes, PolynomialMultiplyWideningUpper,
// Base Intrinsics
HARDWARE_INTRINSIC(ArmBase, LeadingZeroCount, 0, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_clz, INS_clz, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoFloatingPointUsed)
HARDWARE_INTRINSIC(ArmBase, ReverseElementBits, 0, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_rbit, INS_rbit, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoFloatingPointUsed)
+HARDWARE_INTRINSIC(ArmBase, Yield, 0, 0, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Special, HW_Flag_SpecialCodeGen|HW_Flag_SpecialImport)
// ***************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
// ISA Function name SIMD size Number of arguments Instructions Category Flags
diff --git a/src/coreclr/jit/hwintrinsiclistxarch.h b/src/coreclr/jit/hwintrinsiclistxarch.h
index 7179e9854b382f..ce66b6e6906040 100644
--- a/src/coreclr/jit/hwintrinsiclistxarch.h
+++ b/src/coreclr/jit/hwintrinsiclistxarch.h
@@ -199,6 +199,7 @@ HARDWARE_INTRINSIC(Vector256, Xor,
// X86Base Intrinsics
HARDWARE_INTRINSIC(X86Base, BitScanForward, 0, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_bsf, INS_bsf, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoFloatingPointUsed|HW_Flag_NoRMWSemantics)
HARDWARE_INTRINSIC(X86Base, BitScanReverse, 0, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_bsr, INS_bsr, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoFloatingPointUsed|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(X86Base, Pause, 0, 0, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Special, HW_Flag_NoContainment|HW_Flag_NoRMWSemantics)
// ***************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
// ISA Function name SIMD size NumArg Instructions Category Flags
diff --git a/src/coreclr/jit/hwintrinsicxarch.cpp b/src/coreclr/jit/hwintrinsicxarch.cpp
index c0ed9a4de197f4..a565d7b3855447 100644
--- a/src/coreclr/jit/hwintrinsicxarch.cpp
+++ b/src/coreclr/jit/hwintrinsicxarch.cpp
@@ -491,6 +491,7 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic,
{
case InstructionSet_Vector256:
case InstructionSet_Vector128:
+ case InstructionSet_X86Base:
return impBaseIntrinsic(intrinsic, clsHnd, method, sig, simdBaseJitType, retType, simdSize);
case InstructionSet_SSE:
return impSSEIntrinsic(intrinsic, method, sig);
@@ -548,8 +549,13 @@ GenTree* Compiler::impBaseIntrinsic(NamedIntrinsic intrinsic,
return nullptr;
}
- var_types simdBaseType = JitType2PreciseVarType(simdBaseJitType);
- assert(varTypeIsArithmetic(simdBaseType));
+ var_types simdBaseType = TYP_UNKNOWN;
+
+ if (intrinsic != NI_X86Base_Pause)
+ {
+ simdBaseType = JitType2PreciseVarType(simdBaseJitType);
+ assert(varTypeIsArithmetic(simdBaseType));
+ }
switch (intrinsic)
{
@@ -1532,6 +1538,16 @@ GenTree* Compiler::impBaseIntrinsic(NamedIntrinsic intrinsic,
break;
}
+ case NI_X86Base_Pause:
+ {
+ assert(sig->numArgs == 0);
+ assert(JITtype2varType(sig->retType) == TYP_VOID);
+ assert(simdSize == 0);
+
+ retNode = gtNewScalarHWIntrinsicNode(TYP_VOID, intrinsic);
+ break;
+ }
+
default:
{
return nullptr;
@@ -1604,7 +1620,7 @@ GenTree* Compiler::impSSEIntrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HAND
case NI_SSE_StoreFence:
assert(sig->numArgs == 0);
assert(JITtype2varType(sig->retType) == TYP_VOID);
- retNode = gtNewSimdHWIntrinsicNode(TYP_VOID, intrinsic, CORINFO_TYPE_VOID, 0);
+ retNode = gtNewScalarHWIntrinsicNode(TYP_VOID, intrinsic);
break;
default:
@@ -1667,7 +1683,7 @@ GenTree* Compiler::impSSE2Intrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HAN
assert(JITtype2varType(sig->retType) == TYP_VOID);
assert(simdSize == 0);
- retNode = gtNewSimdHWIntrinsicNode(TYP_VOID, intrinsic, CORINFO_TYPE_VOID, simdSize);
+ retNode = gtNewScalarHWIntrinsicNode(TYP_VOID, intrinsic);
break;
}
diff --git a/src/coreclr/jit/instrsarm64.h b/src/coreclr/jit/instrsarm64.h
index 548c13f339469f..fbd74c1030522c 100644
--- a/src/coreclr/jit/instrsarm64.h
+++ b/src/coreclr/jit/instrsarm64.h
@@ -1563,6 +1563,9 @@ INST1(uxth, "uxth", 0, IF_DR_2H, 0x53003C00)
INST1(nop, "nop", 0, IF_SN_0A, 0xD503201F)
// nop SN_0A 1101010100000011 0010000000011111 D503 201F
+INST1(yield, "yield", 0, IF_SN_0A, 0xD503203F)
+ // yield SN_0A 1101010100000011 0010000000111111 D503 203F
+
INST1(bkpt, "bkpt", 0, IF_SN_0A, 0xD43E0000)
// brpt SN_0A 1101010000111110 0000000000000000 D43E 0000 0xF000
diff --git a/src/coreclr/jit/instrsxarch.h b/src/coreclr/jit/instrsxarch.h
index 4dc1fffd098d51..17b94fc81d779e 100644
--- a/src/coreclr/jit/instrsxarch.h
+++ b/src/coreclr/jit/instrsxarch.h
@@ -640,11 +640,11 @@ INST2(rcl, "rcl", IUM_RW, 0x0010D2, BAD_CODE,
INST2(rcl_1, "rcl", IUM_RW, 0x0010D0, 0x0010D0, Writes_OF | Writes_CF
| Reads_CF )
INST2(rcl_N, "rcl", IUM_RW, 0x0010C0, 0x0010C0, Undefined_OF | Writes_CF
- | Reads_CF )
+ | Reads_CF )
INST2(rcr, "rcr", IUM_RW, 0x0018D2, BAD_CODE, Undefined_OF | Writes_CF
| Reads_CF )
INST2(rcr_1, "rcr", IUM_RW, 0x0018D0, 0x0018D0, Writes_OF | Writes_CF
- | Reads_CF )
+ | Reads_CF )
INST2(rcr_N, "rcr", IUM_RW, 0x0018C0, 0x0018C0, Undefined_OF | Writes_CF
| Reads_CF )
INST2(shl, "shl", IUM_RW, 0x0020D2, BAD_CODE, Undefined_OF | Writes_SF | Writes_ZF | Undefined_AF | Writes_PF | Writes_CF )
@@ -683,6 +683,7 @@ INST1(stosq, "stosq", IUM_RD, 0x00AB48,
INST1(int3, "int3", IUM_RD, 0x0000CC, INS_FLAGS_None )
INST1(nop, "nop", IUM_RD, 0x000090, INS_FLAGS_None )
+INST1(pause, "pause", IUM_RD, 0x0090F3, INS_FLAGS_None )
INST1(lock, "lock", IUM_RD, 0x0000F0, INS_FLAGS_None )
INST1(leave, "leave", IUM_RD, 0x0000C9, INS_FLAGS_None )
diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/ArmBase.PlatformNotSupported.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/ArmBase.PlatformNotSupported.cs
index af23cef761ad92..aab444638fda17 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/ArmBase.PlatformNotSupported.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/ArmBase.PlatformNotSupported.cs
@@ -91,5 +91,11 @@ internal Arm64() { }
/// A64: RBIT Wd, Wn
///
public static uint ReverseElementBits(uint value) { throw new PlatformNotSupportedException(); }
+
+ ///
+ /// A32: YIELD
+ /// A64: YIELD
+ ///
+ public static void Yield() { throw new PlatformNotSupportedException(); }
}
}
diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/ArmBase.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/ArmBase.cs
index 4900e618cf2dc3..dd378377f5c506 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/ArmBase.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/ArmBase.cs
@@ -87,5 +87,11 @@ internal Arm64() { }
/// A64: RBIT Wd, Wn
///
public static uint ReverseElementBits(uint value) => ReverseElementBits(value);
+
+ ///
+ /// A32: YIELD
+ /// A64: YIELD
+ ///
+ public static void Yield() => Yield();
}
}
diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/X86/X86Base.PlatformNotSupported.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/X86/X86Base.PlatformNotSupported.cs
index 261ac82076ecb4..9ca497a5b8990b 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/X86/X86Base.PlatformNotSupported.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/X86/X86Base.PlatformNotSupported.cs
@@ -67,9 +67,15 @@ internal X64() { }
internal static uint BitScanReverse(uint value) { throw new PlatformNotSupportedException(); }
///
- /// void __cpuidex(int cpuInfo[4], int function_id, int subfunction_id);
+ /// void __cpuidex (int cpuInfo[4], int function_id, int subfunction_id);
/// CPUID
///
public static (int Eax, int Ebx, int Ecx, int Edx) CpuId(int functionId, int subFunctionId) { throw new PlatformNotSupportedException(); }
+
+ ///
+ /// void _mm_pause (void);
+ /// PAUSE
+ ///
+ public static void Pause() { throw new PlatformNotSupportedException(); }
}
}
diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/X86/X86Base.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/X86/X86Base.cs
index 7f7576be50ad25..c8b230b86166bc 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/X86/X86Base.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/X86/X86Base.cs
@@ -69,7 +69,7 @@ internal X64() { }
internal static uint BitScanReverse(uint value) => BitScanReverse(value);
///
- /// void __cpuidex(int cpuInfo[4], int function_id, int subfunction_id);
+ /// void __cpuidex (int cpuInfo[4], int function_id, int subfunction_id);
/// CPUID
///
public static unsafe (int Eax, int Ebx, int Ecx, int Edx) CpuId(int functionId, int subFunctionId)
@@ -78,5 +78,11 @@ public static unsafe (int Eax, int Ebx, int Ecx, int Edx) CpuId(int functionId,
__cpuidex(cpuInfo, functionId, subFunctionId);
return (cpuInfo[0], cpuInfo[1], cpuInfo[2], cpuInfo[3]);
}
+
+ ///
+ /// void _mm_pause (void);
+ /// PAUSE
+ ///
+ public static void Pause() => Pause();
}
}
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 d4bb25487ad490..c71ed7d1fd624c 100644
--- a/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs
+++ b/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs
@@ -2840,6 +2840,7 @@ internal ArmBase() { }
public static int LeadingZeroCount(uint value) { throw null; }
public static int ReverseElementBits(int value) { throw null; }
public static uint ReverseElementBits(uint value) { throw null; }
+ public static void Yield() { throw null; }
public abstract partial class Arm64
{
internal Arm64() { }
@@ -3653,7 +3654,6 @@ internal X64() { }
public static new bool IsSupported { get { throw null; } }
}
}
-
[System.CLSCompliantAttribute(false)]
[System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("AvxVnni is in preview.")]
public abstract class AvxVnni : System.Runtime.Intrinsics.X86.Avx2
@@ -3674,7 +3674,6 @@ internal X64() { }
public static new bool IsSupported { get { throw null; } }
}
}
-
[System.CLSCompliantAttribute(false)]
public abstract partial class Bmi1 : System.Runtime.Intrinsics.X86.X86Base
{
@@ -4497,6 +4496,7 @@ public abstract partial class X86Base
internal X86Base() { }
public static bool IsSupported { get { throw null; } }
public static (int Eax, int Ebx, int Ecx, int Edx) CpuId(int functionId, int subFunctionId) { throw null; }
+ public static void Pause() { throw null; }
public abstract partial class X64
{
internal X64() { }
diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/ArmBase/Yield.cs b/src/tests/JIT/HardwareIntrinsics/Arm/ArmBase/Yield.cs
new file mode 100644
index 00000000000000..51f0ded9d94536
--- /dev/null
+++ b/src/tests/JIT/HardwareIntrinsics/Arm/ArmBase/Yield.cs
@@ -0,0 +1,34 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+//
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
+using System.Runtime.Intrinsics.Arm;
+
+namespace JIT.HardwareIntrinsics.Arm
+{
+ class Program
+ {
+ const int Pass = 100;
+ const int Fail = 0;
+
+ static unsafe int Main(string[] args)
+ {
+ int testResult = ArmBase.IsSupported ? Pass : Fail;
+
+ try
+ {
+ ArmBase.Yield();
+ }
+ catch (Exception e)
+ {
+ testResult = (ArmBase.IsSupported || (e is not PlatformNotSupportedException)) ? Fail : Pass;
+ }
+
+ return testResult;
+ }
+ }
+}
diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/ArmBase/Yield_r.csproj b/src/tests/JIT/HardwareIntrinsics/Arm/ArmBase/Yield_r.csproj
new file mode 100644
index 00000000000000..168f77656f101b
--- /dev/null
+++ b/src/tests/JIT/HardwareIntrinsics/Arm/ArmBase/Yield_r.csproj
@@ -0,0 +1,13 @@
+
+
+ Exe
+ true
+
+
+ Embedded
+
+
+
+
+
+
diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/ArmBase/Yield_ro.csproj b/src/tests/JIT/HardwareIntrinsics/Arm/ArmBase/Yield_ro.csproj
new file mode 100644
index 00000000000000..ac75e1bac6ed05
--- /dev/null
+++ b/src/tests/JIT/HardwareIntrinsics/Arm/ArmBase/Yield_ro.csproj
@@ -0,0 +1,13 @@
+
+
+ Exe
+ true
+
+
+ Embedded
+ True
+
+
+
+
+
diff --git a/src/tests/JIT/HardwareIntrinsics/X86/X86Base/Pause.cs b/src/tests/JIT/HardwareIntrinsics/X86/X86Base/Pause.cs
new file mode 100644
index 00000000000000..54223b04e66e89
--- /dev/null
+++ b/src/tests/JIT/HardwareIntrinsics/X86/X86Base/Pause.cs
@@ -0,0 +1,34 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+//
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
+using System.Runtime.Intrinsics.X86;
+
+namespace IntelHardwareIntrinsicTest
+{
+ class Program
+ {
+ const int Pass = 100;
+ const int Fail = 0;
+
+ static unsafe int Main(string[] args)
+ {
+ int testResult = X86Base.IsSupported ? Pass : Fail;
+
+ try
+ {
+ X86Base.Pause();
+ }
+ catch (Exception e)
+ {
+ testResult = (X86Base.IsSupported || (e is not PlatformNotSupportedException)) ? Fail : Pass;
+ }
+
+ return testResult;
+ }
+ }
+}
diff --git a/src/tests/JIT/HardwareIntrinsics/X86/X86Base/Pause_r.csproj b/src/tests/JIT/HardwareIntrinsics/X86/X86Base/Pause_r.csproj
new file mode 100644
index 00000000000000..9b005d1608375e
--- /dev/null
+++ b/src/tests/JIT/HardwareIntrinsics/X86/X86Base/Pause_r.csproj
@@ -0,0 +1,13 @@
+
+
+ Exe
+ true
+
+
+ Embedded
+
+
+
+
+
+
diff --git a/src/tests/JIT/HardwareIntrinsics/X86/X86Base/Pause_ro.csproj b/src/tests/JIT/HardwareIntrinsics/X86/X86Base/Pause_ro.csproj
new file mode 100644
index 00000000000000..8943a9d7d3ebac
--- /dev/null
+++ b/src/tests/JIT/HardwareIntrinsics/X86/X86Base/Pause_ro.csproj
@@ -0,0 +1,13 @@
+
+
+ Exe
+ true
+
+
+ Embedded
+ True
+
+
+
+
+