[clang] 7f9b513 - Reapply af57dbf12e54 "Add support for options -frounding-math, ftrapping-math, -ffp-model=, and -ffp-exception-behavior="

Eric Christopher via cfe-commits cfe-commits at lists.llvm.org
Tue Dec 10 15:07:59 PST 2019


So you left some debugging code in that I've fixed thusly:

"Enclosing function uses fp intrinsics"

commit f4a7d5659df7cb56c1baa34a39e9fe2639472741
Author: Eric Christopher <echristo at gmail.com>
Date:   Tue Dec 10 15:02:29 2019 -0800

    Remove debugging printf and reformat code.

On Thu, Dec 5, 2019 at 3:48 AM Melanie Blower via cfe-commits <
cfe-commits at lists.llvm.org> wrote:

>
> Author: Melanie Blower
> Date: 2019-12-05T03:48:04-08:00
> New Revision: 7f9b5138470db1dc58f3bc05631284c653c9ed7a
>
> URL:
> https://github.com/llvm/llvm-project/commit/7f9b5138470db1dc58f3bc05631284c653c9ed7a
> DIFF:
> https://github.com/llvm/llvm-project/commit/7f9b5138470db1dc58f3bc05631284c653c9ed7a.diff
>
> LOG:         Reapply af57dbf12e54 "Add support for options
> -frounding-math, ftrapping-math, -ffp-model=, and -ffp-exception-behavior="
>
>         Patch was reverted because
> https://bugs.llvm.org/show_bug.cgi?id=44048
>         The original patch is modified to set the strictfp IR attribute
>         explicitly in CodeGen instead of as a side effect of IRBuilder.
>         In the 2nd attempt to reapply there was a windows lit test fail,
> the
>         tests were fixed to use wildcard matching.
>
>         Differential Revision: https://reviews.llvm.org/D62731
>
> Added:
>     clang/test/CodeGen/fpconstrained.c
>     clang/test/CodeGen/fpconstrained.cpp
>     clang/test/Driver/fp-model.c
>
> Modified:
>     clang/docs/UsersManual.rst
>     clang/include/clang/AST/Decl.h
>     clang/include/clang/AST/DeclBase.h
>     clang/include/clang/Basic/DiagnosticDriverKinds.td
>     clang/include/clang/Basic/DiagnosticGroups.td
>     clang/include/clang/Basic/LangOptions.def
>     clang/include/clang/Basic/LangOptions.h
>     clang/include/clang/Driver/Options.td
>     clang/lib/AST/Decl.cpp
>     clang/lib/CodeGen/CGCall.cpp
>     clang/lib/CodeGen/CodeGenFunction.cpp
>     clang/lib/CodeGen/CodeGenFunction.h
>     clang/lib/Driver/ToolChains/Clang.cpp
>     clang/lib/Frontend/CompilerInvocation.cpp
>     clang/lib/Sema/SemaExpr.cpp
>     clang/lib/Serialization/ASTReaderDecl.cpp
>     clang/lib/Serialization/ASTWriterDecl.cpp
>     clang/test/Driver/clang_f_opts.c
>     clang/test/Driver/fast-math.c
>     llvm/include/llvm/IR/IRBuilder.h
>     llvm/include/llvm/Target/TargetOptions.h
>     llvm/unittests/IR/IRBuilderTest.cpp
>
> Removed:
>
>
>
>
> ################################################################################
> diff  --git a/clang/docs/UsersManual.rst b/clang/docs/UsersManual.rst
> index 714681d7f4ce..62e2575c6b26 100644
> --- a/clang/docs/UsersManual.rst
> +++ b/clang/docs/UsersManual.rst
> @@ -1231,10 +1231,10 @@ are listed below.
>
>  **-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>
>
> @@ -1319,6 +1319,52 @@ are listed below.
>
>     Defaults to ``-fno-finite-math``.
>
> +.. _opt_frounding-math:
> +
> +**-f[no-]rounding-math**
> +
> +Force floating-point operations to honor the dynamically-set rounding
> mode by default.
> +
> +The result of a floating-point operation often cannot be exactly
> represented in the result type and therefore must be rounded.  IEEE 754
> describes
> diff erent rounding modes that control how to perform this rounding, not
> all of which are supported by all implementations.  C provides interfaces
> (``fesetround`` and ``fesetenv``) for dynamically controlling the rounding
> mode, and while it also recommends certain conventions for changing the
> rounding mode, these conventions are not typically enforced in the ABI.
> Since the rounding mode changes the numerical result of operations, the
> compiler must understand something about it in order to optimize floating
> point operations.
> +
> +Note that floating-point operations performed as part of constant
> initialization are formally performed prior to the start of the program and
> are therefore not subject to the current rounding mode.  This includes the
> initialization of global variables and local ``static`` variables.
> Floating-point operations in these contexts will be rounded using
> ``FE_TONEAREST``.
> +
> +- The option ``-fno-rounding-math`` allows the compiler to assume that
> the rounding mode is set to ``FE_TONEAREST``.  This is the default.
> +- The option ``-frounding-math`` forces the compiler to honor the
> dynamically-set rounding mode.  This prevents optimizations which might
> affect results if the rounding mode changes or is
> diff erent from the default; for example, it prevents floating-point
> operations from being reordered across most calls and prevents
> constant-folding when the result is not exactly representable.
> +
> +.. option:: -ffp-model=<value>
> +
> +   Specify floating point behavior. ``-ffp-model`` is an umbrella
> +   option that encompasses functionality provided by other, single
> +   purpose, 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 the 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
>
> diff  --git a/clang/include/clang/AST/Decl.h
> b/clang/include/clang/AST/Decl.h
> index c1544c9ded94..f4913540bab4 100644
> --- a/clang/include/clang/AST/Decl.h
> +++ b/clang/include/clang/AST/Decl.h
> @@ -2196,6 +2196,10 @@ class FunctionDecl : public DeclaratorDecl,
>    bool usesSEHTry() const { return FunctionDeclBits.UsesSEHTry; }
>    void setUsesSEHTry(bool UST) { FunctionDeclBits.UsesSEHTry = UST; }
>
> +  /// Indicates the function uses Floating Point constrained intrinsics
> +  bool usesFPIntrin() const { return FunctionDeclBits.UsesFPIntrin; }
> +  void setUsesFPIntrin(bool Val) { FunctionDeclBits.UsesFPIntrin = Val; }
> +
>    /// Whether this function has been deleted.
>    ///
>    /// A function that is "deleted" (via the C++0x "= delete" syntax)
>
> diff  --git a/clang/include/clang/AST/DeclBase.h
> b/clang/include/clang/AST/DeclBase.h
> index adea10b33188..54cdb84b6f33 100644
> --- a/clang/include/clang/AST/DeclBase.h
> +++ b/clang/include/clang/AST/DeclBase.h
> @@ -1534,10 +1534,13 @@ class DeclContext {
>
>      /// Store the ODRHash after first calculation.
>      uint64_t HasODRHash : 1;
> +
> +    /// Indicates if the function uses Floating Point Constrained
> Intrinsics
> +    uint64_t UsesFPIntrin : 1;
>    };
>
>    /// Number of non-inherited bits in FunctionDeclBitfields.
> -  enum { NumFunctionDeclBits = 25 };
> +  enum { NumFunctionDeclBits = 26 };
>
>    /// Stores the bits used by CXXConstructorDecl. If modified
>    /// NumCXXConstructorDeclBits and the accessor
> @@ -1554,7 +1557,7 @@ class DeclContext {
>      /// exactly 64 bits and thus the width of NumCtorInitializers
>      /// will need to be shrunk if some bit is added to
> NumDeclContextBitfields,
>      /// NumFunctionDeclBitfields or CXXConstructorDeclBitfields.
> -    uint64_t NumCtorInitializers : 23;
> +    uint64_t NumCtorInitializers : 22;
>      uint64_t IsInheritingConstructor : 1;
>
>      /// Whether this constructor has a trail-allocated explicit specifier.
>
> diff  --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td
> b/clang/include/clang/Basic/DiagnosticDriverKinds.td
> index 39242c972ea2..67faa872e57c 100644
> --- a/clang/include/clang/Basic/DiagnosticDriverKinds.td
> +++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td
> @@ -441,6 +441,10 @@ def warn_drv_experimental_isel_incomplete_opt :
> Warning<
>    "-fexperimental-isel support is incomplete for this architecture at the
> current optimization level">,
>    InGroup<ExperimentalISel>;
>
> +def warn_drv_experimental_fp_control_incomplete_opt : Warning<
> +  "Support for floating point control option %0 is incomplete and
> experimental">,
> +  InGroup<ExperimentalFloatControl>;
> +
>  def warn_drv_moutline_unsupported_opt : Warning<
>    "The '%0' architecture does not support -moutline; flag ignored">,
>    InGroup<OptionIgnored>;
>
> diff  --git a/clang/include/clang/Basic/DiagnosticGroups.td
> b/clang/include/clang/Basic/DiagnosticGroups.td
> index 478b217a19f6..dec293f45af7 100644
> --- a/clang/include/clang/Basic/DiagnosticGroups.td
> +++ b/clang/include/clang/Basic/DiagnosticGroups.td
> @@ -1109,6 +1109,9 @@ def SpirCompat : DiagGroup<"spir-compat">;
>  // Warning for the experimental-isel options.
>  def ExperimentalISel : DiagGroup<"experimental-isel">;
>
> +// Warning for the experimental float control options.
> +def ExperimentalFloatControl : DiagGroup<"experimental-float-control">;
> +
>  // A warning group specifically for warnings related to function
>  // multiversioning.
>  def FunctionMultiVersioning : DiagGroup<"function-multiversion">;
>
> diff  --git a/clang/include/clang/Basic/LangOptions.def
> b/clang/include/clang/Basic/LangOptions.def
> index 68d6ee1dce42..05d96b6c6a13 100644
> --- a/clang/include/clang/Basic/LangOptions.def
> +++ b/clang/include/clang/Basic/LangOptions.def
> @@ -255,6 +255,8 @@ LANGOPT(SinglePrecisionConstants , 1, 0, "treating
> double-precision floating poi
>  LANGOPT(FastRelaxedMath , 1, 0, "OpenCL fast relaxed math")
>  /// FP_CONTRACT mode (on/off/fast).
>  ENUM_LANGOPT(DefaultFPContractMode, FPContractModeKind, 2, FPC_Off, "FP
> contraction type")
> +ENUM_LANGOPT(FPRoundingMode, FPRoundingModeKind, 3, FPR_ToNearest, "FP
> Rounding Mode type")
> +ENUM_LANGOPT(FPExceptionMode, FPExceptionModeKind, 2, FPE_Ignore, "FP
> Exception Behavior Mode type")
>  LANGOPT(NoBitFieldTypeAlign , 1, 0, "bit-field type alignment")
>  LANGOPT(HexagonQdsp6Compat , 1, 0, "hexagon-qdsp6 backward compatibility")
>  LANGOPT(ObjCAutoRefCount , 1, 0, "Objective-C automated reference
> counting")
>
> diff  --git a/clang/include/clang/Basic/LangOptions.h
> b/clang/include/clang/Basic/LangOptions.h
> index 95628280a4a0..ae4a4b2b9e87 100644
> --- a/clang/include/clang/Basic/LangOptions.h
> +++ b/clang/include/clang/Basic/LangOptions.h
> @@ -190,6 +190,34 @@ class LangOptions : public LangOptionsBase {
>      FEA_On
>    };
>
> +  // Values of the following enumerations correspond to metadata arguments
> +  // specified for constrained floating-point intrinsics:
> +  //
> http://llvm.org/docs/LangRef.html#constrained-floating-point-intrinsics.
> +
> +  /// Possible rounding modes.
> +  enum FPRoundingModeKind {
> +    /// Rounding to nearest, corresponds to "round.tonearest".
> +    FPR_ToNearest,
> +    /// Rounding toward -Inf, corresponds to "round.downward".
> +    FPR_Downward,
> +    /// Rounding toward +Inf, corresponds to "round.upward".
> +    FPR_Upward,
> +    /// Rounding toward zero, corresponds to "round.towardzero".
> +    FPR_TowardZero,
> +    /// Is determined by runtime environment, corresponds to
> "round.dynamic".
> +    FPR_Dynamic
> +  };
> +
> +  /// Possible floating point exception behavior.
> +  enum FPExceptionModeKind {
> +    /// Assume that floating-point exceptions are masked.
> +    FPE_Ignore,
> +    /// Transformations do not cause new exceptions but may hide some.
> +    FPE_MayTrap,
> +    /// Strictly preserve the floating-point exception semantics.
> +    FPE_Strict
> +  };
> +
>    enum class LaxVectorConversionKind {
>      /// Permit no implicit vector bitcasts.
>      None,
>
> diff  --git a/clang/include/clang/Driver/Options.td
> b/clang/include/clang/Driver/Options.td
> index a64d0acb06fe..8965131b9001 100644
> --- a/clang/include/clang/Driver/Options.td
> +++ b/clang/include/clang/Driver/Options.td
> @@ -929,6 +929,10 @@ def : Flag<["-"], "fextended-identifiers">,
> Group<clang_ignored_f_Group>;
>  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>;
> @@ -1154,6 +1158,8 @@ def fno_honor_infinities : Flag<["-"],
> "fno-honor-infinities">, Group<f_Group>;
>  // 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>,
> @@ -3242,7 +3248,6 @@ defm profile_values :
> BooleanFFlag<"profile-values">, Group<clang_ignored_gcc_op
>  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>;
>
> diff  --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
> index bfcf7926861f..0301110b7067 100644
> --- a/clang/lib/AST/Decl.cpp
> +++ b/clang/lib/AST/Decl.cpp
> @@ -2793,6 +2793,7 @@ FunctionDecl::FunctionDecl(Kind DK, ASTContext &C,
> DeclContext *DC,
>    FunctionDeclBits.ConstexprKind = ConstexprKind;
>    FunctionDeclBits.InstantiationIsPending = false;
>    FunctionDeclBits.UsesSEHTry = false;
> +  FunctionDeclBits.UsesFPIntrin = false;
>    FunctionDeclBits.HasSkippedBody = false;
>    FunctionDeclBits.WillHaveBody = false;
>    FunctionDeclBits.IsMultiVersion = false;
>
> diff  --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
> index ca6b1d409c24..657c9260e6e6 100644
> --- a/clang/lib/CodeGen/CGCall.cpp
> +++ b/clang/lib/CodeGen/CGCall.cpp
> @@ -4336,6 +4336,13 @@ RValue CodeGenFunction::EmitCall(const
> CGFunctionInfo &CallInfo,
>                               Callee.getAbstractInfo(), Attrs, CallingConv,
>                               /*AttrOnCallSite=*/true);
>
> +  if (const FunctionDecl *FD =
> dyn_cast_or_null<FunctionDecl>(CurFuncDecl))
> +    if (FD->usesFPIntrin())
> +      // All calls within a strictfp function are marked strictfp
> +      Attrs =
> +        Attrs.addAttribute(getLLVMContext(),
> llvm::AttributeList::FunctionIndex,
> +                           llvm::Attribute::StrictFP);
> +
>    // Apply some call-site-specific attributes.
>    // TODO: work this into building the attribute set.
>
> @@ -4385,6 +4392,13 @@ RValue CodeGenFunction::EmitCall(const
> CGFunctionInfo &CallInfo,
>    SmallVector<llvm::OperandBundleDef, 1> BundleList =
>        getBundlesForFunclet(CalleePtr);
>
> +  if (const FunctionDecl *FD =
> dyn_cast_or_null<FunctionDecl>(CurFuncDecl))
> +    if (FD->usesFPIntrin())
> +      // All calls within a strictfp function are marked strictfp
> +      Attrs =
> +        Attrs.addAttribute(getLLVMContext(),
> llvm::AttributeList::FunctionIndex,
> +                           llvm::Attribute::StrictFP);
> +
>    // Emit the actual call/invoke instruction.
>    llvm::CallBase *CI;
>    if (!InvokeDest) {
>
> diff  --git a/clang/lib/CodeGen/CodeGenFunction.cpp
> b/clang/lib/CodeGen/CodeGenFunction.cpp
> index 7f3be896a7b9..fd3020835a4d 100644
> --- a/clang/lib/CodeGen/CodeGenFunction.cpp
> +++ b/clang/lib/CodeGen/CodeGenFunction.cpp
> @@ -33,6 +33,8 @@
>  #include "clang/Frontend/FrontendDiagnostic.h"
>  #include "llvm/IR/DataLayout.h"
>  #include "llvm/IR/Dominators.h"
> +#include "llvm/IR/FPEnv.h"
> +#include "llvm/IR/IntrinsicInst.h"
>  #include "llvm/IR/Intrinsics.h"
>  #include "llvm/IR/MDBuilder.h"
>  #include "llvm/IR/Operator.h"
> @@ -87,6 +89,7 @@ CodeGenFunction::CodeGenFunction(CodeGenModule &cgm,
> bool suppressNewContext)
>      FMF.setAllowReassoc();
>    }
>    Builder.setFastMathFlags(FMF);
> +  SetFPModel();
>  }
>
>  CodeGenFunction::~CodeGenFunction() {
> @@ -102,6 +105,51 @@ CodeGenFunction::~CodeGenFunction() {
>      CGM.getOpenMPRuntime().functionFinished(*this);
>  }
>
> +// Map the LangOption for rounding mode into
> +// the corresponding enum in the IR.
> +static llvm::fp::RoundingMode ToConstrainedRoundingMD(
> +  LangOptions::FPRoundingModeKind Kind) {
> +
> +  switch (Kind) {
> +  case LangOptions::FPR_ToNearest:  return llvm::fp::rmToNearest;
> +  case LangOptions::FPR_Downward:   return llvm::fp::rmDownward;
> +  case LangOptions::FPR_Upward:     return llvm::fp::rmUpward;
> +  case LangOptions::FPR_TowardZero: return llvm::fp::rmTowardZero;
> +  case LangOptions::FPR_Dynamic:    return llvm::fp::rmDynamic;
> +  }
> +  llvm_unreachable("Unsupported FP RoundingMode");
> +}
> +
> +// Map the LangOption for exception behavior into
> +// the corresponding enum in the IR.
> +static llvm::fp::ExceptionBehavior ToConstrainedExceptMD(
> +  LangOptions::FPExceptionModeKind Kind) {
> +
> +  switch (Kind) {
> +  case LangOptions::FPE_Ignore:  return llvm::fp::ebIgnore;
> +  case LangOptions::FPE_MayTrap: return llvm::fp::ebMayTrap;
> +  case LangOptions::FPE_Strict:  return llvm::fp::ebStrict;
> +  }
> +  llvm_unreachable("Unsupported FP Exception Behavior");
> +}
> +
> +void CodeGenFunction::SetFPModel() {
> +  auto fpRoundingMode = ToConstrainedRoundingMD(
> +                          getLangOpts().getFPRoundingMode());
> +  auto fpExceptionBehavior = ToConstrainedExceptMD(
> +                               getLangOpts().getFPExceptionMode());
> +
> +  if (fpExceptionBehavior == llvm::fp::ebIgnore &&
> +      fpRoundingMode == llvm::fp::rmToNearest)
> +    // Constrained intrinsics are not used.
> +    ;
> +  else {
> +    Builder.setIsFPConstrained(true);
> +    Builder.setDefaultConstrainedRounding(fpRoundingMode);
> +    Builder.setDefaultConstrainedExcept(fpExceptionBehavior);
> +  }
> +}
> +
>  CharUnits CodeGenFunction::getNaturalPointeeTypeAlignment(QualType T,
>                                                      LValueBaseInfo
> *BaseInfo,
>                                                      TBAAAccessInfo
> *TBAAInfo) {
> @@ -823,6 +871,10 @@ void CodeGenFunction::StartFunction(GlobalDecl GD,
> QualType RetTy,
>        if (FD->isMain())
>          Fn->addFnAttr(llvm::Attribute::NoRecurse);
>
> +  if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D))
> +    if (FD->usesFPIntrin())
> +      Fn->addFnAttr(llvm::Attribute::StrictFP);
> +
>    // If a custom alignment is used, force realigning to this alignment on
>    // any main function which certainly will need it.
>    if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D))
>
> diff  --git a/clang/lib/CodeGen/CodeGenFunction.h
> b/clang/lib/CodeGen/CodeGenFunction.h
> index 7a2627ccf58b..8f99b090b818 100644
> --- a/clang/lib/CodeGen/CodeGenFunction.h
> +++ b/clang/lib/CodeGen/CodeGenFunction.h
> @@ -4169,6 +4169,9 @@ class CodeGenFunction : public CodeGenTypeCache {
>    /// 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();
> +
>  private:
>    llvm::MDNode *getRangeForLoadFromType(QualType Ty);
>    void EmitReturnOfRValue(RValue RV, QualType Ty);
>
> diff  --git a/clang/lib/Driver/ToolChains/Clang.cpp
> b/clang/lib/Driver/ToolChains/Clang.cpp
> index 03a6de812047..5f8c0cb8a2c1 100644
> --- a/clang/lib/Driver/ToolChains/Clang.cpp
> +++ b/clang/lib/Driver/ToolChains/Clang.cpp
> @@ -2302,9 +2302,18 @@ static void RenderFloatingPointOptions(const
> ToolChain &TC, const Driver &D,
>    bool AssociativeMath = false;
>    bool ReciprocalMath = false;
>    bool SignedZeros = true;
> -  bool TrappingMath = true;
> +  bool TrappingMath = false; // Implemented via -ffp-exception-behavior
> +  bool TrappingMathPresent = false; // Is trapping-math in args, and not
> +                                    // overriden by
> ffp-exception-behavior?
> +  bool RoundingFPMath = false;
> +  bool RoundingMathPresent = false; // Is rounding-math in args?
> +  // -ffp-model values: strict, fast, precise
> +  StringRef FPModel = "";
> +  // -ffp-exception-behavior options: strict, maytrap, ignore
> +  StringRef FPExceptionBehavior = "";
>    StringRef DenormalFPMath = "";
>    StringRef FPContract = "";
> +  bool StrictFPModel = false;
>
>    if (const Arg *A = Args.getLastArg(options::OPT_flimited_precision_EQ))
> {
>      CmdArgs.push_back("-mlimit-float-precision");
> @@ -2312,7 +2321,73 @@ static void RenderFloatingPointOptions(const
> ToolChain &TC, const Driver &D,
>    }
>
>    for (const Arg *A : Args) {
> -    switch (A->getOption().getID()) {
> +    auto optID = A->getOption().getID();
> +    bool PreciseFPModel = false;
> +    switch (optID) {
> +    default:
> +      break;
> +    case options::OPT_frounding_math:
> +    case options::OPT_ftrapping_math:
> +    case options::OPT_ffp_exception_behavior_EQ:
> +      D.Diag(clang::diag::warn_drv_experimental_fp_control_incomplete_opt)
> +          << A->getOption().getName();
> +      break;
> +    case options::OPT_ffp_model_EQ: {
> +      D.Diag(clang::diag::warn_drv_experimental_fp_control_incomplete_opt)
> +          << A->getOption().getName();
> +      // If -ffp-model= is seen, reset to fno-fast-math
> +      HonorINFs = true;
> +      HonorNaNs = true;
> +      // Turning *off* -ffast-math restores the toolchain default.
> +      MathErrno = TC.IsMathErrnoDefault();
> +      AssociativeMath = false;
> +      ReciprocalMath = false;
> +      SignedZeros = true;
> +      // -fno_fast_math restores default denormal and fpcontract handling
> +      DenormalFPMath = "";
> +      FPContract = "";
> +      StringRef Val = A->getValue();
> +      if (OFastEnabled && !Val.equals("fast")) {
> +          // Only -ffp-model=fast is compatible with OFast, ignore.
> +        D.Diag(clang::diag::warn_drv_overriding_flag_option)
> +          << Args.MakeArgString("-ffp-model=" + Val)
> +          << "-Ofast";
> +        break;
> +      }
> +      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.
> +      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")) {
> +        optID = options::OPT_ffast_math;
> +        FPModel = Val;
> +        FPContract = "fast";
> +      } else if (Val.equals("precise")) {
> +        optID = options::OPT_ffp_contract;
> +        FPModel = Val;
> +        FPContract = "fast";
> +        PreciseFPModel = true;
> +      } else if (Val.equals("strict")) {
> +        StrictFPModel = true;
> +        optID = options::OPT_frounding_math;
> +        FPExceptionBehavior = "strict";
> +        FPModel = Val;
> +        TrappingMath = true;
> +      } 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;
>
> @@ -2329,19 +2404,82 @@ static void RenderFloatingPointOptions(const
> ToolChain &TC, const Driver &D,
>      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_ftrapping_math:
> +      if (!TrappingMathPresent && !FPExceptionBehavior.empty() &&
> +          !FPExceptionBehavior.equals("strict"))
> +        // Warn that previous value of option is overridden.
> +        D.Diag(clang::diag::warn_drv_overriding_flag_option)
> +          << Args.MakeArgString("-ffp-exception-behavior=" +
> FPExceptionBehavior)
> +          << "-ftrapping-math";
> +      TrappingMath = true;
> +      TrappingMathPresent = true;
> +      FPExceptionBehavior = "strict";
> +      break;
> +    case options::OPT_fno_trapping_math:
> +      if (!TrappingMathPresent && !FPExceptionBehavior.empty() &&
> +          !FPExceptionBehavior.equals("ignore"))
> +        // Warn that previous value of option is overridden.
> +        D.Diag(clang::diag::warn_drv_overriding_flag_option)
> +          << Args.MakeArgString("-ffp-exception-behavior=" +
> FPExceptionBehavior)
> +          << "-fno-trapping-math";
> +      TrappingMath = false;
> +      TrappingMathPresent = true;
> +      FPExceptionBehavior = "ignore";
> +      break;
> +
> +    case options::OPT_frounding_math:
> +      RoundingFPMath = true;
> +      RoundingMathPresent = true;
> +      break;
> +
> +    case options::OPT_fno_rounding_math:
> +      RoundingFPMath = false;
> +      RoundingMathPresent = false;
> +      break;
>
>      case options::OPT_fdenormal_fp_math_EQ:
>        DenormalFPMath = A->getValue();
>        break;
>
> -    // Validate and pass through -fp-contract option.
> +    // Validate and pass through -ffp-contract option.
>      case options::OPT_ffp_contract: {
>        StringRef Val = A->getValue();
> -      if (Val == "fast" || Val == "on" || Val == "off")
> +      if (PreciseFPModel) {
> +        // -ffp-model=precise enables ffp-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 (!TrappingMathPresent && !FPExceptionBehavior.empty() &&
> +          !FPExceptionBehavior.equals(Val))
> +        // 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);
> +      TrappingMath = TrappingMathPresent = false;
> +      if (Val.equals("ignore") || Val.equals("maytrap"))
> +        FPExceptionBehavior = Val;
> +      else if (Val.equals("strict")) {
> +        FPExceptionBehavior = Val;
> +        TrappingMath = TrappingMathPresent = true;
> +      } else
>          D.Diag(diag::err_drv_unsupported_option_argument)
>              << A->getOption().getName() << Val;
>        break;
> @@ -2361,12 +2499,14 @@ static void RenderFloatingPointOptions(const
> ToolChain &TC, const Driver &D,
>        ReciprocalMath = true;
>        SignedZeros = false;
>        TrappingMath = false;
> +      FPExceptionBehavior = "";
>        break;
>      case options::OPT_fno_unsafe_math_optimizations:
>        AssociativeMath = false;
>        ReciprocalMath = false;
>        SignedZeros = true;
>        TrappingMath = true;
> +      FPExceptionBehavior = "strict";
>        // -fno_unsafe_math_optimizations restores default denormal handling
>        DenormalFPMath = "";
>        break;
> @@ -2384,6 +2524,7 @@ static void RenderFloatingPointOptions(const
> ToolChain &TC, const Driver &D,
>        ReciprocalMath = true;
>        SignedZeros = false;
>        TrappingMath = false;
> +      RoundingFPMath = false;
>        // If fast-math is set then set the fp-contract mode to fast.
>        FPContract = "fast";
>        break;
> @@ -2397,12 +2538,31 @@ static void RenderFloatingPointOptions(const
> ToolChain &TC, const Driver &D,
>        AssociativeMath = false;
>        ReciprocalMath = false;
>        SignedZeros = true;
> -      TrappingMath = true;
> +      TrappingMath = false;
> +      RoundingFPMath = false;
>        // -fno_fast_math restores default denormal and fpcontract handling
>        DenormalFPMath = "";
>        FPContract = "";
>        break;
>      }
> +    if (StrictFPModel) {
> +      // If -ffp-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 -ffp-model=strict
> +        ;
> +      else {
> +        StrictFPModel = false;
> +        FPModel = "";
> +        D.Diag(clang::diag::warn_drv_overriding_flag_option)
> +            << "-ffp-model=strict" <<
> +            ((A->getNumValues() == 0) ?  A->getSpelling()
> +            : Args.MakeArgString(A->getSpelling() + A->getValue()));
> +      }
> +    }
>
>      // If we handled this option claim it
>      A->claim();
> @@ -2430,7 +2590,11 @@ static void RenderFloatingPointOptions(const
> ToolChain &TC, const Driver &D,
>    if (ReciprocalMath)
>      CmdArgs.push_back("-freciprocal-math");
>
> -  if (!TrappingMath)
> +  if (TrappingMath) {
> +    // FP Exception Behavior is also set to strict
> +    assert(FPExceptionBehavior.equals("strict"));
> +    CmdArgs.push_back("-ftrapping-math");
> +  } else if (TrappingMathPresent)
>      CmdArgs.push_back("-fno-trapping-math");
>
>    if (!DenormalFPMath.empty())
> @@ -2440,14 +2604,37 @@ static void RenderFloatingPointOptions(const
> ToolChain &TC, const Driver &D,
>    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 -ffp-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)
>
> diff  --git a/clang/lib/Frontend/CompilerInvocation.cpp
> b/clang/lib/Frontend/CompilerInvocation.cpp
> index 74831e78d8cb..198ae69b7655 100644
> --- a/clang/lib/Frontend/CompilerInvocation.cpp
> +++ b/clang/lib/Frontend/CompilerInvocation.cpp
> @@ -3145,6 +3145,34 @@ static void ParseLangArgs(LangOptions &Opts,
> ArgList &Args, InputKind IK,
>        Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args)
> << Val;
>    }
>
> +  LangOptions::FPRoundingModeKind FPRM = LangOptions::FPR_ToNearest;
> +  if (Args.hasArg(OPT_frounding_math)) {
> +    FPRM = LangOptions::FPR_Dynamic;
> +  }
> +  Opts.setFPRoundingMode(FPRM);
> +
> +  if (Args.hasArg(OPT_ftrapping_math)) {
> +    Opts.setFPExceptionMode(LangOptions::FPE_Strict);
> +  }
> +
> +  if (Args.hasArg(OPT_fno_trapping_math)) {
> +    Opts.setFPExceptionMode(LangOptions::FPE_Ignore);
> +  }
> +
> +  LangOptions::FPExceptionModeKind FPEB = LangOptions::FPE_Ignore;
> +  if (Arg *A = Args.getLastArg(OPT_ffp_exception_behavior_EQ)) {
> +    StringRef Val = A->getValue();
> +    if (Val.equals("ignore"))
> +      FPEB = LangOptions::FPE_Ignore;
> +    else if (Val.equals("maytrap"))
> +      FPEB = LangOptions::FPE_MayTrap;
> +    else if (Val.equals("strict"))
> +      FPEB = LangOptions::FPE_Strict;
> +    else
> +      Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args)
> << Val;
> +  }
> +  Opts.setFPExceptionMode(FPEB);
> +
>    Opts.RetainCommentsFromSystemHeaders =
>        Args.hasArg(OPT_fretain_comments_from_system_headers);
>
>
> diff  --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
> index 7bbda127a540..c53a4b789bed 100644
> --- a/clang/lib/Sema/SemaExpr.cpp
> +++ b/clang/lib/Sema/SemaExpr.cpp
> @@ -13037,6 +13037,16 @@ ExprResult
> Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
>    if (ResultTy.isNull() || LHS.isInvalid() || RHS.isInvalid())
>      return ExprError();
>
> +  if (ResultTy->isRealFloatingType() &&
> +      (getLangOpts().getFPRoundingMode() != LangOptions::FPR_ToNearest ||
> +       getLangOpts().getFPExceptionMode() != LangOptions::FPE_Ignore))
> +    // Mark the current function as usng floating point constrained
> intrinsics
> +    if (FunctionDecl *F = dyn_cast<FunctionDecl>(CurContext))
> +{
> +      F->setUsesFPIntrin(true);
> +      printf("Enclosing function uses fp intrinsics\n");
> +}
> +
>    // Some of the binary operations require promoting operands of half
> vector to
>    // float vectors and truncating the result back to half vector. For
> now, we do
>    // this only when HalfArgsAndReturn is set (that is, when the target is
> arm or
>
> diff  --git a/clang/lib/Serialization/ASTReaderDecl.cpp
> b/clang/lib/Serialization/ASTReaderDecl.cpp
> index 3f7a1ed7fd5c..d989f46c4ab4 100644
> --- a/clang/lib/Serialization/ASTReaderDecl.cpp
> +++ b/clang/lib/Serialization/ASTReaderDecl.cpp
> @@ -886,6 +886,7 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl
> *FD) {
>
>    FD->ODRHash = Record.readInt();
>    FD->setHasODRHash(true);
> +  FD->setUsesFPIntrin(Record.readInt());
>
>    switch ((FunctionDecl::TemplatedKind)Record.readInt()) {
>    case FunctionDecl::TK_NonTemplate:
>
> diff  --git a/clang/lib/Serialization/ASTWriterDecl.cpp
> b/clang/lib/Serialization/ASTWriterDecl.cpp
> index 51902a607ca1..38eb64e52e4a 100644
> --- a/clang/lib/Serialization/ASTWriterDecl.cpp
> +++ b/clang/lib/Serialization/ASTWriterDecl.cpp
> @@ -559,6 +559,7 @@ void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D)
> {
>    Record.AddSourceLocation(D->getEndLoc());
>
>    Record.push_back(D->getODRHash());
> +  Record.push_back(D->usesFPIntrin());
>
>    Record.push_back(D->getTemplatedKind());
>    switch (D->getTemplatedKind()) {
>
> diff  --git a/clang/test/CodeGen/fpconstrained.c
> b/clang/test/CodeGen/fpconstrained.c
> new file mode 100644
> index 000000000000..0a890e2e702e
> --- /dev/null
> +++ b/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() {
> +  // CHECK-LABEL: define {{.*}}void @foo()
> +
> +  // MAYTRAP: llvm.experimental.constrained.fadd.f32(float %{{.*}}, float
> %{{.*}}, metadata !"round.tonearest", metadata !"fpexcept.maytrap")
> +  // EXCEPT: llvm.experimental.constrained.fadd.f32(float %{{.*}}, float
> %{{.*}}, metadata !"round.tonearest", metadata !"fpexcept.strict")
> +  // FPMODELSTRICT: llvm.experimental.constrained.fadd.f32(float %{{.*}},
> float %{{.*}}, metadata !"round.dynamic", metadata !"fpexcept.strict")
> +  // STRICTEXCEPT: llvm.experimental.constrained.fadd.f32(float %{{.*}},
> float %{{.*}}, metadata !"round.dynamic", metadata !"fpexcept.strict")
> +  // STRICTNOEXCEPT: llvm.experimental.constrained.fadd.f32(float
> %{{.*}}, float %{{.*}}, metadata !"round.dynamic", metadata
> !"fpexcept.ignore")
> +  // PRECISE: fadd contract float %{{.*}}, %{{.*}}
> +  // FAST: fadd fast
> +  f0 = f1 + f2;
> +
> +  // CHECK: ret
> +}
>
> diff  --git a/clang/test/CodeGen/fpconstrained.cpp
> b/clang/test/CodeGen/fpconstrained.cpp
> new file mode 100644
> index 000000000000..7aa34c98a487
> --- /dev/null
> +++ b/clang/test/CodeGen/fpconstrained.cpp
> @@ -0,0 +1,47 @@
> +// RUN: %clang_cc1 -x c++ -ftrapping-math -fexceptions -fcxx-exceptions
> -frounding-math -ffp-exception-behavior=strict -emit-llvm -o - %s |
> FileCheck %s -check-prefix=FPMODELSTRICT
> +// RUN: %clang_cc1 -x c++ -ffp-contract=fast -fexceptions
> -fcxx-exceptions -emit-llvm -o - %s | FileCheck %s -check-prefix=PRECISE
> +// RUN: %clang_cc1 -x c++ -ffast-math -fexceptions -fcxx-exceptions
> -ffp-contract=fast -emit-llvm -o - %s | FileCheck %s -check-prefix=FAST
> +// RUN: %clang_cc1 -x c++ -ffast-math -fexceptions -fcxx-exceptions
> -emit-llvm -o - %s | FileCheck %s -check-prefix=FAST
> +// RUN: %clang_cc1 -x c++ -ffast-math -fexceptions -fcxx-exceptions
> -ffp-contract=fast -ffp-exception-behavior=ignore -emit-llvm -o - %s |
> FileCheck %s -check-prefix=FAST
> +// RUN: %clang_cc1 -x c++ -ffast-math -fexceptions -fcxx-exceptions
> -ffp-contract=fast -ffp-exception-behavior=strict -emit-llvm -o - %s |
> FileCheck %s -check-prefix=EXCEPT
> +// RUN: %clang_cc1 -x c++ -ffast-math -fexceptions -fcxx-exceptions
> -ffp-contract=fast -ffp-exception-behavior=maytrap -emit-llvm -o - %s |
> FileCheck %s -check-prefix=MAYTRAP
> +float f0, f1, f2;
> +
> +  template <class>
> +  class aaaa {
> +   public:
> +    ~aaaa();
> +    void b();
> +  };
> +
> +  template <class c>
> +  aaaa<c>::~aaaa() { try {
> +    b();
> +  // CHECK-LABEL: define {{.*}}void @_ZN4aaaaIiED2Ev{{.*}}
> +
> +  } catch (...) {
> +  // MAYTRAP: llvm.experimental.constrained.fadd.f32(float %{{.*}}, float
> %{{.*}}, metadata !"round.tonearest", metadata !"fpexcept.maytrap")
> +  // EXCEPT: llvm.experimental.constrained.fadd.f32(float %{{.*}}, float
> %{{.*}}, metadata !"round.tonearest", metadata !"fpexcept.strict")
> +  // FPMODELSTRICT: llvm.experimental.constrained.fadd.f32(float %{{.*}},
> float %{{.*}}, metadata !"round.dynamic", metadata !"fpexcept.strict")
> +  // STRICTEXCEPT: llvm.experimental.constrained.fadd.f32(float %{{.*}},
> float %{{.*}}, metadata !"round.dynamic", metadata !"fpexcept.strict")
> +  // STRICTNOEXCEPT: llvm.experimental.constrained.fadd.f32(float
> %{{.*}}, float %{{.*}}, metadata !"round.dynamic", metadata
> !"fpexcept.ignore")
> +  // PRECISE: fadd contract float %{{.*}}, %{{.*}}
> +  // FAST: fadd fast
> +  f0 = f1 + f2;
> +
> +  // CHECK: ret void
> +  }
> +  }
> +
> +  class d {
> +   public:
> +    d(const char *, int);
> +    aaaa<int> e;
> +  };
> +
> +float foo() {
> +  d x("", 1);
> +  aaaa<int> a;
> +  return f0;
> +}
> +
>
> diff  --git a/clang/test/Driver/clang_f_opts.c
> b/clang/test/Driver/clang_f_opts.c
> index 17feaab26ab7..fef9cbfb115e 100644
> --- a/clang/test/Driver/clang_f_opts.c
> +++ b/clang/test/Driver/clang_f_opts.c
> @@ -198,6 +198,22 @@
>  // CHECK-EXTENDED-IDENTIFIERS-NOT: "-fextended-identifiers"
>  // CHECK-NO-EXTENDED-IDENTIFIERS: error: unsupported option
> '-fno-extended-identifiers'
>
> +// RUN: %clang -### -S -frounding-math %s 2>&1 | FileCheck
> -check-prefix=CHECK-ROUNDING-MATH %s
> +// CHECK-ROUNDING-MATH: "-cc1"
> +// CHECK-ROUNDING-MATH: "-frounding-math"
> +// CHECK-ROUNDING-MATH-NOT: "-fno-rounding-math"
> +// RUN: %clang -### -S %s 2>&1 | FileCheck
> -check-prefix=CHECK-ROUNDING-MATH-NOT %s
> +// RUN: %clang -### -S -ffp-model=imprecise %s 2>&1 | FileCheck
> -check-prefix=CHECK-FPMODEL %s
> +// CHECK-FPMODEL: unsupported argument 'imprecise' to option 'ffp-model='
> +// RUN: %clang -### -S -ffp-model=precise %s 2>&1 | FileCheck
> -check-prefix=IGNORE %s
> +// RUN: %clang -### -S -ffp-model=strict %s 2>&1 | FileCheck
> -check-prefix=IGNORE %s
> +// RUN: %clang -### -S -ffp-model=fast %s 2>&1 | FileCheck
> -check-prefix=IGNORE %s
> +// RUN: %clang -### -S -ffp-exception-behavior=trap %s 2>&1 | FileCheck
> -check-prefix=CHECK-FPEB %s
> +// CHECK-FPEB: unsupported argument 'trap' to option
> 'ffp-exception-behavior='
> +// RUN: %clang -### -S -ffp-exception-behavior=maytrap %s 2>&1 |
> FileCheck -check-prefix=IGNORE %s
> +// RUN: %clang -### -S -ffp-exception-behavior=ignore %s 2>&1 | FileCheck
> -check-prefix=IGNORE %s
> +// RUN: %clang -### -S -ffp-exception-behavior=strict %s 2>&1 | FileCheck
> -check-prefix=IGNORE %s
> +
>  // RUN: %clang -### -S -fno-pascal-strings -mpascal-strings %s 2>&1 |
> FileCheck -check-prefix=CHECK-M-PASCAL-STRINGS %s
>  // CHECK-M-PASCAL-STRINGS: "-fpascal-strings"
>
> @@ -320,7 +336,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 +400,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
>
> diff  --git a/clang/test/Driver/fast-math.c b/clang/test/Driver/fast-math.c
> index 916384216d8c..da47de260dc9 100644
> --- a/clang/test/Driver/fast-math.c
> +++ b/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"
>
> diff  --git a/clang/test/Driver/fp-model.c b/clang/test/Driver/fp-model.c
> new file mode 100644
> index 000000000000..a3984acef62b
> --- /dev/null
> +++ b/clang/test/Driver/fp-model.c
> @@ -0,0 +1,137 @@
> +// Test that incompatible combinations of -ffp-model= options
> +// and other floating point options get a warning diagnostic.
> +//
> +// REQUIRES: clang-driver
> +
> +// RUN: %clang -### -ffp-model=fast -ffp-contract=off -c %s 2>&1 \
> +// RUN:   | FileCheck --check-prefix=WARN %s
> +// WARN: warning: overriding '-ffp-model=fast' option with
> '-ffp-contract=off' [-Woverriding-t-option]
> +
> +// RUN: %clang -### -ffp-model=fast -ffp-contract=on -c %s 2>&1 \
> +// RUN:   | FileCheck --check-prefix=WARN1 %s
> +// WARN1: warning: overriding '-ffp-model=fast' option with
> '-ffp-contract=on' [-Woverriding-t-option]
> +
> +// RUN: %clang -### -ffp-model=strict -fassociative-math -c %s 2>&1 \
> +// RUN:   | FileCheck --check-prefix=WARN2 %s
> +// WARN2: warning: overriding '-ffp-model=strict' option with
> '-fassociative-math' [-Woverriding-t-option]
> +
> +// RUN: %clang -### -ffp-model=strict -ffast-math -c %s 2>&1 \
> +// RUN:   | FileCheck --check-prefix=WARN3 %s
> +// WARN3: warning: overriding '-ffp-model=strict' option with
> '-ffast-math' [-Woverriding-t-option]
> +
> +// RUN: %clang -### -ffp-model=strict -ffinite-math-only -c %s 2>&1 \
> +// RUN:   | FileCheck --check-prefix=WARN4 %s
> +// WARN4: warning: overriding '-ffp-model=strict' option with
> '-ffinite-math-only' [-Woverriding-t-option]
> +
> +// RUN: %clang -### -ffp-model=strict -ffp-contract=fast -c %s 2>&1 \
> +// RUN:   | FileCheck --check-prefix=WARN5 %s
> +// WARN5: warning: overriding '-ffp-model=strict' option with
> '-ffp-contract=fast' [-Woverriding-t-option]
> +
> +// RUN: %clang -### -ffp-model=strict -ffp-contract=off -c %s 2>&1 \
> +// RUN:   | FileCheck --check-prefix=WARN6 %s
> +// WARN6: warning: overriding '-ffp-model=strict' option with
> '-ffp-contract=off' [-Woverriding-t-option]
> +
> +// RUN: %clang -### -ffp-model=strict -ffp-contract=on -c %s 2>&1 \
> +// RUN:   | FileCheck --check-prefix=WARN7 %s
> +// WARN7: warning: overriding '-ffp-model=strict' option with
> '-ffp-contract=on' [-Woverriding-t-option]
> +
> +// RUN: %clang -### -ffp-model=strict -fno-honor-infinities -c %s 2>&1 \
> +// RUN:   | FileCheck --check-prefix=WARN8 %s
> +// WARN8: warning: overriding '-ffp-model=strict' option with
> '-fno-honor-infinities' [-Woverriding-t-option]
> +
> +// RUN: %clang -### -ffp-model=strict -fno-honor-nans -c %s 2>&1 \
> +// RUN:   | FileCheck --check-prefix=WARN9 %s
> +// WARN9: warning: overriding '-ffp-model=strict' option with
> '-fno-honor-nans' [-Woverriding-t-option]
> +
> +// RUN: %clang -### -ffp-model=strict -fno-rounding-math -c %s 2>&1 \
> +// RUN:   | FileCheck --check-prefix=WARNa %s
> +// WARNa: warning: overriding '-ffp-model=strict' option with
> '-fno-rounding-math' [-Woverriding-t-option]
> +
> +// RUN: %clang -### -ffp-model=strict -fno-signed-zeros -c %s 2>&1 \
> +// RUN:   | FileCheck --check-prefix=WARNb %s
> +// WARNb: warning: overriding '-ffp-model=strict' option with
> '-fno-signed-zeros' [-Woverriding-t-option]
> +
> +// RUN: %clang -### -ffp-model=strict -fno-trapping-math -c %s 2>&1 \
> +// RUN:   | FileCheck --check-prefix=WARNc %s
> +// WARNc: warning: overriding '-ffp-model=strict' option with
> '-fno-trapping-math' [-Woverriding-t-option]
> +
> +// RUN: %clang -### -ffp-model=strict -freciprocal-math -c %s 2>&1 \
> +// RUN:   | FileCheck --check-prefix=WARNd %s
> +// WARNd: warning: overriding '-ffp-model=strict' option with
> '-freciprocal-math' [-Woverriding-t-option]
> +
> +// RUN: %clang -### -ffp-model=strict -funsafe-math-optimizations -c %s
> 2>&1 \
> +// RUN:   | FileCheck --check-prefix=WARNe %s
> +// WARNe: warning: overriding '-ffp-model=strict' option with
> '-funsafe-math-optimizations' [-Woverriding-t-option]
> +
> +// RUN: %clang -### -ffp-model=strict -Ofast -c %s 2>&1 \
> +// RUN:   | FileCheck --check-prefix=WARNf %s
> +// WARNf: warning: overriding '-ffp-model=strict' option with '-Ofast'
> [-Woverriding-t-option]
> +
> +// RUN: %clang -### -c %s 2>&1 \
> +// RUN:   | FileCheck --check-prefix=CHECK-NOROUND %s
> +// CHECK-NOROUND: "-cc1"
> +// CHECK-NOROUND: "-fno-rounding-math"
> +
> +// RUN: %clang -### -frounding-math -c %s 2>&1 \
> +// RUN:   | FileCheck --check-prefix=CHECK-ROUND --implicit-check-not
> ffp-exception-behavior=strict %s
> +// CHECK-ROUND: "-cc1"
> +// CHECK-ROUND: "-frounding-math"
> +
> +// RUN: %clang -### -ftrapping-math -c %s 2>&1 \
> +// RUN:   | FileCheck --check-prefix=CHECK-TRAP %s
> +// CHECK-TRAP: "-cc1"
> +// CHECK-TRAP: "-ftrapping-math"
> +// CHECK-TRAP: "-ffp-exception-behavior=strict"
> +
> +// RUN: %clang -### -nostdinc -ffp-model=fast -c %s 2>&1 \
> +// RUN:   | FileCheck --check-prefix=CHECK-FPM-FAST %s
> +// CHECK-FPM-FAST: "-cc1"
> +// CHECK-FPM-FAST: "-menable-no-infs"
> +// CHECK-FPM-FAST: "-menable-no-nans"
> +// CHECK-FPM-FAST: "-menable-unsafe-fp-math"
> +// CHECK-FPM-FAST: "-fno-signed-zeros"
> +// CHECK-FPM-FAST: "-mreassociate"
> +// CHECK-FPM-FAST: "-freciprocal-math"
> +// CHECK-FPM-FAST: "-ffp-contract=fast"
> +// CHECK-FPM-FAST: "-fno-rounding-math"
> +// CHECK-FPM-FAST: "-ffast-math"
> +// CHECK-FPM-FAST: "-ffinite-math-only"
> +
> +// RUN: %clang -### -nostdinc -ffp-model=precise -c %s 2>&1 \
> +// RUN:   | FileCheck --check-prefix=CHECK-FPM-PRECISE %s
> +// CHECK-FPM-PRECISE: "-cc1"
> +// CHECK-FPM-PRECISE: "-ffp-contract=fast"
> +// CHECK-FPM-PRECISE: "-fno-rounding-math"
> +
> +// RUN: %clang -### -nostdinc -ffp-model=strict -c %s 2>&1 \
> +// RUN:   | FileCheck --check-prefix=CHECK-FPM-STRICT %s
> +// CHECK-FPM-STRICT: "-cc1"
> +// CHECK-FPM-STRICT: "-ftrapping-math"
> +// CHECK-FPM-STRICT: "-frounding-math"
> +// CHECK-FPM-STRICT: "-ffp-exception-behavior=strict"
> +
> +// RUN: %clang -### -nostdinc -ftrapping-math
> -ffp-exception-behavior=ignore -c %s 2>&1 \
> +// RUN:   | FileCheck --check-prefix=CHECK-TRAP-IGNORE %s
> +// CHECK-TRAP-IGNORE: "-cc1"
> +// CHECK-TRAP-IGNORE: "-fno-rounding-math"
> +// CHECK-TRAP-IGNORE: "-ffp-exception-behavior=ignore"
> +
> +
> +// RUN: %clang -### -nostdinc -ffp-exception-behavior=strict -c %s 2>&1 \
> +// RUN:   | FileCheck --check-prefix=CHECK-FEB-STRICT %s
> +// CHECK-FEB-STRICT: "-cc1"
> +// CHECK-FEB-STRICT: "-fno-rounding-math"
> +// CHECK-FEB-STRICT: "-ffp-exception-behavior=strict"
> +
> +// RUN: %clang -### -nostdinc -ffp-exception-behavior=maytrap -c %s 2>&1 \
> +// RUN:   | FileCheck --check-prefix=CHECK-FEB-MAYTRAP %s
> +// CHECK-FEB-MAYTRAP: "-cc1"
> +// CHECK-FEB-MAYTRAP: "-fno-rounding-math"
> +// CHECK-FEB-MAYTRAP: "-ffp-exception-behavior=maytrap"
> +
> +// RUN: %clang -### -nostdinc -ffp-exception-behavior=ignore -c %s 2>&1 \
> +// RUN:   | FileCheck --check-prefix=CHECK-FEB-IGNORE %s
> +// CHECK-FEB-IGNORE: "-cc1"
> +// CHECK-FEB-IGNORE: "-fno-rounding-math"
> +// CHECK-FEB-IGNORE: "-ffp-exception-behavior=ignore"
> +
>
> diff  --git a/llvm/include/llvm/IR/IRBuilder.h
> b/llvm/include/llvm/IR/IRBuilder.h
> index 2d9c72108d3d..24d39c2bc526 100644
> --- a/llvm/include/llvm/IR/IRBuilder.h
> +++ b/llvm/include/llvm/IR/IRBuilder.h
> @@ -265,7 +265,6 @@ class IRBuilderBase {
>    void setConstrainedFPCallAttr(CallInst *I) {
>      if (!I->hasFnAttr(Attribute::StrictFP))
>        I->addAttribute(AttributeList::FunctionIndex, Attribute::StrictFP);
> -    setConstrainedFPFunctionAttr();
>    }
>
>
>  //===--------------------------------------------------------------------===//
>
> diff  --git a/llvm/include/llvm/Target/TargetOptions.h
> b/llvm/include/llvm/Target/TargetOptions.h
> index c395e5bcecf1..d1db4eceabb8 100644
> --- a/llvm/include/llvm/Target/TargetOptions.h
> +++ b/llvm/include/llvm/Target/TargetOptions.h
> @@ -107,7 +107,7 @@ namespace llvm {
>    public:
>      TargetOptions()
>          : PrintMachineCode(false), UnsafeFPMath(false),
> NoInfsFPMath(false),
> -          NoNaNsFPMath(false), NoTrappingFPMath(false),
> +          NoNaNsFPMath(false), NoTrappingFPMath(true),
>            NoSignedZerosFPMath(false),
>            HonorSignDependentRoundingFPMathOption(false),
> NoZerosInBSS(false),
>            GuaranteedTailCallOpt(false), StackSymbolOrdering(true),
>
> diff  --git a/llvm/unittests/IR/IRBuilderTest.cpp
> b/llvm/unittests/IR/IRBuilderTest.cpp
> index d7712fda1270..814da64c7852 100644
> --- a/llvm/unittests/IR/IRBuilderTest.cpp
> +++ b/llvm/unittests/IR/IRBuilderTest.cpp
> @@ -183,6 +183,8 @@ TEST_F(IRBuilderTest, ConstrainedFP) {
>    // See if we get constrained intrinsics instead of non-constrained
>    // instructions.
>    Builder.setIsFPConstrained(true);
> +  auto Parent = BB->getParent();
> +  Parent->addFnAttr(Attribute::StrictFP);
>
>    V = Builder.CreateFAdd(V, V);
>    ASSERT_TRUE(isa<IntrinsicInst>(V));
> @@ -233,7 +235,8 @@ TEST_F(IRBuilderTest, ConstrainedFP) {
>    AttributeSet CallAttrs = II->getAttributes().getFnAttributes();
>    EXPECT_EQ(CallAttrs.hasAttribute(Attribute::StrictFP), true);
>
> -  // Verify attributes on the containing function are created
> automatically.
> +  // Verify attributes on the containing function are created when
> requested.
> +  Builder.setConstrainedFPFunctionAttr();
>    AttributeList Attrs = BB->getParent()->getAttributes();
>    AttributeSet FnAttrs = Attrs.getFnAttributes();
>    EXPECT_EQ(FnAttrs.hasAttribute(Attribute::StrictFP), true);
>
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at lists.llvm.org
> https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20191210/44d40e42/attachment-0001.html>


More information about the cfe-commits mailing list