Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve support for 512-bit Vector<T> #111472

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 3 additions & 0 deletions eng/pipelines/common/templates/runtimes/run-test-job.yml
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,9 @@ jobs:
- jitstress_isas_x86_nosse41
- jitstress_isas_x86_nosse42
- jitstress_isas_x86_nossse3
- jitstress_isas_x86_vectort128
- jitstress_isas_x86_vectort512
- jitstress_isas_x86_noavx512_vectort128
- jitstress_isas_1_x86_noaes
- jitstress_isas_1_x86_noavx
- jitstress_isas_1_x86_noavx2
Expand Down
3 changes: 3 additions & 0 deletions src/coreclr/inc/clrconfigvalues.h
Original file line number Diff line number Diff line change
Expand Up @@ -686,6 +686,9 @@ RETAIL_CONFIG_DWORD_INFO(INTERNAL_GDBJitEmitDebugFrame, W("GDBJitEmitDebugFrame"
#endif

RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_MaxVectorTBitWidth, W("MaxVectorTBitWidth"), 0, "The maximum decimal width, in bits, that Vector<T> is allowed to be. A value less than 128 is treated as the system default.", CLRConfig::LookupOptions::ParseIntegerAsBase10)
#if defined(TARGET_AMD64) || defined(TARGET_X86)
RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_PreferredVectorBitWidth, W("PreferredVectorBitWidth"), 0, "The maximum decimal width, in bits, of fixed-width vectors that may be considered hardware accelerated. A value less than 128 is treated as the system default.", CLRConfig::LookupOptions::ParseIntegerAsBase10)
Copy link
Member

@jkotas jkotas Jan 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we avoid reading the config setting in both VM and the JIT so that there is just one source of truth?

I assume that the JIT should be able to get the PreferredVectorBitWidth from the VM's Vector<T> now that Vector<T> size is set based on it.

Copy link
Member Author

@saucecontrol saucecontrol Jan 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's still a disconnect, because we'll continue to default Vector<T> to 256-bit even when PreferredVectorBitWidth is 512 (or 0 with fully-accelerated AVX-512). i.e. 512-bit Vector<T> will continue to be strictly opt-in for the foreseeable future.

The fact that the fixed-sized vectors are known only JIT-side is odd, and I've been thinking through how it could be cleaned up, but I haven't come up with anything that markedly improves what we have now. If you have ideas, I could give it a shot.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we'll continue to default Vector to 256-bit even when PreferredVectorBitWidth is 512

Is this change a UX improvement then? It seems to make the explanation of how the switches work and interact more complicated.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's early enough in the cycle I think we can allow the default size of Vector to be 512 if the hardware supports it.

It would go out P2 at the latest and give us an early indicator if too many users are broken or regress in performance because of it. Such users can always do MaxVectorTBitWidth=256 as a workaround, particularly if the amount of breaks is "small", and we can revert and do the more complex configuration knobs if the signal is high enough.

Copy link
Member

@tannergooding tannergooding Jan 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think what we will end up conceptually having in the "worst" case is the following:

// Simplified a bit as it doesn't show the handling for invalid user-specified values
// and doesn't show the values used if no user-specified value is given, but which
// are MaxVectorBitWidth and 256, respectively

DOTNET_PreferredVectorBitWidth = Min(UserSpecified, MaxVectorBitWidth)
DOTNET_MaxVectorTBitWidth =  Min(Max(UserSpecified, 256), DOTNET_PreferredVectorBitWidth)

Where MaxVectorBitWidth is the conceptual value the hardware supports and the "worst" case is the need to default Vector to no more than 256-bits in size.

This ensures that sizeof(Vector<T>) is not greater than the maximum size that we report as hardware accelerated. For example, you could not on x64 have Vector512.IsHardwareAccelerated == false and Vector<byte>.Count == 64 as that would add needless complexity to the user consideration.

Ideally though we can simplify it to the following:

DOTNET_PreferredVectorBitWidth = Min(UserSpecified, MaxVectorBitWidth)
DOTNET_MaxVectorTBitWidth =  Min(UserSpecified, DOTNET_PreferredVectorBitWidth)

I think in both cases we don't need the JIT to handle anything, however. We can pick the sizeof Vector entirely on the VM side and then have the JIT simply get it via the compExactlyDependsOn(InstructionSet_VectorT512) checks that currently propagate that size information to the JIT: https://github.com/dotnet/runtime/blob/main/src/coreclr/jit/compiler.h#L9285-L9330

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, but then how does JIT decide which fixed-width classes to report as hardware accelerated? It can't use the VectorT ISA, because we have to continue to support Vector512.IsHardwareAccelerated == true with sizeof(Vector<T>) == 32.

It seems to make the explanation of how the switches work and interact more complicated.

I agree with this either way. The name PreferredVectorBitWidth isn't helping. Perhaps that could be better named. Something like MaxAcceleratedVectorBitWidth?

Then the largest fixed-width vector considered accelerated is Min(MaxAcceleratedVectorBitWidth, [Max hardware SIMD size])

And Vector<T> size is Min(MaxVectorTBitWidth, MaxAcceleratedVectorBitWidth, [Max hardware SIMD size]), where we can still default MaxVectorTBitWidth to 256 for back compat.

That is, of course, the same thing I've implemented here, but the naming is easier to follow. I wouldn't mind taking on a cleanup task to deal with the 'virtual' ISAs that today only JIT knows about. Removing this duplication (if it stays) should be one of the goals of that effort.

Copy link
Member

@tannergooding tannergooding Jan 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, but then how does JIT decide which fixed-width classes to report as hardware accelerated?

In the same way the VM currently sets one of InstructionSet_VectorT### to indicate its size, it should likely be using InstructionSet_Vector### to indicate acceleration.

That is the JIT doesn't need access to PreferredVectorBitWidth nor MaxVectorTBitWidth. Rather instead it knows sizeof(Vector<T>) based on InstructionSet_VectorT### and it knows the opts.preferredVectorByteLength based on the largest InstructionSet_Vector###.

It can then continue internally setting InstructionSet_Vector### itself (after its computed the opts.preferredVectorByteLength value) based on the InstructionSet_Isa that are supported so that we still get the expected codegen, just without reporting itself as accelerated.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

InstructionSet_Vector### is exactly the problem. Today, only JIT knows about those ISAs. Moving them to VM would be a breaking change for R2R and NAOT, because they would also have to pass those to JIT, and they don't.

Fixing that (and I do agree it needs to be fixed) is a much bigger change that is better done separately.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Talked through this on Discord by explaining the difference between readytoruninstructionset and corinfoinstructionset. The latter isn't tracked by R2R but is used by both the JIT (codeman.cpp) and NAOT (CorInfoImpl.cs) VMs. Accordingly, we should be able to do all the selection on the VM side. The nuance was we can't get the JIT info from just the Vector<T> size unless we agree that Vector<T> implicitly grows up to PreferredVectorBitWidth. There are concerns with that due to it historically being no larger than 32-bytes and the likelyhood code may break (bad assumptions were hardcoded) or silently regress (code paths no longer accelerate but were guarded against larger sizes).

The safest thing for us, given that concern, is to have the VM (https://github.com/dotnet/runtime/blob/main/src/coreclr/vm/codeman.cpp#L1225 and https://github.com/dotnet/runtime/blob/main/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs#L4197) start setting InstructionSet_Vector### based on DOTNET_PreferredVectorBitWidth. This ensures we have a single "source of truth" and avoids mirroring config knob access between the JIT/VM. We can then, in a separate PR, do a one line change in the VM to experiment with defaulting Vector to be the same as PreferredVectorBitWidth, rather than restricting it to no more than 256 by default. This makes it easy to back out if the concerns are founded and decently widespread breaks are found.

This keeps things simple with one source of truth and doesn't require more comprehensive refactoring to achieve.

Copy link
Member Author

@saucecontrol saucecontrol Jan 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, I believe I have done what we discussed. It did allow removing a JIT flag and got the throttling logic completely on the VM side, but I couldn't move the Vector### ISAs completely over because the meanings are still overloaded. e.g. InstructionSet_Vector256 can't mean we want fully-accelerated Vector256 (AVX2+PreferredVectorBitWidth>=256) because it still means partially-accelerated Vector256 (AVX) is actually supported.

I also found that we were doing the Vector512 throttling on the AOT side, so I've duplicated the logic to clamp Vector<T> size there as well. So we still have duplicated logic, but I suppose it's a bit cleaner now.

#endif // defined(TARGET_AMD64) || defined(TARGET_X86)

//
// Hardware Intrinsic ISAs; keep in sync with jitconfigvalues.h
Expand Down
4 changes: 0 additions & 4 deletions src/coreclr/inc/corjitflags.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,6 @@ class CORJIT_FLAGS
CORJIT_FLAG_SOFTFP_ABI = 30, // Enable armel calling convention
#endif

#if defined(TARGET_X86) || defined(TARGET_AMD64)
CORJIT_FLAG_VECTOR512_THROTTLING = 31, // On x86/x64, 512-bit vector usage may incur CPU frequency throttling
#endif

};

CORJIT_FLAGS()
Expand Down
10 changes: 5 additions & 5 deletions src/coreclr/inc/jiteeversionguid.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,11 @@ typedef const GUID *LPCGUID;
#define GUID_DEFINED
#endif // !GUID_DEFINED

constexpr GUID JITEEVersionIdentifier = { /* cc0e7adf-e397-40b6-9d14-a7149815c991 */
0xcc0e7adf,
0xe397,
0x40b6,
{0x9d, 0x14, 0xa7, 0x14, 0x98, 0x15, 0xc9, 0x91}
constexpr GUID JITEEVersionIdentifier = { /* 78acb599-d9be-4ea1-8e93-546ec43e0487 */
0x78acb599,
0xd9be,
0x4ea1,
{0x8e, 0x93, 0x54, 0x6e, 0xc4, 0x3e, 0x04, 0x87}
};

//////////////////////////////////////////////////////////////////////////////////////////////////////////
Expand Down
47 changes: 28 additions & 19 deletions src/coreclr/jit/compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2213,9 +2213,34 @@ void Compiler::compSetProcessor()
// don't actually exist. The JIT is in charge of adding those and ensuring
// the total sum of flags is still valid.
#if defined(TARGET_XARCH)
// Get the preferred vector bitwidth, rounding down to the nearest multiple of 128-bits
uint32_t preferredVectorBitWidth = (ReinterpretHexAsDecimal(JitConfig.PreferredVectorBitWidth()) / 128) * 128;
uint32_t preferredVectorByteLength = preferredVectorBitWidth / 8;
// If the VM passed in a virtual vector ISA, it was done to communicate PreferredVectorBitWidth.
// No check is done for the validity of the value, since it will be clamped to max supported by
// hardware and config when queried. We will, therefore, remove the marker ISA and allow it to
// be re-added if appropriate based on the hardware ISA evaluations below.

uint32_t preferredVectorBitWidth = 0;
if (instructionSetFlags.HasInstructionSet(InstructionSet_Vector128))
{
instructionSetFlags.RemoveInstructionSet(InstructionSet_Vector128);
preferredVectorBitWidth = 128;
}
else if (instructionSetFlags.HasInstructionSet(InstructionSet_Vector256))
{
instructionSetFlags.RemoveInstructionSet(InstructionSet_Vector256);
preferredVectorBitWidth = 256;
}
else if (instructionSetFlags.HasInstructionSet(InstructionSet_Vector512))
{
instructionSetFlags.RemoveInstructionSet(InstructionSet_Vector512);
preferredVectorBitWidth = 512;
}

opts.preferredVectorByteLength = preferredVectorBitWidth / 8;

// Only one marker ISA should have been passed in, and it should now be cleared.
assert(!instructionSetFlags.HasInstructionSet(InstructionSet_Vector128) &&
!instructionSetFlags.HasInstructionSet(InstructionSet_Vector256) &&
!instructionSetFlags.HasInstructionSet(InstructionSet_Vector512));

if (instructionSetFlags.HasInstructionSet(InstructionSet_SSE))
{
Expand Down Expand Up @@ -2247,29 +2272,13 @@ void Compiler::compSetProcessor()
assert(instructionSetFlags.HasInstructionSet(InstructionSet_AVX512DQ_VL));

instructionSetFlags.AddInstructionSet(InstructionSet_Vector512);

if ((preferredVectorByteLength == 0) && jitFlags.IsSet(JitFlags::JIT_FLAG_VECTOR512_THROTTLING))
{
// Some architectures can experience frequency throttling when
// executing 512-bit width instructions. To account for this we set the
// default preferred vector width to 256-bits in some scenarios. Power
// users can override this with `DOTNET_PreferredVectorBitWidth=512` to
// allow using such instructions where hardware support is available.
//
// Do not condition this based on stress mode as it makes the support
// reported inconsistent across methods and breaks expectations/functionality

preferredVectorByteLength = 256 / 8;
}
}
else
{
// We shouldn't have EVEX enabled if neither AVX512 nor AVX10v1 are supported
assert(instructionSetFlags.HasInstructionSet(InstructionSet_AVX10v1));
}
}

opts.preferredVectorByteLength = preferredVectorByteLength;
#elif defined(TARGET_ARM64)
if (instructionSetFlags.HasInstructionSet(InstructionSet_AdvSimd))
{
Expand Down
180 changes: 81 additions & 99 deletions src/coreclr/jit/hwintrinsicxarch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1575,34 +1575,6 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic,
break;
}

case NI_Vector128_AsVector:
{
assert(sig->numArgs == 1);
uint32_t vectorTByteLength = getVectorTByteLength();

if (vectorTByteLength == YMM_REGSIZE_BYTES)
{
// Vector<T> is TYP_SIMD32, so we should treat this as a call to Vector128.ToVector256
return impSpecialIntrinsic(NI_Vector128_ToVector256, clsHnd, method, sig R2RARG(&emptyEntryPoint),
simdBaseJitType, retType, simdSize, mustExpand);
}
else if (vectorTByteLength == XMM_REGSIZE_BYTES)
{
// We fold away the cast here, as it only exists to satisfy
// the type system. It is safe to do this here since the retNode type
// and the signature return type are both the same TYP_SIMD.

retNode = impSIMDPopStack();
SetOpLclRelatedToSIMDIntrinsic(retNode);
assert(retNode->gtType == getSIMDTypeForSize(getSIMDTypeSizeInBytes(sig->retTypeSigClass)));
}
else
{
assert(vectorTByteLength == 0);
}
break;
}

case NI_Vector128_AsVector2:
case NI_Vector128_AsVector3:
{
Expand Down Expand Up @@ -1695,10 +1667,13 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic,
}

case TYP_SIMD32:
case TYP_SIMD64:
{
// Vector<T> is TYP_SIMD32, so we should treat this as a call to Vector256.GetLower
return impSpecialIntrinsic(NI_Vector256_GetLower, clsHnd, method, sig R2RARG(&emptyEntryPoint),
simdBaseJitType, retType, simdSize, mustExpand);
// Vector<T> is larger, so we should treat this as a call to the appropriate narrowing intrinsic
intrinsic = simdSize == YMM_REGSIZE_BYTES ? NI_Vector256_GetLower : NI_Vector512_GetLower128;

return impSpecialIntrinsic(intrinsic, clsHnd, method, sig R2RARG(&emptyEntryPoint), simdBaseJitType,
retType, simdSize, mustExpand);
}

default:
Expand All @@ -1722,13 +1697,16 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic,
break;
}

case NI_Vector128_AsVector:
case NI_Vector256_AsVector:
case NI_Vector512_AsVector:
case NI_Vector256_AsVector256:
case NI_Vector512_AsVector512:
{
assert(sig->numArgs == 1);
uint32_t vectorTByteLength = getVectorTByteLength();

if (vectorTByteLength == YMM_REGSIZE_BYTES)
if (vectorTByteLength == simdSize)
{
// We fold away the cast here, as it only exists to satisfy
// the type system. It is safe to do this here since the retNode type
Expand All @@ -1740,86 +1718,90 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic,

break;
}
else if (vectorTByteLength == XMM_REGSIZE_BYTES)
else if (vectorTByteLength != 0)
{
if (compOpportunisticallyDependsOn(InstructionSet_AVX))
{
// We support Vector256 but Vector<T> is only 16-bytes, so we should
// treat this method as a call to Vector256.GetLower or Vector128.ToVector256
// Vector<T> is a different size than the source/target SIMD type, so we should
// treat this as a call to the appropriate narrowing or widening intrinsic.

NamedIntrinsic convertIntrinsic = NI_Illegal;

if (intrinsic == NI_Vector256_AsVector)
switch (vectorTByteLength)
{
case XMM_REGSIZE_BYTES:
{
return impSpecialIntrinsic(NI_Vector256_GetLower, clsHnd, method, sig R2RARG(&emptyEntryPoint),
simdBaseJitType, retType, simdSize, mustExpand);
switch (intrinsic)
{
case NI_Vector256_AsVector:
convertIntrinsic = NI_Vector256_GetLower;
break;
case NI_Vector512_AsVector:
convertIntrinsic = NI_Vector512_GetLower128;
break;
case NI_Vector256_AsVector256:
convertIntrinsic = NI_Vector128_ToVector256;
break;
case NI_Vector512_AsVector512:
convertIntrinsic = NI_Vector128_ToVector512;
break;
default:
unreached();
}
break;
}
else

case YMM_REGSIZE_BYTES:
{
assert(intrinsic == NI_Vector256_AsVector256);
return impSpecialIntrinsic(NI_Vector128_ToVector256, clsHnd, method,
sig R2RARG(&emptyEntryPoint), simdBaseJitType, retType, 16,
mustExpand);
switch (intrinsic)
{
case NI_Vector128_AsVector:
convertIntrinsic = NI_Vector128_ToVector256;
break;
case NI_Vector512_AsVector:
convertIntrinsic = NI_Vector512_GetLower;
break;
case NI_Vector512_AsVector512:
convertIntrinsic = NI_Vector256_ToVector512;
break;
default:
unreached();
}
break;
}
}
}
else
{
assert(vectorTByteLength == 0);
}
break;
}

case NI_Vector512_AsVector:
case NI_Vector512_AsVector512:
{
assert(sig->numArgs == 1);
uint32_t vectorTByteLength = getVectorTByteLength();

if (vectorTByteLength == YMM_REGSIZE_BYTES)
{
assert(IsBaselineVector512IsaSupportedDebugOnly());

// We support Vector512 but Vector<T> is only 32-bytes, so we should
// treat this method as a call to Vector512.GetLower or Vector256.ToVector512

if (intrinsic == NI_Vector512_AsVector)
{
return impSpecialIntrinsic(NI_Vector512_GetLower, clsHnd, method, sig R2RARG(&emptyEntryPoint),
simdBaseJitType, retType, simdSize, mustExpand);
}
else
{
assert(intrinsic == NI_Vector512_AsVector512);
return impSpecialIntrinsic(NI_Vector256_ToVector512, clsHnd, method, sig R2RARG(&emptyEntryPoint),
simdBaseJitType, retType, 32, mustExpand);
}
break;
}
else if (vectorTByteLength == XMM_REGSIZE_BYTES)
{
if (compOpportunisticallyDependsOn(InstructionSet_AVX512F))
{
// We support Vector512 but Vector<T> is only 16-bytes, so we should
// treat this method as a call to Vector512.GetLower128 or Vector128.ToVector512

if (intrinsic == NI_Vector512_AsVector)
case ZMM_REGSIZE_BYTES:
{
return impSpecialIntrinsic(NI_Vector512_GetLower128, clsHnd, method,
sig R2RARG(&emptyEntryPoint), simdBaseJitType, retType, simdSize,
mustExpand);
switch (intrinsic)
{
case NI_Vector128_AsVector:
convertIntrinsic = NI_Vector128_ToVector512;
break;
case NI_Vector256_AsVector:
convertIntrinsic = NI_Vector256_ToVector512;
break;
case NI_Vector256_AsVector256:
convertIntrinsic = NI_Vector512_GetLower;
break;
default:
unreached();
}
break;
}
else

default:
{
assert(intrinsic == NI_Vector512_AsVector512);
return impSpecialIntrinsic(NI_Vector128_ToVector512, clsHnd, method,
sig R2RARG(&emptyEntryPoint), simdBaseJitType, retType, 16,
mustExpand);
unreached();
}
}

unsigned convertSize = simdSize;
bool sizeFound = HWIntrinsicInfo::tryLookupSimdSize(convertIntrinsic, &convertSize);
assert(sizeFound);

return impSpecialIntrinsic(convertIntrinsic, clsHnd, method, sig R2RARG(&emptyEntryPoint),
simdBaseJitType, retType, convertSize, mustExpand);
}
else
{
assert(vectorTByteLength == 0);
}

// VectorT ISA was not present. Fall back to managed.
break;
}

Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/jit/importer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3785,7 +3785,7 @@ GenTree* Compiler::impImportStaticReadOnlyField(CORINFO_FIELD_HANDLE field, CORI
int simdWidth = getSIMDTypeSizeInBytes(fieldClsHnd);
if ((simdWidth > 0) && IsBaselineSimdIsaSupported())
{
assert((totalSize <= 32) && (totalSize <= MaxStructSize));
assert((totalSize <= 64) && (totalSize <= MaxStructSize));
var_types simdType = getSIMDTypeForSize(simdWidth);

bool hwAccelerated = true;
Expand Down
2 changes: 0 additions & 2 deletions src/coreclr/jit/jitconfigvalues.h
Original file line number Diff line number Diff line change
Expand Up @@ -380,8 +380,6 @@ CONFIG_INTEGER(JitBypassAPXCheck, "JitBypassAPXCheck", 0) // Bypass APX
CONFIG_INTEGER(JitStressEvexEncoding, "JitStressEvexEncoding", 0)
#endif

RELEASE_CONFIG_INTEGER(PreferredVectorBitWidth, "PreferredVectorBitWidth", 0) // The preferred decimal width, in bits, to use for any implicit vectorization emitted. A value less than 128 is treated as the system default.

//
// Hardware Intrinsic ISAs; keep in sync with clrconfigvalues.h
//
Expand Down
8 changes: 0 additions & 8 deletions src/coreclr/jit/jitee.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,6 @@ class JitFlags
JIT_FLAG_SOFTFP_ABI = 30, // Enable armel calling convention
#endif

#if defined(TARGET_XARCH)
JIT_FLAG_VECTOR512_THROTTLING = 31, // On Xarch, 512-bit vector usage may incur CPU frequency throttling
#endif

// Note: the mcs tool uses the currently unused upper flags bits when outputting SuperPMI MC file flags.
// See EXTRA_JIT_FLAGS and spmidumphelper.cpp. Currently, these are bits 56 through 63. If they overlap,
// something needs to change.
Expand Down Expand Up @@ -147,10 +143,6 @@ class JitFlags
FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_SOFTFP_ABI, JIT_FLAG_SOFTFP_ABI);
#endif // TARGET_ARM

#if defined(TARGET_X86) || defined(TARGET_AMD64)
FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_VECTOR512_THROTTLING, JIT_FLAG_VECTOR512_THROTTLING);
#endif // TARGET_ARM

#undef FLAGS_EQUAL
}

Expand Down
Loading
Loading