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

Update the patch

- Add a flag to reflect rounding mode change by FENV_ROUND,
- Keep dynamic mode in AST and change it later in CodeGen,
- Add new tests.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D126364

Files:
  clang/include/clang/Basic/LangOptions.h
  clang/include/clang/Sema/Sema.h
  clang/lib/CodeGen/CodeGenFunction.cpp
  clang/lib/Parse/ParsePragma.cpp
  clang/lib/Sema/Sema.cpp
  clang/lib/Sema/SemaAttr.cpp
  clang/test/AST/ast-dump-fpfeatures.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,15 @@
   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_04a(float x, float y) {
+  #pragma float_control(except, on)
+  return x + y;
+}
+// CHECK-LABEL: @func_04a
+// CHECK: call float @llvm.experimental.constrained.fadd.f32(float {{.*}}, float {{.*}}, metadata !"round.tonearest", metadata !"fpexcept.strict")
 
 
 float func_05(float x, float y) {
@@ -57,18 +65,117 @@
   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) {
   x -= y;
   if (x) {
     #pragma STDC FENV_ACCESS ON
-    y *= 2;
+    y *= 2.0F;
   }
-  return y + 4;
+  return y + 4.0F;
 }
 // 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.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_08a(float x, float y) {
+  #pragma STDC FENV_ROUND FE_TONEAREST
+  #pragma STDC FENV_ACCESS ON
+  return x + y;
+}
+// CHECK-LABEL: @func_08a
+// CHECK: call float @llvm.experimental.constrained.fadd.f32(float {{.*}}, float {{.*}}, metadata !"round.tonearest", 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")
+
+
+float func_13(float x, float y) {
+  x -= y;
+  {
+    #pragma STDC FENV_ROUND FE_TONEAREST
+    #pragma STDC FENV_ACCESS ON
+    y *= 2.0F;
+  }
+  {
+    #pragma STDC FENV_ACCESS ON
+    return y + 4.0F;
+  }
+}
+// CHECK-LABEL: @func_13
+// 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.tonearest", metadata !"fpexcept.strict")
 // CHECK: call float @llvm.experimental.constrained.fadd.f32(float {{.*}}, float {{.*}}, metadata !"round.dynamic", metadata !"fpexcept.strict")
+
+
+float func_14(float x, float y) {
+  #pragma STDC FENV_ROUND FE_DYNAMIC
+  #pragma STDC FENV_ACCESS ON
+  return x + y;
+}
+// CHECK-LABEL: @func_14
+// CHECK: call float @llvm.experimental.constrained.fadd.f32(float {{.*}}, float {{.*}}, metadata !"round.dynamic", metadata !"fpexcept.strict")
+
+
+float func_15(float x, float y) {
+  #pragma STDC FENV_ROUND FE_DYNAMIC
+  return x + y;
+}
+// CHECK-LABEL: @func_15
+// CHECK: call float @llvm.experimental.constrained.fadd.f32(float {{.*}}, float {{.*}}, metadata !"round.tonearest", metadata !"fpexcept.ignore")
Index: clang/test/AST/ast-dump-fpfeatures.cpp
===================================================================
--- clang/test/AST/ast-dump-fpfeatures.cpp
+++ clang/test/AST/ast-dump-fpfeatures.cpp
@@ -109,7 +109,7 @@
 }
 
 // CHECK-LABEL: FunctionDecl {{.*}} func_12 'float (float, float)'
-// CHECK:         BinaryOperator {{.*}} 'float' '+' RoundingMode=tonearest
+// CHECK:         BinaryOperator {{.*}} 'float' '+' RoundingMode=dynamic
 
 #pragma STDC FENV_ROUND FE_TONEAREST
 
Index: clang/lib/Sema/SemaAttr.cpp
===================================================================
--- clang/lib/Sema/SemaAttr.cpp
+++ clang/lib/Sema/SemaAttr.cpp
@@ -1246,18 +1246,12 @@
   CurFPFeatures = NewFPFeatures.applyOverrides(getLangOpts());
 }
 
-void Sema::setRoundingMode(SourceLocation Loc, llvm::RoundingMode FPR) {
-  // C2x: 7.6.2p3  If the FE_DYNAMIC mode is specified and FENV_ACCESS is "off",
-  // the translator may assume that the default rounding mode is in effect.
-  if (FPR == llvm::RoundingMode::Dynamic &&
-      !CurFPFeatures.getAllowFEnvAccess() &&
-      CurFPFeatures.getFPExceptionMode() == LangOptions::FPE_Ignore)
-    FPR = llvm::RoundingMode::NearestTiesToEven;
-
+void Sema::ActOnPragmaFEnvRound(SourceLocation Loc, llvm::RoundingMode FPR) {
   FPOptionsOverride NewFPFeatures = CurFPFeatureOverrides();
   NewFPFeatures.setRoundingModeOverride(FPR);
   FpPragmaStack.Act(Loc, PSK_Set, StringRef(), NewFPFeatures);
   CurFPFeatures = NewFPFeatures.applyOverrides(getLangOpts());
+  IsRoundingModeSet = true;
 }
 
 void Sema::setExceptionMode(SourceLocation Loc,
@@ -1278,12 +1272,24 @@
     // 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 RoundingMode to Dynamic and ExceptionBehavior
+    // to Strict unless they are already overwritten.
+    if (!IsRoundingModeSet)
+      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);
Index: clang/lib/Sema/Sema.cpp
===================================================================
--- clang/lib/Sema/Sema.cpp
+++ clang/lib/Sema/Sema.cpp
@@ -2662,10 +2662,12 @@
     : S(S), OldFPFeaturesState(S.CurFPFeatures),
       OldOverrides(S.FpPragmaStack.CurrentValue),
       OldEvalMethod(S.PP.getCurrentFPEvalMethod()),
-      OldFPPragmaLocation(S.PP.getLastFPEvalPragmaLocation()) {}
+      OldFPPragmaLocation(S.PP.getLastFPEvalPragmaLocation()),
+      OldIsRoundingModeSet(S.IsRoundingModeSet) {}
 
 Sema::FPFeaturesStateRAII::~FPFeaturesStateRAII() {
   S.CurFPFeatures = OldFPFeaturesState;
   S.FpPragmaStack.CurrentValue = OldOverrides;
   S.PP.setCurrentFPEvalMethod(OldFPPragmaLocation, OldEvalMethod);
+  S.IsRoundingModeSet = OldIsRoundingModeSet;
 }
Index: clang/lib/Parse/ParsePragma.cpp
===================================================================
--- clang/lib/Parse/ParsePragma.cpp
+++ clang/lib/Parse/ParsePragma.cpp
@@ -804,7 +804,7 @@
       reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
 
   SourceLocation PragmaLoc = ConsumeAnnotationToken();
-  Actions.setRoundingMode(PragmaLoc, RM);
+  Actions.ActOnPragmaFEnvRound(PragmaLoc, RM);
 }
 
 StmtResult Parser::HandlePragmaCaptured()
Index: clang/lib/CodeGen/CodeGenFunction.cpp
===================================================================
--- clang/lib/CodeGen/CodeGenFunction.cpp
+++ clang/lib/CodeGen/CodeGenFunction.cpp
@@ -146,7 +146,7 @@
   FMFGuard.emplace(CGF.Builder);
 
   llvm::RoundingMode NewRoundingBehavior =
-      static_cast<llvm::RoundingMode>(FPFeatures.getRoundingMode());
+      FPFeatures.getEffectiveRoundingMode();
   CGF.Builder.setDefaultConstrainedRounding(NewRoundingBehavior);
   auto NewExceptionBehavior =
       ToConstrainedExceptMD(static_cast<LangOptions::FPExceptionModeKind>(
Index: clang/include/clang/Sema/Sema.h
===================================================================
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -704,6 +704,9 @@
     return result;
   }
 
+  /// Was rounding mode overridden by pragma FENV_ROUND?
+  bool IsRoundingModeSet = false;
+
   // RAII object to push / pop sentinel slots for all MS #pragma stacks.
   // Actions should be performed only if we enter / exit a C++ method body.
   class PragmaStackSentinelRAII {
@@ -1571,6 +1574,7 @@
     FPOptionsOverride OldOverrides;
     LangOptions::FPEvalMethodKind OldEvalMethod;
     SourceLocation OldFPPragmaLocation;
+    bool OldIsRoundingModeSet;
   };
 
   void addImplicitTypedef(StringRef Name, QualType T);
@@ -10282,7 +10286,7 @@
                                LangOptions::FPExceptionModeKind);
 
   /// Called to set constant rounding mode for floating point operations.
-  void setRoundingMode(SourceLocation Loc, llvm::RoundingMode);
+  void ActOnPragmaFEnvRound(SourceLocation Loc, llvm::RoundingMode);
 
   /// Called to set exception behavior for floating point operations.
   void setExceptionMode(SourceLocation Loc, LangOptions::FPExceptionModeKind);
Index: clang/include/clang/Basic/LangOptions.h
===================================================================
--- clang/include/clang/Basic/LangOptions.h
+++ clang/include/clang/Basic/LangOptions.h
@@ -669,6 +669,16 @@
            getAllowFEnvAccess();
   }
 
+  RoundingMode getEffectiveRoundingMode() const {
+    RoundingMode RM = getRoundingMode();
+    // C2x: 7.6.2p3  If the FE_DYNAMIC mode is specified and FENV_ACCESS is
+    // "off", the translator may assume that the default rounding mode is in
+    // effect.
+    if (RM == RoundingMode::Dynamic && !getAllowFEnvAccess())
+      RM = RoundingMode::NearestTiesToEven;
+    return RM;
+  }
+
   bool operator==(FPOptions other) const { return Value == other.Value; }
 
   /// Return the default value of FPOptions that's used when trailing
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to