-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Update the JIT to recognize the IsSupported property for all HWIntrinsics #23751
Conversation
@@ -15,7 +15,7 @@ namespace System.Runtime.Intrinsics.Arm.Arm64 | |||
[CLSCompliant(false)] | |||
public static class Base | |||
{ | |||
public static bool IsSupported { get { return false; }} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
An alternative to marking these explicitly as Intrinsic
would be to mark all methods under System.Runtime.Intrinsics
as [Intrinsic]
and then have the importer create the PNSE
node for unsupported ones.
One benefit of doing that would be that we wouldn't need the separate *.PlatformNotSupported.cs
files for every ISA. The downside would be that you would get a stack overflow on runtimes that don't recognize the intrinsics at all...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that it makes the most sense to just mark the IsSupported
ones. Otherwise, rather than the stack overflow behavior, I think we'd have to make it a requirement that all compilers on all platforms generate a throw to PNSE for any unrecognized System.Runtime.Intrinsics method, and I don't think that would be the right direction to go.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we'd have to make it a requirement that all compilers on all platforms generate a throw to PNSE for any unrecognized System.Runtime.Intrinsics method, and I don't think that would be the right direction to go.
I'm not so sure, I think that's the contract we have already defined for the HWIntrinsics
and one that we plan on documenting. But, I think it can also be a separate discussion and shouldn't block the PR (I also don't feel particularly strongly about it).
@@ -101,45 +94,45 @@ InstructionSet Compiler::lookupHWIntrinsicISA(const char* className) | |||
// | |||
// Return Value: | |||
// Id for the hardware intrinsic. | |||
// | |||
// TODO-Throughput: replace sequential search by hash lookup | |||
NamedIntrinsic Compiler::lookupHWIntrinsic(const char* className, const char* methodName) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is basically identical to the x86 version now; but I wanted to just merge the HWIntrinsicInfo
code in general in a follow up PR; rather than doing it piecemeal.
@@ -3458,6 +3458,21 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis, | |||
ni = lookupNamedIntrinsic(method); | |||
|
|||
#ifdef FEATURE_HW_INTRINSICS | |||
if (ni == NI_IsSupported_True) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We might be able to make this more general and move it out of FEATURE_HW_INTRINSICS
; so we have a single spot for methods which are statically true/false...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What other methods do you have in mind?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few are probably: BitConverter.IsLittleEndian
, Environment.Is64BitProcess
, and Vector.IsHardwareAccelerated
which rely on other explicit recognition or JIT tricks.
There are likely others already and more to exist in the future as well.... The return gtNewIconNode(true);
code isn't particular complex; but it might be nice to just be able to do the check and return NI_IsSupported_True
or NI_IsSupported_False
from lookupNamedIntrinsic
; rather than having multiple separate paths that all do the same thing.
Validated both via the existing tests and locally by looking at the disassembly that this is working as expected on x86/x64. What is the AzDO command for running the HWIntrinsic outer loop tests so I can also validate in CI? |
Several of the test failures are due to https://github.com/dotnet/coreclr/issues/23730 |
ARM failures are mostly due to a missing import for the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't realize that this would be as straightforward as this - thanks @tannergooding !
@@ -15,7 +15,7 @@ namespace System.Runtime.Intrinsics.Arm.Arm64 | |||
[CLSCompliant(false)] | |||
public static class Base | |||
{ | |||
public static bool IsSupported { get { return false; }} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that it makes the most sense to just mark the IsSupported
ones. Otherwise, rather than the stack overflow behavior, I think we'd have to make it a requirement that all compilers on all platforms generate a throw to PNSE for any unrecognized System.Runtime.Intrinsics method, and I don't think that would be the right direction to go.
@@ -3458,6 +3458,21 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis, | |||
ni = lookupNamedIntrinsic(method); | |||
|
|||
#ifdef FEATURE_HW_INTRINSICS | |||
if (ni == NI_IsSupported_True) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What other methods do you have in mind?
if ((namespaceName == nullptr) || (className == nullptr) || (methodName == nullptr)) | ||
{ | ||
return result; | ||
JITDUMP("Not recognized, not enough metadata\n"); | ||
return NI_Illegal; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Excellent; this needed more info in the dump - thanks!
I can't find it. I looked on the AzDO builds page here: https://dev.azure.com/dnceng/public/_build?definitionId=98 but I don't see the hw intrinsics testing modes. @echesakovMSFT do we have them? |
Could you please explain rationale for doing this? Why the current structure does not work? (The change does not look like an improvement to me from what is mentioned here.) |
No we don't have HWIntrinsics-related build definitions in AzDO yet But I have ported all the definitions of the Jenkins scenarios coreclr/tests/testenvironment.proj Lines 82 to 91 in 126aaf4
so it should be pretty straighforward to add one more AzDO build definition and enable running those scenarios /cc @RussKeldorph |
@jkotas, this resolves https://github.com/dotnet/coreclr/issues/20379. We had an existing problem that the JIT would not always eliminate all the code from This just centralizes things so that the |
Why is that? Having left-overs after a inlining a trivial method that returns |
I asked a similar question here https://github.com/dotnet/coreclr/issues/20379#issuecomment-474484086 and JIT limits was brought up. This aligned with other work that we wanted to do (more sharing of the lookup code), so put up the PR. |
ok. I guess that actual problem may be folks writing way too big methods with hardware intrintrisics that are hitting the limits. We should be splitting them into multiple methods per architecture, like here:
|
Right, and I believe that is the guidance we have been pushing and following. However, there are likely still cases where the branching and logic is itself fairly complex. The default case is that users will have 3-4 paths: An x86/x64 accelerated path, a ARM/ARM64 accelerated path, and a Software Fallback path. Each architecture may then have individual ISA paths that it might take (such as SSE vs AVX or optional optimizations if SSE3 or SSE41 are available, etc). Some code may also be taking advantage of a There are also cases where it isn't just a straightforward "exclusive" code path. The ASCIIUtility code you linked, for example, is a mix of software and vectorized code and itself already requires |
…rted and ThrowPNSE
…ormNotSupported HWIntrinsic files
Rebased to pick up the latest test fixes from master. |
ARM failures look unrelated. One is an assert in
|
@jkotas, do you have any pushback against this being merged? |
Looks fine to me. |
…sics (dotnet/coreclr#23751) * Moving some JITDUMP calls into Compiler::lookupNamedIntrinsic * Marking the IsSupported methods as Intrinsic for all HWIntrinsic ISAs * Updating the hwintrinsic importation to more generally handle IsSupported and ThrowPNSE * Applying formatting patch. * Adding using System.Runtime.CompilerServices to the various x86 PlatformNotSupported HWIntrinsic files Commit migrated from dotnet/coreclr@1b4d7c7
CC. @CarolEidt