RISC-V / GCC 10: invalid operation not set in acos and asin
Aurelien Jarno
aurelien@aurel32.net
Wed May 13 20:16:20 GMT 2020
On 2020-05-13 15:41, Adhemerval Zanella via Libc-alpha wrote:
>
>
> On 13/05/2020 13:27, Aurelien Jarno wrote:
> > Hi all,
> >
> > When trying to build the glibc with GCC 10 on riscv64 and then run
> > the glibc testsuite, I get the following additional testsuite failures
> > compared to GCC 9:
> >
> > | FAIL: math/test-double-acos
> > | FAIL: math/test-double-asin
> > | FAIL: math/test-float32x-acos
> > | FAIL: math/test-float32x-asin
> > | FAIL: math/test-float64-acos
> > | FAIL: math/test-float64-asin
> >
> > Here is the detailed output returned by test-double-acos (they are all
> > similar):
> >
> > | FAIL: math/test-double-acos
> > | original exit status 1
> > | testing double (without inline functions)
> > | Failure: acos (inf): Exception "Invalid operation" not set
> > | Failure: acos (-inf): Exception "Invalid operation" not set
> > | Failure: acos (1.125): Exception "Invalid operation" not set
> > | Failure: acos (-1.125): Exception "Invalid operation" not set
> > | Failure: acos (max_value): Exception "Invalid operation" not set
> > | Failure: acos (-max_value): Exception "Invalid operation" not set
> > | Failure: acos_downward (inf): Exception "Invalid operation" not set
> > | Failure: acos_downward (-inf): Exception "Invalid operation" not set
> > | Failure: acos_downward (1.125): Exception "Invalid operation" not set
> > | Failure: acos_downward (-1.125): Exception "Invalid operation" not set
> > | Failure: acos_downward (max_value): Exception "Invalid operation" not set
> > | Failure: acos_downward (-max_value): Exception "Invalid operation" not set
> > | Failure: acos_towardzero (inf): Exception "Invalid operation" not set
> > | Failure: acos_towardzero (-inf): Exception "Invalid operation" not set
> > | Failure: acos_towardzero (1.125): Exception "Invalid operation" not set
> > | Failure: acos_towardzero (-1.125): Exception "Invalid operation" not set
> > | Failure: acos_towardzero (max_value): Exception "Invalid operation" not set
> > | Failure: acos_towardzero (-max_value): Exception "Invalid operation" not set
> > | Failure: acos_upward (inf): Exception "Invalid operation" not set
> > | Failure: acos_upward (-inf): Exception "Invalid operation" not set
> > | Failure: acos_upward (1.125): Exception "Invalid operation" not set
> > | Failure: acos_upward (-1.125): Exception "Invalid operation" not set
> > | Failure: acos_upward (max_value): Exception "Invalid operation" not set
> > | Failure: acos_upward (-max_value): Exception "Invalid operation" not set
> > |
> > | Test suite completed:
> > | 372 test cases plus 368 tests for exception flags and
> > | 368 tests for errno executed.
> > | 24 errors occurred.
> >
> > I have tracked the issue to the following piece of code from
> > sysdeps/ieee754/dbl-64/e_asin.c:
> >
> > | else {
> > | u.i[HIGH_HALF]=0x7ff00000;
> > | v.i[HIGH_HALF]=0x7ff00000;
> > | u.i[LOW_HALF]=0;
> > | v.i[LOW_HALF]=0;
> > | return u.x/v.x;
> > | }
> >
> > GCC 10 optimizes out that code and loads a NaN value from memory instead
> > of doing the division, which explains why the invalid operation
> > exception is not set.
> >
> > The problem doesn't appear with the acosf/asinf, which set the result to
> > NaN using (x-x)/(x-x). I have tried that trick for acos/asin and it
> > works fine, at least for riscv64. I wonder if it is an acceptable
> > solution or if there is a better way to do that.
>
> Maybe to force the invalid operation we can use:
>
> math_force_eval (0.0 / 0.0);
> return NAN;
>
> And for underflow handling we have math/math-underflow.h, maybe
> add a math/math-invalid.h with macros to simplify it?
I confirm this technique works. It also works with math_opt_barrier
after marking it with __volatile__, so that the result from 0.0/0.0 can
be returned directly instead of potentially generating extra
instructions to create a NaN.
--
Aurelien Jarno GPG: 4096R/1DDD8C9B
aurelien@aurel32.net http://www.aurel32.net
More information about the Libc-alpha
mailing list