sepavloff updated this revision to Diff 298375.
sepavloff added a comment.

Remade the patch


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D88498

Files:
  clang/include/clang/Basic/LangOptions.h
  clang/include/clang/Sema/Sema.h
  clang/lib/Parse/Parser.cpp
  clang/lib/Sema/Sema.cpp
  clang/lib/Sema/SemaDecl.cpp
  clang/test/AST/const-fpfeatures-strict.c
  clang/test/CodeGenCXX/rounding-math.cpp
  clang/test/SemaCXX/rounding-math-diag.cpp
  clang/test/SemaCXX/rounding-math.cpp

Index: clang/test/SemaCXX/rounding-math.cpp
===================================================================
--- /dev/null
+++ clang/test/SemaCXX/rounding-math.cpp
@@ -0,0 +1,39 @@
+// RUN: %clang_cc1 -triple x86_64-linux -verify -frounding-math -Wno-unknown-pragmas %s
+// expected-no-diagnostics
+
+// nextUp(1.F) == 0x1.000002p0F
+
+static_assert(1.0F + 0x0.000001p0F == 0x1.0p0F, "");
+
+char Arr01[1 + (1.0F + 0x0.000001p0F > 1.0F)];
+static_assert(sizeof(Arr01) == 1, "");
+
+struct S1 {
+  int : (1.0F + 0x0.000001p0F > 1.0F);
+  int f;
+};
+static_assert(sizeof(S1) == sizeof(int), "");
+
+#pragma STDC FENV_ROUND FE_UPWARD
+static_assert(1.0F + 0x0.000001p0F == 0x1.000002p0F, "");
+
+char Arr01u[1 + (1.0F + 0x0.000001p0F > 1.0F)];
+static_assert(sizeof(Arr01u) == 2, "");
+
+struct S1u {
+  int : (1.0F + 0x0.000001p0F > 1.0F);
+  int f;
+};
+static_assert(sizeof(S1u) > sizeof(int), "");
+
+#pragma STDC FENV_ROUND FE_DOWNWARD
+static_assert(1.0F + 0x0.000001p0F == 1.0F, "");
+
+char Arr01d[1 + (1.0F + 0x0.000001p0F > 1.0F)];
+static_assert(sizeof(Arr01d) == 1, "");
+
+struct S1d {
+  int : (1.0F + 0x0.000001p0F > 1.0F);
+  int f;
+};
+static_assert(sizeof(S1d) == sizeof(int), "");
Index: clang/test/SemaCXX/rounding-math-diag.cpp
===================================================================
--- /dev/null
+++ clang/test/SemaCXX/rounding-math-diag.cpp
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -triple x86_64-linux -verify -frounding-math %s
+
+void func_01() {
+  const float C1 = 1.0F + 0x0.000001p0F; // expected-note{{declared here}}
+                                         // expected-note@-1{{cannot evaluate this expression if rounding mode is dynamic}}
+  static_assert(C1 == 1.0F, "");         // expected-error{{static_assert expression is not an integral constant expression}}
+                                         // expected-note@-1{{initializer of 'C1' is not a constant expression}}
+}
Index: clang/test/CodeGenCXX/rounding-math.cpp
===================================================================
--- /dev/null
+++ clang/test/CodeGenCXX/rounding-math.cpp
@@ -0,0 +1,22 @@
+// RUN: %clang_cc1 -S -emit-llvm -triple i386-linux -Wno-unknown-pragmas -frounding-math %s -o - | FileCheck %s
+
+constexpr float func_01(float x, float y) {
+  return x + y;
+}
+
+float V1 = func_01(1.0F, 0x0.000001p0F);
+float V2 = 1.0F + 0x0.000001p0F;
+float V3 = func_01(1.0F, 2.0F);
+
+// CHECK: @V1 = {{.*}}global float 0.000000e+00, align 4
+// CHECK: @V2 = {{.*}}global float 1.000000e+00, align 4
+// CHECK: @V3 = {{.*}}global float 3.000000e+00, align 4
+
+// CHECK-LABEL: define internal void @__cxx_global_var_init()
+// CHECK:       call float @_Z7func_01ff(float 1.000000e+00, float 0x3E70000000000000)
+// CHECK:       store {{.*}}, float* @V1, align 4
+// CHECK:       ret void
+
+// CHECK-LABEL: define {{.*}} float @_Z7func_01ff(float %x, float %y)
+// CHECK:       call float @llvm.experimental.constrained.fadd.f32({{.*}}, metadata !"round.dynamic", metadata !"fpexcept.ignore")
+// CHECK:       ret float
Index: clang/test/AST/const-fpfeatures-strict.c
===================================================================
--- /dev/null
+++ clang/test/AST/const-fpfeatures-strict.c
@@ -0,0 +1,43 @@
+// RUN: %clang_cc1 -S -emit-llvm -ffp-exception-behavior=strict -Wno-unknown-pragmas %s -o - | FileCheck %s
+
+float PR47807 = -8.6563630030e-03;
+
+// nextUp(1.F) == 0x1.000002p0F
+
+struct S {
+  float f;
+};
+
+static struct S var_01 = {0x1.000001p0};
+struct S *func_01() {
+  return &var_01;
+}
+
+struct S var_02 = {0x1.000001p0};
+
+struct S *func_03() {
+  static struct S var_03 = {0x1.000001p0};
+  return &var_03;
+}
+
+// CHECK: @var_01 = {{.*}} %struct.S { float 1.000000e+00 }
+// CHECK: @var_02 = {{.*}} %struct.S { float 1.000000e+00 }
+// CHECK: @func_03.var_03 = {{.*}} %struct.S { float 1.000000e+00 }
+
+#pragma STDC FENV_ROUND FE_UPWARD
+
+static struct S var_04 = {0x1.000001p0};
+struct S *func_04() {
+  return &var_04;
+}
+
+struct S var_05 = {0x1.000001p0};
+
+struct S *func_06() {
+  static struct S var_06 = {0x1.000001p0};
+  return &var_06;
+}
+
+// CHECK: @var_04 = {{.*}} %struct.S { float 0x3FF0000020000000 }
+// CHECK: @var_05 = {{.*}} %struct.S { float 0x3FF0000020000000 }
+// CHECK: @func_06.var_06 = {{.*}} %struct.S { float 0x3FF0000020000000 }
Index: clang/lib/Sema/SemaDecl.cpp
===================================================================
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -14134,6 +14134,11 @@
       getCurLexicalContext()->getDeclKind() != Decl::ObjCImplementation)
     Diag(FD->getLocation(), diag::warn_function_def_in_objc_container);
 
+  // If the current FP mode differ from that defined by the LangOptions,
+  // set the required FP mode.
+  if (getLangOpts().getFPRoundingMode() == LangOptions::RoundingMode::Dynamic)
+    setCurFPFeatures(FPOptions(getLangOpts()));
+
   return D;
 }
 
Index: clang/lib/Sema/Sema.cpp
===================================================================
--- clang/lib/Sema/Sema.cpp
+++ clang/lib/Sema/Sema.cpp
@@ -378,6 +378,16 @@
   DeclarationName BuiltinVaList = &Context.Idents.get("__builtin_va_list");
   if (IdResolver.begin(BuiltinVaList) == IdResolver.end())
     PushOnScopeChains(Context.getBuiltinVaListDecl(), TUScope);
+
+  if (getLangOpts().getFPRoundingMode() == LangOptions::RoundingMode::Dynamic) {
+    // If command line options specify '-frounding-math', the default rounding
+    // mode is 'dynamic'. It however is applied to function bodies only. At the
+    // file level the constant rounding mode is in effect, which is identical to
+    // the default mode at the beginning.
+    FPOptions NewFPO = getCurFPFeatures();
+    NewFPO.setRoundingMode(llvm::RoundingMode::NearestTiesToEven);
+    setCurFPFeatures(NewFPO);
+  }
 }
 
 Sema::~Sema() {
Index: clang/lib/Parse/Parser.cpp
===================================================================
--- clang/lib/Parse/Parser.cpp
+++ clang/lib/Parse/Parser.cpp
@@ -1278,6 +1278,10 @@
   ParseScope BodyScope(this, Scope::FnScope | Scope::DeclScope |
                                  Scope::CompoundStmtScope);
 
+  // If '-frounding-math' was specified, FP options are adjusted at the entry
+  // to function.
+  Sema::FPFeaturesStateRAII SavedFPOptions(Actions);
+
   // Tell the actions module that we have entered a function definition with the
   // specified Declarator for the function.
   Sema::SkipBodyInfo SkipBody;
Index: clang/include/clang/Sema/Sema.h
===================================================================
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -589,13 +589,7 @@
   // This stack tracks the current state of Sema.CurFPFeatures.
   PragmaStack<FPOptionsOverride> FpPragmaStack;
   FPOptionsOverride CurFPFeatureOverrides() {
-    FPOptionsOverride result;
-    if (!FpPragmaStack.hasValue()) {
-      result = FPOptionsOverride();
-    } else {
-      result = FpPragmaStack.CurrentValue;
-    }
-    return result;
+    return FpPragmaStack.CurrentValue;
   }
 
   // RAII object to push / pop sentinel slots for all MS #pragma stacks.
@@ -1429,7 +1423,6 @@
 
   const LangOptions &getLangOpts() const { return LangOpts; }
   OpenCLOptions &getOpenCLOptions() { return OpenCLFeatures; }
-  FPOptions     &getCurFPFeatures() { return CurFPFeatures; }
 
   DiagnosticsEngine &getDiagnostics() const { return Diags; }
   SourceManager &getSourceManager() const { return SourceMgr; }
@@ -1439,6 +1432,12 @@
   ASTMutationListener *getASTMutationListener() const;
   ExternalSemaSource* getExternalSource() const { return ExternalSource; }
 
+  const FPOptions &getCurFPFeatures() const { return CurFPFeatures; }
+  void setCurFPFeatures(FPOptions FPO) {
+    FpPragmaStack.CurrentValue = FPOptionsOverride(FPO, CurFPFeatures);
+    CurFPFeatures = FPO;
+  }
+
   ///Registers an external source. If an external source already exists,
   /// creates a multiplex external source and appends to it.
   ///
Index: clang/include/clang/Basic/LangOptions.h
===================================================================
--- clang/include/clang/Basic/LangOptions.h
+++ clang/include/clang/Basic/LangOptions.h
@@ -455,6 +455,15 @@
     return Opts;
   }
 
+  storage_type getDiffWith(FPOptions FPO) const {
+    storage_type Diff = 0;
+#define OPTION(NAME, TYPE, WIDTH, PREVIOUS)                                    \
+  if (get##NAME() != FPO.get##NAME())                                          \
+    Diff |= NAME##Mask;
+#include "clang/Basic/FPOptions.def"
+    return Diff;
+  }
+
   // We can define most of the accessors automatically:
 #define OPTION(NAME, TYPE, WIDTH, PREVIOUS)                                    \
   TYPE get##NAME() const {                                                     \
@@ -503,6 +512,8 @@
       : Options(LO), OverrideMask(OverrideMaskBits) {}
   FPOptionsOverride(FPOptions FPO)
       : Options(FPO), OverrideMask(OverrideMaskBits) {}
+  FPOptionsOverride(FPOptions New, FPOptions Old)
+      : Options(New), OverrideMask(New.getDiffWith(Old)) {}
 
   bool requiresTrailingStorage() const { return OverrideMask != 0; }
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to