mibintc updated this revision to Diff 219364.
mibintc retitled this revision from "[RFC] Add support for options -fp-model= 
and -fp-speculation= : specify floating point behavior" to "[RFC] Add support 
for options -frounding-math -fp-model= and -fp-exception-behavior= : specify 
floating point behavior".
mibintc edited the summary of this revision.
mibintc added a comment.

Addressed comments from @rjmccall and @andrew.w.kaylor.  Added -frounding-math 
option and -ffp-exception-behavior= option. Dropped -ffp-speculation= option.  
Added details about how the new options conflict with existing floating point 
options. Rewrote
RenderFloatingPointOptions using pseudo code to show how option conflicts will 
be detected.


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/LangOptions.h
  clang/include/clang/Driver/Options.td
  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

Index: clang/test/CodeGen/fpconstrained.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/fpconstrained.c
@@ -0,0 +1,23 @@
+// RUN: %clang_cc1 -fp-model=strict -emit-llvm -o - %s | FileCheck %s -check-prefix=STRICT
+// RUN: %clang_cc1 -fp-model=precise -emit-llvm -o - %s | FileCheck %s -check-prefix=PRECISE
+// RUN: %clang_cc1 -fp-model=fast -emit-llvm -o - %s | FileCheck %s -check-prefix=FAST
+// RUN: %clang_cc1 -fp-model=fast -fp-exception-behavior=ignore -emit-llvm -o - %s | FileCheck %s -check-prefix=NOEXCEPT
+// RUN: %clang_cc1 -fp-model=fast -fp-exception-behavior=strict -emit-llvm -o - %s | FileCheck %s -check-prefix=EXCEPT
+// RUN: %clang_cc1 -fp-model=fast -fp-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")
+  // NOEXCEPT: llvm.experimental.constrained.fadd.f32(float %0, float %1, metadata !"round.tonearest", metadata !"fpexcept.ignore")
+  // STRICT: 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 float
+  // FAST: fadd fast
+  f0 = f1 + f2;
+
+  // CHECK: ret
+}
Index: clang/lib/Frontend/CompilerInvocation.cpp
===================================================================
--- clang/lib/Frontend/CompilerInvocation.cpp
+++ clang/lib/Frontend/CompilerInvocation.cpp
@@ -3074,6 +3074,45 @@
       Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Val;
   }
 
+  LangOptions::FPModelKind FPM = LangOptions::FPM_Off;
+  if (Arg *A = Args.getLastArg(OPT_fp_model_EQ)) {
+    StringRef Val = A->getValue();
+    if (Val == "precise")
+      FPM = LangOptions::FPM_Precise;
+    else if (Val == "strict")
+      FPM = LangOptions::FPM_Strict;
+    else if (Val == "fast")
+      FPM = LangOptions::FPM_Fast;
+    else
+      llvm_unreachable("invalid -fp-model setting");
+  }
+  Opts.getFPMOptions().setFPModelSetting(FPM);
+
+  LangOptions::FPExceptionBehaviorKind FPE = LangOptions::FPE_Off;
+  if (Arg *A = Args.getLastArg(OPT_fp_exception_behavior_EQ)) {
+    StringRef Val = A->getValue();
+    if (Val == "ignore")
+      FPE = LangOptions::FPE_Ignore;
+    else if (Val == "maytrap")
+      FPE = LangOptions::FPE_MayTrap;
+    else if (Val == "strict")
+      FPE = LangOptions::FPE_Strict;
+    else
+      llvm_unreachable("invalid -fp-exception-behavior setting");
+    Opts.getFPMOptions().setFPExceptionBehaviorSetting(FPE);
+  }
+
+  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);
+  }
+
   Opts.RetainCommentsFromSystemHeaders =
       Args.hasArg(OPT_fretain_comments_from_system_headers);
 
@@ -3443,6 +3482,15 @@
     // FIXME: Should we really be calling this for an Language::Asm input?
     ParseLangArgs(LangOpts, Args, DashX, Res.getTargetOpts(),
                   Res.getPreprocessorOpts(), Diags);
+    auto fpm = LangOpts.getFPMOptions().getFPModelSetting();
+    if (fpm == LangOptions::FPM_Fast) {
+      auto CGOpts = Res.getCodeGenOpts();
+      CGOpts.NoInfsFPMath = true;
+      CGOpts.UnsafeFPMath = true;
+      CGOpts.ReciprocalMath = true;
+      CGOpts.NoTrappingMath = true;
+      CGOpts.NoSignedZeros = true;
+    }
     if (Res.getFrontendOpts().ProgramAction == frontend::RewriteObjC)
       LangOpts.ObjCExceptions = 1;
     if (T.isOSDarwin() && DashX.isPreprocessed()) {
Index: clang/lib/Driver/ToolChains/Clang.cpp
===================================================================
--- clang/lib/Driver/ToolChains/Clang.cpp
+++ clang/lib/Driver/ToolChains/Clang.cpp
@@ -2299,6 +2299,158 @@
   if (C.getDriver().embedBitcodeEnabled() ||
       C.getDriver().embedBitcodeMarkerOnly())
     Args.AddLastArg(CmdArgs, options::OPT_fembed_bitcode_EQ);
+};
+
+// This is just a capture of all the floating point options that
+// need to be treated specially in RenderFloatingPointOptions, as well
+// as simplifying the parameterized options (e.g. fp-model=precise) into
+// simple enumeration values.
+enum floatOpt {
+    fp_Ofast,
+    fp_ffast_math,
+    fp_fno_fast_math,
+    fp_flimited_precision_EQ,
+    fp_model_strict,
+    fp_model_fast,
+    fp_model_precise,
+    fp_fno_rounding_math,
+    fp_frounding_math,
+    fp_exception_behavior_ignore,
+    fp_exception_behavior_maytrap,
+    fp_exception_behavior_strict,
+    fp_fhonor_infinities,
+    fp_fno_honor_infinities,
+    fp_fhonor_nans,
+    fp_fno_honor_nans,
+    fp_fmath_errno,
+    fp_fno_math_errno,
+    fp_fassociative_math,
+    fp_fno_associative_math,
+    fp_freciprocal_math,
+    fp_fno_reciprocal_math,
+    fp_fsigned_zeros,
+    fp_fno_signed_zeros,
+    fp_ftrapping_math,
+    fp_fno_trapping_math,
+    fp_fdenormal_fp_math_EQ,
+    fp_ffp_contract_on,
+    fp_ffp_contract_off,
+    fp_ffp_contract_fast,
+    fp_ffinite_math_only,
+    fp_fno_finite_math_only,
+    fp_funsafe_math_optimizations,
+    fp_fno_unsafe_math_optimizations,
+    fp_fno_strict_float_cast_overflow,
+    fp_fstrict_float_cast_overflow,
+    fp_Count};
+
+// Show which floating point options conflict with each other
+// FIXME, not all conflicts are present e.g.
+// the conflict array should show that ffast-math conflicts with
+// fno-fast math etc.
+// FIXME, this won't compile on gcc5, will need to use a different
+// representation
+constexpr bool fpConflict[fp_Count][fp_Count] = {
+  /* fp_Ofast */
+    { [fp_model_strict]=true },
+  /* fp_ffast_math */
+    { [fp_model_strict]=true },
+  /* fp_fno_fast_math */
+    { false },
+  /* fp_flimited_precision_EQ */
+    { false },
+  /* fp_model_strict */
+    {[fp_Ofast]=true, [fp_ffast_math]=true,
+     [fp_model_precise] = true,
+     [fp_model_fast] = true,
+     [fp_exception_behavior_ignore] = true,
+     [fp_exception_behavior_maytrap] = true,
+     [fp_fno_honor_infinities] = true,
+     [fp_fno_honor_nans] = true,
+     [fp_fassociative_math] = true,
+     [fp_freciprocal_math] = true,
+     [fp_fno_signed_zeros] = true,
+     [fp_fno_trapping_math] = true,
+     [fp_ffp_contract_on] = true,
+     [fp_ffp_contract_fast] = true,
+     [fp_ffinite_math_only] = true,
+     [fp_funsafe_math_optimizations] = true},
+
+  /* fp_model_fast */
+    { [fp_model_strict]=true, [fp_model_precise]=true },
+  /* fp_model_precise */
+    { [fp_model_strict]=true, [fp_model_fast]=true},
+  /* fp_fno_rounding_math */
+    { false },
+  /* fp_frounding_math */
+    { [fp_model_fast]=true, [fp_model_precise]=true },
+  /* fp_exception_behavior_ignore */
+    { [fp_model_strict]=true },
+  /* fp_exception_behavior_maytrap */
+    { [fp_model_strict]=true },
+  /* fp_exception_behavior_strict */
+    { [fp_exception_behavior_ignore]=true, 
+      [fp_exception_behavior_maytrap]=true },
+  /* fp_fhonor_infinities */
+    { false },
+  /* fp_fno_honor_infinities */
+    { [fp_model_strict]=true },
+  /* fp_fhonor_nans */
+    { false },
+  /* fp_fno_honor_nans */
+    { [fp_model_strict]=true },
+  /* fp_fmath_errno */
+    { false },
+  /* fp_fno_math_errno */
+    { false },
+  /* fp_fassociative_math */
+    { [fp_model_strict]=true },
+  /* fp_fno_associative_math */
+    { false },
+  /* fp_freciprocal_math */
+    { [fp_model_strict]=true },
+  /* fp_fno_reciprocal_math */
+    { false },
+  /* fp_fsigned_zeros */
+    { false },
+  /* fp_fno_signed_zeros */
+    { [fp_model_strict]=true },
+  /* fp_ftrapping_math */
+    { false },
+  /* fp_fno_trapping_math */
+    { [fp_model_strict]=true },
+  /* fp_fdenormal_fp_math_EQ */
+
+  /* fp_ffp_contract_on */
+    { [fp_model_strict]=true, [fp_model_fast]=true },
+  /* fp_ffp_contract_off */
+    { [fp_model_precise]=true, [fp_model_fast]=true },
+  /* fp_ffp_contract_fast */
+    { [fp_model_strict]=true, [fp_model_precise]=true },
+  /* fp_ffinite_math_only */
+    { [fp_model_strict]=true },
+  /* fp_fno_finite_math_only */
+    { false },
+  /* fp_funsafe_math_optimizations */
+    { [fp_model_strict]=true },
+  /* fp_fno_unsafe_math_optimizations */
+    { false },
+  /* fp_fno_strict_float_cast_overflow */
+    { false },
+  /* fp_fstrict_float_cast_overflow */
+    { false }};
+
+// Convert Arg to floatOpt if possible
+// Return invalid value 'fp_Count' if A is not a valid fp argument
+// Issue error or warning diagnostics for malformed options.
+static floatOpt option_to_floatOpt(const Arg *A, const Driver &d,
+                                   bool OFastEnabled)
+{
+  // The simple options such as trapping-math are simply converted into
+  // the corresponding enumeration value
+  // and in the case of options that have arguments e.g.
+  // fp-model=strict or fp-contract=on, flatten them into a
+  // simple enumeration value.
 }
 
 static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
@@ -2309,16 +2461,8 @@
   // "umbrella" flags, so we do this by stepping through the flags incrementally
   // adjusting what we think is enabled/disabled, then at the end setting the
   // LLVM flags based on the final state.
-  bool HonorINFs = true;
-  bool HonorNaNs = true;
-  // -fmath-errno is the default on some platforms, e.g. BSD-derived OSes.
-  bool MathErrno = TC.IsMathErrnoDefault();
-  bool AssociativeMath = false;
-  bool ReciprocalMath = false;
-  bool SignedZeros = true;
-  bool TrappingMath = true;
-  StringRef DenormalFPMath = "";
-  StringRef FPContract = "";
+
+  bool fpEnabled[fp_Count] = {false};
 
   if (const Arg *A = Args.getLastArg(options::OPT_flimited_precision_EQ)) {
     CmdArgs.push_back("-mlimit-float-precision");
@@ -2326,133 +2470,34 @@
   }
 
   for (const Arg *A : Args) {
-    switch (A->getOption().getID()) {
-    // If this isn't an FP option skip the claim below
-    default: continue;
-
-    // Options controlling individual features
-    case options::OPT_fhonor_infinities:    HonorINFs = true;         break;
-    case options::OPT_fno_honor_infinities: HonorINFs = false;        break;
-    case options::OPT_fhonor_nans:          HonorNaNs = true;         break;
-    case options::OPT_fno_honor_nans:       HonorNaNs = false;        break;
-    case options::OPT_fmath_errno:          MathErrno = true;         break;
-    case options::OPT_fno_math_errno:       MathErrno = false;        break;
-    case options::OPT_fassociative_math:    AssociativeMath = true;   break;
-    case options::OPT_fno_associative_math: AssociativeMath = false;  break;
-    case options::OPT_freciprocal_math:     ReciprocalMath = true;    break;
-    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_fno_trapping_math:    TrappingMath = false;     break;
-
-    case options::OPT_fdenormal_fp_math_EQ:
-      DenormalFPMath = A->getValue();
-      break;
-
-    // Validate and pass through -fp-contract option.
-    case options::OPT_ffp_contract: {
-      StringRef Val = A->getValue();
-      if (Val == "fast" || Val == "on" || Val == "off")
-        FPContract = Val;
-      else
-        D.Diag(diag::err_drv_unsupported_option_argument)
-            << A->getOption().getName() << Val;
-      break;
-    }
-
-    case options::OPT_ffinite_math_only:
-      HonorINFs = false;
-      HonorNaNs = false;
-      break;
-    case options::OPT_fno_finite_math_only:
-      HonorINFs = true;
-      HonorNaNs = true;
-      break;
-
-    case options::OPT_funsafe_math_optimizations:
-      AssociativeMath = true;
-      ReciprocalMath = true;
-      SignedZeros = false;
-      TrappingMath = false;
-      break;
-    case options::OPT_fno_unsafe_math_optimizations:
-      AssociativeMath = false;
-      ReciprocalMath = false;
-      SignedZeros = true;
-      TrappingMath = true;
-      // -fno_unsafe_math_optimizations restores default denormal handling
-      DenormalFPMath = "";
-      break;
-
-    case options::OPT_Ofast:
-      // If -Ofast is the optimization level, then -ffast-math should be enabled
-      if (!OFastEnabled)
-        continue;
-      LLVM_FALLTHROUGH;
-    case options::OPT_ffast_math:
-      HonorINFs = false;
-      HonorNaNs = false;
-      MathErrno = false;
-      AssociativeMath = true;
-      ReciprocalMath = true;
-      SignedZeros = false;
-      TrappingMath = false;
-      // If fast-math is set then set the fp-contract mode to fast.
-      FPContract = "fast";
-      break;
-    case options::OPT_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;
-      // -fno_fast_math restores default denormal and fpcontract handling
-      DenormalFPMath = "";
-      FPContract = "";
-      break;
+    auto thisOption = option_to_floatOpt(A, OFastEnabled);
+    if (thisOption == fp_Count) 
+      // Arg wasn't a legal fp option, skip.
+      continue;
+    if (fpConflict[thisOpt] & fpEnabled) {
+      // This option conflicts with floating point options
+      // previously listed on the command line, this option will
+      // override the preivously listed enablements.
+      // FIXME: Issue warning diagnostic when fp-model or fp-exception-behavior
+      // options override or are overridden.
+      // FIXME: will need to use a different representation for conflict
+      // array which allow vector boolean operations
+      // FIXME may need to create a separate enablement vector which is
+      // different from the conflict vector.
+      fpEnabled &= !fpConflict[thisOpt];
     }
+    fpEnabled[thisOption] = true;
 
     // If we handled this option claim it
     A->claim();
   }
 
-  if (!HonorINFs)
-    CmdArgs.push_back("-menable-no-infs");
-
-  if (!HonorNaNs)
-    CmdArgs.push_back("-menable-no-nans");
-
-  if (MathErrno)
-    CmdArgs.push_back("-fmath-errno");
-
-  if (!MathErrno && AssociativeMath && ReciprocalMath && !SignedZeros &&
-      !TrappingMath)
-    CmdArgs.push_back("-menable-unsafe-fp-math");
-
-  if (!SignedZeros)
-    CmdArgs.push_back("-fno-signed-zeros");
-
-  if (AssociativeMath && !SignedZeros && !TrappingMath)
-    CmdArgs.push_back("-mreassociate");
-
-  if (ReciprocalMath)
-    CmdArgs.push_back("-freciprocal-math");
-
-  if (!TrappingMath)
-    CmdArgs.push_back("-fno-trapping-math");
-
-  if (!DenormalFPMath.empty())
-    CmdArgs.push_back(
-        Args.MakeArgString("-fdenormal-fp-math=" + DenormalFPMath));
-
-  if (!FPContract.empty())
-    CmdArgs.push_back(Args.MakeArgString("-ffp-contract=" + FPContract));
+  // Iterate through fpEnabled and print out the
+  // fp options that have been enabled
+  for (const auto O : floatOpt) {
+    if (thisOption == fp_Count) continue;
+    // FIXME dump this option setting via CmdArgs.push_back
+  }
 
   ParseMRecip(D, Args, CmdArgs);
 
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,68 @@
     CGM.getOpenMPRuntime().functionFinished(*this);
 }
 
+void CodeGenFunction::SetFPModel(void)
+{
+  auto fpModel = getLangOpts().getFPMOptions().getFPModelSetting();
+  auto fpExceptionBehavior =
+         getLangOpts().getFPMOptions().getFPExceptionBehaviorSetting();
+
+  // Translate the compiler options into
+  // the 3 settings that are transmitted to the IR Builder
+  bool IsConstrainedRounding = false;
+  bool IsConstrainedExcept = false;
+  llvm::ConstrainedFPIntrinsic::RoundingMode ConstrainedRoundingMD;
+  llvm::ConstrainedFPIntrinsic::ExceptionBehavior ConstrainedExceptMD =
+    llvm::ConstrainedFPIntrinsic::ebIgnore;
+
+  switch (fpModel) {
+  case LangOptions::FPM_Off:
+  case LangOptions::FPM_Precise:
+  case LangOptions::FPM_Fast:
+    break;
+  case LangOptions::FPM_Strict:
+    IsConstrainedRounding = true;
+    ConstrainedRoundingMD = llvm::ConstrainedFPIntrinsic::rmDynamic;
+    IsConstrainedExcept = true;
+    ConstrainedExceptMD = llvm::ConstrainedFPIntrinsic::ebStrict;
+    break;
+  default:
+    llvm_unreachable("Unsupported FP Model");
+  }
+
+  switch (fpExceptionBehavior) {
+  case LangOptions::FPE_Off:
+    break;
+  case LangOptions::FPE_Ignore:
+    IsConstrainedExcept = true;
+    ConstrainedExceptMD = llvm::ConstrainedFPIntrinsic::ebIgnore;
+    break;
+  case LangOptions::FPE_MayTrap:
+    IsConstrainedExcept = true;
+    ConstrainedExceptMD = llvm::ConstrainedFPIntrinsic::ebMayTrap;
+    break;
+  case LangOptions::FPE_Strict:
+    IsConstrainedExcept = true;
+    ConstrainedExceptMD = llvm::ConstrainedFPIntrinsic::ebStrict;
+    break;
+  default:
+    llvm_unreachable("Unsupported FP Exception Behavior");
+  }
+
+  if (IsConstrainedExcept && !IsConstrainedRounding) {
+    // If the rounding mode isn't set explicitly above, then use ebToNearest
+    // as the value when the constrained intrinsic is created
+    IsConstrainedRounding = true;
+    ConstrainedRoundingMD = llvm::ConstrainedFPIntrinsic::rmToNearest;
+  }
+
+  if (IsConstrainedExcept || IsConstrainedRounding) {
+    Builder.setIsFPConstrained(true);
+    Builder.setDefaultConstrainedRounding(ConstrainedRoundingMD);
+    Builder.setDefaultConstrainedExcept(ConstrainedExceptMD);
+  }
+}
+
 CharUnits CodeGenFunction::getNaturalPointeeTypeAlignment(QualType T,
                                                     LValueBaseInfo *BaseInfo,
                                                     TBAAAccessInfo *TBAAInfo) {
Index: clang/include/clang/Driver/Options.td
===================================================================
--- clang/include/clang/Driver/Options.td
+++ clang/include/clang/Driver/Options.td
@@ -915,6 +915,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 fp_model_EQ : Joined<["-"], "ffp-model=">, Group<f_Group>, Flags<[CC1Option]>,
+  HelpText<"Controls the semantics of floating-point calculations.">;
+def fp_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>;
@@ -1131,7 +1135,9 @@
 // This option was originally misspelt "infinites" [sic].
 def : Flag<["-"], "fhonor-infinites">, Alias<fhonor_infinities>;
 def : Flag<["-"], "fno-honor-infinites">, Alias<fno_honor_infinities>;
-def ftrapping_math : Flag<["-"], "ftrapping-math">, Group<f_Group>, Flags<[CC1Option]>;
+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 frounding_math : Flag<["-"], "frounding-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>,
   Flags<[CC1Option]>, HelpText<"Form fused FP ops (e.g. FMAs): fast (everywhere)"
Index: clang/include/clang/Basic/LangOptions.h
===================================================================
--- clang/include/clang/Basic/LangOptions.h
+++ clang/include/clang/Basic/LangOptions.h
@@ -184,6 +184,21 @@
     FEA_On
   };
 
+  enum FPModelKind {
+    // -fp-model option is not specified
+    FPM_Off,
+    FPM_Precise,
+    FPM_Strict,
+    FPM_Fast
+  };
+
+  enum FPExceptionBehaviorKind {
+   // -fp-exception-behavior option not specified
+   FPE_Off,
+   FPE_Ignore,
+   FPE_MayTrap,
+   FPE_Strict
+  };
 
 public:
   /// Set of enabled sanitizers.
@@ -307,6 +322,36 @@
 
   /// Return the OpenCL C or C++ version as a VersionTuple.
   VersionTuple getOpenCLVersionTuple() const;
+
+  /// Floating point model options
+  class FPModelOptions {
+  public:
+    FPModelOptions() : FPM(LangOptions::FPM_Off),
+                       FPE(LangOptions::FPE_Off) {}
+
+    LangOptions::FPModelKind getFPModelSetting() const {
+      return FPM;
+    }
+    void setFPModelSetting(LangOptions::FPModelKind Value) {FPM = Value;}
+
+    LangOptions::FPExceptionBehaviorKind getFPExceptionBehaviorSetting() const
+    {
+      return FPE;
+    }
+    void setFPExceptionBehaviorSetting(
+           LangOptions::FPExceptionBehaviorKind Value) {
+      FPE = Value;
+    }
+
+  private:
+    LangOptions::FPModelKind FPM = LangOptions::FPM_Off;
+    LangOptions::FPExceptionBehaviorKind FPE = LangOptions::FPE_Off;
+  };
+
+  FPModelOptions& getFPMOptions() { return fpm_options; }
+  FPModelOptions getFPMOptions() const { return fpm_options; }
+private:
+  FPModelOptions fpm_options;
 };
 
 /// Floating point control options
Index: clang/docs/UsersManual.rst
===================================================================
--- clang/docs/UsersManual.rst
+++ clang/docs/UsersManual.rst
@@ -1296,6 +1296,72 @@
    With the 'no-strict' option, Clang attempts to match the overflowing behavior
    of the target's native float-to-int conversion instructions.
 
+.. option:: -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,
+   The option ``-fno-rounding-math``, which is the default,
+   specifies the ``tonearest`` rounding mode.
+   The rounding mode ``dynamic`` informs the 
+   compiler that it must not assume any particular rounding mode
+   this is the setting implemented by the switch ``-frounding-math``.
+   ``-ffrounding-math`` has the same meaning as ``-ffp-model=strict``.
+   Consequently, this option sets exception behavior to strict and
+   it conflicts with ``-ffast-math`` etc.
+   FIXME: Not certain if ``-frounding-math`` should have identical semantics to
+   ``-ffp-model=strict``, or merely establish the rounding mode setting
+   parameter to the llvm floating point constrained intrinsics.
+
+.. option:: -ffp-model=<value>
+
+   Specify floating point behavior.  ``-ffp-model`` is an umbrella
+   option that encompasses functionality provided by lower level, single
+   purpose, clang fp options. Conflicts can exist between pairs of options
+   on the command line. If the ``-ffp-model`` or ``-ffp-exception-behavior``
+   conflict with other fp options on the command line, then some or all of
+   the earlier fp options will be disabled.  ``-ffast-math`` and any of its
+   lower-level floating point enablements conflict with ``-ffp-model=strict``,
+   and the same is true for ``-funsafe-math-optimizations`` and
+   ``-ffinite-math``.  If ``-ffp-model-strict`` appears on the command line,
+   then it behaves as though both ``-ffp-model-strict`` and ``-fno-fast-math``
+   appeared on the command line.  Since ``-ffp-model=strict`` implies
+  ``-ffp-exception-behavior=strict``, ``-ffp-model=strict`` also conflicts
+   with ``-ffp-exception-behavior=ignore`` and
+   ``-ffp-exception-behavior=maytrap``.  When ``-ffp-model`` appears on the
+   command line, it overrides any previous setting of ``-ffp-model``.
+   ``-ffp-model=fast`` is very similar to ``-ffast-math``: it also sets
+   the __FAST_MATH__ macro setting.  In addition to the FMF flags, this option
+   enables ``-fp-contract=fast``, and conflicts with: ``-fp-contract=on``,
+   ``-fp-contract=off``.
+
+   Valid values are: ``precise``, ``strict``, ``fast``.
+   Details:
+
+   * ``precise`` Disables optimizations that are not value-safe on floating-point data, although FP contraction (FMA) is enabled (``fp-contract=fast``).
+   * ``strict`` Enables precise and except, and disables contractions (FMA).
+   * ``fast`` Equivalent to -ffast-math
+
+.. 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.
+
+
+
 .. option:: -fwhole-program-vtables
 
    Enable whole-program vtable optimizations, such as single-implementation
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to