Skip to content

JIT: Allow baseline intrinsics in JIT code unconditionally #116196

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

Merged
merged 5 commits into from
Jun 7, 2025

Conversation

saucecontrol
Copy link
Member

Under the current JIT rules, the config knobs meant for testing HWIntrinsics APIs and fallback code also impact codegen for ordinary casts. Some casts are implemented directly in codegen, where we freely emit SSE/SSE2 code with no ISA checks, while the casts implemented in lowering create HWIntrinsic nodes that end up hitting ISA validation checks in codegen and must, therefore, be gated by compOpportunisticallyDependsOn.

This PR adds the baseline ISAs to the supported set unconditionally so that we can freely use the HWIntrinsics in any JIT phase. It continues to honor config knobs (specifically DOTNET_EnableHWIntrinsic) when resolving managed HWIntrinsic methods so that user code is unaffected by the change.

In addition to the fgMorphExpandCast simplification in this PR, this change will allow

  • removal of the double->int/uint cast helpers
  • moving ulong->floating fallback cast implementation from codegen to lowering, which will open up additional optimization.

@github-actions github-actions bot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Jun 1, 2025
@dotnet-policy-service dotnet-policy-service bot added the community-contribution Indicates that the PR has been added by a community member label Jun 1, 2025
Copy link
Contributor

Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch
See info in area-owners.md if you want to be subscribed.

@saucecontrol saucecontrol marked this pull request as ready for review June 1, 2025 21:30
@saucecontrol
Copy link
Member Author

cc @tannergooding

Diffs are a slight improvement over the other approach.

I tried adding the baseline ISAs unconditionally VM-side, but that breaks R2R under DOTNET_EnableHWIntrinsic=0 since the VM doesn't know the baseline ISAs should be off and thus disagrees with JIT. This approach splits the difference.

Comment on lines 2022 to 2026
instructionSetFlags.AddInstructionSet(InstructionSet_Vector128);
instructionSetFlags.AddInstructionSet(InstructionSet_X86Base);
#ifdef TARGET_AMD64
instructionSetFlags.AddInstructionSet(InstructionSet_X86Base_X64);
#endif // TARGET_AMD64
Copy link
Member

Choose a reason for hiding this comment

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

Why here and not before the preferredVectorBitWidth checks?

Copy link
Member Author

Choose a reason for hiding this comment

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

No particular reason other than leaving the preferredVectorBitWidth comments close to the others since they're kind of related. I can move it if you prefer.

Copy link
Member

Choose a reason for hiding this comment

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

It would make a difference on if preferredVectorBitWidth is 0 rather than 128, right?

Do we meaningfully need to support that given the changes?

Copy link
Member Author

Choose a reason for hiding this comment

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

Ah yeah, none of Vector### can be added until we've checked the VM ISA set to resolve preferredVectorBitWidth. We can move up the X86Base adds if that reads better to you.

Copy link
Member

Choose a reason for hiding this comment

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

I think it's fine, just wanted to confirm it's intentional.

A comment explaining we're adding it and why its after would be goodness though, as future readers might forget the context.

Copy link
Member Author

Choose a reason for hiding this comment

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

Added a couple more comments.

Comment on lines 8915 to 8930
bool IsBaselineSimdIsaSupported()
{
#ifdef FEATURE_SIMD
#if defined(TARGET_XARCH)
CORINFO_InstructionSet minimumIsa = InstructionSet_X86Base;
#elif defined(TARGET_ARM64)
CORINFO_InstructionSet minimumIsa = InstructionSet_AdvSimd;
#if defined(TARGET_XARCH) || defined(TARGET_ARM64)
return true;
#elif defined(TARGET_LOONGARCH64)
// TODO: supporting SIMD feature for LoongArch64.
assert(!"unimplemented yet on LA");
CORINFO_InstructionSet minimumIsa = 0;
return false;
#else
#error Unsupported platform
#endif // !TARGET_XARCH && !TARGET_ARM64 && !TARGET_LOONGARCH64

return compOpportunisticallyDependsOn(minimumIsa);
#else
return false;
#endif
}
Copy link
Member

Choose a reason for hiding this comment

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

Is this needed? Can we just remove it or otherwise change the name to something more meaningful?

Copy link
Member Author

@saucecontrol saucecontrol Jun 4, 2025

Choose a reason for hiding this comment

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

We could get rid of this entirely if we got rid of FEATURE_SIMD, or rather made the assumption TARGET_XARCH and TARGET_ARM64 always imply it. I removed all calls to it except those that aren't guarded by FEATURE_SIMD, so it's at least const true or false based on that define.

Copy link
Member

Choose a reason for hiding this comment

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

Should we rename it to something like IfFeatureSimd() or similar instead or just change those paths to be properly guarded by #ifdef FEATURE_SIMD?

Copy link
Member Author

Choose a reason for hiding this comment

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

Either of those is fine with me. I was kind of thinking a separate effort to clean up FEATURE_SIMD and FEATURE_HW_INTRINSICS defines would be in order, particularly since Arm64 is inconsistent in whether those are checked at all. I don't even know if you can build without them currently.

Copy link
Member

Choose a reason for hiding this comment

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

I don't even know if you can build without them currently.

We really don't want to build without them for Arm64 or x64 at this point.

Realistically it's for Unix x86 (which I think someone is working on fixing) and for community platforms that are in their initial onboarding stages.

I'm definitely in favor of a cleanup/simplification around the ifdefs.

Copy link
Member Author

Choose a reason for hiding this comment

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

They're on for x86 Unix as well since #111861, and AFAIK, it's all working.

I forgot this is called from a few places that are cross-architecture, to make unrolling decisions and such. I'm not sure if there's a name that makes more sense for all cases, but I can at least remove the calls from the platform-specific files for xarch and Arm64.

Copy link
Member Author

Choose a reason for hiding this comment

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

Turns out I was able to get rid of this cleanly. As long as we don't bring back any non-SIMD builds for xarch or Arm64, it's not needed.

@tannergooding
Copy link
Member

CC. @dotnet/jit-contrib, @EgorBo for secondary review

@tannergooding tannergooding requested a review from EgorBo June 6, 2025 19:50
@saucecontrol
Copy link
Member Author

saucecontrol commented Jun 6, 2025

Latest diff run shows a small TP improvement on Arm64, and the same asm diffs as before (mostly inlining of cast logic, and SIMD stack zeroing).

This change will only have diffs with DOTNET_EnableHWIntrinsic=0, so presumably these are test projects that explicitly set it.

@EgorBo
Copy link
Member

EgorBo commented Jun 6, 2025

LGTM but let's spin a few outerloops JIC

Does it mean EnableSSE/EnableSSE2 are no-op knobs now?

@EgorBo
Copy link
Member

EgorBo commented Jun 6, 2025

/azp list

This comment was marked as resolved.

@EgorBo
Copy link
Member

EgorBo commented Jun 6, 2025

/azp run runtime-coreclr outerloop, runtime-coreclr jitstress-isas-x86, runtime-coreclr jitstress-isas-arm, Fuzzlyn

Copy link

Azure Pipelines successfully started running 4 pipeline(s).

@saucecontrol
Copy link
Member Author

Does it mean EnableSSE/EnableSSE2 are no-op knobs now?

Those were removed in #115983. It was always the case that the only way to disable X86Base and ArmBase was with EnableHWIntrinsic -- just now it's the full baseline group.

@tannergooding tannergooding merged commit 39ecf52 into dotnet:main Jun 7, 2025
184 of 192 checks passed
@saucecontrol saucecontrol deleted the baseline-isa branch June 7, 2025 14:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI community-contribution Indicates that the PR has been added by a community member
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants