public inbox for libc-alpha@sourceware.org
 help / color / mirror / Atom feed
* nearbyint(double) on aarch64 vs. riscv
@ 2020-07-20 19:00 Vineet Gupta
  2020-07-20 19:43 ` Adhemerval Zanella
  0 siblings, 1 reply; 5+ messages in thread
From: Vineet Gupta @ 2020-07-20 19:00 UTC (permalink / raw)
  To: libc-alpha @ sourceware . org; +Cc: Joseph Myers, Szabolcs Nagy

Hi,

I'm curious about the codegen for nearbyint() on aarc64.
From a build of off of build-many-glibc.py I see:

000000000003c8e8 <nearbyint>:
   3c8e8:	frinti	d0, d0
   3c8ec:	ret

vs. rv64imafdc

0000000000030ff8 <nearbyint>:
   30ff8:	*frflags*	a4
   30ffc:	feq.d	a5,fa0,fa0
   31000:	fabs.d	fa5,fa0
   31004:	beqz	a5,31026 <nearbyint+0x2e>
   31006:	auipc	a5,0x43
   3100a:	fld	fa4,-694(a5) # 73d50 <factor+0x28>
   3100e:	flt.d	a5,fa5,fa4
   31012:	beqz	a5,31024 <nearbyint+0x2c>
   31014:	fcvt.l.d	a5,fa0
   31018:	fcvt.d.l	fa5,a5
   3101c:	fsgnj.d	fa0,fa5,fa0
   31020:	*fsflags*	a4
   31024:	ret
   31026:	fadd.d	fa0,fa0,fa0
   3102a:	ret

So RISCV is using the conversion instructions and also disabling the FPU
exceptions around the math code.

AARCH64 uses FRINTI instruction which per [1] can generate exceptions (atleast set
flags in FPSR). Isn't the code supposed to wrap __builtin_nearbyint() with
feholdexcept() / fesetenv().

I'm assuming FPU flags are callee preserved since the caller may not know what
goes down the rabbit hole ?

[1] ARM compiler asm user guide https://developer.arm.com/documentation/dui0802/a/

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: nearbyint(double) on aarch64 vs. riscv
  2020-07-20 19:00 nearbyint(double) on aarch64 vs. riscv Vineet Gupta
@ 2020-07-20 19:43 ` Adhemerval Zanella
  2020-07-20 19:52   ` Joseph Myers
  0 siblings, 1 reply; 5+ messages in thread
From: Adhemerval Zanella @ 2020-07-20 19:43 UTC (permalink / raw)
  To: libc-alpha



On 20/07/2020 16:00, Vineet Gupta via Libc-alpha wrote:
> Hi,
> 
> I'm curious about the codegen for nearbyint() on aarc64.
> From a build of off of build-many-glibc.py I see:
> 
> 000000000003c8e8 <nearbyint>:
>    3c8e8:	frinti	d0, d0
>    3c8ec:	ret
> 
> vs. rv64imafdc
> 
> 0000000000030ff8 <nearbyint>:
>    30ff8:	*frflags*	a4
>    30ffc:	feq.d	a5,fa0,fa0
>    31000:	fabs.d	fa5,fa0
>    31004:	beqz	a5,31026 <nearbyint+0x2e>
>    31006:	auipc	a5,0x43
>    3100a:	fld	fa4,-694(a5) # 73d50 <factor+0x28>
>    3100e:	flt.d	a5,fa5,fa4
>    31012:	beqz	a5,31024 <nearbyint+0x2c>
>    31014:	fcvt.l.d	a5,fa0
>    31018:	fcvt.d.l	fa5,a5
>    3101c:	fsgnj.d	fa0,fa5,fa0
>    31020:	*fsflags*	a4
>    31024:	ret
>    31026:	fadd.d	fa0,fa0,fa0
>    3102a:	ret
> 
> So RISCV is using the conversion instructions and also disabling the FPU
> exceptions around the math code.
> 
> AARCH64 uses FRINTI instruction which per [1] can generate exceptions (atleast set
> flags in FPSR). Isn't the code supposed to wrap __builtin_nearbyint() with
> feholdexcept() / fesetenv().

If you check ARM Architecture Reference Manual for ARMv8-A architecture profile f
on the 'frinti' description for scalar (C7.2.143) its operation is defined as:

  CheckFPAdvSIMDEnabled64();
  bits(datasize) result;
  bits(datasize) operand = V[n];
  result = FPRoundInt(operand, FPCR, rounding, FALSE);
  V[d] = result;

And later FPRoundInt is defined as:

  bits(N) FPRoundInt(bits(N) op, FPCRType fpcr, FPRounding rounding, boolean exact)
    [...]
    else
    // extract integer component
    int_result = RoundDown(value);
    error = value - Real(int_result);

    // Convert integer value into an equivalent real value
    real_result = Real(int_result);

    // Re-encode as a floating-point value, result is always exact
    if real_result == 0.0 then
      result = FPZero(sign);
    else
      result = FPRound(real_result, fpcr, FPRounding_ZERO);

    // Generate inexact exceptions
    if error != 0.0 && exact then
      FPProcessException(FPExc_Inexact, fpcr);

Afaik RoundDown does not generate any exception by definition.  The FPRound 
operation might generat an FP exception, however since the argument used is 
always an integer neither undeflow, inexact, or invalid operation would happen.

An inexact exception is just generated is 'exact' is true and frinti 
explicit sets it to false (different than frintx).

I am not sure exactly why the documentation does state that a floating-point 
exception can be generated by frinti.

> 
> I'm assuming FPU flags are callee preserved since the caller may not know what
> goes down the rabbit hole ?
> 
> [1] ARM compiler asm user guide https://developer.arm.com/documentation/dui0802/a/
> 


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: nearbyint(double) on aarch64 vs. riscv
  2020-07-20 19:43 ` Adhemerval Zanella
@ 2020-07-20 19:52   ` Joseph Myers
  2020-07-21 20:03     ` Vineet Gupta
  0 siblings, 1 reply; 5+ messages in thread
From: Joseph Myers @ 2020-07-20 19:52 UTC (permalink / raw)
  To: Adhemerval Zanella; +Cc: libc-alpha

On Mon, 20 Jul 2020, Adhemerval Zanella via Libc-alpha wrote:

> I am not sure exactly why the documentation does state that a floating-point 
> exception can be generated by frinti.

Because the "invalid" exception would be generated for signaling NaNs, and 
the architecture-specific "input denormal" exception might also be 
generated by the FPUnpack part of the operation.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: nearbyint(double) on aarch64 vs. riscv
  2020-07-20 19:52   ` Joseph Myers
@ 2020-07-21 20:03     ` Vineet Gupta
  2020-07-21 20:26       ` Joseph Myers
  0 siblings, 1 reply; 5+ messages in thread
From: Vineet Gupta @ 2020-07-21 20:03 UTC (permalink / raw)
  To: Joseph Myers, Adhemerval Zanella; +Cc: libc-alpha

On 7/20/20 12:52 PM, Joseph Myers wrote:
> On Mon, 20 Jul 2020, Adhemerval Zanella via Libc-alpha wrote:
> 
>> I am not sure exactly why the documentation does state that a floating-point 
>> exception can be generated by frinti.
> 
> Because the "invalid" exception would be generated for signaling NaNs, and 
> the architecture-specific "input denormal" exception might also be 
> generated by the FPUnpack part of the operation.

But even for these arcane cases, isn't nearbyint() expected to "hold" FP
exceptions. It would be really easy to test/break this even with existing math tests.


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: nearbyint(double) on aarch64 vs. riscv
  2020-07-21 20:03     ` Vineet Gupta
@ 2020-07-21 20:26       ` Joseph Myers
  0 siblings, 0 replies; 5+ messages in thread
From: Joseph Myers @ 2020-07-21 20:26 UTC (permalink / raw)
  To: Vineet Gupta; +Cc: Adhemerval Zanella, libc-alpha

On Tue, 21 Jul 2020, Vineet Gupta via Libc-alpha wrote:

> On 7/20/20 12:52 PM, Joseph Myers wrote:
> > On Mon, 20 Jul 2020, Adhemerval Zanella via Libc-alpha wrote:
> > 
> >> I am not sure exactly why the documentation does state that a floating-point 
> >> exception can be generated by frinti.
> > 
> > Because the "invalid" exception would be generated for signaling NaNs, and 
> > the architecture-specific "input denormal" exception might also be 
> > generated by the FPUnpack part of the operation.
> 
> But even for these arcane cases, isn't nearbyint() expected to "hold" FP
> exceptions. It would be really easy to test/break this even with existing math tests.

math/test-nearbyint-except-2.c verifies that nearbyint works when traps on 
"inexact" are enabled.  The generic libm tests cover the case of default 
exception handling, including for sNaN arguments.  There are no 
expectations that glibc does anything in particular with non-IEEE 
exceptions such as "input denormal".

"hold" is not an IEEE concept.  Floating-point exceptions are signaled, 
which, with default exception handling, generally results in a flag being 
raised and a default result returned.  The requirements on nearbyint 
relate to its observable behavior, which in standard C means the return 
value and (standard) exception flags raised when it returns.  The 
requirements include that an sNaN argument results in a qNaN return value 
with "invalid" raised, but that noninteger (finite) arguments do not 
result in "inexact" raised.  Whether the implementation just uses an 
instruction with the relevant effect, or whether it has to save and 
restore exception state internally, doesn't matter as long as the observed 
behavior is as expcted.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2020-07-21 20:26 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-07-20 19:00 nearbyint(double) on aarch64 vs. riscv Vineet Gupta
2020-07-20 19:43 ` Adhemerval Zanella
2020-07-20 19:52   ` Joseph Myers
2020-07-21 20:03     ` Vineet Gupta
2020-07-21 20:26       ` Joseph Myers

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).