Summary: | x86 FMA - wrong rounding mode | ||
---|---|---|---|
Product: | [Developer tools] valgrind | Reporter: | jl_kdebugs <jl_kdebugs> |
Component: | vex | Assignee: | Paul Floyd <pjfloyd> |
Status: | REPORTED --- | ||
Severity: | normal | CC: | albin.ahlback, laurent.rineau, pjfloyd |
Priority: | NOR | ||
Version: | 3.19.0 | ||
Target Milestone: | --- | ||
Platform: | unspecified | ||
OS: | Linux | ||
See Also: | https://bugs.kde.org/show_bug.cgi?id=136779 | ||
Latest Commit: | Version Fixed In: | ||
Sentry Crash Report: | |||
Attachments: | fmatest.cpp reproducer |
Action is happening inside vex `dis_FMA` and `h_generic_calc_MAddF32` Rounding can be quite misleading but from my understanding the issue is that `dis_FMA` will (in case of vfnmadd used here) negate the result of `h_generic_calc_MAddF32`. But for this special case (zero) this is broken/wrong since it will negate the positive zero from `h_generic_calc_MAddF32`. The negation of the result should either be "conditional" or the MAddF32 implementation needs to be changed to propagate signs and return -0.0, which will then be changed to the correct value of +0.0. I'm not familiar with the valgrind codebase so it's hard for me to pinpoint a fix. This also came up for multiple developers in FLINT. Please see our issue at https://github.com/flintlib/flint/issues/1366. Codegen is 00000000004013e0 <_Z7naccFMAPfff>: 4013e0: c4 e2 71 ad 07 vfnmadd213ss (%rdi),%xmm1,%xmm0 4013e5: c5 fa 11 07 vmovss %xmm0,(%rdi) 4013e9: c3 ret 4013ea: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1) Looking briefly at the code, it could be rounding but it could also be an error in the negation |
Created attachment 154139 [details] fmatest.cpp reproducer SUMMARY It seems the valgrind VM will always round down for the FMA instructions. So assuming the program didn't change the rounding mode, valgrind computes the wrong result: 0.0 + (- (0.0 * 1.0)) = -0.0 which should be 0.0 in all cases except _MM_ROUND_DOWN, which is not the default. STEPS TO REPRODUCE 1. Compile attached cpp with "g++ -O2 -mfma fmatest.cpp" 2. Run natively, observe no negative numbers 3. Run through valgrind with "valgrind --tool=none ./a.out" and observe the wrong results OBSERVED RESULT negative zero EXPECTED RESULT positive zero Even if not implementing switching rounding modes, the most common rounding mode should be chosen