sepavloff created this revision.
sepavloff added reviewers: aaron.ballman, andrew.w.kaylor, rjmccall, efriedma, 
kpn.
Herald added a project: All.
sepavloff requested review of this revision.
Herald added a project: clang.

Previously `#pragma STDC FENV_ACCESS ON` always set dynamic rounding
mode and strict exception handling. It is however too pessimistic in
many cases. In practice the pragma can be used to change rounding mode
only or to check exception flags without changing rounding mode. It
could be made by using other pragmas, `FENV_ROUND` or `clang fp
exception`, but their effect was overwritten by `FENV_ACCESS`. This
change modifies treatment of this pragma so that it sets rounding and
exception handling only if they are not set by other pragmas.

Also `#pragma STDC FENV_ACCESS OFF` turned off only FEnvAccess flag
leaving rounding mode and exception handling unchanged, which does not
make sense in many cases. The change fixes this behavior also.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D126364

Files:
  clang/lib/Sema/SemaAttr.cpp
  clang/test/CodeGen/pragma-fenv_access.c

Index: clang/test/CodeGen/pragma-fenv_access.c
===================================================================
--- clang/test/CodeGen/pragma-fenv_access.c
+++ clang/test/CodeGen/pragma-fenv_access.c
@@ -20,7 +20,7 @@
   return x + y;
 }
 // CHECK-LABEL: @func_02
-// CHECK: call float @llvm.experimental.constrained.fadd.f32(float {{.*}}, float {{.*}}, metadata !"round.dynamic", metadata !"fpexcept.ignore")
+// CHECK: call float @llvm.experimental.constrained.fadd.f32(float {{.*}}, float {{.*}}, metadata !"round.tonearest", metadata !"fpexcept.ignore")
 
 
 float func_03(float x, float y) {
@@ -41,7 +41,7 @@
   return x + y;
 }
 // CHECK-LABEL: @func_04
-// CHECK: call float @llvm.experimental.constrained.fadd.f32(float {{.*}}, float {{.*}}, metadata !"round.dynamic", metadata !"fpexcept.ignore")
+// CHECK: fadd float
 
 
 float func_05(float x, float y) {
@@ -57,7 +57,7 @@
   return x + y;
 }
 // CHECK-LABEL: @func_06
-// CHECK: call float @llvm.experimental.constrained.fadd.f32(float {{.*}}, float {{.*}}, metadata !"round.dynamic", metadata !"fpexcept.ignore")
+// CHECK: fadd float
 
 
 float func_07(float x, float y) {
@@ -69,6 +69,58 @@
   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.fsub.f32(float {{.*}}, float {{.*}}, metadata !"round.tonearest", metadata !"fpexcept.ignore")
 // 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")
+// CHECK: call float @llvm.experimental.constrained.fadd.f32(float {{.*}}, float {{.*}}, metadata !"round.tonearest", metadata !"fpexcept.ignore")
+
+
+float func_08(float x, float y) {
+  #pragma STDC FENV_ROUND FE_UPWARD
+  #pragma STDC FENV_ACCESS ON
+  return x + y;
+}
+// CHECK-LABEL: @func_08
+// CHECK:  call float @llvm.experimental.constrained.fadd.f32({{.*}}, metadata !"round.upward", metadata !"fpexcept.strict")
+
+
+float func_09(float x, float y) {
+  #pragma clang fp exceptions(maytrap)
+  #pragma STDC FENV_ACCESS ON
+  return x + y;
+}
+// CHECK-LABEL: @func_09
+// CHECK:  call float @llvm.experimental.constrained.fadd.f32({{.*}}, metadata !"round.dynamic", metadata !"fpexcept.maytrap")
+
+float func_10(float x, float y) {
+  #pragma clang fp exceptions(maytrap)
+  #pragma STDC FENV_ROUND FE_UPWARD
+  #pragma STDC FENV_ACCESS ON
+  return x + y;
+}
+// CHECK-LABEL: @func_10
+// CHECK:  call float @llvm.experimental.constrained.fadd.f32({{.*}}, metadata !"round.upward", metadata !"fpexcept.maytrap")
+
+float func_11(float x, float y, float z) {
+  #pragma STDC FENV_ACCESS ON
+  float res = x * y;
+  {
+    #pragma STDC FENV_ACCESS OFF
+    return res + z;
+  }
+}
+// CHECK-LABEL: @func_11
+// CHECK:  call float @llvm.experimental.constrained.fmul.f32({{.*}}, metadata !"round.dynamic", metadata !"fpexcept.strict")
+// CHECK:  call float @llvm.experimental.constrained.fadd.f32({{.*}}, metadata !"round.tonearest", metadata !"fpexcept.ignore")
+
+float func_12(float x, float y, float z) {
+  #pragma STDC FENV_ROUND FE_TOWARDZERO
+  #pragma STDC FENV_ACCESS ON
+  float res = x * y;
+  {
+    #pragma STDC FENV_ACCESS OFF
+    return res + z;
+  }
+}
+// CHECK-LABEL: @func_12
+// CHECK:  call float @llvm.experimental.constrained.fmul.f32({{.*}}, metadata !"round.towardzero", metadata !"fpexcept.strict")
+// CHECK:  call float @llvm.experimental.constrained.fadd.f32({{.*}}, metadata !"round.towardzero", metadata !"fpexcept.ignore")
Index: clang/lib/Sema/SemaAttr.cpp
===================================================================
--- clang/lib/Sema/SemaAttr.cpp
+++ clang/lib/Sema/SemaAttr.cpp
@@ -1278,12 +1278,29 @@
     // pragma, or by using the /fp:precise or /fp:strict compiler options
     if (!isPreciseFPEnabled())
       Diag(Loc, diag::err_pragma_fenv_requires_precise);
+    // Enabling FENV access sets the RoundingMode to Dynamic
+    // and ExceptionBehavior to Strict unless they are already overwritten.
+    if (!NewFPFeatures.hasRoundingModeOverride())
+      NewFPFeatures.setRoundingModeOverride(llvm::RoundingMode::Dynamic);
+    else if (NewFPFeatures.getRoundingModeOverride() ==
+             llvm::RoundingMode::NearestTiesToEven) {
+      if (NewFPFeatures.hasAllowFEnvAccessOverride())
+        NewFPFeatures.setRoundingModeOverride(llvm::RoundingMode::Dynamic);
+    }
+    if (!NewFPFeatures.hasFPExceptionModeOverride())
+      NewFPFeatures.setFPExceptionModeOverride(LangOptions::FPE_Strict);
+    else if (NewFPFeatures.getFPExceptionModeOverride() ==
+             LangOptions::FPE_Ignore) {
+      if (NewFPFeatures.hasAllowFEnvAccessOverride())
+        NewFPFeatures.setFPExceptionModeOverride(LangOptions::FPE_Strict);
+    }
     NewFPFeatures.setAllowFEnvAccessOverride(true);
-    // Enabling FENV access sets the RoundingMode to Dynamic.
-    // and ExceptionBehavior to Strict
-    NewFPFeatures.setRoundingModeOverride(llvm::RoundingMode::Dynamic);
-    NewFPFeatures.setFPExceptionModeOverride(LangOptions::FPE_Strict);
   } else {
+    if (CurFPFeatures.getRoundingMode() == llvm::RoundingMode::Dynamic)
+      NewFPFeatures.setRoundingModeOverride(
+          llvm::RoundingMode::NearestTiesToEven);
+    if (CurFPFeatures.getFPExceptionMode() != LangOptions::FPE_Ignore)
+      NewFPFeatures.setFPExceptionModeOverride(LangOptions::FPE_Ignore);
     NewFPFeatures.setAllowFEnvAccessOverride(false);
   }
   FpPragmaStack.Act(Loc, PSK_Set, StringRef(), NewFPFeatures);
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to