Trapping math for RISC-V

Hi all,

I am going to start working on trapping-math for RISC-V, If anyone is currently working then please let me know!

Is support for trapping-math already there in RISCV?? Because not seeing any warnings in latest…

@asb maybe you know someone who might know?

I’m curious about this too.
@kito-cheng @jrtc27 Do you know whether we support this or not? If not, I think it can be put in future TODO list out of compatibility.

Floating point is an area I’m not so familiar with. It seems like it should mostly be about the middle-end optimisation passes though, unless SelectionDAG is doing things?

My rudimentary understanding about floating point trapping math is that the program should raise a trap instead of just set fflags when an exception like div zero, invalid input, illegal operations, etc occurs.
The asm will be like:

  f<op> fa0, fa1, fa2
  // check fflags
  beqz <fflags>, .success // continue if no exception
trap:
  ecall xxx // call to trap
success:
  ...

We need supports of compiler and runtime to achieve this since RISC-V F/D instructions won’t trap by default like X86.
Some other ARCHs like AArch64(?) have the same issue.
References:

Aarch64 supports floating-point exceptions in some hardware, but where it’s unsupported there’s no software-emulation implementation of traps. I’m not aware of any architectures where someone’s attempted to implement software-emulation of floating-point traps when the hardware doesn’t support them.

It’s more complex to implement than described above, because traps should not trigger based on accrued exception bits, but only on flags raised by the operation being executed.

Thus, to emulate this correctly, you need to

  1. Write zero to FFLAGS, and save the previous value into a register
  2. Execute the FP instruction
  3. Read the enabled-trap-bits from wherever that’s stored.
  4. AND new FFLAGS with those enabled-trap bits.
  5. OR the flags saved in step 1 back into current FFLAGS register.
  6. Branch over the call to the trap handler if the result of step 4 was zero.
  7. Call the trap handler, providing it the result of step 4, so it knows which flag to set in the siginfo_t passed to the signal handler.

You’ll also need to define an ABI for where the trap-enable bits are stored – possibly that must be handled by the kernel, since the value should be cleared and restored around signal handlers? Or maybe it can be handled by libc? And you’ll also define the ABI for how to invoke the trap handler…

This really seems an awful lot of complexity…and a lot of overhead. I would, instead, encourage everyone to just avoid the need to do this.

1 Like