-
-
Notifications
You must be signed in to change notification settings - Fork 5.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add floating point environment to task state #51277
Comments
LLVM assumes fenv is set to default [1]. In order for the code to be correct under a different fenv LLVM provides constraint fp ops [2]. I am not convinced we should expose There is the additional issue of the Julia optimizer performing constant propagation which like LLVM assumes a specific So I think to provide sensible semantics we should follow LLVM's lead, provide constraint fp semantics (codegen thereof is a bit tricky) and added complication is that our math functions are implemented in Julia, LLVM also has constrained libm functions [3]. [1] https://llvm.org/docs/LangRef.html#floating-point-environment |
To clarify, my eventual aim would be to support (in order of priority)
There are effectively two things we would need to change:
However I don't think 2 is actually necessary precondition for 1: personally I would actually find it useful to be able to trap on NaN even if it wasn't 100% correct all of the time (i.e. it missed some, or caught the occasional spurious exception). Moreover, I think we probably do need runtime support before we can discuss what changes to the compiler are needed. What I would like to propose would be to add the minimum necessary features to support 1 in Julia itself (basically what I propose above, along with some variant of #47930), and we can put the actual interface itself could either be in a package or an experimental module. |
This is a fair point: I would be curious to know what this would add to the cost of a task switch. |
If we decide to add constrained ops to the language and thus have proper semantics for this in the optimizer and code-generator we may have to consider the fenv state that we need to store and restore on Task-Switch and exception handling. Otherwise access to the fenv is not yet defined behavior (even though we use it for rounding semantics, but we may get away with that since it's unlikely we will switch tasks). We should probably replace the rounding code with calls to constrained intrinsics. |
we actually deprecated that a while back. Currently |
Ah! Just grepped and didn't see that the only usage was in the tests https://github.com/JuliaLang/julia/blob/4af6be80f238fce9cd124925d488a4c7171cf74a/test/rounding.jl#L80C1-L80C1 |
I think having the floating point environment be global (or task local) state is just a design mistake. Rather, the operations should take explicit floating point controls (possible hidden behind abstractions) and if the hardware has global FP state, the compiler should mux it. Of course, dynamically scoped floating point state can be re-built on top of that if really desired, but I'm not sure it would be. |
Just here to say that something that gets As part of a long-running thread on the precision of |
It is a platform ABI mistake in most existing compilers (since the ABI fails to specify whether it is a callee or caller saved register, resulting in compilers failing to do either). But is that ABI bug possible for us to fix, given the legacy of compilers implementing this badly? It seems like we would need to define it as callee-saved to be compatible, and declare it is an LLVM bug for any of our function calls (e.g. fesetenv) to fail to restore registers, unless they are intrinsic functions (e.g. llvm.set.fpmode). In theory this is fixable in LLVM, because the compiler already implements this for every other register except for this one, but it might require significant work. |
I'd like to make the floating point environment (which controls rounding mode and floating point exceptions) a bit more useful. Currently we use the C behavior where the floating point environment is set per-thread, which doesn't really make sense in the context of tasks which can switch threads.
I'd like to propose adding the floating point environment (
fenv_t
object) to the task state. The simplest approach I can think of is that every time a thread switches tasks, we capture the current floating point environment of the current task and save it to the struct (viafegetenv
), and set the environment to that of the new task (viafesetenv
). In this way, the floating point environment should follow the task (and be inherited by child tasks).The text was updated successfully, but these errors were encountered: