How to reproduce this bug on a FreeBSD 14.0-CURRENT #10 main-n245559-d22883d7154: echo 'CFLAGS+=-mavx' >> /etc/make.conf cd /usr/src/lib/msun make clean && make && make install /usr/tests/lib/msun/ctrig_test test_zero_input *** Check failed: /usr/src/lib/msun/tests/ctrig_test.c:154: ctanhf fetestexcept((0x04 | 0x20 | 0x01 | 0x08 | 0x10)) (0x1) != 0 *** Check failed: /usr/src/lib/msun/tests/ctrig_test.c:154: ctanhf fetestexcept((0x04 | 0x20 | 0x01 | 0x08 | 0x10)) (0x1) != 0 *** Check failed: /usr/src/lib/msun/tests/ctrig_test.c:154: ctanhf fetestexcept((0x04 | 0x20 | 0x01 | 0x08 | 0x10)) (0x1) != 0 *** Check failed: /usr/src/lib/msun/tests/ctrig_test.c:154: ctanhf fetestexcept((0x04 | 0x20 | 0x01 | 0x08 | 0x10)) (0x1) != 0 *** Check failed: /usr/src/lib/msun/tests/ctrig_test.c:155: ctanf fetestexcept((0x04 | 0x20 | 0x01 | 0x08 | 0x10)) (0x1) != 0 *** Check failed: /usr/src/lib/msun/tests/ctrig_test.c:155: ctanf fetestexcept((0x04 | 0x20 | 0x01 | 0x08 | 0x10)) (0x1) != 0 *** Check failed: /usr/src/lib/msun/tests/ctrig_test.c:155: ctanf fetestexcept((0x04 | 0x20 | 0x01 | 0x08 | 0x10)) (0x1) != 0 *** Check failed: /usr/src/lib/msun/tests/ctrig_test.c:155: ctanf fetestexcept((0x04 | 0x20 | 0x01 | 0x08 | 0x10)) (0x1) != 0 failed: 8 checks failed; see output for more details
This is what happens on my system (I just set CPUTYPE=sandybridge): testing csinh(0 + 0 I) == 0 + 0 I testing csinh(0 + -0 I) == 0 + -0 I testing csinhf(0 + 0 I) == 0 + 0 I testing csinhf(0 + -0 I) == 0 + -0 I testing csinh(-0 + -0 I) == -0 + -0 I testing csinh(-0 + 0 I) == -0 + 0 I testing csinhf(-0 + -0 I) == -0 + -0 I testing csinhf(-0 + 0 I) == -0 + 0 I testing csin(0 + 0 I) == 0 + 0 I testing csin(0 + -0 I) == 0 + -0 I testing csinf(0 + 0 I) == 0 + 0 I testing csinf(0 + -0 I) == 0 + -0 I testing csin(-0 + -0 I) == -0 + -0 I testing csin(-0 + 0 I) == -0 + 0 I testing csinf(-0 + -0 I) == -0 + -0 I testing csinf(-0 + 0 I) == -0 + 0 I testing ccosh(0 + 0 I) == 1 + 0 I testing ccosh(0 + -0 I) == 1 + -0 I testing ccoshf(0 + 0 I) == 1 + 0 I testing ccoshf(0 + -0 I) == 1 + -0 I testing ccosh(-0 + -0 I) == 1 + 0 I testing ccosh(-0 + 0 I) == 1 + -0 I testing ccoshf(-0 + -0 I) == 1 + 0 I testing ccoshf(-0 + 0 I) == 1 + -0 I testing ccos(0 + 0 I) == 1 + -0 I testing ccos(0 + -0 I) == 1 + 0 I testing ccosf(0 + 0 I) == 1 + -0 I testing ccosf(0 + -0 I) == 1 + 0 I testing ccos(-0 + -0 I) == 1 + -0 I testing ccos(-0 + 0 I) == 1 + 0 I testing ccosf(-0 + -0 I) == 1 + -0 I testing ccosf(-0 + 0 I) == 1 + 0 I testing ctanh(0 + 0 I) == 0 + 0 I testing ctanh(0 + -0 I) == 0 + -0 I testing ctanhf(0 + 0 I) == 0 + 0 I *** Check failed: /usr/src/lib/msun/tests/ctrig_test.c:147: ctanhf fetestexcept((0x04 | 0x20 | 0x01 | 0x08 | 0x10)) (0x1) != 0 testing ctanhf(0 + -0 I) == 0 + -0 I *** Check failed: /usr/src/lib/msun/tests/ctrig_test.c:147: ctanhf fetestexcept((0x04 | 0x20 | 0x01 | 0x08 | 0x10)) (0x1) != 0 testing ctanh(-0 + -0 I) == -0 + -0 I testing ctanh(-0 + 0 I) == -0 + 0 I testing ctanhf(-0 + -0 I) == -0 + -0 I *** Check failed: /usr/src/lib/msun/tests/ctrig_test.c:147: ctanhf fetestexcept((0x04 | 0x20 | 0x01 | 0x08 | 0x10)) (0x1) != 0 testing ctanhf(-0 + 0 I) == -0 + 0 I *** Check failed: /usr/src/lib/msun/tests/ctrig_test.c:147: ctanhf fetestexcept((0x04 | 0x20 | 0x01 | 0x08 | 0x10)) (0x1) != 0 testing ctan(0 + 0 I) == 0 + 0 I testing ctan(0 + -0 I) == 0 + -0 I testing ctanf(0 + 0 I) == 0 + 0 I *** Check failed: /usr/src/lib/msun/tests/ctrig_test.c:148: ctanf fetestexcept((0x04 | 0x20 | 0x01 | 0x08 | 0x10)) (0x1) != 0 testing ctanf(0 + -0 I) == 0 + -0 I *** Check failed: /usr/src/lib/msun/tests/ctrig_test.c:148: ctanf fetestexcept((0x04 | 0x20 | 0x01 | 0x08 | 0x10)) (0x1) != 0 testing ctan(-0 + -0 I) == -0 + -0 I testing ctan(-0 + 0 I) == -0 + 0 I testing ctanf(-0 + -0 I) == -0 + -0 I *** Check failed: /usr/src/lib/msun/tests/ctrig_test.c:148: ctanf fetestexcept((0x04 | 0x20 | 0x01 | 0x08 | 0x10)) (0x1) != 0 testing ctanf(-0 + 0 I) == -0 + 0 I *** Check failed: /usr/src/lib/msun/tests/ctrig_test.c:148: ctanf fetestexcept((0x04 | 0x20 | 0x01 | 0x08 | 0x10)) (0x1) != 0 failed: 8 checks failed; see output for more details So it's the exception masks that don't match. IIRC Alexander recently adjusted most of these tests to print the "bad" values if they were failing, but it doesn't really print the actual exception bits. Probably there's some code in ctan and ctanh that takes a shortcut here and precalculates the result, as we've seen before. Sprinkling some volatile or compiling ctan/ctanh with -fno-builtin might help...
OK, for some reason the divide operation in the imaginary part in line 77 gives rise to FE_INVALID (0x1), but *only* if more advanced CPU instructions are used: 41 float complex 42 ctanhf(float complex z) 43 { ... 72 t = tanf(y); 73 beta = 1.0 + t * t; 74 s = sinhf(x); 75 rho = sqrtf(1 + s * s); 76 denom = 1 + beta * s * s; 77 return (CMPLXF((beta * rho * s) / denom, t / denom)); For example, one of the test cases has both x and y at zero, and this results in the values: t=0, beta=1, s=0, rho=1, denom=1 The real part of the return statement calculates (beta * rho * s) / denom = (1 * 1 * 0) / 1 = 0, but this does *not* change the FP exception flags. The imaginary part calculates t / denom = 0 / 1, and for some reason this sets FE_INVALID! It's tricky to debug this using printfs though, since this also causes FE_INEXACT, due to some floating point logic in the guts of printf. Now, as to why compiling for bog-standard x86_64, which *does* use SSE and SSE2, does not raise FE_INVALID, I'm not sure yet.
Hmm it seems that we have a case here that is similar to what is described here: https://stackoverflow.com/questions/63125919/how-to-avoid-floating-point-exceptions-in-unused-simd-lanes The gist being that clang indeed uses the vdivps (Divide Packed Single-Precision) instruction by default, so the two calculations (beta * rho * s) / denom, t / denom) are emitted as: #DEBUG_VALUE: ctanhf:denom <- $xmm2 .loc 1 77 35 is_stmt 1 # src/lib/msun/src/s_ctanhf.c:77:35 vmulss %xmm1, %xmm3, %xmm1 .loc 1 77 41 is_stmt 0 # src/lib/msun/src/s_ctanhf.c:77:41 vmulss %xmm1, %xmm0, %xmm0 .loc 1 77 46 # src/lib/msun/src/s_ctanhf.c:77:46 vinsertps $16, -80(%rbp), %xmm0, %xmm0 # 16-byte Folded Reload # xmm0 = xmm0[0],mem[0],xmm0[2,3] vmovsldup %xmm2, %xmm1 # xmm1 = xmm2[0,0,2,2] vdivps %xmm1, %xmm0, %xmm0 Now the problem with vdivps is apparently that the unused 'lanes' of the SIMD registers can still result in floating point exception bits being set, such as FE_INVALID (in this case probably because the unused lanes have zero in them, giving 0/0). That stackoverflow article suggests using clang's -ffp-exception-behavior=maytrap option (documented at <https://releases.llvm.org/11.0.1/tools/clang/docs/UsersManual.html#cmdoption-ffp-exception-behavior>), meaning "The compiler avoids transformations that may raise exceptions that would not have been raised by the original code". It is supported from clang 10 onwards. In practice, this indeed avoids using vdivps, and uses vdivss (Divide Scalar Single-Precision) instead, and the assembly for line 77 then looks like: #DEBUG_VALUE: ctanhf:denom <- $xmm1 .loc 1 77 35 is_stmt 1 # src/lib/msun/src/s_ctanhf.c:77:35 vmulss %xmm2, %xmm4, %xmm2 .loc 1 77 41 is_stmt 0 # src/lib/msun/src/s_ctanhf.c:77:41 vmulss %xmm0, %xmm2, %xmm0 .loc 1 77 46 # src/lib/msun/src/s_ctanhf.c:77:46 vdivss %xmm1, %xmm0, %xmm2 vmovss -80(%rbp), %xmm0 # 4-byte Reload # xmm0 = mem[0],zero,zero,zero #DEBUG_VALUE: ctanhf:t <- $xmm0 .loc 1 77 57 # src/lib/msun/src/s_ctanhf.c:77:57 vdivss %xmm1, %xmm0, %xmm0 And indeed, in this case the FE_INVALID is gone, and the tests succeed. I guess it may be good to use this -ffp-exception-behavior=maytrap flag for the whole of lib/msun, as many of these functions rely on this behavior. It does not seem to be required for gcc.
A commit in branch main references this bug: URL: https://cgit.FreeBSD.org/src/commit/?id=3b00222f156dca5700c839d73e36daf479fa640c commit 3b00222f156dca5700c839d73e36daf479fa640c Author: Dimitry Andric <dim@FreeBSD.org> AuthorDate: 2021-04-09 23:07:54 +0000 Commit: Dimitry Andric <dim@FreeBSD.org> CommitDate: 2021-04-10 11:59:57 +0000 Avoid raising unexpected floating point exceptions in libm When using clang with x86_64 CPUs that support AVX, some floating point transformations may raise exceptions that would not have been raised by the original code. To avoid this, use the -fp-exception-behavior=maytrap flag, introduced in clang 10.0.0. In particular, this fixes a number of test failures with ctanhf(3) and ctanf(3), when libm is compiled with -mavx. An unexpected FE_INVALID exception is then raised, because clang emits vdivps instructions to perform certain divides. (The vdivps instruction operates on multiple single-precision float operands simultaneously, but the exceptions may be influenced by unused parts of the XMM registers. In this particular case, it was calculating 0 / 0, which results in FE_INVALID.) If -fp-exception-behavior=maytrap is specified however, clang uses vdivss instructions instead, which work on one operand, and should not raise unexpected exceptions. Reported by: olivier Reviewed by: arichardson PR: 254911 MFC after: 1 week Differential Revision: https://reviews.freebsd.org/D29686 lib/msun/Makefile | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-)
A commit in branch main references this bug: URL: https://cgit.FreeBSD.org/src/commit/?id=bae9fd0b33462e9506c3ac3400089c6dbc4aee8f commit bae9fd0b33462e9506c3ac3400089c6dbc4aee8f Author: Dimitry Andric <dim@FreeBSD.org> AuthorDate: 2021-04-10 14:02:49 +0000 Commit: Dimitry Andric <dim@FreeBSD.org> CommitDate: 2021-04-10 14:02:58 +0000 Only use -fp-exception-behavior=maytrap on x86, for now After 3b00222f156d, it turns out that clang only supports strict floating point semantics for SystemZ and x86 at the moment, while for other architectures it is still experimental. Therefore, only use -fp-exception-behavior=maytrap on x86 for now, otherwise this option results in "error: overriding currently unsupported use of floating point exceptions on this target [-Werror,-Wunsupported-floating-point-opt]" on other architectures. Fixes: 3b00222f156d PR: 254911 MFC after: 1 week lib/msun/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
^Triage: assign to committer that resolved, for MFC tracking.
A commit in branch stable/13 references this bug: URL: https://cgit.FreeBSD.org/src/commit/?id=bda3bf09d82daf4352691a7b3a5b0e1cff66a5fd commit bda3bf09d82daf4352691a7b3a5b0e1cff66a5fd Author: Dimitry Andric <dim@FreeBSD.org> AuthorDate: 2021-04-09 23:07:54 +0000 Commit: Dimitry Andric <dim@FreeBSD.org> CommitDate: 2021-04-15 18:33:54 +0000 Avoid raising unexpected floating point exceptions in libm When using clang with x86_64 CPUs that support AVX, some floating point transformations may raise exceptions that would not have been raised by the original code. To avoid this, use the -fp-exception-behavior=maytrap flag, introduced in clang 10.0.0. In particular, this fixes a number of test failures with ctanhf(3) and ctanf(3), when libm is compiled with -mavx. An unexpected FE_INVALID exception is then raised, because clang emits vdivps instructions to perform certain divides. (The vdivps instruction operates on multiple single-precision float operands simultaneously, but the exceptions may be influenced by unused parts of the XMM registers. In this particular case, it was calculating 0 / 0, which results in FE_INVALID.) If -fp-exception-behavior=maytrap is specified however, clang uses vdivss instructions instead, which work on one operand, and should not raise unexpected exceptions. Reported by: olivier Reviewed by: arichardson PR: 254911 Differential Revision: https://reviews.freebsd.org/D29686 (cherry picked from commit 3b00222f156dca5700c839d73e36daf479fa640c) Only use -fp-exception-behavior=maytrap on x86, for now After 3b00222f156d, it turns out that clang only supports strict floating point semantics for SystemZ and x86 at the moment, while for other architectures it is still experimental. Therefore, only use -fp-exception-behavior=maytrap on x86 for now, otherwise this option results in "error: overriding currently unsupported use of floating point exceptions on this target [-Werror,-Wunsupported-floating-point-opt]" on other architectures. Fixes: 3b00222f156d PR: 254911 (cherry picked from commit bae9fd0b33462e9506c3ac3400089c6dbc4aee8f) lib/msun/Makefile | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-)
A commit in branch stable/12 references this bug: URL: https://cgit.FreeBSD.org/src/commit/?id=f2e38602de89608b46a3b920fc222fdcf50864dd commit f2e38602de89608b46a3b920fc222fdcf50864dd Author: Dimitry Andric <dim@FreeBSD.org> AuthorDate: 2021-04-09 23:07:54 +0000 Commit: Dimitry Andric <dim@FreeBSD.org> CommitDate: 2021-04-15 18:38:49 +0000 Avoid raising unexpected floating point exceptions in libm When using clang with x86_64 CPUs that support AVX, some floating point transformations may raise exceptions that would not have been raised by the original code. To avoid this, use the -fp-exception-behavior=maytrap flag, introduced in clang 10.0.0. In particular, this fixes a number of test failures with ctanhf(3) and ctanf(3), when libm is compiled with -mavx. An unexpected FE_INVALID exception is then raised, because clang emits vdivps instructions to perform certain divides. (The vdivps instruction operates on multiple single-precision float operands simultaneously, but the exceptions may be influenced by unused parts of the XMM registers. In this particular case, it was calculating 0 / 0, which results in FE_INVALID.) If -fp-exception-behavior=maytrap is specified however, clang uses vdivss instructions instead, which work on one operand, and should not raise unexpected exceptions. Reported by: olivier Reviewed by: arichardson PR: 254911 Differential Revision: https://reviews.freebsd.org/D29686 (cherry picked from commit 3b00222f156dca5700c839d73e36daf479fa640c) Only use -fp-exception-behavior=maytrap on x86, for now After 3b00222f156d, it turns out that clang only supports strict floating point semantics for SystemZ and x86 at the moment, while for other architectures it is still experimental. Therefore, only use -fp-exception-behavior=maytrap on x86 for now, otherwise this option results in "error: overriding currently unsupported use of floating point exceptions on this target [-Werror,-Wunsupported-floating-point-opt]" on other architectures. Fixes: 3b00222f156d PR: 254911 (cherry picked from commit bae9fd0b33462e9506c3ac3400089c6dbc4aee8f) lib/msun/Makefile | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-)
A commit in branch stable/11 references this bug: URL: https://cgit.FreeBSD.org/src/commit/?id=cabc474b2dc9c6741b240e454da86a7ff2ff9f9c commit cabc474b2dc9c6741b240e454da86a7ff2ff9f9c Author: Dimitry Andric <dim@FreeBSD.org> AuthorDate: 2021-04-09 23:07:54 +0000 Commit: Dimitry Andric <dim@FreeBSD.org> CommitDate: 2021-04-15 18:52:57 +0000 Avoid raising unexpected floating point exceptions in libm When using clang with x86_64 CPUs that support AVX, some floating point transformations may raise exceptions that would not have been raised by the original code. To avoid this, use the -fp-exception-behavior=maytrap flag, introduced in clang 10.0.0. In particular, this fixes a number of test failures with ctanhf(3) and ctanf(3), when libm is compiled with -mavx. An unexpected FE_INVALID exception is then raised, because clang emits vdivps instructions to perform certain divides. (The vdivps instruction operates on multiple single-precision float operands simultaneously, but the exceptions may be influenced by unused parts of the XMM registers. In this particular case, it was calculating 0 / 0, which results in FE_INVALID.) If -fp-exception-behavior=maytrap is specified however, clang uses vdivss instructions instead, which work on one operand, and should not raise unexpected exceptions. Reported by: olivier Reviewed by: arichardson PR: 254911 Differential Revision: https://reviews.freebsd.org/D29686 (cherry picked from commit 3b00222f156dca5700c839d73e36daf479fa640c) Only use -fp-exception-behavior=maytrap on x86, for now After 3b00222f156d, it turns out that clang only supports strict floating point semantics for SystemZ and x86 at the moment, while for other architectures it is still experimental. Therefore, only use -fp-exception-behavior=maytrap on x86 for now, otherwise this option results in "error: overriding currently unsupported use of floating point exceptions on this target [-Werror,-Wunsupported-floating-point-opt]" on other architectures. Fixes: 3b00222f156d PR: 254911 (cherry picked from commit bae9fd0b33462e9506c3ac3400089c6dbc4aee8f) lib/msun/Makefile | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-)
A commit in branch main references this bug: URL: https://cgit.FreeBSD.org/src/commit/?id=e2157cd0000f6dbb6465d7a885f2dcfd4d3596cb commit e2157cd0000f6dbb6465d7a885f2dcfd4d3596cb Author: Dimitry Andric <dim@FreeBSD.org> AuthorDate: 2021-11-05 21:26:16 +0000 Commit: Dimitry Andric <dim@FreeBSD.org> CommitDate: 2021-11-05 21:27:20 +0000 Partially revert ac76bc1145dd because it is no longer necessary In ac76bc1145dd, I added a few volatiles to work around ctrig_test failures with {inf,inf}. This is not necessary anymore now, since in 3b00222f156d we added -fp-exception-behavior=maytrap for clang >= 10 in libm's Makefile. (The flag tells clang to use stricter floating point semantics, which libm depends on.) PR: 244732, 254911 Fixes: ac76bc1145dd MFC after: 3 days lib/msun/src/s_ccoshf.c | 2 +- lib/msun/src/s_ctanh.c | 2 +- lib/msun/src/s_ctanhf.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-)
A commit in branch stable/13 references this bug: URL: https://cgit.FreeBSD.org/src/commit/?id=188a9517358e9dba97fb8dd682540bc915beed40 commit 188a9517358e9dba97fb8dd682540bc915beed40 Author: Dimitry Andric <dim@FreeBSD.org> AuthorDate: 2021-11-05 21:26:16 +0000 Commit: Dimitry Andric <dim@FreeBSD.org> CommitDate: 2021-11-08 21:00:47 +0000 Partially revert ac76bc1145dd because it is no longer necessary In ac76bc1145dd, I added a few volatiles to work around ctrig_test failures with {inf,inf}. This is not necessary anymore now, since in 3b00222f156d we added -fp-exception-behavior=maytrap for clang >= 10 in libm's Makefile. (The flag tells clang to use stricter floating point semantics, which libm depends on.) PR: 244732, 254911 Fixes: ac76bc1145dd (cherry picked from commit e2157cd0000f6dbb6465d7a885f2dcfd4d3596cb) lib/msun/src/s_ccoshf.c | 2 +- lib/msun/src/s_ctanh.c | 2 +- lib/msun/src/s_ctanhf.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-)
A commit in branch stable/12 references this bug: URL: https://cgit.FreeBSD.org/src/commit/?id=d92735449c54a15f6f048ccefd61a9583d1935d0 commit d92735449c54a15f6f048ccefd61a9583d1935d0 Author: Dimitry Andric <dim@FreeBSD.org> AuthorDate: 2021-11-05 21:26:16 +0000 Commit: Dimitry Andric <dim@FreeBSD.org> CommitDate: 2021-11-08 21:12:26 +0000 Partially revert ac76bc1145dd because it is no longer necessary In ac76bc1145dd, I added a few volatiles to work around ctrig_test failures with {inf,inf}. This is not necessary anymore now, since in 3b00222f156d we added -fp-exception-behavior=maytrap for clang >= 10 in libm's Makefile. (The flag tells clang to use stricter floating point semantics, which libm depends on.) PR: 244732, 254911 Fixes: ac76bc1145dd (cherry picked from commit e2157cd0000f6dbb6465d7a885f2dcfd4d3596cb) lib/msun/src/s_ccoshf.c | 2 +- lib/msun/src/s_ctanh.c | 2 +- lib/msun/src/s_ctanhf.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-)
A commit in branch stable/11 references this bug: URL: https://cgit.FreeBSD.org/src/commit/?id=ca7ffd26b3b56cf94f8ee6d373d1cb47eb046fe0 commit ca7ffd26b3b56cf94f8ee6d373d1cb47eb046fe0 Author: Dimitry Andric <dim@FreeBSD.org> AuthorDate: 2021-11-05 21:26:16 +0000 Commit: Dimitry Andric <dim@FreeBSD.org> CommitDate: 2021-11-08 21:14:41 +0000 Partially revert ac76bc1145dd because it is no longer necessary In ac76bc1145dd, I added a few volatiles to work around ctrig_test failures with {inf,inf}. This is not necessary anymore now, since in 3b00222f156d we added -fp-exception-behavior=maytrap for clang >= 10 in libm's Makefile. (The flag tells clang to use stricter floating point semantics, which libm depends on.) PR: 244732, 254911 Fixes: ac76bc1145dd (cherry picked from commit e2157cd0000f6dbb6465d7a885f2dcfd4d3596cb) lib/msun/src/s_ccoshf.c | 2 +- lib/msun/src/s_ctanh.c | 2 +- lib/msun/src/s_ctanhf.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-)