mibintc updated this revision to Diff 223090.
mibintc added a comment.

In the previous review, @rjmccall asked me to redo the existing floating point 
option documentation before submitting this patch.  I got the floating point 
documentation update committed, and I've worked on this patch more to get the 
floating point "render options" checking implemented.  This patch needs more 
test cases, and there might be a bug or 2 in the "render options" checking.   I 
wanted to show you this work especially to get your reaction to the changes to 
the floating point options

This patch adds support for frounding-math and ftrapping-math and new options 
fp-model= and fp-exception-behavior=; fp-model is an "umbrella" option.


Repository:
  rL LLVM

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

https://reviews.llvm.org/D62731

Files:
  clang/docs/UsersManual.rst
  clang/include/clang/Basic/CodeGenOptions.def
  clang/include/clang/Basic/LangOptions.h
  clang/include/clang/Driver/Options.td
  clang/lib/CodeGen/BackendUtil.cpp
  clang/lib/CodeGen/CodeGenFunction.cpp
  clang/lib/CodeGen/CodeGenFunction.h
  clang/lib/Driver/ToolChains/Clang.cpp
  clang/lib/Frontend/CompilerInvocation.cpp
  clang/test/CodeGen/fpconstrained.c
  clang/test/Driver/clang_f_opts.c
  clang/test/Driver/fast-math.c
  llvm/include/llvm/Target/TargetOptions.h

Index: llvm/include/llvm/Target/TargetOptions.h
===================================================================
--- llvm/include/llvm/Target/TargetOptions.h
+++ llvm/include/llvm/Target/TargetOptions.h
@@ -107,7 +107,7 @@
   public:
     TargetOptions()
         : PrintMachineCode(false), UnsafeFPMath(false), NoInfsFPMath(false),
-          NoNaNsFPMath(false), NoTrappingFPMath(false),
+          NoNaNsFPMath(false), NoTrappingFPMath(true), RoundingFPMath(false),
           NoSignedZerosFPMath(false),
           HonorSignDependentRoundingFPMathOption(false), NoZerosInBSS(false),
           GuaranteedTailCallOpt(false), StackSymbolOrdering(true),
@@ -154,6 +154,11 @@
     /// specifies that there are no trap handlers to handle exceptions.
     unsigned NoTrappingFPMath : 1;
 
+    /// RoundingFPMath - This flag is enabled when the
+    /// -enable-rounding-fp-math is specified on the command line. This
+    /// specifies dynamic rounding mode.
+    unsigned RoundingFPMath : 1;
+
     /// NoSignedZerosFPMath - This flag is enabled when the
     /// -enable-no-signed-zeros-fp-math is specified on the command line. This
     /// specifies that optimizations are allowed to treat the sign of a zero
Index: clang/test/Driver/fast-math.c
===================================================================
--- clang/test/Driver/fast-math.c
+++ clang/test/Driver/fast-math.c
@@ -170,11 +170,11 @@
 // RUN: %clang -### -fno-fast-math -ffast-math -c %s 2>&1 \
 // RUN:   | FileCheck --check-prefix=CHECK-FAST-MATH %s
 // RUN: %clang -### -funsafe-math-optimizations -ffinite-math-only \
-// RUN:     -fno-math-errno -ffp-contract=fast -c %s 2>&1 \
+// RUN:     -fno-math-errno -ffp-contract=fast -fno-rounding-math -c %s 2>&1 \
 // RUN:   | FileCheck --check-prefix=CHECK-FAST-MATH %s
 // RUN: %clang -### -fno-honor-infinities -fno-honor-nans -fno-math-errno \
 // RUN:     -fassociative-math -freciprocal-math -fno-signed-zeros \
-// RUN:     -fno-trapping-math -ffp-contract=fast -c %s 2>&1 \
+// RUN:     -fno-trapping-math -ffp-contract=fast -fno-rounding-math -c %s 2>&1 \
 // RUN:   | FileCheck --check-prefix=CHECK-FAST-MATH %s
 // CHECK-FAST-MATH: "-cc1"
 // CHECK-FAST-MATH: "-ffast-math"
Index: clang/test/Driver/clang_f_opts.c
===================================================================
--- clang/test/Driver/clang_f_opts.c
+++ clang/test/Driver/clang_f_opts.c
@@ -320,7 +320,6 @@
 // RUN: -fprefetch-loop-arrays                                                \
 // RUN: -fprofile-correction                                                  \
 // RUN: -fprofile-values                                                      \
-// RUN: -frounding-math                                                       \
 // RUN: -fschedule-insns                                                      \
 // RUN: -fsignaling-nans                                                      \
 // RUN: -fstrength-reduce                                                     \
@@ -385,7 +384,6 @@
 // CHECK-WARNING-DAG: optimization flag '-fprefetch-loop-arrays' is not supported
 // CHECK-WARNING-DAG: optimization flag '-fprofile-correction' is not supported
 // CHECK-WARNING-DAG: optimization flag '-fprofile-values' is not supported
-// CHECK-WARNING-DAG: optimization flag '-frounding-math' is not supported
 // CHECK-WARNING-DAG: optimization flag '-fschedule-insns' is not supported
 // CHECK-WARNING-DAG: optimization flag '-fsignaling-nans' is not supported
 // CHECK-WARNING-DAG: optimization flag '-fstrength-reduce' is not supported
Index: clang/test/CodeGen/fpconstrained.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/fpconstrained.c
@@ -0,0 +1,23 @@
+// RUN: %clang_cc1 -ftrapping-math -frounding-math -ffp-exception-behavior=strict -emit-llvm -o - %s | FileCheck %s -check-prefix=FPMODELSTRICT
+// RUN: %clang_cc1 -ffp-contract=fast -emit-llvm -o - %s | FileCheck %s -check-prefix=PRECISE
+// RUN: %clang_cc1 -ffast-math -ffp-contract=fast -emit-llvm -o - %s | FileCheck %s -check-prefix=FAST
+// RUN: %clang_cc1 -ffast-math -emit-llvm -o - %s | FileCheck %s -check-prefix=FAST
+// RUN: %clang_cc1 -ffast-math -ffp-contract=fast -ffp-exception-behavior=ignore -emit-llvm -o - %s | FileCheck %s -check-prefix=FAST
+// RUN: %clang_cc1 -ffast-math -ffp-contract=fast -ffp-exception-behavior=strict -emit-llvm -o - %s | FileCheck %s -check-prefix=EXCEPT
+// RUN: %clang_cc1 -ffast-math -ffp-contract=fast -ffp-exception-behavior=maytrap -emit-llvm -o - %s | FileCheck %s -check-prefix=MAYTRAP
+float f0, f1, f2;
+
+void foo(void) {
+  // CHECK-LABEL: define {{.*}}void @foo()
+
+  // MAYTRAP: llvm.experimental.constrained.fadd.f32(float %0, float %1, metadata !"round.tonearest", metadata !"fpexcept.maytrap")
+  // EXCEPT: llvm.experimental.constrained.fadd.f32(float %0, float %1, metadata !"round.tonearest", metadata !"fpexcept.strict")
+  // FPMODELSTRICT: llvm.experimental.constrained.fadd.f32(float %0, float %1, metadata !"round.dynamic", metadata !"fpexcept.strict")
+  // STRICTEXCEPT: llvm.experimental.constrained.fadd.f32(float %0, float %1, metadata !"round.dynamic", metadata !"fpexcept.strict")
+  // STRICTNOEXCEPT: llvm.experimental.constrained.fadd.f32(float %0, float %1, metadata !"round.dynamic", metadata !"fpexcept.ignore")
+  // PRECISE: fadd contract float %0, %1
+  // FAST: fadd fast
+  f0 = f1 + f2;
+
+  // CHECK: ret
+}
Index: clang/lib/Frontend/CompilerInvocation.cpp
===================================================================
--- clang/lib/Frontend/CompilerInvocation.cpp
+++ clang/lib/Frontend/CompilerInvocation.cpp
@@ -3090,6 +3090,50 @@
       Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Val;
   }
 
+  if (Args.hasArg(OPT_frounding_math)) {
+    Opts.getFPMOptions().setFPRoundingModeSetting(LangOptions::FPRM_Dynamic);
+  }
+
+  if (Args.hasArg(OPT_fno_rounding_math)) {
+    Opts.getFPMOptions().setFPRoundingModeSetting(LangOptions::FPRM_ToNearest);
+  }
+
+  if (Args.hasArg(OPT_ftrapping_math)) {
+    Opts.getFPMOptions().setFPExceptionBehaviorSetting(LangOptions::FPEB_Strict);
+  }
+
+  if (Args.hasArg(OPT_fno_trapping_math)) {
+    Opts.getFPMOptions().setFPExceptionBehaviorSetting(LangOptions::FPEB_Ignore);
+  }
+
+  LangOptions::FPExceptionBehaviorKind FPEB = LangOptions::FPEB_Ignore;
+  if (Arg *A = Args.getLastArg(OPT_ffp_exception_behavior_EQ)) {
+    StringRef Val = A->getValue();
+    if (Val.equals("ignore"))
+      FPEB = LangOptions::FPEB_Ignore;
+    else if (Val.equals("maytrap"))
+      FPEB = LangOptions::FPEB_MayTrap;
+    else if (Val.equals("strict"))
+      FPEB = LangOptions::FPEB_Strict;
+    else
+      Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Val;
+    Opts.getFPMOptions().setFPExceptionBehaviorSetting(FPEB);
+  }
+
+#if 0
+//don't need it
+  if (FPM == LangOptions::FPM_Precise)
+    // This doesn't correspond to constrained fp,
+    // equivalent to -fp-contract=fast
+    Opts.setDefaultFPContractMode(LangOptions::FPC_Fast);
+  else if (FPM == LangOptions::FPM_Fast) {
+    // This doesn't correspond to constrained fp, equivalent to -ffast-math
+    Opts.FastMath = true;
+    Opts.FiniteMathOnly = true;
+    Opts.setDefaultFPContractMode(LangOptions::FPC_Fast);
+  }
+#endif
+
   Opts.RetainCommentsFromSystemHeaders =
       Args.hasArg(OPT_fretain_comments_from_system_headers);
 
Index: clang/lib/Driver/ToolChains/Clang.cpp
===================================================================
--- clang/lib/Driver/ToolChains/Clang.cpp
+++ clang/lib/Driver/ToolChains/Clang.cpp
@@ -2323,9 +2323,22 @@
   bool AssociativeMath = false;
   bool ReciprocalMath = false;
   bool SignedZeros = true;
-  bool TrappingMath = true;
+  bool TrappingMath = false;
+  bool RoundingFPMath = false;
+  bool RoundingMathPresent = false;
+  // -fp-model options:
+  StringRef FPModel = "";
+  //bool FPM_Precise = false;
+  //bool FPM_Strict = false;
+  //bool FPM_Fast = false;
+  // -fp-exception-behavior options:
+  StringRef FPExceptionBehavior = "";
+  //bool FPE_Ignore = false;
+  //bool FPE_MayTrap = false;
+  //bool FPE_Stric = false;
   StringRef DenormalFPMath = "";
   StringRef FPContract = "";
+  bool StrictFPModel = false;
 
   if (const Arg *A = Args.getLastArg(options::OPT_flimited_precision_EQ)) {
     CmdArgs.push_back("-mlimit-float-precision");
@@ -2333,7 +2346,74 @@
   }
 
   for (const Arg *A : Args) {
-    switch (A->getOption().getID()) {
+    auto optID = A->getOption().getID();
+    bool PreciseFPModel = false;
+    switch (optID) {
+    default:
+      break;
+    case options::OPT_ffp_model_EQ: {
+      StrictFPModel = false;
+      PreciseFPModel = true;
+      // ffp-model= is a Driver option, it is entirely rewritten into more
+      // granular options before being passed into cc1.
+      // Use the gcc option in the switch below.
+      StringRef Val = A->getValue();
+      if (!FPModel.empty() && !FPModel.equals(Val)) {
+        D.Diag(clang::diag::warn_drv_overriding_flag_option)
+          << Args.MakeArgString("-ffp-model=" + FPModel)
+          << Args.MakeArgString("-ffp-model=" + Val);
+        FPContract = "";
+      }
+      if (Val.equals("fast")) {
+        if (!FPContract.empty() && !FPContract.equals("fast"))
+          // FPContract has already been set to something else
+          // so warn about the override.
+          D.Diag(clang::diag::warn_drv_overriding_flag_option)
+            << Args.MakeArgString("-ffp-contract=" + FPContract)
+            << "-ffp-contract=fast";
+        optID = options::OPT_ffast_math;
+        FPModel = Val;
+        FPContract = "fast";
+      } else if (Val.equals("precise")) {
+        if (!FPContract.empty() && !FPContract.equals("fast"))
+          D.Diag(clang::diag::warn_drv_overriding_flag_option)
+            << Args.MakeArgString("-ffp-contract=" + FPContract)
+            << "-ffp-contract=fast";
+        optID = options::OPT_ffp_contract;
+        FPModel = Val;
+        FPContract = "fast";
+        PreciseFPModel = true;
+      } else if (Val.equals("strict")) {
+        StrictFPModel = true;
+        if (!FPContract.empty() && !FPContract.equals("strict"))
+          D.Diag(clang::diag::warn_drv_overriding_flag_option)
+            << Args.MakeArgString("-ffp-contract=" + FPContract)
+            << "-ffp-contract=strict";
+        optID = options::OPT_frounding_math;
+        FPModel = Val;
+        // fp-model=strict also enables fno-fast-math
+        HonorINFs = true;
+        HonorNaNs = true;
+        // Turning on -ffast-math (with either flag) removes the need for
+        // MathErrno. However, turning *off* -ffast-math merely restores the
+        // toolchain default (which may be false).
+        MathErrno = TC.IsMathErrnoDefault();
+        AssociativeMath = false;
+        ReciprocalMath = false;
+        SignedZeros = true;
+        TrappingMath = true;
+        RoundingFPMath = true;
+        // -fno_fast_math restores default denormal and fpcontract handling
+        DenormalFPMath = "";
+        FPContract = "";
+      } else
+        D.Diag(diag::err_drv_unsupported_option_argument)
+            << A->getOption().getName() << Val;
+      break;
+      }
+    }
+
+    switch (optID) {
     // If this isn't an FP option skip the claim below
     default: continue;
 
@@ -2350,8 +2430,24 @@
     case options::OPT_fno_reciprocal_math:  ReciprocalMath = false;   break;
     case options::OPT_fsigned_zeros:        SignedZeros = true;       break;
     case options::OPT_fno_signed_zeros:     SignedZeros = false;      break;
-    case options::OPT_ftrapping_math:       TrappingMath = true;      break;
+    case options::OPT_ftrapping_math:
+      TrappingMath = true;
+      FPExceptionBehavior = "strict";
+      break;
     case options::OPT_fno_trapping_math:    TrappingMath = false;     break;
+    case options::OPT_frounding_math:
+      // The default setting for frounding-math is True and ffast-math
+      // sets fno-rounding-math, but we only want to use constrained
+      // floating point intrinsics if the option is specifically requested.
+      RoundingFPMath = true;
+      RoundingMathPresent = true;
+      FPExceptionBehavior = "strict";
+      break;
+    case options::OPT_fno_rounding_math:
+      RoundingFPMath = false;
+      RoundingMathPresent = false;
+      FPExceptionBehavior = "";
+      break;
 
     case options::OPT_fdenormal_fp_math_EQ:
       DenormalFPMath = A->getValue();
@@ -2360,10 +2456,38 @@
     // Validate and pass through -fp-contract option.
     case options::OPT_ffp_contract: {
       StringRef Val = A->getValue();
-      if (Val == "fast" || Val == "on" || Val == "off")
+      if (PreciseFPModel) {
+        // -fp-model=precise enables fp-contract=fast as a side effect
+        // the FPContract value has already been set to a string literal
+        // and the Val string isn't a pertinent value.
+        ;
+      } else if (Val.equals("fast") || Val.equals("on") || Val.equals("off"))
         FPContract = Val;
       else
         D.Diag(diag::err_drv_unsupported_option_argument)
+           << A->getOption().getName() << Val;
+      break;
+    }
+
+    // Validate and pass through -ffp-model option.
+    case options::OPT_ffp_model_EQ:
+      // This should only occur in the error case
+      // since the optID has been replaced by a more granular
+      // floating point option.
+      break;
+
+    // Validate and pass through -ffp-exception-behavior option.
+    case options::OPT_ffp_exception_behavior_EQ: {
+      StringRef Val = A->getValue();
+      if (!FPExceptionBehavior.empty())
+        // Warn that previous value of option is overridden.
+        D.Diag(clang::diag::warn_drv_overriding_flag_option)
+          << Args.MakeArgString("-ffp-exception-behavior=" + FPExceptionBehavior)
+          << Args.MakeArgString("-ffp-exception-behavior=" + Val);
+      if (Val.equals("ignore") || Val.equals("maytrap") || Val.equals("strict"))
+        FPExceptionBehavior = Val;
+      else
+        D.Diag(diag::err_drv_unsupported_option_argument)
             << A->getOption().getName() << Val;
       break;
     }
@@ -2405,6 +2529,7 @@
       ReciprocalMath = true;
       SignedZeros = false;
       TrappingMath = false;
+      RoundingFPMath = false;
       // If fast-math is set then set the fp-contract mode to fast.
       FPContract = "fast";
       break;
@@ -2419,11 +2544,35 @@
       ReciprocalMath = false;
       SignedZeros = true;
       TrappingMath = true;
+      RoundingFPMath = true;
       // -fno_fast_math restores default denormal and fpcontract handling
       DenormalFPMath = "";
       FPContract = "";
       break;
     }
+    if (StrictFPModel) {
+      // If fp-model=strict has been specified on command line but
+      // subsequent options conflict then emit warning diagnostic.
+      if (HonorINFs && HonorNaNs &&
+        !AssociativeMath && !ReciprocalMath &&
+        SignedZeros && TrappingMath && RoundingFPMath &&
+        DenormalFPMath.empty() && FPContract.empty())
+        // OK: Current Arg doesn't conflict with fp-model=strict
+        ;
+      else {
+        StrictFPModel = false;
+        FPModel = "";
+        StringRef Val = A->getValue();
+        if (Val.empty())
+          D.Diag(clang::diag::warn_drv_overriding_flag_option)
+            << "-ffp-model=strict"
+            << A->getSpelling();
+        else
+          D.Diag(clang::diag::warn_drv_overriding_flag_option)
+            << "-ffp-model=strict"
+            << Args.MakeArgString(A->getSpelling() + Val);
+      }
+    }
 
     // If we handled this option claim it
     A->claim();
@@ -2451,7 +2600,10 @@
   if (ReciprocalMath)
     CmdArgs.push_back("-freciprocal-math");
 
-  if (!TrappingMath)
+  if (TrappingMath)
+    // Note: FP Exception Behavior is also set to strict
+    CmdArgs.push_back("-ftrapping-math");
+  else
     CmdArgs.push_back("-fno-trapping-math");
 
   if (!DenormalFPMath.empty())
@@ -2461,14 +2613,37 @@
   if (!FPContract.empty())
     CmdArgs.push_back(Args.MakeArgString("-ffp-contract=" + FPContract));
 
+  if (!RoundingFPMath)
+    CmdArgs.push_back(Args.MakeArgString("-fno-rounding-math"));
+
+  if (RoundingFPMath && RoundingMathPresent)
+    CmdArgs.push_back(Args.MakeArgString("-frounding-math"));
+
+  if (!FPExceptionBehavior.empty())
+    CmdArgs.push_back(Args.MakeArgString("-ffp-exception-behavior=" +
+                      FPExceptionBehavior));
+
   ParseMRecip(D, Args, CmdArgs);
 
   // -ffast-math enables the __FAST_MATH__ preprocessor macro, but check for the
   // individual features enabled by -ffast-math instead of the option itself as
   // that's consistent with gcc's behaviour.
   if (!HonorINFs && !HonorNaNs && !MathErrno && AssociativeMath &&
-      ReciprocalMath && !SignedZeros && !TrappingMath)
+      ReciprocalMath && !SignedZeros && !TrappingMath && !RoundingFPMath) {
     CmdArgs.push_back("-ffast-math");
+    if (FPModel.equals("fast")) {
+      if (FPContract.equals("fast"))
+        // All set, do nothing.
+        ;
+      else if (FPContract.empty())
+        // Enable fp-contract=fast
+        CmdArgs.push_back(Args.MakeArgString("-ffp-contract=fast"));
+      else
+        D.Diag(clang::diag::warn_drv_overriding_flag_option)
+          << "-ffp-model=fast"
+          << Args.MakeArgString("-ffp-contract=" + FPContract);
+    }
+  }
 
   // Handle __FINITE_MATH_ONLY__ similarly.
   if (!HonorINFs && !HonorNaNs)
Index: clang/lib/CodeGen/CodeGenFunction.h
===================================================================
--- clang/lib/CodeGen/CodeGenFunction.h
+++ clang/lib/CodeGen/CodeGenFunction.h
@@ -4148,6 +4148,9 @@
   /// point operation, expressed as the maximum relative error in ulp.
   void SetFPAccuracy(llvm::Value *Val, float Accuracy);
 
+  /// SetFPModel - Control floating point behavior via fp-model settings.
+  void SetFPModel(void);
+
 private:
   llvm::MDNode *getRangeForLoadFromType(QualType Ty);
   void EmitReturnOfRValue(RValue RV, QualType Ty);
Index: clang/lib/CodeGen/CodeGenFunction.cpp
===================================================================
--- clang/lib/CodeGen/CodeGenFunction.cpp
+++ clang/lib/CodeGen/CodeGenFunction.cpp
@@ -33,6 +33,7 @@
 #include "clang/Frontend/FrontendDiagnostic.h"
 #include "llvm/IR/DataLayout.h"
 #include "llvm/IR/Dominators.h"
+#include "llvm/IR/IntrinsicInst.h"
 #include "llvm/IR/Intrinsics.h"
 #include "llvm/IR/MDBuilder.h"
 #include "llvm/IR/Operator.h"
@@ -87,6 +88,7 @@
     FMF.setAllowReassoc();
   }
   Builder.setFastMathFlags(FMF);
+  SetFPModel();
 }
 
 CodeGenFunction::~CodeGenFunction() {
@@ -102,6 +104,62 @@
     CGM.getOpenMPRuntime().functionFinished(*this);
 }
 
+void CodeGenFunction::SetFPModel(void)
+{
+  auto fpRoundingMode = getLangOpts().getFPMOptions().getFPRoundingModeSetting();
+  auto fpExceptionBehavior =
+         getLangOpts().getFPMOptions().getFPExceptionBehaviorSetting();
+
+  // Translate the compiler options into
+  // the settings that are transmitted to the IR Builder
+  llvm::ConstrainedFPIntrinsic::RoundingMode ConstrainedRoundingMD;
+  llvm::ConstrainedFPIntrinsic::ExceptionBehavior ConstrainedExceptMD;
+
+  switch (fpRoundingMode) {
+  case LangOptions::FPRM_ToNearest:
+    ConstrainedRoundingMD = llvm::ConstrainedFPIntrinsic::rmToNearest;
+    break;
+  case LangOptions::FPRM_Downward:
+    ConstrainedRoundingMD = llvm::ConstrainedFPIntrinsic::rmDownward;
+    break;
+  case LangOptions::FPRM_Upward:
+    ConstrainedRoundingMD = llvm::ConstrainedFPIntrinsic::rmUpward;
+    break;
+  case LangOptions::FPRM_ToZero:
+    ConstrainedRoundingMD = llvm::ConstrainedFPIntrinsic::rmTowardZero;
+    break;
+  case LangOptions::FPRM_Dynamic:
+    ConstrainedRoundingMD = llvm::ConstrainedFPIntrinsic::rmDynamic;
+    break;
+  default:
+    llvm_unreachable("Unsupported FP RoundingMode");
+  }
+
+  switch (fpExceptionBehavior) {
+  case LangOptions::FPEB_Ignore:
+    ConstrainedExceptMD = llvm::ConstrainedFPIntrinsic::ebIgnore;
+    break;
+  case LangOptions::FPEB_MayTrap:
+    ConstrainedExceptMD = llvm::ConstrainedFPIntrinsic::ebMayTrap;
+    break;
+  case LangOptions::FPEB_Strict:
+    ConstrainedExceptMD = llvm::ConstrainedFPIntrinsic::ebStrict;
+    break;
+  default:
+    llvm_unreachable("Unsupported FP Exception Behavior");
+  }
+
+  if (fpExceptionBehavior == LangOptions::FPEB_Ignore &&
+      fpRoundingMode == LangOptions::FPRM_ToNearest)
+    // Constrained intrinsics are not used.
+    ;
+  else {
+    Builder.setIsFPConstrained(true);
+    Builder.setDefaultConstrainedRounding(ConstrainedRoundingMD);
+    Builder.setDefaultConstrainedExcept(ConstrainedExceptMD);
+  }
+}
+
 CharUnits CodeGenFunction::getNaturalPointeeTypeAlignment(QualType T,
                                                     LValueBaseInfo *BaseInfo,
                                                     TBAAAccessInfo *TBAAInfo) {
Index: clang/lib/CodeGen/BackendUtil.cpp
===================================================================
--- clang/lib/CodeGen/BackendUtil.cpp
+++ clang/lib/CodeGen/BackendUtil.cpp
@@ -475,6 +475,7 @@
   Options.NoNaNsFPMath = CodeGenOpts.NoNaNsFPMath;
   Options.NoZerosInBSS = CodeGenOpts.NoZeroInitializedInBSS;
   Options.UnsafeFPMath = CodeGenOpts.UnsafeFPMath;
+  Options.RoundingFPMath = CodeGenOpts.RoundingFPMath;
   Options.StackAlignmentOverride = CodeGenOpts.StackAlignment;
   Options.FunctionSections = CodeGenOpts.FunctionSections;
   Options.DataSections = CodeGenOpts.DataSections;
Index: clang/include/clang/Driver/Options.td
===================================================================
--- clang/include/clang/Driver/Options.td
+++ clang/include/clang/Driver/Options.td
@@ -924,6 +924,10 @@
 def : Flag<["-"], "fno-extended-identifiers">, Group<f_Group>, Flags<[Unsupported]>;
 def fhosted : Flag<["-"], "fhosted">, Group<f_Group>;
 def fdenormal_fp_math_EQ : Joined<["-"], "fdenormal-fp-math=">, Group<f_Group>, Flags<[CC1Option]>;
+def ffp_model_EQ : Joined<["-"], "ffp-model=">, Group<f_Group>, Flags<[DriverOption]>,
+  HelpText<"Controls the semantics of floating-point calculations.">;
+def ffp_exception_behavior_EQ : Joined<["-"], "ffp-exception-behavior=">, Group<f_Group>, Flags<[CC1Option]>,
+  HelpText<"Specifies the exception behavior of floating-point operations.">;
 def ffast_math : Flag<["-"], "ffast-math">, Group<f_Group>, Flags<[CC1Option]>,
   HelpText<"Allow aggressive, lossy floating-point optimizations">;
 def fno_fast_math : Flag<["-"], "fno-fast-math">, Group<f_Group>;
@@ -1140,6 +1144,8 @@
 // This option was originally misspelt "infinites" [sic].
 def : Flag<["-"], "fhonor-infinites">, Alias<fhonor_infinities>;
 def : Flag<["-"], "fno-honor-infinites">, Alias<fno_honor_infinities>;
+def frounding_math : Flag<["-"], "frounding-math">, Group<f_Group>, Flags<[CC1Option]>;
+def fno_rounding_math : Flag<["-"], "fno-rounding-math">, Group<f_Group>, Flags<[CC1Option]>;
 def ftrapping_math : Flag<["-"], "ftrapping-math">, Group<f_Group>, Flags<[CC1Option]>;
 def fno_trapping_math : Flag<["-"], "fno-trapping-math">, Group<f_Group>, Flags<[CC1Option]>;
 def ffp_contract : Joined<["-"], "ffp-contract=">, Group<f_Group>,
@@ -3168,7 +3174,6 @@
 defm regs_graph : BooleanFFlag<"regs-graph">, Group<clang_ignored_f_Group>;
 defm rename_registers : BooleanFFlag<"rename-registers">, Group<clang_ignored_gcc_optimization_f_Group>;
 defm ripa : BooleanFFlag<"ripa">, Group<clang_ignored_f_Group>;
-defm rounding_math : BooleanFFlag<"rounding-math">, Group<clang_ignored_gcc_optimization_f_Group>;
 defm schedule_insns : BooleanFFlag<"schedule-insns">, Group<clang_ignored_gcc_optimization_f_Group>;
 defm schedule_insns2 : BooleanFFlag<"schedule-insns2">, Group<clang_ignored_gcc_optimization_f_Group>;
 defm see : BooleanFFlag<"see">, Group<clang_ignored_f_Group>;
Index: clang/include/clang/Basic/LangOptions.h
===================================================================
--- clang/include/clang/Basic/LangOptions.h
+++ clang/include/clang/Basic/LangOptions.h
@@ -184,6 +184,31 @@
     FEA_On
   };
 
+  enum FPRoundingModeKind {
+    // Round to the nearest integer - IEEE rounding mode
+    FPRM_ToNearest,  // This is the default
+    // Rounding mode is dynamic: optimizer assumes that rounding mode
+    // is unknown.
+    FPRM_Dynamic,
+    // Round down - IEEE rounding mode
+    FPRM_Downward,
+    // Round up - IEEE rounding mode
+    FPRM_Upward,
+    // Round towards zero - IEEE rounding mode
+    FPRM_ToZero
+  };
+
+  enum FPExceptionBehaviorKind {
+   // Floating point exceptions are not handled: fp exceptions are masked.
+   FPEB_Ignore,  // This is the default
+   // Optimizer will avoid transformations that may raise exceptions that would
+   // not have been raised by unoptimized code
+   FPEB_MayTrap,
+   // Optimizer will strictly preserve the fp exception semantics of the
+   // unoptimized code
+   FPEB_Strict
+  };
+
   enum class LaxVectorConversionKind {
     /// Permit no implicit vector bitcasts.
     None,
@@ -317,6 +342,38 @@
 
   /// Return the OpenCL C or C++ version as a VersionTuple.
   VersionTuple getOpenCLVersionTuple() const;
+
+  /// Floating point model options
+  class FPModelOptions {
+  public:
+    FPModelOptions() : FPRM(LangOptions::FPRM_ToNearest),
+                       FPEB(LangOptions::FPEB_Ignore) {}
+
+    LangOptions::FPRoundingModeKind getFPRoundingModeSetting() const {
+      return FPRM;
+    }
+    void setFPRoundingModeSetting(LangOptions::FPRoundingModeKind Value) {
+      FPRM = Value;
+    }
+
+    LangOptions::FPExceptionBehaviorKind getFPExceptionBehaviorSetting() const
+    {
+      return FPEB;
+    }
+    void setFPExceptionBehaviorSetting(
+           LangOptions::FPExceptionBehaviorKind Value) {
+      FPEB = Value;
+    }
+
+  private:
+    LangOptions::FPRoundingModeKind FPRM = LangOptions::FPRM_ToNearest;
+    LangOptions::FPExceptionBehaviorKind FPEB = LangOptions::FPEB_Ignore;
+  };
+
+  FPModelOptions& getFPMOptions() { return fpm_options; }
+  FPModelOptions getFPMOptions() const { return fpm_options; }
+private:
+  FPModelOptions fpm_options;
 };
 
 /// Floating point control options
Index: clang/include/clang/Basic/CodeGenOptions.def
===================================================================
--- clang/include/clang/Basic/CodeGenOptions.def
+++ clang/include/clang/Basic/CodeGenOptions.def
@@ -234,6 +234,7 @@
 CODEGENOPT(RerollLoops       , 1, 0) ///< Control whether loops are rerolled.
 CODEGENOPT(NoUseJumpTables   , 1, 0) ///< Set when -fno-jump-tables is enabled.
 CODEGENOPT(UnsafeFPMath      , 1, 0) ///< Allow unsafe floating point optzns.
+CODEGENOPT(RoundingFPMath    , 1, 0) ///< Rounding floating point optzns.
 CODEGENOPT(UnwindTables      , 1, 0) ///< Emit unwind tables.
 CODEGENOPT(VectorizeLoop     , 1, 0) ///< Run loop vectorizer.
 CODEGENOPT(VectorizeSLP      , 1, 0) ///< Run SLP vectorizer.
Index: clang/docs/UsersManual.rst
===================================================================
--- clang/docs/UsersManual.rst
+++ clang/docs/UsersManual.rst
@@ -1219,10 +1219,10 @@
 
 **-f[no-]trapping-math**
 
-   ``-fno-trapping-math`` allows optimizations that assume that
-   floating point operations cannot generate traps such as divide-by-zero,
-   overflow and underflow. Defaults to ``-ftrapping-math``.
-   Currently this option has no effect.
+   Control floating point exception behavior. ``-fno-trapping-math`` allows optimizations that assume that floating point operations cannot generate traps such as divide-by-zero, overflow and underflow.
+
+- The option ``-ftrapping-math`` behaves identically to ``-ffp-exception-behavior=strict``.
+- The option ``-fno-trapping-math`` behaves identically to ``-ffp-exception-behavior=ignore``.   This is the default.
 
 .. option:: -ffp-contract=<value>
 
@@ -1307,6 +1307,53 @@
 
    Defaults to ``-fno-finite-math``.
 
+.. _opt_frounding-math:
+
+**-f[no-]rounding-math**
+
+   LLVM constrained floating point supports five rounding modes: ``tonearest``,
+   ``downward``, ``upward``, ``towardzero`` and ``dynamic``. The first four
+   values represent corresponding IEEE rounding rules, and the ``dynamic``
+   mode informs the compiler that it must not assume any particular
+   rounding mode.
+
+- The option ``-fno-rounding-math`` specifies ``tonearest`` rounding mode. This is the default.
+- The option ``-frounding-math`` specifies ``dynamic`` rounding mode.
+- The option ``-frounding-math`` behaves identically to ``-ffp-model=strict``.  Consequently, this option also sets ``-ffp-exception-behavior=strict``.
+
+.. option:: -ffp-model=<value>
+
+   Specify floating point behavior. ``-ffp-model`` is an umbrella
+   option that encompasses functionality provided by lower level, single
+   purpose, clang floating point options.  Valid values are: ``precise``, ``strict``,
+   and ``fast``.
+   Details:
+
+   * ``precise`` Disables optimizations that are not value-safe on floating-point data, although FP contraction (FMA) is enabled (``-ffp-contract=fast``).  This is clang's default behavior.
+   * ``strict`` Enables ``-frounding-math`` and ``-ffp-exception-behavior=strict``, and disables contractions (FMA).  All of the ``-ffast-math`` enablements are disabled.
+   * ``fast`` Behaves identically to specifying both ``-ffast-math`` and ``ffp-contract=fast``
+
+   Note: If your command line specifies multiple instances
+   of the ``-ffp-model`` option, or if your command line option specifies
+   ``-ffp-model`` and later on the command line selects a floating point
+   option that has the effect of negating part of the  ``ffp-model`` that
+   has been selected, then the compiler will issue a diagnostic warning
+   that the override has occurred.
+
+.. option:: -ffp-exception-behavior=<value>
+
+   Specify the floating-point exception behavior.
+
+   Valid values are: ``ignore``, ``maytrap``, and ``strict``.
+   The default value is ``ignore``.  Details:
+
+   * ``ignore`` The compiler assumes that the exception status flags will not be read and that floating point exceptions will be masked.
+   * ``maytrap`` The compiler avoids transformations that may raise exceptions that would not have been raised by the original code. Constant folding performed by the compiler is exempt from this option.
+   * ``strict`` The compiler ensures that all transformations strictly preserve the floating point exception semantics of the original code.
+
+
+
+
 .. _controlling-code-generation:
 
 Controlling Code Generation
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to