Skip to content

Math.Round[F](x, MidpointRounding) doesn't use VROUNDS[SD] outside of "to even"  #98164

@colejohnson66

Description

@colejohnson66

Description

It appears that Math[F].Round doesn't always use VROUNDS[SD] with an embedded round control. It does use VROUNDS[SD] for "to even" as that follows MXCSR

The "round control" bits of VROUNDS[SD] are as follows:

  • 00: nearest/to even
  • 01: down/to negative infinity
  • 10: up/to positive infinity
  • 11: truncate/to zero

Bit three of the immediate is set to use MXCSR.RC and cleared to use the embedded round control bits. It looks like the JIT only uses VROUND[SD] with "use MXCSR" set.

Data

Expected behavior occurs for "to even" rounding, but with the "use MXCSR" bit set - hence the suspicion. In this case, no harm, no foul.
https://sharplab.io/#v2:EYLgxg9gTgpgtADwGwBYA0AXEBDAzgWwB8ABAJgEYBYAKBuIGYACM58gdhoG8bHfmmAJhACuwADYxGAFRi4MACiGiJjAG7YxASkYBeAHw8+RgLLYMACwB0AJREA7AfPVi0jYwEsBABwju7GW2EHPwBzSykIAFFVGDtNAG4aAF8gA

using System;

public class Program
{
    public double Test(double val) =>
        Math.Round(val, MidpointRounding.ToEven);
}
Program.Test(Double)
    L0000: vzeroupper
    L0003: vroundsd xmm0, xmm0, xmm1, 4
    L0009: ret

However, using a mode that is not set in MXCSR calls into the framework for help instead of using an embedding rounding mode. For the below, VROUNDSD should be used with an immediate of b010 (ignore MXCSR, and use "round up/to infinity").

https://sharplab.io/#v2:EYLgxg9gTgpgtADwGwBYA0AXEBDAzgWwB8ABAJgEYBYAKBuIGYACM58gdhoG8bHfmmAJhACuwADYxGAFRi4MACiGiJjAG7YxASkYBeAHw8+RgLLYMACwB0AJREA7AfPVi0jYwEsBABwju7GW2EHPwBzSykIAAUIXHcMd1UYAEk7ADM/OIBPTQBuGgBfIA===

using System;

public class Program
{
    public double Test(double val) =>
        Math.Round(val, MidpointRounding.ToPositiveInfinity);
}
Program.Test(Double)
    L0000: vzeroupper
    L0003: vmovaps xmm0, xmm1
    L0007: xor edx, edx
    L0009: mov r8d, 4
    L000f: mov rax, 0x7ff7e0257618
    L0019: jmp qword ptr [rax]

Expected behavior for this would be:

Program.Test(Double)
    L0000: vzeroupper
    L0003: vroundsd xmm0, xmm0, xmm1, 2
    L0009: ret

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions