rsmith accepted this revision.
rsmith added a comment.
This revision is now accepted and ready to land.

Thanks, I'm happy with this, though please wait a day or two for comments from 
the other reviewers.

We should also add some documentation covering the rules we're using for the 
floating-point environment in C++, particularly around initializers for 
variables with static storage duration, given that that's not governed by any 
language standard.



================
Comment at: clang/test/CodeGen/fp-floatcontrol-pragma.cpp:159
+  //CHECK: store float 3.0{{.*}}retval{{.*}}
+  static double v = 1.0 / 3.0;
+  //CHECK-FENV: llvm.experimental.constrained.fptrunc.f32.f64{{.*}}
----------------
mibintc wrote:
> @rsmith - the division is constant folded.  is that right? 
Yes, that's in line with our new expectations for C++. Specifically: for static 
/ thread-local variables, first try evaluating the initializer in a constant 
context, including in the constant floating point environment (just like in C), 
and then, if that fails, fall back to emitting runtime code to perform the 
initialization (which might in general be in a different FP environment). Given 
that `1.0 / 3.0` is a constant initializer, it should get folded using the 
constant rounding mode. But, for example:

```
double f() {
  int n = 0;
  static double v = 1.0 / 3.0 + 0 * n;
  return v;
}
```

... should emit a constrained `fdiv` at runtime, because the read of `n` causes 
the initializer to not be a constant initializer. And similarly:

```
double f() {
  double v = 1.0 / 3.0 + 0 * n;
  return v;
}
```

... should emit a constrained `fdiv`, because `v` is not a static storage 
duration variable, so there is formally no "first try evaluating the 
initializer as a constant" step.


================
Comment at: clang/test/Parser/pragma-fenv_access.c:28
+#if defined(CPP) & defined(STRICT)
+//not-expected-error@+3 {{constexpr variable 'frac' must be initialized by a 
constant expression}}
+//not-expected-note@+2 {{compile time floating point arithmetic suppressed in 
strict evaluation modes}}
----------------
mibintc wrote:
> @rsmith no diagnostic, is this OK?
Under the new approach from D89360, I would expect no diagnostic with `CONST` 
defined as `constexpr`, because the initializer is then manifestly 
constant-evaluated, so should be evaluated in the constant rounding mode.

With `CONST` defined as merely `const`, I'd expect that we emit a constrained 
floating-point operation using the runtime rounding mode here. You can test 
that we don't constant-evaluate the value of a (non-`constexpr`) `const float` 
variable by using this hack (with `CONST` defined as `const`):

```
enum {
  e1 = (int)one, e3 = (int)three, e4 = (int)four, e_four_quarters = 
(int)(frac_ok * 4)
};
static_assert(e1 == 1  && e3 == 3 && e4 == 4 && e_four_quarters == 1, "");
enum {
  e_three_thirds = (int)(frac * 3) // expected-error {{not an integral constant 
expression}}
};
```

(The hack here is that we permit constant folding in the values of enumerators, 
and we allow constant folding to look at the evaluated values of `const float` 
variables. This should not be allowed for `frac`, because attempting to 
evaluate its initializer should fail.)


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D87528/new/

https://reviews.llvm.org/D87528

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to