Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Workaround an MSVC bug with __libm_sse2_sincos_ #98207

Merged
merged 7 commits into from
Feb 10, 2024

Conversation

tannergooding
Copy link
Member

@tannergooding tannergooding commented Feb 9, 2024

This resolves #98204

There is currently a bug in MSVCRT where __libm_sse2_sincos (which is used by fp:fast) is trying to rely on the fact that sin(x + PI / 2) == cos(x) and so calls into __vdecl_sin2 when it should instead call __vdecl_sincos2. This causes it to return sin for both results given a large enough input, which leads to incorrect results.

@dotnet-issue-labeler dotnet-issue-labeler bot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Feb 9, 2024
@ghost ghost assigned tannergooding Feb 9, 2024
@ghost
Copy link

ghost commented Feb 9, 2024

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

Issue Details

This resolves #98204

There is currently a bug in MSVCRT where __libm_sse2_sincos (which is used by fp:fast) calls __vdecl_sin2 when it should instead call __vdecl_sincos2. This causes it to return sin for both results, which leads to incorrect results.

Author: tannergooding
Assignees: tannergooding
Labels:

area-CodeGen-coreclr

Milestone: -

@tannergooding
Copy link
Member Author

tannergooding commented Feb 9, 2024

CC. @jkoritzinsky and @jkotas, this will somewhat conflict with #98048.

I think it'd be good to get this in first as it likely needs backporting to .NET 8 (unintentional regression not caused by us, in API surface that's existed since .NET 6).

@jkotas
Copy link
Member

jkotas commented Feb 9, 2024

There is currently a bug in MSVCRT where __libm_sse2_sincos (which is used by fp:fast) calls __vdecl_sin2 when it should instead call __vdecl_sincos2. This causes it to return sin for both results, which leads to incorrect results.

Why was this bug missed by our existing SinCos tests?

@ghost
Copy link

ghost commented Feb 9, 2024

Tagging subscribers to this area: @dotnet/area-system-numerics
See info in area-owners.md if you want to be subscribed.

Issue Details

This resolves #98204

There is currently a bug in MSVCRT where __libm_sse2_sincos (which is used by fp:fast) calls __vdecl_sin2 when it should instead call __vdecl_sincos2. This causes it to return sin for both results, which leads to incorrect results.

Author: tannergooding
Assignees: tannergooding
Labels:

area-System.Numerics, area-CodeGen-coreclr

Milestone: -

@jkotas jkotas removed the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Feb 9, 2024
@stephentoub
Copy link
Member

customer reported

I'm not exactly "customer" :)

@tannergooding
Copy link
Member Author

Why was this bug missed by our existing SinCos tests?

It looks like __libm_sse2_sincos is trying to rely on the fact that sin(x + PI / 2) == cos(x) and so adjusts the second input by that much. This is correct for infinitely precise arithmetic, but for floating-point means that cos is less accurate than it should be for regular values and will not work at all for large values due to the increasing gap between which numbers are representable (it breaks down entirely around 1e16, but starts showing issues far earlier).

Given that its just calling into SVML and SVML provides a dedicated __vdecl_sincos2, that should really be getting used instead.

We missed this because we were testing normal input ranges and not testing anything quite so large, effectively relying on the fact that the underlying libm implementation is expected to be largely correct, and that we simply want to minimally validate the bindings are accurate and that it matches any IEEE 754 required behavior (such as sin(+0) == +0 and sin(-0) == -0, with no exception)

@stephentoub
Copy link
Member

For reference, I found it because I'd implemented a vectorized TensorPrimitives.SinCos and our tests that validate it against the scalar T.SinCos were failing a bunch of tests where we do exercise a wide range of values.

Copy link
Member

@jkotas jkotas left a comment

Choose a reason for hiding this comment

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

Thanks

Copy link
Member

@stephentoub stephentoub left a comment

Choose a reason for hiding this comment

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

thanks

@tannergooding tannergooding merged commit dfcbcb4 into dotnet:main Feb 10, 2024
147 of 152 checks passed
@tannergooding tannergooding deleted the fix-98204 branch February 10, 2024 22:44
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

double.Cos and double.SinCos can produce very different results
3 participants