Skip to content

Numerical < and == comparisons aren't fused into <= #78385

Closed
@stephentoub

Description

@stephentoub

Repro:
SharpLab

#nullable disable
using System.Numerics;
using SharpLab.Runtime;

public class C
{
    [JitGeneric(typeof(int))]
    public static bool M1<T>(T value) where T : INumberBase<T> =>
        T.IsNegative(value) || T.IsZero(value);
    
    public static bool M2(int value) =>
        value < 0 || value == 0;
    
    [JitGeneric(typeof(int))]
    public static bool M3<T>(T value) where T : INumberBase<T>, IComparisonOperators<T,T,bool> =>
        value <= T.Zero;
    
    public static bool M4(int value) =>
        value <= 0;
}

Both M1 (generic) and M2 (non-generic) that do separate negative and zero checks produce:

    L0000: test ecx, ecx
    L0002: jl short L000c
    L0004: xor eax, eax
    L0006: test ecx, ecx
    L0008: sete al
    L000b: ret
    L000c: mov eax, 1
    L0011: ret

whereas both M3 (generic) and M4 (non-generic) that do combined negative and zero checks produce:

    L0000: xor eax, eax
    L0002: test ecx, ecx
    L0004: setle al
    L0007: ret

Similarly for >=.

The approved design of #78222 was based on the idea that these would be the same, and thus the generic methods there could constrain T to just being INumberBase<T> and not require IComparisonOperators<T,T,bool> as well, but if it's going to remain producing worse code, we should reconsider.

cc: @EgorBo, @tannergooding

Metadata

Metadata

Labels

area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions