[PATCH] D69272: Enable '#pragma STDC FENV_ACCESS' in frontend

2020-11-15 Thread Serge Pavlov via Phabricator via cfe-commits
sepavloff abandoned this revision.
sepavloff added a comment.

Implemented in D87528 .


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D69272

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


[PATCH] D69272: Enable '#pragma STDC FENV_ACCESS' in frontend

2020-09-14 Thread Melanie Blower via Phabricator via cfe-commits
mibintc added a comment.

In D69272#2271338 , @sepavloff wrote:

> In D69272#2268337 , @mibintc wrote:
>
>> I am working on a task to ensure that clang is doing floating point constant 
>> folding correctly.
>
> Could you please share your plans on it? I recently also started implementing 
> constant folding in `ExprConstant.cpp`. I have not made anything substantial 
> yet, so I can easily switch to another task. Do you have any estimation when 
> you could prepare the first version of the patch?

I've been given a vague assignment, something along the lines "investigate 
floating point constant folding and make sure that the semantics are correct. " 
In the Intel ICL compiler, there were some circumstances of the semantics not 
being correct.  I saw Richard's comments in this review, and Intel also needs 
FENV_ACCESS implemented so I thought I'd start here.  I'm not a floating point 
expert, but of course some of my colleagues at Intel are!  I am pretty slow but 
it's my area of focus.

>> But sometimes, if the floating point semantics are set to 'strict', even 
>> tho' folding has occurred successfully in ExprConstant.cpp, when i look at 
>> emit-llvm, there is arithmetic emitted for the floating point expression;
>
> I used a bit different approach, may be it could be useful for you too. An 
> initializer for global variable must be a constant, so things like `const xxx 
> = 1.0 + 2.0` are evaluated. No llvm arithmetic occurs in the resulting ll 
> file. Using `pragma STDC FENV_ROUND` floating point environment may be set to 
> non-default state, which constant evaluator must use.

When I implemented clang #pragma float_control, I noticed that initialization 
expressions in classes were not subject to the pragma's that are active in the 
source file. Those expressions are pulled out and processed differently than 
the function bodies. I'll upload later today a patch that uses 
Expr->getFPFeaturesInEffect() to inhibit constant folding in ExprConstant.cpp.

> In D69272#2268387 , @kpn wrote:
>
>> Say, in D80952  I added support for 
>> disabling strictfp support when a target doesn't support it. But it only 
>> applies to command line arguments.
>>
>> Is there any chance at all that relevant pragmas can also be disabled with 
>> the warning in the same cases?
>
> This is definitely a good idea.

I'll look into it, thank you


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D69272

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


[PATCH] D69272: Enable '#pragma STDC FENV_ACCESS' in frontend

2020-09-14 Thread Serge Pavlov via Phabricator via cfe-commits
sepavloff added a comment.

In D69272#2268337 , @mibintc wrote:

> I am working on a task to ensure that clang is doing floating point constant 
> folding correctly.

Could you please share your plans on it? I recently also started implementing 
constant folding in `ExprConstant.cpp`. I have not made anything substantial 
yet, so I can easily switch to another task. Do you have any estimation when 
you could prepare the first version of the patch?

> But sometimes, if the floating point semantics are set to 'strict', even tho' 
> folding has occurred successfully in ExprConstant.cpp, when i look at 
> emit-llvm, there is arithmetic emitted for the floating point expression;

I used a bit different approach, may be it could be useful for you too. An 
initializer for global variable must be a constant, so things like `const xxx = 
1.0 + 2.0` are evaluated. No llvm arithmetic occurs in the resulting ll file. 
Using `pragma STDC FENV_ROUND` floating point environment may be set to 
non-default state, which constant evaluator must use.

In D69272#2268387 , @kpn wrote:

> Say, in D80952  I added support for 
> disabling strictfp support when a target doesn't support it. But it only 
> applies to command line arguments.
>
> Is there any chance at all that relevant pragmas can also be disabled with 
> the warning in the same cases?

This is definitely a good idea.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D69272

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


[PATCH] D69272: Enable '#pragma STDC FENV_ACCESS' in frontend

2020-09-11 Thread Kevin P. Neal via Phabricator via cfe-commits
kpn added a comment.

Say, in D80952  I added support for disabling 
strictfp support when a target doesn't support it. But it only applies to 
command line arguments.

Is there any chance at all that relevant pragmas can also be disabled with the 
warning in the same cases?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D69272

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


[PATCH] D69272: Enable '#pragma STDC FENV_ACCESS' in frontend

2020-09-11 Thread Melanie Blower via Phabricator via cfe-commits
mibintc added a comment.

Hello, I rebased this and made a few changes here, 
https://reviews.llvm.org/D87528 ; I added a question about floating point 
constant folding in that review, I'm going to duplicate it here,

My question is about constant folding. I am working on a task to ensure that 
clang is doing floating point constant folding correctly. I thought the 
constant folding was in AST/ExprConstant.cpp and indeed constant folding does 
occur there. But sometimes, if the floating point semantics are set to 
'strict', even tho' folding has occurred successfully in ExprConstant.cpp, when 
i look at emit-llvm, there is arithmetic emitted for the floating point 
expression;  For example if you use the command line option 
-ffp-exception-behavior=strict and you compile this function, it will emit the 
add instruction; but without the option you will see the folded expression.  
Either way, if you put a breakpoint inside ExprConstant.cpp the calculation of 
the floating sum does occur.  The function is float myAdd(void) { return 1.0 + 
2.0; }

So where is the decision made that backs out the fold?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D69272

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


[PATCH] D69272: Enable '#pragma STDC FENV_ACCESS' in frontend

2020-02-07 Thread John McCall via Phabricator via cfe-commits
rjmccall added a comment.

In 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 
>   #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



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


[PATCH] D69272: Enable '#pragma STDC FENV_ACCESS' in frontend

2020-02-07 Thread Richard Smith - zygoloid via Phabricator via cfe-commits
rsmith requested changes to this revision.
rsmith added a comment.
This revision now requires changes to proceed.

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).


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D69272



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


[PATCH] D69272: Enable '#pragma STDC FENV_ACCESS' in frontend

2020-02-06 Thread John McCall via Phabricator via cfe-commits
rjmccall added inline comments.



Comment at: clang/lib/Sema/SemaStmt.cpp:386
+  if (FPFeatures.allowFEnvAccess()) {
+FunctionDecl *F = getCurFunctionDecl();
+F->setUsesFPIntrin(true);

There isn't necessarily a current function declaration; this is usable in 
blocks, ObjC methods, etc.  It's even usable in global initializers because of 
statement-expressions. An attribute is really a much more flexible way of 
setting this information.

Sema has a concept of the current function scope; I think you should probably 
track this bit there and then copy that as appropriate to the FunctionDecl / 
ObjCMethodDecl / BlockDecl / lambda invocation function / whatever when the 
function body is done.

You should also handle templates, which means you'll need to set the FPOptions 
in the current function scope to the appropriate baseline when starting to 
instantiate a function definition.  constexpr-if means you can't just propagate 
the bit from the template.  I would suggest a rule where, for template 
patterns, the attribute is used solely to represent the baseline rather than 
whether the function actually contains any local pragmas.  Or maybe you already 
need to record the baseline for the outermost scope?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D69272



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


[PATCH] D69272: Enable '#pragma STDC FENV_ACCESS' in frontend

2020-01-29 Thread Serge Pavlov via Phabricator via cfe-commits
sepavloff updated this revision to Diff 241352.
sepavloff added a comment.

Avoid using custom attribute, use Function::useFPIntrin instead.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D69272

Files:
  clang/include/clang/Basic/DiagnosticParseKinds.td
  clang/include/clang/Sema/Sema.h
  clang/lib/CodeGen/CodeGenFunction.cpp
  clang/lib/CodeGen/CodeGenModule.cpp
  clang/lib/CodeGen/CodeGenModule.h
  clang/lib/Parse/ParsePragma.cpp
  clang/lib/Parse/ParseStmt.cpp
  clang/lib/Sema/SemaStmt.cpp
  clang/test/CodeGen/pragma-fenv_access.c
  clang/test/Parser/pragma-fenv_access.c
  clang/test/Preprocessor/pragma_unknown.c

Index: clang/test/Preprocessor/pragma_unknown.c
===
--- clang/test/Preprocessor/pragma_unknown.c
+++ clang/test/Preprocessor/pragma_unknown.c
@@ -16,15 +16,6 @@
 // CHECK: {{^}}#pragma STDC FP_CONTRACT DEFAULT{{$}}
 // CHECK: {{^}}#pragma STDC FP_CONTRACT IN_BETWEEN{{$}}
 
-#pragma STDC FENV_ACCESS ON  // expected-warning {{pragma STDC FENV_ACCESS ON is not supported, ignoring pragma}}
-#pragma STDC FENV_ACCESS OFF
-#pragma STDC FENV_ACCESS DEFAULT
-#pragma STDC FENV_ACCESS IN_BETWEEN   // expected-warning {{expected 'ON' or 'OFF' or 'DEFAULT' in pragma}}
-// CHECK: {{^}}#pragma STDC FENV_ACCESS ON{{$}}
-// CHECK: {{^}}#pragma STDC FENV_ACCESS OFF{{$}}
-// CHECK: {{^}}#pragma STDC FENV_ACCESS DEFAULT{{$}}
-// CHECK: {{^}}#pragma STDC FENV_ACCESS IN_BETWEEN{{$}}
-
 #pragma STDC CX_LIMITED_RANGE ON
 #pragma STDC CX_LIMITED_RANGE OFF
 #pragma STDC CX_LIMITED_RANGE DEFAULT 
Index: clang/test/Parser/pragma-fenv_access.c
===
--- /dev/null
+++ clang/test/Parser/pragma-fenv_access.c
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+#pragma STDC FENV_ACCESS IN_BETWEEN   // expected-warning {{expected 'ON' or 'OFF' or 'DEFAULT' in pragma}}
+
+#pragma STDC FENV_ACCESS OFF
+
+float func_04(int x, float y) {
+  if (x)
+return y + 2;
+  #pragma STDC FENV_ACCESS ON // expected-error{{'#pragma STDC FENV_ACCESS' can only appear at file scope or at the start of a compound statement}}
+  return x + y;
+}
Index: clang/test/CodeGen/pragma-fenv_access.c
===
--- /dev/null
+++ clang/test/CodeGen/pragma-fenv_access.c
@@ -0,0 +1,62 @@
+// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck %s
+
+#pragma STDC FENV_ACCESS ON
+
+float func_01(float x, float y) {
+  return x + y;
+}
+// CHECK-LABEL: @func_01
+// CHECK: call float @llvm.experimental.constrained.fadd.f32(float {{.*}}, float {{.*}}, metadata !"round.dynamic", metadata !"fpexcept.strict")
+
+
+float func_02(float x, float y) {
+  #pragma STDC FENV_ACCESS OFF
+  return x + y;
+}
+// CHECK-LABEL: @func_02
+// CHECK: fadd float {{.*}}
+
+
+float func_03(float x, float y) {
+  return x + y;
+}
+// CHECK-LABEL: @func_03
+// CHECK: call float @llvm.experimental.constrained.fadd.f32(float {{.*}}, float {{.*}}, metadata !"round.dynamic", metadata !"fpexcept.strict")
+
+
+#pragma STDC FENV_ACCESS OFF
+
+float func_04(float x, float y) {
+  return x + y;
+}
+// CHECK-LABEL: @func_04
+// CHECK: fadd float {{.*}}
+
+
+float func_05(float x, float y) {
+  #pragma STDC FENV_ACCESS ON
+  return x + y;
+}
+// CHECK-LABEL: @func_05
+// CHECK: call float @llvm.experimental.constrained.fadd.f32(float {{.*}}, float {{.*}}, metadata !"round.dynamic", metadata !"fpexcept.strict")
+
+
+float func_06(float x, float y) {
+  return x + y;
+}
+// CHECK-LABEL: @func_06
+// CHECK: fadd float {{.*}}
+
+
+float func_07(float x, float y) {
+  x -= y;
+  if (x) {
+#pragma STDC FENV_ACCESS ON
+y *= 2;
+  }
+  return y + 4;
+}
+// CHECK-LABEL: @func_07
+// CHECK: call float @llvm.experimental.constrained.fsub.f32(float {{.*}}, float {{.*}}, metadata !"round.dynamic", metadata !"fpexcept.strict")
+// CHECK: call float @llvm.experimental.constrained.fmul.f32(float {{.*}}, float {{.*}}, metadata !"round.dynamic", metadata !"fpexcept.strict")
+// CHECK: call float @llvm.experimental.constrained.fadd.f32(float {{.*}}, float {{.*}}, metadata !"round.dynamic", metadata !"fpexcept.strict")
Index: clang/lib/Sema/SemaStmt.cpp
===
--- clang/lib/Sema/SemaStmt.cpp
+++ clang/lib/Sema/SemaStmt.cpp
@@ -381,6 +381,13 @@
   PopCompoundScope();
 }
 
+void Sema::ActOnAfterCompoundStatementLeadingPragmas() {
+  if (FPFeatures.allowFEnvAccess()) {
+FunctionDecl *F = getCurFunctionDecl();
+F->setUsesFPIntrin(true);
+  }
+}
+
 sema::CompoundScopeInfo &Sema::getCurCompoundScope() const {
   return getCurFunction()->CompoundScopes.back();
 }
Index: clang/lib/Parse/ParseStmt.cpp
===
--- clang/lib/Parse/ParseStmt.cpp
+++ clang/lib/Parse/ParseStmt.cpp
@@ -365,

[PATCH] D69272: Enable '#pragma STDC FENV_ACCESS' in frontend

2019-12-26 Thread Serge Pavlov via Phabricator via cfe-commits
sepavloff updated this revision to Diff 235392.
sepavloff added a comment.

Updated patch

Removed the previous limitation on use of the pragma, which restricted the
pragma to the topmost block only. It should favor users who do not bother
about performance but want the usage be as defined by the Standard.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D69272

Files:
  clang/include/clang/Basic/Attr.td
  clang/include/clang/Basic/DiagnosticParseKinds.td
  clang/include/clang/Sema/Sema.h
  clang/lib/CodeGen/CodeGenFunction.cpp
  clang/lib/CodeGen/CodeGenModule.cpp
  clang/lib/CodeGen/CodeGenModule.h
  clang/lib/Parse/ParsePragma.cpp
  clang/lib/Parse/ParseStmt.cpp
  clang/lib/Sema/SemaStmt.cpp
  clang/lib/Sema/TreeTransform.h
  clang/test/CodeGen/pragma-fenv_access.c
  clang/test/Parser/pragma-fenv_access.c
  clang/test/Preprocessor/pragma_unknown.c

Index: clang/test/Preprocessor/pragma_unknown.c
===
--- clang/test/Preprocessor/pragma_unknown.c
+++ clang/test/Preprocessor/pragma_unknown.c
@@ -16,15 +16,6 @@
 // CHECK: {{^}}#pragma STDC FP_CONTRACT DEFAULT{{$}}
 // CHECK: {{^}}#pragma STDC FP_CONTRACT IN_BETWEEN{{$}}
 
-#pragma STDC FENV_ACCESS ON  // expected-warning {{pragma STDC FENV_ACCESS ON is not supported, ignoring pragma}}
-#pragma STDC FENV_ACCESS OFF
-#pragma STDC FENV_ACCESS DEFAULT
-#pragma STDC FENV_ACCESS IN_BETWEEN   // expected-warning {{expected 'ON' or 'OFF' or 'DEFAULT' in pragma}}
-// CHECK: {{^}}#pragma STDC FENV_ACCESS ON{{$}}
-// CHECK: {{^}}#pragma STDC FENV_ACCESS OFF{{$}}
-// CHECK: {{^}}#pragma STDC FENV_ACCESS DEFAULT{{$}}
-// CHECK: {{^}}#pragma STDC FENV_ACCESS IN_BETWEEN{{$}}
-
 #pragma STDC CX_LIMITED_RANGE ON
 #pragma STDC CX_LIMITED_RANGE OFF
 #pragma STDC CX_LIMITED_RANGE DEFAULT 
Index: clang/test/Parser/pragma-fenv_access.c
===
--- /dev/null
+++ clang/test/Parser/pragma-fenv_access.c
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+#pragma STDC FENV_ACCESS IN_BETWEEN   // expected-warning {{expected 'ON' or 'OFF' or 'DEFAULT' in pragma}}
+
+#pragma STDC FENV_ACCESS OFF
+
+float func_04(int x, float y) {
+  if (x)
+return y + 2;
+  #pragma STDC FENV_ACCESS ON // expected-error{{'#pragma STDC FENV_ACCESS' can only appear at file scope or at the start of a compound statement}}
+  return x + y;
+}
Index: clang/test/CodeGen/pragma-fenv_access.c
===
--- /dev/null
+++ clang/test/CodeGen/pragma-fenv_access.c
@@ -0,0 +1,62 @@
+// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck %s
+
+#pragma STDC FENV_ACCESS ON
+
+float func_01(float x, float y) {
+  return x + y;
+}
+// CHECK-LABEL: @func_01
+// CHECK: call float @llvm.experimental.constrained.fadd.f32(float {{.*}}, float {{.*}}, metadata !"round.dynamic", metadata !"fpexcept.strict")
+
+
+float func_02(float x, float y) {
+  #pragma STDC FENV_ACCESS OFF
+  return x + y;
+}
+// CHECK-LABEL: @func_02
+// CHECK: fadd float {{.*}}
+
+
+float func_03(float x, float y) {
+  return x + y;
+}
+// CHECK-LABEL: @func_03
+// CHECK: call float @llvm.experimental.constrained.fadd.f32(float {{.*}}, float {{.*}}, metadata !"round.dynamic", metadata !"fpexcept.strict")
+
+
+#pragma STDC FENV_ACCESS OFF
+
+float func_04(float x, float y) {
+  return x + y;
+}
+// CHECK-LABEL: @func_04
+// CHECK: fadd float {{.*}}
+
+
+float func_05(float x, float y) {
+  #pragma STDC FENV_ACCESS ON
+  return x + y;
+}
+// CHECK-LABEL: @func_05
+// CHECK: call float @llvm.experimental.constrained.fadd.f32(float {{.*}}, float {{.*}}, metadata !"round.dynamic", metadata !"fpexcept.strict")
+
+
+float func_06(float x, float y) {
+  return x + y;
+}
+// CHECK-LABEL: @func_06
+// CHECK: fadd float {{.*}}
+
+
+float func_07(float x, float y) {
+  x -= y;
+  if (x) {
+#pragma STDC FENV_ACCESS ON
+y *= 2;
+  }
+  return y + 4;
+}
+// CHECK-LABEL: @func_07
+// CHECK: call float @llvm.experimental.constrained.fsub.f32(float {{.*}}, float {{.*}}, metadata !"round.dynamic", metadata !"fpexcept.strict")
+// CHECK: call float @llvm.experimental.constrained.fmul.f32(float {{.*}}, float {{.*}}, metadata !"round.dynamic", metadata !"fpexcept.strict")
+// CHECK: call float @llvm.experimental.constrained.fadd.f32(float {{.*}}, float {{.*}}, metadata !"round.dynamic", metadata !"fpexcept.strict")
Index: clang/lib/Sema/TreeTransform.h
===
--- clang/lib/Sema/TreeTransform.h
+++ clang/lib/Sema/TreeTransform.h
@@ -9837,7 +9837,7 @@
   RHS.get() == E->getRHS())
 return E;
 
-  Sema::FPContractStateRAII FPContractState(getSema());
+  Sema::FPFeaturesStateRAII FPFeaturesState(getSema());
   getSema().FPFeatures = E->getFPFeatures();
 
   return getDerived().RebuildBinaryOperator(E->ge