mibintc updated this revision to Diff 211770.
mibintc added a comment.
Herald added subscribers: hiraditya, mgorny.

The IRBuilder now has  been taught about constrained fadd and friends.  I 
simply updated my patches to work with the committed revision.  Note that this 
diff now contains what was formerly being reviewed separately in clang+llvm.  
Also let's discuss the new llvm file fpState.h. In this revision I didn't spend 
a lot of time pondering the best way to support this in the current world, i 
just made a simple update so it would build.

I could put the entire patch under clang and not create new files in llvm.  I 
think it would be an advantage to have the interpretation of the floating point 
command line switches occur in llvm itself. For one reason, because Intel plans 
to contribute the same options in the Fortran compiler as well as the clang 
compiler. This puts the switch logic into a single place.  Other languages may 
want to add support for the options too. Note, we also plan to implement inline 
pragma's for clang which allow the fp modes to be set for the duration of a 
code block.

I think it would be convenient to have an "unset" setting for the different 
constrained modes, otherwise you need a boolean that says "no value was 
provided for this option".  But i'm a frontend person so I may need to have my 
attitude adjusted.

When I was coding this before, I needed to pull out FPState.h from within 
IRBuilder because otherwise I needed to sprinkle additional include directives 
in many clang files, if it's pulled out like this to be more or less standalone 
then that problem resolved.


Repository:
  rL LLVM

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

https://reviews.llvm.org/D62731

Files:
  clang/include/clang/Basic/LangOptions.h
  clang/include/clang/Driver/CC1Options.td
  clang/include/clang/Driver/Options.td
  clang/lib/CodeGen/CodeGenFunction.cpp
  clang/lib/Driver/ToolChains/Clang.cpp
  clang/lib/Frontend/CompilerInvocation.cpp
  clang/test/Driver/clang_f_opts.c
  llvm/include/llvm/IR/FPState.h
  llvm/lib/IR/CMakeLists.txt
  llvm/lib/IR/FPState.cpp
  llvm/unittests/IR/IRBuilderTest.cpp

Index: llvm/unittests/IR/IRBuilderTest.cpp
===================================================================
--- llvm/unittests/IR/IRBuilderTest.cpp
+++ llvm/unittests/IR/IRBuilderTest.cpp
@@ -10,6 +10,7 @@
 #include "llvm/IR/BasicBlock.h"
 #include "llvm/IR/DIBuilder.h"
 #include "llvm/IR/DataLayout.h"
+#include "llvm/IR/FPState.h"
 #include "llvm/IR/Function.h"
 #include "llvm/IR/IntrinsicInst.h"
 #include "llvm/IR/LLVMContext.h"
@@ -195,6 +196,68 @@
   EXPECT_EQ(CII->getIntrinsicID(), Intrinsic::experimental_constrained_fadd);
   ASSERT_TRUE(CII->getExceptionBehavior() == ConstrainedFPIntrinsic::ebMayTrap);
   ASSERT_TRUE(CII->getRoundingMode() == ConstrainedFPIntrinsic::rmDownward);
+  //
+  // Use FPState to update the builder settings
+  FPState fpState(Builder);
+
+  fpState.updateBuilder(FPState::FPM_Off, FPState::FPME_Off, FPState::FPS_Off);
+  V = Builder.CreateFAdd(V, V);
+  ASSERT_TRUE(!isa<ConstrainedFPIntrinsic>(V));
+
+  fpState.updateBuilder(FPState::FPM_Precise, FPState::FPME_Off,
+                        FPState::FPS_Off);
+  V = Builder.CreateFAdd(V, V);
+  ASSERT_TRUE(!isa<ConstrainedFPIntrinsic>(V));
+
+  fpState.updateBuilder(FPState::FPM_Strict, FPState::FPME_Off,
+                        FPState::FPS_Off);
+  V = Builder.CreateFAdd(V, V);
+  CII = cast<ConstrainedFPIntrinsic>(V);
+  ASSERT_TRUE(isa<ConstrainedFPIntrinsic>(V));
+  ASSERT_TRUE(CII->getExceptionBehavior() == ConstrainedFPIntrinsic::ebStrict);
+  ASSERT_TRUE(CII->getRoundingMode() == ConstrainedFPIntrinsic::rmDynamic);
+
+  fpState.updateBuilder(FPState::FPM_Off, FPState::FPME_Except,
+                        FPState::FPS_Off);
+  V = Builder.CreateFAdd(V, V);
+  CII = cast<ConstrainedFPIntrinsic>(V);
+  ASSERT_TRUE(isa<ConstrainedFPIntrinsic>(V));
+  ASSERT_TRUE(CII->getExceptionBehavior() == ConstrainedFPIntrinsic::ebStrict);
+  ASSERT_TRUE(CII->getRoundingMode() == ConstrainedFPIntrinsic::rmToNearest);
+
+  fpState.updateBuilder(FPState::FPM_Off, FPState::FPME_NoExcept,
+                        FPState::FPS_Off);
+  V = Builder.CreateFAdd(V, V);
+  CII = cast<ConstrainedFPIntrinsic>(V);
+  ASSERT_TRUE(isa<ConstrainedFPIntrinsic>(V));
+  ASSERT_TRUE(CII->getExceptionBehavior() == ConstrainedFPIntrinsic::ebIgnore);
+  ASSERT_TRUE(CII->getRoundingMode() == ConstrainedFPIntrinsic::rmToNearest);
+
+  fpState.updateBuilder(FPState::FPM_Fast, FPState::FPME_Off, FPState::FPS_Off);
+  V = Builder.CreateFAdd(V, V);
+  ASSERT_TRUE(!isa<ConstrainedFPIntrinsic>(V));
+
+  fpState.updateBuilder(FPState::FPM_Off, FPState::FPME_Off, FPState::FPS_Fast);
+  V = Builder.CreateFAdd(V, V);
+  CII = cast<ConstrainedFPIntrinsic>(V);
+  ASSERT_TRUE(isa<ConstrainedFPIntrinsic>(V));
+  ASSERT_TRUE(CII->getExceptionBehavior() == ConstrainedFPIntrinsic::ebIgnore);
+  ASSERT_TRUE(CII->getRoundingMode() == ConstrainedFPIntrinsic::rmToNearest);
+
+  fpState.updateBuilder(FPState::FPM_Off, FPState::FPME_Off,
+                        FPState::FPS_Strict);
+  V = Builder.CreateFAdd(V, V);
+  CII = cast<ConstrainedFPIntrinsic>(V);
+  ASSERT_TRUE(isa<ConstrainedFPIntrinsic>(V));
+  ASSERT_TRUE(CII->getExceptionBehavior() == ConstrainedFPIntrinsic::ebStrict);
+  ASSERT_TRUE(CII->getRoundingMode() == ConstrainedFPIntrinsic::rmToNearest);
+
+  fpState.updateBuilder(FPState::FPM_Off, FPState::FPME_Off, FPState::FPS_Safe);
+  V = Builder.CreateFAdd(V, V);
+  CII = cast<ConstrainedFPIntrinsic>(V);
+  ASSERT_TRUE(isa<ConstrainedFPIntrinsic>(V));
+  ASSERT_TRUE(CII->getExceptionBehavior() == ConstrainedFPIntrinsic::ebMayTrap);
+  ASSERT_TRUE(CII->getRoundingMode() == ConstrainedFPIntrinsic::rmToNearest);
 
   Builder.CreateRetVoid();
   EXPECT_FALSE(verifyModule(*M));
Index: llvm/lib/IR/FPState.cpp
===================================================================
--- /dev/null
+++ llvm/lib/IR/FPState.cpp
@@ -0,0 +1,85 @@
+#include "llvm/IR/FPState.h"
+#include "llvm/IR/IRBuilder.h"
+
+namespace llvm {
+FPState::FPState(IRBuilderBase &B)
+    : Builder(B), FPM(FPM_Off), FPME(FPME_Off), FPS(FPS_Off) {}
+
+void FPState::updateBuilder(FPModelKind fpModel,
+                            FPModelExceptKind fpModelExcept,
+                            FPSpeculationKind fpSpeculation) {
+  // Save the new settings in the state variables.
+  FPM = fpModel;
+  FPME = fpModelExcept;
+  FPS = fpSpeculation;
+
+  // Translate the compiler options into
+  // the 3 settings that are transmitted to the IR Builder
+  bool IsConstrainedRounding = false;
+  bool IsConstrainedExcept = false;
+  ConstrainedFPIntrinsic::RoundingMode ConstrainedRoundingMD;
+  ConstrainedFPIntrinsic::ExceptionBehavior ConstrainedExceptMD;
+
+  switch (fpModel) {
+  case FPM_Off:
+  case FPM_Precise:
+  case FPM_Fast:
+    break;
+  case FPM_Strict:
+    IsConstrainedRounding = true;
+    ConstrainedRoundingMD = ConstrainedFPIntrinsic::rmDynamic;
+    IsConstrainedExcept = true;
+    ConstrainedExceptMD = ConstrainedFPIntrinsic::ebStrict;
+    break;
+  default:
+    llvm_unreachable("Unsupported FP Model");
+  }
+
+  switch (fpModelExcept) {
+  case FPME_Off:
+    break;
+  case FPME_Except:
+    IsConstrainedExcept = true;
+    ConstrainedExceptMD = ConstrainedFPIntrinsic::ebStrict;
+    break;
+  case FPME_NoExcept:
+    IsConstrainedExcept = true;
+    ConstrainedExceptMD = ConstrainedFPIntrinsic::ebIgnore;
+    break;
+  default:
+    llvm_unreachable("Unsupported FP Except Model");
+  }
+
+  switch (fpSpeculation) {
+  case FPS_Off:
+    break;
+  case FPS_Fast:
+    IsConstrainedExcept = true;
+    ConstrainedExceptMD = ConstrainedFPIntrinsic::ebIgnore;
+    break;
+  case FPS_Strict:
+    IsConstrainedExcept = true;
+    ConstrainedExceptMD = ConstrainedFPIntrinsic::ebStrict;
+    break;
+  case FPS_Safe:
+    IsConstrainedExcept = true;
+    ConstrainedExceptMD = ConstrainedFPIntrinsic::ebMayTrap;
+    break;
+  default:
+    llvm_unreachable("Unsupported FP Speculation");
+  }
+
+  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 = ConstrainedFPIntrinsic::rmToNearest;
+  }
+
+  Builder.setIsFPConstrained(IsConstrainedExcept || IsConstrainedRounding);
+  if (IsConstrainedExcept || IsConstrainedRounding) {
+    Builder.setDefaultConstrainedRounding(ConstrainedRoundingMD);
+    Builder.setDefaultConstrainedExcept(ConstrainedExceptMD);
+  }
+}
+} // end namespace llvm
Index: llvm/lib/IR/CMakeLists.txt
===================================================================
--- llvm/lib/IR/CMakeLists.txt
+++ llvm/lib/IR/CMakeLists.txt
@@ -22,6 +22,7 @@
   DiagnosticInfo.cpp
   DiagnosticPrinter.cpp
   Dominators.cpp
+  FPState.cpp
   Function.cpp
   GVMaterializer.cpp
   Globals.cpp
Index: llvm/include/llvm/IR/FPState.h
===================================================================
--- /dev/null
+++ llvm/include/llvm/IR/FPState.h
@@ -0,0 +1,39 @@
+#ifndef LLVM_FPSTATE_H
+#define LLVM_FPSTATE_H
+namespace llvm {
+
+class MDNode;
+class IRBuilderBase;
+class FPState {
+public:
+  enum FPModelKind { FPM_Off, FPM_Precise, FPM_Strict, FPM_Fast };
+
+  enum FPModelExceptKind { FPME_Off, FPME_Except, FPME_NoExcept };
+
+  enum FPSpeculationKind { FPS_Off, FPS_Fast, FPS_Strict, FPS_Safe };
+
+  enum ConstrainedExceptKind { CE_Off, CE_Strict, CE_Ignore, CE_MayTrap };
+  enum ConstrainedRoundingKind {
+    CR_Off,
+    CR_Dynamic,
+    CR_ToNearest,
+    CR_Downward,
+    CR_Upward,
+    CR_ToZero
+  };
+
+private:
+  IRBuilderBase &Builder;
+  FPModelKind FPM;
+  FPModelExceptKind FPME;
+  FPSpeculationKind FPS;
+
+public:
+  FPState(IRBuilderBase &B);
+  // function to update builder.
+  void updateBuilder(FPModelKind fpModel, FPModelExceptKind fpModelExcept,
+                     FPSpeculationKind fpSpeculation);
+};
+} // end namespace llvm
+
+#endif // LLVM_FPSTATE_H
Index: clang/test/Driver/clang_f_opts.c
===================================================================
--- clang/test/Driver/clang_f_opts.c
+++ clang/test/Driver/clang_f_opts.c
@@ -217,6 +217,11 @@
 // RUN: %clang -### -S -fexec-charset=iso-8859-1 -o /dev/null %s 2>&1 | FileCheck -check-prefix=CHECK-INVALID-INPUT-CHARSET %s
 // CHECK-INVALID-INPUT-CHARSET: error: invalid value 'iso-8859-1' in '-fexec-charset=iso-8859-1'
 
+// RUN: %clang -### -S -fp-model=fast -fp-model=except -o /dev/null %s 2>&1 | FileCheck -check-prefix=CHECK-INVALID-FAST-EXCEPT %s
+// RUN: %clang -### -S -fp-model=fast -fp-model=except -o /dev/null %s 2>&1 | FileCheck -check-prefix=CHECK-INVALID-FAST-EXCEPT %s
+// CHECK-INVALID-FAST-EXCEPT: error: invalid argument 'fp-model=fast' not allowed with 'fp-model=except'
+//
+
 // Test that we don't error on these.
 // RUN: %clang -### -S -Werror                                                \
 // RUN:     -falign-functions -falign-functions=2 -fno-align-functions        \
Index: clang/lib/Frontend/CompilerInvocation.cpp
===================================================================
--- clang/lib/Frontend/CompilerInvocation.cpp
+++ clang/lib/Frontend/CompilerInvocation.cpp
@@ -3043,6 +3043,59 @@
       Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Val;
   }
 
+  llvm::FPState::FPModelKind FPM = llvm::FPState::FPM_Off;
+  if (Arg *A = Args.getLastArg(OPT_fp_model_EQ)) {
+    StringRef Val = A->getValue();
+    if (Val == "precise")
+      FPM = llvm::FPState::FPM_Precise;
+    else if (Val == "strict")
+      FPM = llvm::FPState::FPM_Strict;
+    else if (Val == "fast")
+      FPM = llvm::FPState::FPM_Fast;
+    else
+      llvm_unreachable("invalid -fp-model setting");
+  }
+  Opts.setDefaultFPModel(FPM);
+
+  llvm::FPState::FPModelExceptKind FPME = llvm::FPState::FPME_Off;
+  if (const Arg *A =
+          Args.getLastArg(OPT_fp_model_except, OPT_no_fp_model_except))
+    switch (A->getOption().getID()) {
+    case OPT_fp_model_except:
+      FPME = llvm::FPState::FPME_Except;
+      break;
+    case OPT_no_fp_model_except:
+      FPME = llvm::FPState::FPME_NoExcept;
+      break;
+    default:
+      llvm_unreachable("invalid -fp-model-except setting");
+    }
+  Opts.setDefaultFPModelExcept(FPME);
+
+  llvm::FPState::FPSpeculationKind FPS = llvm::FPState::FPS_Off;
+  if (Arg *A = Args.getLastArg(OPT_fp_speculation_EQ)) {
+    StringRef Val = A->getValue();
+    if (Val == "fast")
+      FPS = llvm::FPState::FPS_Fast;
+    else if (Val == "strict")
+      FPS = llvm::FPState::FPS_Strict;
+    else if (Val == "safe")
+      FPS = llvm::FPState::FPS_Safe;
+    else
+      llvm_unreachable("invalid -fp-speculation setting");
+    Opts.setDefaultFPSpeculation(FPS);
+  }
+
+  if (FPM == llvm::FPState::FPM_Precise)
+    // This doesn't correspond to constrained fp, equivalent to -fp-contract=on
+    Opts.setDefaultFPContractMode(LangOptions::FPC_On);
+  else if (FPM == llvm::FPState::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);
 
@@ -3408,6 +3461,15 @@
     // FIXME: Should we really be calling this for an InputKind::Asm input?
     ParseLangArgs(LangOpts, Args, DashX, Res.getTargetOpts(),
                   Res.getPreprocessorOpts(), Diags);
+    auto fpm = LangOpts.getDefaultFPModel();
+    if (fpm == llvm::FPState::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
@@ -33,6 +33,7 @@
 #include "clang/Driver/XRayArgs.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/Config/llvm-config.h"
+#include "llvm/IR/FPState.h"
 #include "llvm/Option/ArgList.h"
 #include "llvm/Support/CodeGen.h"
 #include "llvm/Support/Compression.h"
@@ -2263,6 +2264,9 @@
   bool TrappingMath = true;
   StringRef DenormalFPMath = "";
   StringRef FPContract = "";
+  llvm::FPState::FPModelKind FPModel = llvm::FPState::FPM_Off;
+  llvm::FPState::FPModelExceptKind FPModelExcept = llvm::FPState::FPME_Off;
+  llvm::FPState::FPSpeculationKind FPSpeculation = llvm::FPState::FPS_Off;
 
   if (const Arg *A = Args.getLastArg(options::OPT_flimited_precision_EQ)) {
     CmdArgs.push_back("-mlimit-float-precision");
@@ -2273,6 +2277,39 @@
     switch (A->getOption().getID()) {
     // If this isn't an FP option skip the claim below
     default: continue;
+    // Options controlling floating point model and speculation
+    case options::OPT_fp_model_EQ: {
+      StringRef Val = A->getValue();
+      if (Val == "precise")
+        FPModel = llvm::FPState::FPM_Precise;
+      else if (Val == "strict")
+        FPModel = llvm::FPState::FPM_Strict;
+      else if (Val == "except")
+        FPModelExcept = llvm::FPState::FPME_Except;
+      else if (Val == "except-")
+        FPModelExcept = llvm::FPState::FPME_NoExcept;
+      else if (Val == "fast")
+        FPModel = llvm::FPState::FPM_Fast;
+      else {
+        D.Diag(diag::err_drv_invalid_value) << "-fp-model" << Val;
+        continue;
+      }
+      break;
+    }
+    case options::OPT_fp_speculation_EQ: {
+      StringRef Val = A->getValue();
+      if (Val == "fast")
+        FPSpeculation = llvm::FPState::FPS_Fast;
+      else if (Val == "strict")
+        FPSpeculation = llvm::FPState::FPS_Strict;
+      else if (Val == "safe")
+        FPSpeculation = llvm::FPState::FPS_Safe;
+      else {
+        D.Diag(diag::err_drv_invalid_value) << A->getAsString(Args) << Val;
+        continue;
+      }
+      break;
+    }
 
     // Options controlling individual features
     case options::OPT_fhonor_infinities:    HonorINFs = true;         break;
@@ -2366,6 +2403,56 @@
     A->claim();
   }
 
+  if ((FPModelExcept == llvm::FPState::FPME_Except) &&
+      (FPModel == llvm::FPState::FPM_Fast))
+    D.Diag(diag::err_drv_argument_not_allowed_with) << "fp-model=fast"
+                                                    << "fp-model=except";
+
+  switch (FPModel) {
+  case llvm::FPState::FPM_Precise:
+    CmdArgs.push_back("-fp-model=precise");
+    break;
+  case llvm::FPState::FPM_Strict:
+    CmdArgs.push_back("-fp-model=strict");
+    break;
+  case llvm::FPState::FPM_Fast:
+    CmdArgs.push_back("-fp-model=fast");
+    break;
+  case llvm::FPState::FPM_Off:
+    break;
+  default:
+    llvm_unreachable("Unrecognized FPModel");
+  }
+
+  switch (FPModelExcept) {
+  case llvm::FPState::FPME_Except:
+    CmdArgs.push_back("-fp-model-except");
+    break;
+  case llvm::FPState::FPME_NoExcept:
+    CmdArgs.push_back("-no-fpmodel-except-");
+    break;
+  case llvm::FPState::FPME_Off:
+    break;
+  default:
+    llvm_unreachable("Unrecognized FPModel");
+  }
+
+  switch (FPSpeculation) {
+  case llvm::FPState::FPS_Fast:
+    CmdArgs.push_back("-fp-speculation=fast");
+    break;
+  case llvm::FPState::FPS_Strict:
+    CmdArgs.push_back("-fp-speculation=strict");
+    break;
+  case llvm::FPState::FPS_Safe:
+    CmdArgs.push_back("-fp-speculation=safe");
+    break;
+  case llvm::FPState::FPS_Off:
+    break;
+  default:
+    llvm_unreachable("Unrecognized FPSpeculation");
+  }
+
   if (!HonorINFs)
     CmdArgs.push_back("-menable-no-infs");
 
Index: clang/lib/CodeGen/CodeGenFunction.cpp
===================================================================
--- clang/lib/CodeGen/CodeGenFunction.cpp
+++ clang/lib/CodeGen/CodeGenFunction.cpp
@@ -90,6 +90,11 @@
     FMF.setAllowReassoc();
   }
   Builder.setFastMathFlags(FMF);
+  llvm::FPState fpState(Builder);
+  auto fpModel = getLangOpts().getDefaultFPModel();
+  auto fpModelExcept = getLangOpts().getDefaultFPModelExcept();
+  auto fpSpeculation = getLangOpts().getDefaultFPSpeculation();
+  fpState.updateBuilder(fpModel, fpModelExcept, fpSpeculation);
 }
 
 CodeGenFunction::~CodeGenFunction() {
Index: clang/include/clang/Driver/Options.td
===================================================================
--- clang/include/clang/Driver/Options.td
+++ clang/include/clang/Driver/Options.td
@@ -910,6 +910,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<["-"], "fp-model=">, Group<f_Group>, Flags<[CC1Option]>,
+  HelpText<"Controls the semantics of floating-point calculations.">;
+def fp_speculation_EQ : Joined<["-"], "fp-speculation=">, Group<f_Group>, Flags<[CC1Option]>,
+  HelpText<"Specifies the mode in which to speculate on 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>;
Index: clang/include/clang/Driver/CC1Options.td
===================================================================
--- clang/include/clang/Driver/CC1Options.td
+++ clang/include/clang/Driver/CC1Options.td
@@ -781,6 +781,10 @@
   HelpText<"Use the native __fp16 type for arguments and returns (and skip ABI-specific lowering)">;
 def fallow_half_arguments_and_returns : Flag<["-"], "fallow-half-arguments-and-returns">,
   HelpText<"Allow function arguments and returns of type half">;
+def fp_model_except : Flag<["-"], "fp-model-except">,
+  HelpText<"Controls the constrained exception setting of floating-point calculations.">;
+def no_fp_model_except : Flag<["-"], "no-fp-model-except">,
+  HelpText<"Exceptions in floating-point calculations are ignored.">;
 def fdefault_calling_conv_EQ : Joined<["-"], "fdefault-calling-conv=">,
   HelpText<"Set default calling convention">, Values<"cdecl,fastcall,stdcall,vectorcall,regcall">;
 def finclude_default_header : Flag<["-"], "finclude-default-header">,
Index: clang/include/clang/Basic/LangOptions.h
===================================================================
--- clang/include/clang/Basic/LangOptions.h
+++ clang/include/clang/Basic/LangOptions.h
@@ -21,6 +21,7 @@
 #include "clang/Basic/Visibility.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/Triple.h"
+#include "llvm/IR/FPState.h"
 #include <string>
 #include <vector>
 
@@ -178,6 +179,29 @@
     FEA_On
   };
 
+  llvm::FPState::FPModelKind DefaultFPModel = llvm::FPState::FPM_Off;
+  llvm::FPState::FPModelKind getDefaultFPModel() const {
+    return DefaultFPModel;
+  }
+  void setDefaultFPModel(llvm::FPState::FPModelKind Value) {
+    DefaultFPModel = Value;
+  }
+  llvm::FPState::FPModelExceptKind DefaultFPModelExcept =
+      llvm::FPState::FPME_Off;
+  llvm::FPState::FPModelExceptKind getDefaultFPModelExcept() const {
+    return DefaultFPModelExcept;
+  }
+  void setDefaultFPModelExcept(llvm::FPState::FPModelExceptKind Value) {
+    DefaultFPModelExcept = Value;
+  }
+  llvm::FPState::FPSpeculationKind DefaultFPSpeculation =
+      llvm::FPState::FPS_Off;
+  llvm::FPState::FPSpeculationKind getDefaultFPSpeculation() const {
+    return DefaultFPSpeculation;
+  }
+  void setDefaultFPSpeculation(llvm::FPState::FPSpeculationKind Value) {
+    DefaultFPSpeculation = Value;
+  }
 
 public:
   /// Set of enabled sanitizers.
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to