Skip to content

Constant mod over chars can use a cheaper FastMod #111492

Open
@MihaZupan

Description

@MihaZupan

#101001 added a faster variant of FastMod that SearchValues now uses when it knows that the value and divisor are both < 2^16 (i.e. chars).
Instead of

uint highbits = (uint)(((((multiplier * value) >> 32) + 1) * divisor) >> 32);

we can use
ulong result = ((ulong)(multiplier * value) * divisor) >> 32;


Is it worth teaching the JIT to do something similar when it knows that values are in range?

int Mod1(char c) => c % 42;
int Mod2(char c) => (int)(((ulong)(102261127u * c) * 42) >> 32);
Test.Mod1(Char)
    L0000: movzx eax, cx
    L0003: mov ecx, eax
    L0005: shr ecx, 1
    L0007: imul rcx, 0x30c30c31
    L000e: shr rcx, 0x22
    L0012: imul ecx, 0x2a
    L0015: sub eax, ecx
    L0017: ret

Test.Mod2(Char)
    L0000: movzx eax, cx
    L0003: imul eax, 0x6186187
    L0009: imul rax, 0x2a
    L000d: shr rax, 0x20
    L0011: ret

sharplab

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMIhelp wanted[up-for-grabs] Good issue for external contributorsin-prThere is an active PR which will close this issue when it is merged

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions