Skip to content

JIT: Transform floating SELECT(a < b, a, b) to NativeMin(a, b)#128402

Closed
BoyBaykiller wants to merge 2 commits into
dotnet:mainfrom
BoyBaykiller:select-to-native-min-max
Closed

JIT: Transform floating SELECT(a < b, a, b) to NativeMin(a, b)#128402
BoyBaykiller wants to merge 2 commits into
dotnet:mainfrom
BoyBaykiller:select-to-native-min-max

Conversation

@BoyBaykiller
Copy link
Copy Markdown
Contributor

@BoyBaykiller BoyBaykiller commented May 20, 2026

Example:

static float Min(float a, float b)
{
    return a < b ? a : b;
}
;; ------ BASE
G_M000_IG02: 
       vucomiss xmm1, xmm0
       jbe      SHORT G_M000_IG04
 
G_M000_IG03:
       ret      
 
G_M000_IG04:
       vmovaps  xmm0, xmm1
 
G_M000_IG05: 
       ret      

;; ------ DIFF
G_M21498_IG02: 
       vminss   xmm0, xmm0, xmm1

G_M21498_IG03:
       ret      

Handles all these cases. I compared the codegen of every single one against it to be sure its correct:
https://godbolt.org/z/389jvnfW4

Fix #116802

@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 May 20, 2026
@dotnet-policy-service dotnet-policy-service Bot added the community-contribution Indicates that the PR has been added by a community member label May 20, 2026
@dotnet-policy-service
Copy link
Copy Markdown
Contributor

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

* enable diffs
Copy link
Copy Markdown
Contributor

Copilot AI left a 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 extends CoreCLR JIT if-conversion select optimization to recognize floating-point conditional selects that compute min/max (e.g., a < b ? a : b) and replace them with a native SIMD min/max node on xarch, enabling codegen like vminss/vmaxss instead of compare + branch.

Changes:

  • Allow GT_STORE_LCL_VAR / GT_RETURN if-conversion when the value type is floating-point (in addition to integral/I).
  • Add TrySelectToMinMax to rewrite eligible floating GT_SELECT nodes into gtNewSimdMinMaxNativeNode (xarch).
  • Add an early bailout to avoid producing floating-point GT_SELECT nodes unless they optimize to a non-SELECT form.

Comment on lines 208 to 212
// Ensure the operation has integer type.
if (!varTypeIsIntegralOrI(tree))
if (!varTypeIsIntegralOrI(tree) && !varTypeIsFloating(tree))
{
return false;
}
Comment on lines 640 to 645
if (select->OperIs(GT_SELECT))
{
#ifdef TARGET_RISCV64
JITDUMP("Skipping if-conversion that could not be optimized to ordinary operations\n");
return true;
}
#endif
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

we call gtNewConditionalNode before which counts as change

Comment thread src/coreclr/jit/ifconversion.cpp
@BoyBaykiller
Copy link
Copy Markdown
Contributor Author

@MihuBot -nuget

@tannergooding
Copy link
Copy Markdown
Member

As per Discord, I'm not in favor of this specific optimization.

The a < b ? a : b pattern is fairly specific to xarch and is likely a deoptimization on other platforms since they do not have a single instruction variant. Such code is rarely dependent on the "return b for NaN or if both are zero" behavior and so switching to use MinNative(a, b) is almost always preferred, as it accelerates to minss on xarch and to an appropriate single instruction on other platforms.

In general I'd like to push users towards a path of success and accelerating a "bad practice" doesn't help achieve that.

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.

JIT: Generate v{min/max}ss for a > b ? a : b pattern instead of cmp + jmp

3 participants