[PATCH] D69272: Enable '#pragma STDC FENV_ACCESS' in frontend
John McCall via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Fri Feb 7 18:55:47 PST 2020
rjmccall added a comment.
In D69272#1865266 <https://reviews.llvm.org/D69272#1865266>, @rsmith wrote:
> I don't see any changes to the constant evaluator here. You need to properly handle constant evaluation within `FENV_ACCESS ON` contexts, somehow, or you'll miscompile floating-point operations with constant operands. Probably the easiest thing would be to treat all rounded FP operations as non-constant in an `FENV_ACCESS ON` region, though in C++ `constexpr` evaluations we could permit rounded FP operations if the evaluation began in an `FENV_ACCESS OFF` region (that way we know the computations should be done in the default FP environment because `feset*` are not `constexpr` functions).
FWIW, C does actually specify behavior here:
> C2x (n2454)
> **F.8.4 Constant expressions**
> p1. An arithmetic constant expression of floating type, other than one in an initializer for an object that has static or thread storage duration, is evaluated (as if) during execution; thus, it is affected by any operative floating-point control modes and raises floating-point exceptions as required by IEC 60559 (provided the state for the FENV_ACCESS pragma is "on").
>
> p2. Example:
>
> #include <fenv.h>
> #pragma STDC FENV_ACCESS ON
> void f(void)
> {
> float w[] = { 0.0/0.0 }; // raises an exception
> static float x = 0.0/0.0; // does not raise an exception
> float y = 0.0/0.0; // raises an exception
> double z = 0.0/0.0; // raises an exception
> /* ... */
> }
>
>
> p3. For the static initialization, the division is done at translation time, raising no (execution-time) floating-point exceptions. On the other hand, for the three automatic initializations the invalid division occurs at execution time.
>
> **F.8.2 Translation**
> p1. During translation, constant rounding direction modes are in effect where specified. Elsewhere, during translation the IEC 60559 default modes are in effect:
>
> - The rounding direction mode is rounding to nearest.
> - The rounding precision mode (if supported) is set so that results are not shortened.
> - Trapping or stopping (if supported) is disabled on all floating-point exceptions.
>
> p2. (Recommended practice) The implementation should produce a diagnostic message for each translation-time floating-point exception, other than "inexact"; the implementation should then proceed with the translation of the program.
Some of this translates naturally to C++: e.g. `constexpr` evaluations are always "during translation" and therefore should honor rounding modes but not the dynamic environment. Of course, C++ also allows static initialization to be non-constant, and we don't really want an implementation decision (or the presence of one perhaps-unexpectedly non-constexpr sub-expression) to cause gross differences in behavior. I think the most consistent rule is to say that `FENV_ACCESS` just doesn't apply to the direct initializers of file-scope variables and static data members, so if you want static initialization to be environment-aware, you need to move it into a function with the pragma active, which then (as you suggest) cannot be constant-folded. I guess `FENV_ACCESS` *would* apply to the initialization of static local variable unless it was `constinit`, which would be a C vs. C++ inconsistency but hopefully an understandable one.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D69272/new/
https://reviews.llvm.org/D69272
More information about the cfe-commits
mailing list