-
Notifications
You must be signed in to change notification settings - Fork 5.3k
Intrinsify Enum.Equals to avoid boxing #122779
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
base: main
Are you sure you want to change the base?
Conversation
src/coreclr/jit/importercalls.cpp
Outdated
| } | ||
|
|
||
| CORINFO_CLASS_HANDLE underlyingEnumCls; | ||
| if (info.compCompHnd->isEnum(cls1, &underlyingEnumCls) != TypeCompareState::Must) |
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.
Why is this check needed?
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.
Why is this check needed?
Not really needed judging by the managed impl, although, it does have a Debug.Assert(rt.IsActualEnum) so I converted the check to an assert.
Intrinsifying |
GetHashCode has no CQ issues it seems. Other use-cases seem to be in huge methods which require inlining to benefit from it and rely on escape analysis heavily. My initial impl was |
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.
Pull request overview
This PR intrinsifies Enum.Equals to avoid boxing and dramatically improve performance. When comparing enums, the JIT now recognizes calls to Enum.Equals and generates optimized code that directly compares the underlying integral values without boxing. The PR demonstrates a reduction from 70 bytes of assembly with boxing allocations to just 10 bytes of efficient comparison code.
Key changes:
- Added JIT intrinsic recognition for
Enum.Equalsmethod - Implemented optimization pass that unboxes enum arguments and compares underlying values directly
- Added comprehensive test suite covering all enum underlying types, generic scenarios, and edge cases
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| src/libraries/System.Private.CoreLib/src/System/Enum.cs | Marks Enum.Equals method with [Intrinsic] attribute to enable JIT recognition |
| src/coreclr/jit/namedintrinsiclist.h | Adds NI_System_Enum_Equals to the named intrinsic enumeration |
| src/coreclr/jit/compiler.h | Declares impFoldEnumEquals function for the optimization implementation |
| src/coreclr/jit/importercalls.cpp | Implements the intrinsic optimization logic including type checking, unboxing, and comparison generation; also fixes a typo in an existing comment |
| src/tests/JIT/Intrinsics/EnumIntrinsics.cs | Comprehensive test suite covering all enum types (sbyte through ulong), generics, different underlying types, flags, boxing scenarios, and null handling |
| src/tests/JIT/Intrinsics/EnumIntrinsics.csproj | Test project configuration for the new intrinsic tests |
Closes #122684
Codegen for
Test<MethodImplOptions>(before):Codegen for
Test<MethodImplOptions>(after):Technically, we could also make Enum.Equals inlineable and intrinsify
InternalGetCorElementType. but that seems to be more fragile.