-
Notifications
You must be signed in to change notification settings - Fork 5.2k
Description
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 even01: down/to negative infinity10: up/to positive infinity11: 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: retHowever, 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").
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