[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