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