[clang] fce82c0 - Revert "Reapply "Add support for #pragma float_control" with improvements to"

Melanie Blower via cfe-commits cfe-commits at lists.llvm.org
Fri May 1 10:31:38 PDT 2020


Author: Melanie Blower
Date: 2020-05-01T10:31:09-07:00
New Revision: fce82c0ed310174fe48e2402ac731b6340098389

URL: https://github.com/llvm/llvm-project/commit/fce82c0ed310174fe48e2402ac731b6340098389
DIFF: https://github.com/llvm/llvm-project/commit/fce82c0ed310174fe48e2402ac731b6340098389.diff

LOG: Revert "Reapply "Add support for #pragma float_control" with improvements to"

This reverts commit 69aacaf699922ffe0450f567e21208c10c84731f.

Added: 
    

Modified: 
    clang/docs/LanguageExtensions.rst
    clang/include/clang/AST/Expr.h
    clang/include/clang/AST/Stmt.h
    clang/include/clang/Basic/DiagnosticParseKinds.td
    clang/include/clang/Basic/DiagnosticSemaKinds.td
    clang/include/clang/Basic/LangOptions.def
    clang/include/clang/Basic/LangOptions.h
    clang/include/clang/Basic/PragmaKinds.h
    clang/include/clang/Basic/TokenKinds.def
    clang/include/clang/Parse/Parser.h
    clang/include/clang/Sema/Sema.h
    clang/include/clang/Serialization/ASTBitCodes.h
    clang/include/clang/Serialization/ASTReader.h
    clang/include/clang/Serialization/ASTWriter.h
    clang/lib/AST/ASTImporter.cpp
    clang/lib/AST/Expr.cpp
    clang/lib/Analysis/BodyFarm.cpp
    clang/lib/CodeGen/CGExprScalar.cpp
    clang/lib/CodeGen/CGObjC.cpp
    clang/lib/CodeGen/CGStmtOpenMP.cpp
    clang/lib/CodeGen/CodeGenFunction.cpp
    clang/lib/CodeGen/CodeGenFunction.h
    clang/lib/Frontend/CompilerInvocation.cpp
    clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp
    clang/lib/Frontend/Rewrite/RewriteObjC.cpp
    clang/lib/Parse/ParseDeclCXX.cpp
    clang/lib/Parse/ParsePragma.cpp
    clang/lib/Parse/ParseStmt.cpp
    clang/lib/Parse/Parser.cpp
    clang/lib/Sema/Sema.cpp
    clang/lib/Sema/SemaAttr.cpp
    clang/lib/Sema/SemaDeclCXX.cpp
    clang/lib/Sema/SemaExpr.cpp
    clang/lib/Sema/SemaExprObjC.cpp
    clang/lib/Sema/SemaOverload.cpp
    clang/lib/Sema/SemaPseudoObject.cpp
    clang/lib/Sema/SemaStmt.cpp
    clang/lib/Serialization/ASTReader.cpp
    clang/lib/Serialization/ASTReaderStmt.cpp
    clang/lib/Serialization/ASTWriter.cpp
    clang/lib/Serialization/ASTWriterStmt.cpp
    clang/test/CodeGen/builtins-nvptx.c
    clang/test/CodeGen/constrained-math-builtins.c
    clang/test/CodeGen/fast-math.c
    clang/test/CodeGen/fp-contract-on-pragma.cpp
    clang/test/CodeGen/fp-contract-pragma.cpp
    clang/test/CodeGen/fpconstrained.c
    clang/test/CodeGen/fpconstrained.cpp
    clang/test/CodeGenOpenCL/relaxed-fpmath.cl
    clang/test/CodeGenOpenCL/single-precision-constant.cl
    clang/test/Headers/nvptx_device_math_sin.c
    clang/test/Headers/nvptx_device_math_sin.cpp
    llvm/include/llvm/IR/IRBuilder.h

Removed: 
    clang/test/CodeGen/fp-floatcontrol-class.cpp
    clang/test/CodeGen/fp-floatcontrol-pragma.cpp
    clang/test/CodeGen/fp-floatcontrol-stack.cpp
    clang/test/PCH/pragma-floatcontrol.c
    clang/test/Parser/fp-floatcontrol-syntax.cpp


################################################################################
diff  --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst
index 1c753ea0e569..11114e82a6e5 100644
--- a/clang/docs/LanguageExtensions.rst
+++ b/clang/docs/LanguageExtensions.rst
@@ -3197,41 +3197,6 @@ The pragma can also be used with ``off`` which turns FP contraction off for a
 section of the code. This can be useful when fast contraction is otherwise
 enabled for the translation unit with the ``-ffp-contract=fast`` flag.
 
-The ``#pragma float_control`` pragma allows precise floating-point
-semantics and floating-point exception behavior to be specified
-for a section of the source code. This pragma can only appear at file scope or
-at the start of a compound statement (excluding comments). When using within a
-compound statement, the pragma is active within the scope of the compound
-statement.  This pragma is modeled after a Microsoft pragma with the
-same spelling and syntax.  For pragmas specified at file scope, a stack
-is supported so that the ``pragma float_control`` settings can be pushed or popped.
-
-When ``pragma float_control(precise, on)`` is enabled, the section of code
-governed by the pragma uses precise floating point semantics, effectively
-``-ffast-math`` is disabled and ``-ffp-contract=on``
-(fused multiply add) is enabled.
-
-When ``pragma float_control(except, on)`` is enabled, the section of code governed
-by the pragma behaves as though the command-line option
-``-ffp-exception-behavior=strict`` is enabled,
-when ``pragma float_control(precise, off)`` is enabled, the section of code
-governed by the pragma behaves as though the command-line option
-``-ffp-exception-behavior=ignore`` is enabled.
-
-The full syntax this pragma supports is
-``float_control(except|precise, on|off [, push])`` and
-``float_control(push|pop)``.
-The ``push`` and ``pop`` forms, including using ``push`` as the optional
-third argument, can only occur at file scope.
-
-.. code-block:: c++
-
-  for(...) {
-    // This block will be compiled with -fno-fast-math and -ffp-contract=on
-    #pragma float_control(precise, on)
-    a = b[i] * c[i] + e;
-  }
-
 Specifying an attribute for multiple declarations (#pragma clang attribute)
 ===========================================================================
 

diff  --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index 6c83bc6c649d..4d89234b0da7 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -2107,48 +2107,26 @@ class ParenExpr : public Expr {
 ///   applied to a non-complex value, the former returns its operand and the
 ///   later returns zero in the type of the operand.
 ///
-class UnaryOperator final
-    : public Expr,
-      private llvm::TrailingObjects<UnaryOperator, FPOptions> {
+class UnaryOperator : public Expr {
   Stmt *Val;
 
-  size_t numTrailingObjects(OverloadToken<FPOptions>) const {
-    return UnaryOperatorBits.HasFPFeatures ? 1 : 0;
-  }
-
-  FPOptions &getTrailingFPFeatures() {
-    assert(UnaryOperatorBits.HasFPFeatures);
-    return *getTrailingObjects<FPOptions>();
-  }
-
-  const FPOptions &getTrailingFPFeatures() const {
-    assert(UnaryOperatorBits.HasFPFeatures);
-    return *getTrailingObjects<FPOptions>();
-  }
-
 public:
   typedef UnaryOperatorKind Opcode;
 
-protected:
-  UnaryOperator(const ASTContext &Ctx, Expr *input, Opcode opc, QualType type,
-                ExprValueKind VK, ExprObjectKind OK, SourceLocation l,
-                bool CanOverflow, FPOptions FPFeatures);
+  UnaryOperator(Expr *input, Opcode opc, QualType type, ExprValueKind VK,
+                ExprObjectKind OK, SourceLocation l, bool CanOverflow)
+      : Expr(UnaryOperatorClass, type, VK, OK), Val(input) {
+    UnaryOperatorBits.Opc = opc;
+    UnaryOperatorBits.CanOverflow = CanOverflow;
+    UnaryOperatorBits.Loc = l;
+    setDependence(computeDependence(this));
+  }
 
   /// Build an empty unary operator.
-  explicit UnaryOperator(bool HasFPFeatures, EmptyShell Empty)
-      : Expr(UnaryOperatorClass, Empty) {
+  explicit UnaryOperator(EmptyShell Empty) : Expr(UnaryOperatorClass, Empty) {
     UnaryOperatorBits.Opc = UO_AddrOf;
-    UnaryOperatorBits.HasFPFeatures = HasFPFeatures;
   }
 
-public:
-  static UnaryOperator *CreateEmpty(const ASTContext &C, bool hasFPFeatures);
-
-  static UnaryOperator *Create(const ASTContext &C, Expr *input, Opcode opc,
-                               QualType type, ExprValueKind VK,
-                               ExprObjectKind OK, SourceLocation l,
-                               bool CanOverflow, FPOptions FPFeatures);
-
   Opcode getOpcode() const {
     return static_cast<Opcode>(UnaryOperatorBits.Opc);
   }
@@ -2170,18 +2148,6 @@ class UnaryOperator final
   bool canOverflow() const { return UnaryOperatorBits.CanOverflow; }
   void setCanOverflow(bool C) { UnaryOperatorBits.CanOverflow = C; }
 
-  // Get the FP contractability status of this operator. Only meaningful for
-  // operations on floating point types.
-  bool isFPContractableWithinStatement(const LangOptions &LO) const {
-    return getFPFeatures(LO).allowFPContractWithinStatement();
-  }
-
-  // Get the FENV_ACCESS status of this operator. Only meaningful for
-  // operations on floating point types.
-  bool isFEnvAccessOn(const LangOptions &LO) const {
-    return getFPFeatures(LO).allowFEnvAccess();
-  }
-
   /// isPostfix - Return true if this is a postfix operation, like x++.
   static bool isPostfix(Opcode Op) {
     return Op == UO_PostInc || Op == UO_PostDec;
@@ -2248,30 +2214,6 @@ class UnaryOperator final
   const_child_range children() const {
     return const_child_range(&Val, &Val + 1);
   }
-
-  /// Is FPFeatures in Trailing Storage?
-  bool hasStoredFPFeatures() const { return UnaryOperatorBits.HasFPFeatures; }
-
-protected:
-  /// Get FPFeatures from trailing storage
-  FPOptions getStoredFPFeatures() const { return getTrailingFPFeatures(); }
-
-  /// Set FPFeatures in trailing storage, used only by Serialization
-  void setStoredFPFeatures(FPOptions F) { getTrailingFPFeatures() = F; }
-
-public:
-  // Get the FP features status of this operator. Only meaningful for
-  // operations on floating point types.
-  FPOptions getFPFeatures(const LangOptions &LO) const {
-    if (UnaryOperatorBits.HasFPFeatures)
-      return getStoredFPFeatures();
-    return FPOptions::defaultWithoutTrailingStorage(LO);
-  }
-
-  friend TrailingObjects;
-  friend class ASTReader;
-  friend class ASTStmtReader;
-  friend class ASTStmtWriter;
 };
 
 /// Helper class for OffsetOfExpr.

diff  --git a/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h
index 5db3ad3a138c..58c03291c1ed 100644
--- a/clang/include/clang/AST/Stmt.h
+++ b/clang/include/clang/AST/Stmt.h
@@ -427,11 +427,6 @@ class alignas(void *) Stmt {
 
     unsigned Opc : 5;
     unsigned CanOverflow : 1;
-    //
-    /// This is only meaningful for operations on floating point
-    /// types when additional values need to be in trailing storage.
-    /// It is 0 otherwise.
-    unsigned HasFPFeatures : 1;
 
     SourceLocation Loc;
   };
@@ -615,7 +610,7 @@ class alignas(void *) Stmt {
     unsigned OperatorKind : 6;
 
     // Only meaningful for floating point types.
-    unsigned FPFeatures : 14;
+    unsigned FPFeatures : 8;
   };
 
   class CXXRewrittenBinaryOperatorBitfields {

diff  --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td
index 9400a87c0ef3..337614c33661 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -1097,9 +1097,9 @@ def warn_pragma_init_seg_unsupported_target : Warning<
   "'#pragma init_seg' is only supported when targeting a "
   "Microsoft environment">,
   InGroup<IgnoredPragmas>;
-// - #pragma restricted to file scope or start of compound statement
-def err_pragma_file_or_compound_scope : Error<
-  "'#pragma %0' can only appear at file scope or at the start of a "
+// - #pragma fp_contract
+def err_pragma_fp_contract_scope : Error<
+  "'#pragma fp_contract' can only appear at file scope or at the start of a "
   "compound statement">;
 // - #pragma stdc unknown
 def ext_stdc_pragma_ignored : ExtWarn<"unknown pragma in STDC namespace">,
@@ -1118,10 +1118,6 @@ def warn_pragma_comment_ignored : Warning<"'#pragma comment %0' ignored">,
 def err_pragma_detect_mismatch_malformed : Error<
   "pragma detect_mismatch is malformed; it requires two comma-separated "
   "string literals">;
-// - #pragma float_control
-def err_pragma_float_control_malformed : Error<
-  "pragma float_control is malformed; use 'float_control({push|pop})' or "
-  "'float_control({precise|except}, {on|off} [,push])'">;
 // - #pragma pointers_to_members
 def err_pragma_pointers_to_members_unknown_kind : Error<
   "unexpected %0, expected to see one of %select{|'best_case', 'full_generality', }1"
@@ -1336,6 +1332,9 @@ def err_pragma_fp_invalid_option : Error<
 def err_pragma_fp_invalid_argument : Error<
   "unexpected argument '%0' to '#pragma clang fp %1'; "
   "expected 'on', 'fast' or 'off'">;
+def err_pragma_fp_scope : Error<
+  "'#pragma clang fp' can only appear at file scope or at the start of a "
+  "compound statement">;
 
 def err_pragma_invalid_keyword : Error<
   "invalid argument; expected 'enable'%select{|, 'full'}0%select{|, 'assume_safety'}1 or 'disable'">;

diff  --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index ac53ad6ab344..154da867d00b 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -858,16 +858,6 @@ def warn_pragma_pack_pop_identifier_and_alignment : Warning<
   "specifying both a name and alignment to 'pop' is undefined">;
 def warn_pragma_pop_failed : Warning<"#pragma %0(pop, ...) failed: %1">,
   InGroup<IgnoredPragmas>;
-def err_pragma_fc_pp_scope : Error<
-  "'#pragma float_control push/pop' can only appear at file scope">;
-def err_pragma_fc_noprecise_requires_nofenv : Error<
-  "'#pragma float_control(precise, off)' is illegal when fenv_access is enabled">;
-def err_pragma_fc_except_requires_precise : Error<
-  "'#pragma float_control(except, on)' is illegal when precise is disabled">;
-def err_pragma_fc_noprecise_requires_noexcept : Error<
-  "'#pragma float_control(precise, off)' is illegal when except is enabled">;
-def err_pragma_fenv_requires_precise : Error<
-  "'#pragma STDC FENV_ACCESS ON' is illegal when precise is disabled">;
 def warn_cxx_ms_struct :
   Warning<"ms_struct may not produce Microsoft-compatible layouts for classes "
           "with base classes or virtual functions">,

diff  --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def
index 289f9c3f50e2..1464aac8df7e 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -191,12 +191,6 @@ COMPATIBLE_LANGOPT(Deprecated        , 1, 0, "__DEPRECATED predefined macro")
 COMPATIBLE_LANGOPT(FastMath          , 1, 0, "fast FP math optimizations, and __FAST_MATH__ predefined macro")
 COMPATIBLE_LANGOPT(FiniteMathOnly    , 1, 0, "__FINITE_MATH_ONLY__ predefined macro")
 COMPATIBLE_LANGOPT(UnsafeFPMath      , 1, 0, "Unsafe Floating Point Math")
-COMPATIBLE_LANGOPT(AllowFPReassoc    , 1, 0, "Permit Floating Point reassociation")
-COMPATIBLE_LANGOPT(NoHonorNaNs       , 1, 0, "Permit Floating Point optimization without regard to NaN")
-COMPATIBLE_LANGOPT(NoHonorInfs       , 1, 0, "Permit Floating Point optimization without regard to infinities")
-COMPATIBLE_LANGOPT(NoSignedZero      , 1, 0, "Permit Floating Point optimization without regard to signed zeros")
-COMPATIBLE_LANGOPT(AllowRecip        , 1, 0, "Permit Floating Point reciprocal")
-COMPATIBLE_LANGOPT(ApproxFunc        , 1, 0, "Permit Floating Point approximation")
 
 BENIGN_LANGOPT(ObjCGCBitmapPrint , 1, 0, "printing of GC's bitmap layout for __weak/__strong ivars")
 

diff  --git a/clang/include/clang/Basic/LangOptions.h b/clang/include/clang/Basic/LangOptions.h
index 61b4b87ebd0e..76ddd7051fd3 100644
--- a/clang/include/clang/Basic/LangOptions.h
+++ b/clang/include/clang/Basic/LangOptions.h
@@ -304,8 +304,6 @@ class LangOptions : public LangOptionsBase {
   /// input is a header file (i.e. -x c-header).
   bool IsHeaderFile = false;
 
-  bool denormalIsIEEE = false;
-
   LangOptions();
 
   // Define accessors/mutators for language options of enumeration type.
@@ -379,33 +377,28 @@ class FPOptions {
   using RoundingMode = llvm::RoundingMode;
 
 public:
-  FPOptions()
-      : fp_contract(LangOptions::FPC_Off), fenv_access(LangOptions::FEA_Off),
-        rounding(LangOptions::FPR_ToNearest),
-        exceptions(LangOptions::FPE_Ignore), allow_reassoc(0), no_nans(0),
-        no_infs(0), no_signed_zeros(0), allow_reciprocal(0), approx_func(0) {}
+  FPOptions() : fp_contract(LangOptions::FPC_Off),
+                fenv_access(LangOptions::FEA_Off),
+                rounding(LangOptions::FPR_ToNearest),
+                exceptions(LangOptions::FPE_Ignore)
+        {}
 
   // Used for serializing.
-  explicit FPOptions(unsigned I) { getFromOpaqueInt(I); }
+  explicit FPOptions(unsigned I)
+      : fp_contract(I & 3),
+        fenv_access((I >> 2) & 1),
+        rounding   ((I >> 3) & 7),
+        exceptions ((I >> 6) & 3)
+        {}
 
   explicit FPOptions(const LangOptions &LangOpts)
       : fp_contract(LangOpts.getDefaultFPContractMode()),
         fenv_access(LangOptions::FEA_Off),
-        rounding(static_cast<unsigned>(LangOpts.getFPRoundingMode())),
-        exceptions(LangOpts.getFPExceptionMode()),
-        allow_reassoc(LangOpts.FastMath || LangOpts.AllowFPReassoc),
-        no_nans(LangOpts.FastMath || LangOpts.NoHonorNaNs),
-        no_infs(LangOpts.FastMath || LangOpts.NoHonorInfs),
-        no_signed_zeros(LangOpts.FastMath || LangOpts.NoSignedZero),
-        allow_reciprocal(LangOpts.FastMath || LangOpts.AllowRecip),
-        approx_func(LangOpts.FastMath || LangOpts.ApproxFunc) {}
+        rounding(LangOptions::FPR_ToNearest),
+        exceptions(LangOptions::FPE_Ignore)
+        {}
   // FIXME: Use getDefaultFEnvAccessMode() when available.
 
-  void setFastMath(bool B = true) {
-    allow_reassoc = no_nans = no_infs = no_signed_zeros = approx_func =
-        allow_reciprocal = B;
-  }
-
   /// Return the default value of FPOptions that's used when trailing
   /// storage isn't required.
   static FPOptions defaultWithoutTrailingStorage(const LangOptions &LO);
@@ -440,18 +433,6 @@ class FPOptions {
     fenv_access = LangOptions::FEA_On;
   }
 
-  void setFPPreciseEnabled(bool Value) {
-    if (Value) {
-      /* Precise mode implies fp_contract=on and disables ffast-math */
-      setFastMath(false);
-      setAllowFPContractWithinStatement();
-    } else {
-      /* Precise mode implies fp_contract=fast and enables ffast-math */
-      setFastMath(true);
-      setAllowFPContractAcrossStatement();
-    }
-  }
-
   void setDisallowFEnvAccess() { fenv_access = LangOptions::FEA_Off; }
 
   RoundingMode getRoundingMode() const {
@@ -470,22 +451,6 @@ class FPOptions {
     exceptions = EM;
   }
 
-  /// FMF Flag queries
-  bool allowAssociativeMath() const { return allow_reassoc; }
-  bool noHonorNaNs() const { return no_nans; }
-  bool noHonorInfs() const { return no_infs; }
-  bool noSignedZeros() const { return no_signed_zeros; }
-  bool allowReciprocalMath() const { return allow_reciprocal; }
-  bool allowApproximateFunctions() const { return approx_func; }
-
-  /// Flag setters
-  void setAllowAssociativeMath(bool B = true) { allow_reassoc = B; }
-  void setNoHonorNaNs(bool B = true) { no_nans = B; }
-  void setNoHonorInfs(bool B = true) { no_infs = B; }
-  void setNoSignedZeros(bool B = true) { no_signed_zeros = B; }
-  void setAllowReciprocalMath(bool B = true) { allow_reciprocal = B; }
-  void setAllowApproximateFunctions(bool B = true) { approx_func = B; }
-
   bool isFPConstrained() const {
     return getRoundingMode() != RoundingMode::NearestTiesToEven ||
            getExceptionMode() != LangOptions::FPE_Ignore ||
@@ -495,23 +460,7 @@ class FPOptions {
   /// Used to serialize this.
   unsigned getAsOpaqueInt() const {
     return fp_contract | (fenv_access << 2) | (rounding << 3) |
-           (exceptions << 6) | (allow_reassoc << 8) | (no_nans << 9) |
-           (no_infs << 10) | (no_signed_zeros << 11) |
-           (allow_reciprocal << 12) | (approx_func << 13);
-  }
-
-  /// Used with getAsOpaqueInt() to manage the float_control pragma stack.
-  void getFromOpaqueInt(unsigned I) {
-    fp_contract = (static_cast<LangOptions::FPContractModeKind>(I & 3));
-    fenv_access = (static_cast<LangOptions::FEnvAccessModeKind>((I >> 2) & 1));
-    rounding = static_cast<unsigned>(static_cast<RoundingMode>((I >> 3) & 7));
-    exceptions = (static_cast<LangOptions::FPExceptionModeKind>((I >> 6) & 3));
-    allow_reassoc = ((I >> 8) & 1);
-    no_nans = ((I >> 9) & 1);
-    no_infs = ((I >> 10) & 1);
-    no_signed_zeros = ((I >> 11) & 1);
-    allow_reciprocal = ((I >> 12) & 1);
-    approx_func = ((I >> 13) & 1);
+           (exceptions << 6);
   }
 
 private:
@@ -522,25 +471,6 @@ class FPOptions {
   unsigned fenv_access : 1;
   unsigned rounding : 3;
   unsigned exceptions : 2;
-  /// Allow reassociation transformations for floating-point instructions.
-  unsigned allow_reassoc : 1;
-  /// No NaNs - Allow optimizations to assume the arguments and result
-  /// are not NaN. If an argument is a nan, or the result would be a nan,
-  /// it produces a :ref:`poison value <poisonvalues>` instead.
-  unsigned no_nans : 1;
-  /// No Infs - Allow optimizations to assume the arguments and result
-  /// are not +/-Inf. If an argument is +/-Inf, or the result would be +/-Inf,
-  /// it produces a :ref:`poison value <poisonvalues>` instead.
-  unsigned no_infs : 1;
-  /// No Signed Zeros - Allow optimizations to treat the sign of a zero
-  /// argument or result as insignificant.
-  unsigned no_signed_zeros : 1;
-  /// Allow Reciprocal - Allow optimizations to use the reciprocal
-  /// of an argument rather than perform division.
-  unsigned allow_reciprocal : 1;
-  /// Approximate functions - Allow substitution of approximate calculations
-  /// for functions (sin, log, sqrt, etc).
-  unsigned approx_func : 1;
 };
 
 /// Describes the kind of translation unit being processed.

diff  --git a/clang/include/clang/Basic/PragmaKinds.h b/clang/include/clang/Basic/PragmaKinds.h
index 82c0d5f0a551..103b97db718b 100644
--- a/clang/include/clang/Basic/PragmaKinds.h
+++ b/clang/include/clang/Basic/PragmaKinds.h
@@ -25,15 +25,6 @@ enum PragmaMSStructKind {
   PMSST_ON   // #pragms ms_struct on
 };
 
-enum PragmaFloatControlKind {
-  PFC_Unknown,
-  PFC_Precise,   // #pragma float_control(precise, [,on])
-  PFC_NoPrecise, // #pragma float_control(precise, off)
-  PFC_Except,    // #pragma float_control(except [,on])
-  PFC_NoExcept,  // #pragma float_control(except, off)
-  PFC_Push,      // #pragma float_control(push)
-  PFC_Pop        // #pragma float_control(pop)
-};
 }
 
 #endif

diff  --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def
index 6ca5f0e30ade..07058962fc85 100644
--- a/clang/include/clang/Basic/TokenKinds.def
+++ b/clang/include/clang/Basic/TokenKinds.def
@@ -809,11 +809,6 @@ PRAGMA_ANNOTATION(pragma_fp_contract)
 // handles them.
 PRAGMA_ANNOTATION(pragma_fenv_access)
 
-// Annotation for #pragma float_control
-// The lexer produces these so that they only take effect when the parser
-// handles them.
-PRAGMA_ANNOTATION(pragma_float_control)
-
 // Annotation for #pragma pointers_to_members...
 // The lexer produces these so that they only take effect when the parser
 // handles them.

diff  --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index 4a8acf5cd196..d8642996de79 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -182,7 +182,6 @@ class Parser : public CodeCompletionHandler {
   std::unique_ptr<PragmaHandler> PCSectionHandler;
   std::unique_ptr<PragmaHandler> MSCommentHandler;
   std::unique_ptr<PragmaHandler> MSDetectMismatchHandler;
-  std::unique_ptr<PragmaHandler> FloatControlHandler;
   std::unique_ptr<PragmaHandler> MSPointersToMembers;
   std::unique_ptr<PragmaHandler> MSVtorDisp;
   std::unique_ptr<PragmaHandler> MSInitSeg;
@@ -742,10 +741,6 @@ class Parser : public CodeCompletionHandler {
   /// #pragma STDC FENV_ACCESS...
   void HandlePragmaFEnvAccess();
 
-  /// Handle the annotation token produced for
-  /// #pragma float_control
-  void HandlePragmaFloatControl();
-
   /// \brief Handle the annotation token produced for
   /// #pragma clang fp ...
   void HandlePragmaFP();

diff  --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 394a7838351e..0c1241f45ef5 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -555,9 +555,6 @@ class Sema final {
   PragmaStack<StringLiteral *> ConstSegStack;
   PragmaStack<StringLiteral *> CodeSegStack;
 
-  // This stack tracks the current state of Sema.CurFPFeatures.
-  PragmaStack<unsigned> FpPragmaStack;
-
   // RAII object to push / pop sentinel slots for all MS #pragma stacks.
   // Actions should be performed only if we enter / exit a C++ method body.
   class PragmaStackSentinelRAII {
@@ -1353,7 +1350,7 @@ class Sema final {
   /// should not be used elsewhere.
   void EmitCurrentDiagnostic(unsigned DiagID);
 
-  /// Records and restores the CurFPFeatures state on entry/exit of compound
+  /// Records and restores the FPFeatures state on entry/exit of compound
   /// statements.
   class FPFeaturesStateRAII {
   public:
@@ -9569,18 +9566,6 @@ class Sema final {
   void ActOnPragmaDetectMismatch(SourceLocation Loc, StringRef Name,
                                  StringRef Value);
 
-  /// Are precise floating point semantics currently enabled?
-  bool isPreciseFPEnabled() {
-    return LangOpts.denormalIsIEEE && !CurFPFeatures.allowAssociativeMath() &&
-           !CurFPFeatures.noSignedZeros() &&
-           !CurFPFeatures.allowReciprocalMath() &&
-           !CurFPFeatures.allowApproximateFunctions();
-  }
-
-  /// ActOnPragmaFloatControl - Call on well-formed \#pragma float_control
-  void ActOnPragmaFloatControl(SourceLocation Loc, PragmaMsStackAction Action,
-                               PragmaFloatControlKind Value);
-
   /// ActOnPragmaUnused - Called on well-formed '\#pragma unused'.
   void ActOnPragmaUnused(const Token &Identifier,
                          Scope *curScope,
@@ -9621,8 +9606,7 @@ class Sema final {
 
   /// ActOnPragmaFenvAccess - Called on well formed
   /// \#pragma STDC FENV_ACCESS
-  void ActOnPragmaFEnvAccess(SourceLocation Loc,
-                             LangOptions::FEnvAccessModeKind FPC);
+  void ActOnPragmaFEnvAccess(LangOptions::FEnvAccessModeKind FPC);
 
   /// Called to set rounding mode for floating point operations.
   void setRoundingMode(llvm::RoundingMode);

diff  --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h
index 14d052a62719..d5a27f487fa9 100644
--- a/clang/include/clang/Serialization/ASTBitCodes.h
+++ b/clang/include/clang/Serialization/ASTBitCodes.h
@@ -686,9 +686,6 @@ namespace serialization {
 
       /// Record code for the Decls to be checked for deferred diags.
       DECLS_TO_CHECK_FOR_DEFERRED_DIAGS = 64,
-
-      /// Record code for \#pragma float_control options.
-      FLOAT_CONTROL_PRAGMA_OPTIONS = 65,
     };
 
     /// Record types used within a source manager block.

diff  --git a/clang/include/clang/Serialization/ASTReader.h b/clang/include/clang/Serialization/ASTReader.h
index beaacefbc5c7..11a537fad5d5 100644
--- a/clang/include/clang/Serialization/ASTReader.h
+++ b/clang/include/clang/Serialization/ASTReader.h
@@ -857,18 +857,6 @@ class ASTReader
   int PragmaMSPointersToMembersState = -1;
   SourceLocation PointersToMembersPragmaLocation;
 
-  /// The pragma float_control state.
-  Optional<unsigned> FpPragmaCurrentValue;
-  SourceLocation FpPragmaCurrentLocation;
-  struct FpPragmaStackEntry {
-    unsigned Value;
-    SourceLocation Location;
-    SourceLocation PushLocation;
-    StringRef SlotLabel;
-  };
-  llvm::SmallVector<FpPragmaStackEntry, 2> FpPragmaStack;
-  llvm::SmallVector<std::string, 2> FpPragmaStrings;
-
   /// The pragma pack state.
   Optional<unsigned> PragmaPackCurrentValue;
   SourceLocation PragmaPackCurrentLocation;

diff  --git a/clang/include/clang/Serialization/ASTWriter.h b/clang/include/clang/Serialization/ASTWriter.h
index 398fa40f95eb..bc5a782f20cc 100644
--- a/clang/include/clang/Serialization/ASTWriter.h
+++ b/clang/include/clang/Serialization/ASTWriter.h
@@ -505,7 +505,6 @@ class ASTWriter : public ASTDeserializationListener,
   void WriteMSStructPragmaOptions(Sema &SemaRef);
   void WriteMSPointersToMembersPragmaOptions(Sema &SemaRef);
   void WritePackPragmaOptions(Sema &SemaRef);
-  void WriteFloatControlPragmaOptions(Sema &SemaRef);
   void WriteModuleFileExtension(Sema &SemaRef,
                                 ModuleFileExtensionWriter &Writer);
 

diff  --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index 10035162299e..477c035d8a59 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -6660,10 +6660,9 @@ ExpectedStmt ASTNodeImporter::VisitUnaryOperator(UnaryOperator *E) {
   if (Err)
     return std::move(Err);
 
-  return UnaryOperator::Create(
-      Importer.getToContext(), ToSubExpr, E->getOpcode(), ToType,
-      E->getValueKind(), E->getObjectKind(), ToOperatorLoc, E->canOverflow(),
-      E->getFPFeatures(Importer.getFromContext().getLangOpts()));
+  return new (Importer.getToContext()) UnaryOperator(
+      ToSubExpr, E->getOpcode(), ToType, E->getValueKind(), E->getObjectKind(),
+      ToOperatorLoc, E->canOverflow());
 }
 
 ExpectedStmt

diff  --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index 36083d3227c7..bb27f40994dc 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -1358,8 +1358,7 @@ CallExpr *CallExpr::CreateTemporary(void *Mem, Expr *Fn, QualType Ty,
   assert(!(reinterpret_cast<uintptr_t>(Mem) % alignof(CallExpr)) &&
          "Misaligned memory in CallExpr::CreateTemporary!");
   return new (Mem) CallExpr(CallExprClass, Fn, /*PreArgs=*/{}, /*Args=*/{}, Ty,
-                            VK, RParenLoc,
-                            /*MinNumArgs=*/0, UsesADL);
+                            VK, RParenLoc, /*MinNumArgs=*/0, UsesADL);
 }
 
 CallExpr *CallExpr::CreateEmpty(const ASTContext &Ctx, unsigned NumArgs,
@@ -4446,38 +4445,6 @@ CompoundAssignOperator *CompoundAssignOperator::Create(
                              CompLHSType, CompResultType);
 }
 
-UnaryOperator *UnaryOperator::CreateEmpty(const ASTContext &C,
-                                          bool hasFPFeatures) {
-  void *Mem = C.Allocate(totalSizeToAlloc<FPOptions>(hasFPFeatures),
-                         alignof(UnaryOperator));
-  return new (Mem) UnaryOperator(hasFPFeatures, EmptyShell());
-}
-
-UnaryOperator::UnaryOperator(const ASTContext &Ctx, Expr *input, Opcode opc,
-                             QualType type, ExprValueKind VK, ExprObjectKind OK,
-                             SourceLocation l, bool CanOverflow,
-                             FPOptions FPFeatures)
-    : Expr(UnaryOperatorClass, type, VK, OK), Val(input) {
-  UnaryOperatorBits.Opc = opc;
-  UnaryOperatorBits.CanOverflow = CanOverflow;
-  UnaryOperatorBits.Loc = l;
-  UnaryOperatorBits.HasFPFeatures =
-      FPFeatures.requiresTrailingStorage(Ctx.getLangOpts());
-  setDependence(computeDependence(this));
-}
-
-UnaryOperator *UnaryOperator::Create(const ASTContext &C, Expr *input,
-                                     Opcode opc, QualType type,
-                                     ExprValueKind VK, ExprObjectKind OK,
-                                     SourceLocation l, bool CanOverflow,
-                                     FPOptions FPFeatures) {
-  bool HasFPFeatures = FPFeatures.requiresTrailingStorage(C.getLangOpts());
-  unsigned Size = totalSizeToAlloc<FPOptions>(HasFPFeatures);
-  void *Mem = C.Allocate(Size, alignof(UnaryOperator));
-  return new (Mem)
-      UnaryOperator(C, input, opc, type, VK, OK, l, CanOverflow, FPFeatures);
-}
-
 const OpaqueValueExpr *OpaqueValueExpr::findInCopyConstruct(const Expr *e) {
   if (const ExprWithCleanups *ewc = dyn_cast<ExprWithCleanups>(e))
     e = ewc->getSubExpr();

diff  --git a/clang/lib/Analysis/BodyFarm.cpp b/clang/lib/Analysis/BodyFarm.cpp
index e10fbce71146..852954618463 100644
--- a/clang/lib/Analysis/BodyFarm.cpp
+++ b/clang/lib/Analysis/BodyFarm.cpp
@@ -146,10 +146,9 @@ DeclRefExpr *ASTMaker::makeDeclRefExpr(
 }
 
 UnaryOperator *ASTMaker::makeDereference(const Expr *Arg, QualType Ty) {
-  return UnaryOperator::Create(C, const_cast<Expr *>(Arg), UO_Deref, Ty,
+  return new (C) UnaryOperator(const_cast<Expr*>(Arg), UO_Deref, Ty,
                                VK_LValue, OK_Ordinary, SourceLocation(),
-                               /*CanOverflow*/ false,
-                               FPOptions(C.getLangOpts()));
+                              /*CanOverflow*/ false);
 }
 
 ImplicitCastExpr *ASTMaker::makeLvalueToRvalue(const Expr *Arg, QualType Ty) {
@@ -448,16 +447,15 @@ static Stmt *create_call_once(ASTContext &C, const FunctionDecl *D) {
   QualType DerefType = Deref->getType();
 
   // Negation predicate.
-  UnaryOperator *FlagCheck = UnaryOperator::Create(
-      C,
+  UnaryOperator *FlagCheck = new (C) UnaryOperator(
       /* input=*/
       M.makeImplicitCast(M.makeLvalueToRvalue(Deref, DerefType), DerefType,
                          CK_IntegralToBoolean),
-      /* opc=*/UO_LNot,
-      /* QualType=*/C.IntTy,
-      /* ExprValueKind=*/VK_RValue,
-      /* ExprObjectKind=*/OK_Ordinary, SourceLocation(),
-      /* CanOverflow*/ false, FPOptions(C.getLangOpts()));
+      /* opc=*/ UO_LNot,
+      /* QualType=*/ C.IntTy,
+      /* ExprValueKind=*/ VK_RValue,
+      /* ExprObjectKind=*/ OK_Ordinary, SourceLocation(),
+      /* CanOverflow*/ false);
 
   // Create assignment.
   BinaryOperator *FlagAssignment = M.makeAssignment(
@@ -520,9 +518,9 @@ static Stmt *create_dispatch_once(ASTContext &C, const FunctionDecl *D) {
 
   // (2) Create the assignment to the predicate.
   Expr *DoneValue =
-      UnaryOperator::Create(C, M.makeIntegerLiteral(0, C.LongTy), UO_Not,
-                            C.LongTy, VK_RValue, OK_Ordinary, SourceLocation(),
-                            /*CanOverflow*/ false, FPOptions(C.getLangOpts()));
+      new (C) UnaryOperator(M.makeIntegerLiteral(0, C.LongTy), UO_Not, C.LongTy,
+                            VK_RValue, OK_Ordinary, SourceLocation(),
+                            /*CanOverflow*/false);
 
   BinaryOperator *B =
     M.makeAssignment(

diff  --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp
index 76f58b284eeb..c3f2352f68f2 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -217,14 +217,7 @@ static bool CanElideOverflowCheck(const ASTContext &Ctx, const BinOpInfo &Op) {
 /// Update the FastMathFlags of LLVM IR from the FPOptions in LangOptions.
 static void updateFastMathFlags(llvm::FastMathFlags &FMF,
                                 FPOptions FPFeatures) {
-  FMF.setAllowReassoc(FPFeatures.allowAssociativeMath());
-  FMF.setNoNaNs(FPFeatures.noHonorNaNs());
-  FMF.setNoInfs(FPFeatures.noHonorInfs());
-  FMF.setNoSignedZeros(FPFeatures.noSignedZeros());
-  FMF.setAllowReciprocal(FPFeatures.allowReciprocalMath());
-  FMF.setApproxFunc(FPFeatures.allowApproximateFunctions());
-  FMF.setAllowContract(FPFeatures.allowFPContractAcrossStatement() ||
-                       FPFeatures.allowFPContractWithinStatement());
+  FMF.setAllowContract(FPFeatures.allowFPContractAcrossStatement());
 }
 
 /// Propagate fast-math flags from \p Op to the instruction in \p V.
@@ -237,25 +230,6 @@ static Value *propagateFMFlags(Value *V, const BinOpInfo &Op) {
   return V;
 }
 
-static void setBuilderFlagsFromFPFeatures(CGBuilderTy &Builder,
-                                          CodeGenFunction &CGF,
-                                          FPOptions FPFeatures) {
-  auto NewRoundingBehavior = FPFeatures.getRoundingMode();
-  Builder.setDefaultConstrainedRounding(NewRoundingBehavior);
-  auto NewExceptionBehavior =
-      ToConstrainedExceptMD(FPFeatures.getExceptionMode());
-  Builder.setDefaultConstrainedExcept(NewExceptionBehavior);
-  auto FMF = Builder.getFastMathFlags();
-  updateFastMathFlags(FMF, FPFeatures);
-  Builder.setFastMathFlags(FMF);
-  assert((CGF.CurFuncDecl == nullptr || Builder.getIsFPConstrained() ||
-          isa<CXXConstructorDecl>(CGF.CurFuncDecl) ||
-          isa<CXXDestructorDecl>(CGF.CurFuncDecl) ||
-          (NewExceptionBehavior == llvm::fp::ebIgnore &&
-           NewRoundingBehavior == llvm::RoundingMode::NearestTiesToEven)) &&
-         "FPConstrained should be enabled on entire function");
-}
-
 class ScalarExprEmitter
   : public StmtVisitor<ScalarExprEmitter, Value*> {
   CodeGenFunction &CGF;
@@ -770,9 +744,6 @@ class ScalarExprEmitter
       return EmitOverflowCheckedBinOp(Ops);
 
     if (Ops.LHS->getType()->isFPOrFPVectorTy()) {
-      //  Preserve the old values
-      llvm::IRBuilder<>::FastMathFlagGuard FMFG(Builder);
-      setBuilderFlagsFromFPFeatures(Builder, CGF, Ops.FPFeatures);
       Value *V = Builder.CreateFMul(Ops.LHS, Ops.RHS, "mul");
       return propagateFMFlags(V, Ops);
     }
@@ -2362,14 +2333,13 @@ Value *ScalarExprEmitter::VisitExprWithCleanups(ExprWithCleanups *E) {
 //===----------------------------------------------------------------------===//
 
 static BinOpInfo createBinOpInfoFromIncDec(const UnaryOperator *E,
-                                           llvm::Value *InVal, bool IsInc,
-                                           FPOptions FPFeatures) {
+                                           llvm::Value *InVal, bool IsInc) {
   BinOpInfo BinOp;
   BinOp.LHS = InVal;
   BinOp.RHS = llvm::ConstantInt::get(InVal->getType(), 1, false);
   BinOp.Ty = E->getType();
   BinOp.Opcode = IsInc ? BO_Add : BO_Sub;
-  BinOp.FPFeatures = FPFeatures;
+  // FIXME: once UnaryOperator carries FPFeatures, copy it here.
   BinOp.E = E;
   return BinOp;
 }
@@ -2389,8 +2359,7 @@ llvm::Value *ScalarExprEmitter::EmitIncDecConsiderOverflowBehavior(
   case LangOptions::SOB_Trapping:
     if (!E->canOverflow())
       return Builder.CreateNSWAdd(InVal, Amount, Name);
-    return EmitOverflowCheckedBinOp(createBinOpInfoFromIncDec(
-        E, InVal, IsInc, E->getFPFeatures(CGF.getLangOpts())));
+    return EmitOverflowCheckedBinOp(createBinOpInfoFromIncDec(E, InVal, IsInc));
   }
   llvm_unreachable("Unknown SignedOverflowBehaviorTy");
 }
@@ -2536,8 +2505,8 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
       value = EmitIncDecConsiderOverflowBehavior(E, value, isInc);
     } else if (E->canOverflow() && type->isUnsignedIntegerType() &&
                CGF.SanOpts.has(SanitizerKind::UnsignedIntegerOverflow)) {
-      value = EmitOverflowCheckedBinOp(createBinOpInfoFromIncDec(
-          E, value, isInc, E->getFPFeatures(CGF.getLangOpts())));
+      value =
+          EmitOverflowCheckedBinOp(createBinOpInfoFromIncDec(E, value, isInc));
     } else {
       llvm::Value *amt = llvm::ConstantInt::get(value->getType(), amount, true);
       value = Builder.CreateAdd(value, amt, isInc ? "inc" : "dec");
@@ -2737,7 +2706,7 @@ Value *ScalarExprEmitter::VisitUnaryMinus(const UnaryOperator *E) {
   BinOp.LHS = llvm::Constant::getNullValue(BinOp.RHS->getType());
   BinOp.Ty = E->getType();
   BinOp.Opcode = BO_Sub;
-  BinOp.FPFeatures = E->getFPFeatures(CGF.getLangOpts());
+  // FIXME: once UnaryOperator carries FPFeatures, copy it here.
   BinOp.E = E;
   return EmitSub(BinOp);
 }
@@ -2754,12 +2723,9 @@ Value *ScalarExprEmitter::VisitUnaryLNot(const UnaryOperator *E) {
     Value *Oper = Visit(E->getSubExpr());
     Value *Zero = llvm::Constant::getNullValue(Oper->getType());
     Value *Result;
-    if (Oper->getType()->isFPOrFPVectorTy()) {
-      llvm::IRBuilder<>::FastMathFlagGuard FMFG(Builder);
-      setBuilderFlagsFromFPFeatures(Builder, CGF,
-                                    E->getFPFeatures(CGF.getLangOpts()));
+    if (Oper->getType()->isFPOrFPVectorTy())
       Result = Builder.CreateFCmp(llvm::CmpInst::FCMP_OEQ, Oper, Zero, "cmp");
-    } else
+    else
       Result = Builder.CreateICmp(llvm::CmpInst::ICMP_EQ, Oper, Zero, "cmp");
     return Builder.CreateSExt(Result, ConvertType(E->getType()), "sext");
   }
@@ -3168,10 +3134,7 @@ Value *ScalarExprEmitter::EmitDiv(const BinOpInfo &Ops) {
   }
 
   if (Ops.LHS->getType()->isFPOrFPVectorTy()) {
-    llvm::Value *Val;
-    llvm::IRBuilder<>::FastMathFlagGuard FMFG(Builder);
-    setBuilderFlagsFromFPFeatures(Builder, CGF, Ops.FPFeatures);
-    Val = Builder.CreateFDiv(Ops.LHS, Ops.RHS, "div");
+    llvm::Value *Val = Builder.CreateFDiv(Ops.LHS, Ops.RHS, "div");
     if (CGF.getLangOpts().OpenCL &&
         !CGF.CGM.getCodeGenOpts().CorrectlyRoundedDivSqrt) {
       // OpenCL v1.1 s7.4: minimum accuracy of single precision / is 2.5ulp
@@ -3543,8 +3506,6 @@ Value *ScalarExprEmitter::EmitAdd(const BinOpInfo &op) {
     return EmitOverflowCheckedBinOp(op);
 
   if (op.LHS->getType()->isFPOrFPVectorTy()) {
-    llvm::IRBuilder<>::FastMathFlagGuard FMFG(Builder);
-    setBuilderFlagsFromFPFeatures(Builder, CGF, op.FPFeatures);
     // Try to form an fmuladd.
     if (Value *FMulAdd = tryEmitFMulAdd(op, CGF, Builder))
       return FMulAdd;
@@ -3727,8 +3688,6 @@ Value *ScalarExprEmitter::EmitSub(const BinOpInfo &op) {
       return EmitOverflowCheckedBinOp(op);
 
     if (op.LHS->getType()->isFPOrFPVectorTy()) {
-      llvm::IRBuilder<>::FastMathFlagGuard FMFG(Builder);
-      setBuilderFlagsFromFPFeatures(Builder, CGF, op.FPFeatures);
       // Try to form an fmuladd.
       if (Value *FMulAdd = tryEmitFMulAdd(op, CGF, Builder, true))
         return FMulAdd;
@@ -4055,8 +4014,6 @@ Value *ScalarExprEmitter::EmitCompare(const BinaryOperator *E,
     if (BOInfo.isFixedPointOp()) {
       Result = EmitFixedPointBinOp(BOInfo);
     } else if (LHS->getType()->isFPOrFPVectorTy()) {
-      llvm::IRBuilder<>::FastMathFlagGuard FMFG(Builder);
-      setBuilderFlagsFromFPFeatures(Builder, CGF, BOInfo.FPFeatures);
       if (!IsSignaling)
         Result = Builder.CreateFCmp(FCmpOpc, LHS, RHS, "cmp");
       else
@@ -4209,9 +4166,6 @@ Value *ScalarExprEmitter::VisitBinLAnd(const BinaryOperator *E) {
     Value *RHS = Visit(E->getRHS());
     Value *Zero = llvm::ConstantAggregateZero::get(LHS->getType());
     if (LHS->getType()->isFPOrFPVectorTy()) {
-      llvm::IRBuilder<>::FastMathFlagGuard FMFG(Builder);
-      setBuilderFlagsFromFPFeatures(Builder, CGF,
-                                    E->getFPFeatures(CGF.getLangOpts()));
       LHS = Builder.CreateFCmp(llvm::CmpInst::FCMP_UNE, LHS, Zero, "cmp");
       RHS = Builder.CreateFCmp(llvm::CmpInst::FCMP_UNE, RHS, Zero, "cmp");
     } else {
@@ -4296,9 +4250,6 @@ Value *ScalarExprEmitter::VisitBinLOr(const BinaryOperator *E) {
     Value *RHS = Visit(E->getRHS());
     Value *Zero = llvm::ConstantAggregateZero::get(LHS->getType());
     if (LHS->getType()->isFPOrFPVectorTy()) {
-      llvm::IRBuilder<>::FastMathFlagGuard FMFG(Builder);
-      setBuilderFlagsFromFPFeatures(Builder, CGF,
-                                    E->getFPFeatures(CGF.getLangOpts()));
       LHS = Builder.CreateFCmp(llvm::CmpInst::FCMP_UNE, LHS, Zero, "cmp");
       RHS = Builder.CreateFCmp(llvm::CmpInst::FCMP_UNE, RHS, Zero, "cmp");
     } else {

diff  --git a/clang/lib/CodeGen/CGObjC.cpp b/clang/lib/CodeGen/CGObjC.cpp
index ff4591a3c446..e3df22aef2c1 100644
--- a/clang/lib/CodeGen/CGObjC.cpp
+++ b/clang/lib/CodeGen/CGObjC.cpp
@@ -3556,17 +3556,17 @@ CodeGenFunction::GenerateObjCAtomicSetterCopyHelperFunction(
 
   StartFunction(FD, ReturnTy, Fn, FI, args);
 
-  DeclRefExpr DstExpr(C, &DstDecl, false, DestTy, VK_RValue, SourceLocation());
-  UnaryOperator *DST = UnaryOperator::Create(
-      C, &DstExpr, UO_Deref, DestTy->getPointeeType(), VK_LValue, OK_Ordinary,
-      SourceLocation(), false, FPOptions(C.getLangOpts()));
+  DeclRefExpr DstExpr(getContext(), &DstDecl, false, DestTy, VK_RValue,
+                      SourceLocation());
+  UnaryOperator DST(&DstExpr, UO_Deref, DestTy->getPointeeType(),
+                    VK_LValue, OK_Ordinary, SourceLocation(), false);
 
-  DeclRefExpr SrcExpr(C, &SrcDecl, false, SrcTy, VK_RValue, SourceLocation());
-  UnaryOperator *SRC = UnaryOperator::Create(
-      C, &SrcExpr, UO_Deref, SrcTy->getPointeeType(), VK_LValue, OK_Ordinary,
-      SourceLocation(), false, FPOptions(C.getLangOpts()));
+  DeclRefExpr SrcExpr(getContext(), &SrcDecl, false, SrcTy, VK_RValue,
+                      SourceLocation());
+  UnaryOperator SRC(&SrcExpr, UO_Deref, SrcTy->getPointeeType(),
+                    VK_LValue, OK_Ordinary, SourceLocation(), false);
 
-  Expr *Args[2] = {DST, SRC};
+  Expr *Args[2] = { &DST, &SRC };
   CallExpr *CalleeExp = cast<CallExpr>(PID->getSetterCXXAssignment());
   CXXOperatorCallExpr *TheCall = CXXOperatorCallExpr::Create(
       C, OO_Equal, CalleeExp->getCallee(), Args, DestTy->getPointeeType(),
@@ -3642,15 +3642,14 @@ CodeGenFunction::GenerateObjCAtomicGetterCopyHelperFunction(
   DeclRefExpr SrcExpr(getContext(), &SrcDecl, false, SrcTy, VK_RValue,
                       SourceLocation());
 
-  UnaryOperator *SRC = UnaryOperator::Create(
-      C, &SrcExpr, UO_Deref, SrcTy->getPointeeType(), VK_LValue, OK_Ordinary,
-      SourceLocation(), false, FPOptions(C.getLangOpts()));
+  UnaryOperator SRC(&SrcExpr, UO_Deref, SrcTy->getPointeeType(),
+                    VK_LValue, OK_Ordinary, SourceLocation(), false);
 
   CXXConstructExpr *CXXConstExpr =
     cast<CXXConstructExpr>(PID->getGetterCXXConstructor());
 
   SmallVector<Expr*, 4> ConstructorArgs;
-  ConstructorArgs.push_back(SRC);
+  ConstructorArgs.push_back(&SRC);
   ConstructorArgs.append(std::next(CXXConstExpr->arg_begin()),
                          CXXConstExpr->arg_end());
 

diff  --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp
index ae3094430fdf..02075be36dd5 100644
--- a/clang/lib/CodeGen/CGStmtOpenMP.cpp
+++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp
@@ -3055,9 +3055,8 @@ void CodeGenFunction::EmitSections(const OMPExecutableDirective &S) {
         C, &IVRefExpr, &UBRefExpr, BO_LE, C.BoolTy, VK_RValue, OK_Ordinary,
         S.getBeginLoc(), FPOptions(C.getLangOpts()));
     // Increment for loop counter.
-    UnaryOperator *Inc = UnaryOperator::Create(
-        C, &IVRefExpr, UO_PreInc, KmpInt32Ty, VK_RValue, OK_Ordinary,
-        S.getBeginLoc(), true, FPOptions(C.getLangOpts()));
+    UnaryOperator Inc(&IVRefExpr, UO_PreInc, KmpInt32Ty, VK_RValue, OK_Ordinary,
+                      S.getBeginLoc(), true);
     auto &&BodyGen = [CapturedStmt, CS, &S, &IV](CodeGenFunction &CGF) {
       // Iterate through all sections and emit a switch construct:
       // switch (IV) {
@@ -3127,7 +3126,7 @@ void CodeGenFunction::EmitSections(const OMPExecutableDirective &S) {
     // IV = LB;
     CGF.EmitStoreOfScalar(CGF.EmitLoadOfScalar(LB, S.getBeginLoc()), IV);
     // while (idx <= UB) { BODY; ++idx; }
-    CGF.EmitOMPInnerLoop(S, /*RequiresCleanup=*/false, Cond, Inc, BodyGen,
+    CGF.EmitOMPInnerLoop(S, /*RequiresCleanup=*/false, Cond, &Inc, BodyGen,
                          [](CodeGenFunction &) {});
     // Tell the runtime we are done.
     auto &&CodeGen = [&S](CodeGenFunction &CGF) {

diff  --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index 4fcf31a5f1aa..24e01c46045e 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -117,8 +117,8 @@ CodeGenFunction::~CodeGenFunction() {
 
 // Map the LangOption for exception behavior into
 // the corresponding enum in the IR.
-llvm::fp::ExceptionBehavior
-clang::ToConstrainedExceptMD(LangOptions::FPExceptionModeKind Kind) {
+static llvm::fp::ExceptionBehavior ToConstrainedExceptMD(
+  LangOptions::FPExceptionModeKind Kind) {
 
   switch (Kind) {
   case LangOptions::FPE_Ignore:  return llvm::fp::ebIgnore;
@@ -133,10 +133,15 @@ void CodeGenFunction::SetFPModel() {
   auto fpExceptionBehavior = ToConstrainedExceptMD(
                                getLangOpts().getFPExceptionMode());
 
-  Builder.setDefaultConstrainedRounding(RM);
-  Builder.setDefaultConstrainedExcept(fpExceptionBehavior);
-  Builder.setIsFPConstrained(fpExceptionBehavior != llvm::fp::ebIgnore ||
-                             RM != llvm::RoundingMode::NearestTiesToEven);
+  if (fpExceptionBehavior == llvm::fp::ebIgnore &&
+      RM == llvm::RoundingMode::NearestTiesToEven)
+    // Constrained intrinsics are not used.
+    ;
+  else {
+    Builder.setIsFPConstrained(true);
+    Builder.setDefaultConstrainedRounding(RM);
+    Builder.setDefaultConstrainedExcept(fpExceptionBehavior);
+  }
 }
 
 CharUnits CodeGenFunction::getNaturalPointeeTypeAlignment(QualType T,
@@ -914,11 +919,9 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
       Fn->addFnAttr(llvm::Attribute::NoRecurse);
   }
 
-  if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) {
-    Builder.setIsFPConstrained(FD->usesFPIntrin());
+  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.

diff  --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index 2639fd815ea1..0e09eb75e8ad 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -4575,11 +4575,6 @@ inline llvm::Value *DominatingLLVMValue::restore(CodeGenFunction &CGF,
 }
 
 }  // end namespace CodeGen
-
-// Map the LangOption for floating point exception behavior into
-// the corresponding enum in the IR.
-llvm::fp::ExceptionBehavior
-ToConstrainedExceptMD(LangOptions::FPExceptionModeKind Kind);
 }  // end namespace clang
 
 #endif

diff  --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index 391f0e929eb5..b327fa902f67 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -2455,7 +2455,7 @@ static const StringRef GetInputKindName(InputKind IK) {
 
 static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
                           const TargetOptions &TargetOpts,
-                          PreprocessorOptions &PPOpts, CodeGenOptions &CGOpts,
+                          PreprocessorOptions &PPOpts,
                           DiagnosticsEngine &Diags) {
   // FIXME: Cleanup per-file based stuff.
   LangStandard::Kind LangStd = LangStandard::lang_unspecified;
@@ -3187,19 +3187,6 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
   Opts.UnsafeFPMath = Args.hasArg(OPT_menable_unsafe_fp_math) ||
                       Args.hasArg(OPT_cl_unsafe_math_optimizations) ||
                       Args.hasArg(OPT_cl_fast_relaxed_math);
-  Opts.AllowFPReassoc = Opts.FastMath || CGOpts.Reassociate;
-  Opts.NoHonorNaNs =
-      Opts.FastMath || CGOpts.NoNaNsFPMath || Opts.FiniteMathOnly;
-  Opts.NoHonorInfs =
-      Opts.FastMath || CGOpts.NoInfsFPMath || Opts.FiniteMathOnly;
-  Opts.NoSignedZero = Opts.FastMath || CGOpts.NoSignedZeros;
-  Opts.AllowRecip = Opts.FastMath || CGOpts.ReciprocalMath;
-  // Currently there's no clang option to enable this individually
-  Opts.ApproxFunc = Opts.FastMath;
-  Opts.denormalIsIEEE =
-      !(CGOpts.FPDenormalMode.isValid() && CGOpts.FP32DenormalMode.isValid()) ||
-      (CGOpts.FPDenormalMode == llvm::DenormalMode::getIEEE() &&
-       CGOpts.FP32DenormalMode == llvm::DenormalMode::getIEEE());
 
   if (Arg *A = Args.getLastArg(OPT_ffp_contract)) {
     StringRef Val = A->getValue();
@@ -3653,7 +3640,7 @@ bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Res,
     // Other LangOpts are only initialized when the input is not AST or LLVM IR.
     // FIXME: Should we really be calling this for an Language::Asm input?
     ParseLangArgs(LangOpts, Args, DashX, Res.getTargetOpts(),
-                  Res.getPreprocessorOpts(), Res.getCodeGenOpts(), Diags);
+                  Res.getPreprocessorOpts(), Diags);
     if (Res.getFrontendOpts().ProgramAction == frontend::RewriteObjC)
       LangOpts.ObjCExceptions = 1;
     if (T.isOSDarwin() && DashX.isPreprocessed()) {

diff  --git a/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp b/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp
index bb195ade1409..c46ba9832c0d 100644
--- a/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp
+++ b/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp
@@ -2587,10 +2587,9 @@ Stmt *RewriteModernObjC::RewriteObjCStringLiteral(ObjCStringLiteral *Exp) {
                                    strType, nullptr, SC_Static);
   DeclRefExpr *DRE = new (Context)
       DeclRefExpr(*Context, NewVD, false, strType, VK_LValue, SourceLocation());
-  Expr *Unop = UnaryOperator::Create(
-      const_cast<ASTContext &>(*Context), DRE, UO_AddrOf,
-      Context->getPointerType(DRE->getType()), VK_RValue, OK_Ordinary,
-      SourceLocation(), false, FPOptions(Context->getLangOpts()));
+  Expr *Unop = new (Context)
+      UnaryOperator(DRE, UO_AddrOf, Context->getPointerType(DRE->getType()),
+                    VK_RValue, OK_Ordinary, SourceLocation(), false);
   // cast to NSConstantString *
   CastExpr *cast = NoTypeInfoCStyleCastExpr(Context, Exp->getType(),
                                             CK_CPointerToObjCPointerCast, Unop);
@@ -3284,10 +3283,10 @@ Stmt *RewriteModernObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
       // we need the cast below. For example:
       // (struct __rw_objc_super *)&__rw_objc_super((id)self, (id)objc_getClass("SUPER"))
       //
-      SuperRep = UnaryOperator::Create(
-          const_cast<ASTContext &>(*Context), SuperRep, UO_AddrOf,
-          Context->getPointerType(SuperRep->getType()), VK_RValue, OK_Ordinary,
-          SourceLocation(), false, FPOptions(Context->getLangOpts()));
+      SuperRep = new (Context) UnaryOperator(SuperRep, UO_AddrOf,
+                               Context->getPointerType(SuperRep->getType()),
+                                             VK_RValue, OK_Ordinary,
+                                             SourceLocation(), false);
       SuperRep = NoTypeInfoCStyleCastExpr(Context,
                                           Context->getPointerType(superType),
                                           CK_BitCast, SuperRep);
@@ -3302,10 +3301,10 @@ Stmt *RewriteModernObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
                                                    superType, VK_LValue,
                                                    ILE, false);
       // struct __rw_objc_super *
-      SuperRep = UnaryOperator::Create(
-          const_cast<ASTContext &>(*Context), SuperRep, UO_AddrOf,
-          Context->getPointerType(SuperRep->getType()), VK_RValue, OK_Ordinary,
-          SourceLocation(), false, FPOptions(Context->getLangOpts()));
+      SuperRep = new (Context) UnaryOperator(SuperRep, UO_AddrOf,
+                               Context->getPointerType(SuperRep->getType()),
+                                             VK_RValue, OK_Ordinary,
+                                             SourceLocation(), false);
     }
     MsgExprs.push_back(SuperRep);
     break;
@@ -3379,10 +3378,10 @@ Stmt *RewriteModernObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
       // we need the cast below. For example:
       // (struct __rw_objc_super *)&__rw_objc_super((id)self, (id)objc_getClass("SUPER"))
       //
-      SuperRep = UnaryOperator::Create(
-          const_cast<ASTContext &>(*Context), SuperRep, UO_AddrOf,
-          Context->getPointerType(SuperRep->getType()), VK_RValue, OK_Ordinary,
-          SourceLocation(), false, FPOptions(Context->getLangOpts()));
+      SuperRep = new (Context) UnaryOperator(SuperRep, UO_AddrOf,
+                               Context->getPointerType(SuperRep->getType()),
+                               VK_RValue, OK_Ordinary,
+                               SourceLocation(), false);
       SuperRep = NoTypeInfoCStyleCastExpr(Context,
                                Context->getPointerType(superType),
                                CK_BitCast, SuperRep);
@@ -4706,10 +4705,9 @@ Stmt *RewriteModernObjC::RewriteLocalVariableExternalStorage(DeclRefExpr *DRE) {
   if (VarDecl *Var = dyn_cast<VarDecl>(VD))
     if (!ImportedLocalExternalDecls.count(Var))
       return DRE;
-  Expr *Exp = UnaryOperator::Create(const_cast<ASTContext &>(*Context), DRE,
-                                    UO_Deref, DRE->getType(), VK_LValue,
-                                    OK_Ordinary, DRE->getLocation(), false,
-                                    FPOptions(Context->getLangOpts()));
+  Expr *Exp = new (Context) UnaryOperator(DRE, UO_Deref, DRE->getType(),
+                                          VK_LValue, OK_Ordinary,
+                                          DRE->getLocation(), false);
   // Need parens to enforce precedence.
   ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(),
                                           Exp);
@@ -5295,12 +5293,11 @@ Stmt *RewriteModernObjC::SynthBlockInitExpr(BlockExpr *Exp,
   VarDecl *NewVD = VarDecl::Create(
       *Context, TUDecl, SourceLocation(), SourceLocation(),
       &Context->Idents.get(DescData), Context->VoidPtrTy, nullptr, SC_Static);
-  UnaryOperator *DescRefExpr = UnaryOperator::Create(
-      const_cast<ASTContext &>(*Context),
+  UnaryOperator *DescRefExpr = new (Context) UnaryOperator(
       new (Context) DeclRefExpr(*Context, NewVD, false, Context->VoidPtrTy,
                                 VK_LValue, SourceLocation()),
       UO_AddrOf, Context->getPointerType(Context->VoidPtrTy), VK_RValue,
-      OK_Ordinary, SourceLocation(), false, FPOptions(Context->getLangOpts()));
+      OK_Ordinary, SourceLocation(), false);
   InitExprs.push_back(DescRefExpr);
 
   // Add initializers for any closure decl refs.
@@ -5317,10 +5314,9 @@ Stmt *RewriteModernObjC::SynthBlockInitExpr(BlockExpr *Exp,
         if (HasLocalVariableExternalStorage(*I)) {
           QualType QT = (*I)->getType();
           QT = Context->getPointerType(QT);
-          Exp = UnaryOperator::Create(const_cast<ASTContext &>(*Context), Exp,
-                                      UO_AddrOf, QT, VK_RValue, OK_Ordinary,
-                                      SourceLocation(), false,
-                                      FPOptions(Context->getLangOpts()));
+          Exp = new (Context) UnaryOperator(Exp, UO_AddrOf, QT, VK_RValue,
+                                            OK_Ordinary, SourceLocation(),
+                                            false);
         }
       } else if (isTopLevelBlockPointerType((*I)->getType())) {
         FD = SynthBlockInitFunctionDecl((*I)->getName());
@@ -5335,10 +5331,9 @@ Stmt *RewriteModernObjC::SynthBlockInitExpr(BlockExpr *Exp,
         if (HasLocalVariableExternalStorage(*I)) {
           QualType QT = (*I)->getType();
           QT = Context->getPointerType(QT);
-          Exp = UnaryOperator::Create(const_cast<ASTContext &>(*Context), Exp,
-                                      UO_AddrOf, QT, VK_RValue, OK_Ordinary,
-                                      SourceLocation(), false,
-                                      FPOptions(Context->getLangOpts()));
+          Exp = new (Context) UnaryOperator(Exp, UO_AddrOf, QT, VK_RValue,
+                                            OK_Ordinary, SourceLocation(),
+                                            false);
         }
 
       }
@@ -5376,10 +5371,10 @@ Stmt *RewriteModernObjC::SynthBlockInitExpr(BlockExpr *Exp,
       // captured nested byref variable has its address passed. Do not take
       // its address again.
       if (!isNestedCapturedVar)
-        Exp = UnaryOperator::Create(
-            const_cast<ASTContext &>(*Context), Exp, UO_AddrOf,
-            Context->getPointerType(Exp->getType()), VK_RValue, OK_Ordinary,
-            SourceLocation(), false, FPOptions(Context->getLangOpts()));
+          Exp = new (Context) UnaryOperator(Exp, UO_AddrOf,
+                                     Context->getPointerType(Exp->getType()),
+                                     VK_RValue, OK_Ordinary, SourceLocation(),
+                                     false);
       Exp = NoTypeInfoCStyleCastExpr(Context, castT, CK_BitCast, Exp);
       InitExprs.push_back(Exp);
     }
@@ -5403,10 +5398,9 @@ Stmt *RewriteModernObjC::SynthBlockInitExpr(BlockExpr *Exp,
     NewRep = DRE;
   }
 
-  NewRep = UnaryOperator::Create(
-      const_cast<ASTContext &>(*Context), NewRep, UO_AddrOf,
-      Context->getPointerType(NewRep->getType()), VK_RValue, OK_Ordinary,
-      SourceLocation(), false, FPOptions(Context->getLangOpts()));
+  NewRep = new (Context) UnaryOperator(NewRep, UO_AddrOf,
+                             Context->getPointerType(NewRep->getType()),
+                             VK_RValue, OK_Ordinary, SourceLocation(), false);
   NewRep = NoTypeInfoCStyleCastExpr(Context, FType, CK_BitCast,
                                     NewRep);
   // Put Paren around the call.
@@ -7545,10 +7539,10 @@ Stmt *RewriteModernObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) {
                                           CK_BitCast,
                                           PE);
 
-      Expr *Exp = UnaryOperator::Create(const_cast<ASTContext &>(*Context),
-                                        castExpr, UO_Deref, IvarT, VK_LValue,
-                                        OK_Ordinary, SourceLocation(), false,
-                                        FPOptions(Context->getLangOpts()));
+
+      Expr *Exp = new (Context) UnaryOperator(castExpr, UO_Deref, IvarT,
+                                              VK_LValue, OK_Ordinary,
+                                              SourceLocation(), false);
       PE = new (Context) ParenExpr(OldRange.getBegin(),
                                    OldRange.getEnd(),
                                    Exp);

diff  --git a/clang/lib/Frontend/Rewrite/RewriteObjC.cpp b/clang/lib/Frontend/Rewrite/RewriteObjC.cpp
index 8b618d90b47e..4674f7c6a38c 100644
--- a/clang/lib/Frontend/Rewrite/RewriteObjC.cpp
+++ b/clang/lib/Frontend/Rewrite/RewriteObjC.cpp
@@ -2514,10 +2514,9 @@ Stmt *RewriteObjC::RewriteObjCStringLiteral(ObjCStringLiteral *Exp) {
                                    strType, nullptr, SC_Static);
   DeclRefExpr *DRE = new (Context)
       DeclRefExpr(*Context, NewVD, false, strType, VK_LValue, SourceLocation());
-  Expr *Unop = UnaryOperator::Create(
-      const_cast<ASTContext &>(*Context), DRE, UO_AddrOf,
-      Context->getPointerType(DRE->getType()), VK_RValue, OK_Ordinary,
-      SourceLocation(), false, FPOptions(Context->getLangOpts()));
+  Expr *Unop = new (Context)
+      UnaryOperator(DRE, UO_AddrOf, Context->getPointerType(DRE->getType()),
+                    VK_RValue, OK_Ordinary, SourceLocation(), false);
   // cast to NSConstantString *
   CastExpr *cast = NoTypeInfoCStyleCastExpr(Context, Exp->getType(),
                                             CK_CPointerToObjCPointerCast, Unop);
@@ -2715,10 +2714,10 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
       // we need the cast below. For example:
       // (struct objc_super *)&__rw_objc_super((id)self, (id)objc_getClass("SUPER"))
       //
-      SuperRep = UnaryOperator::Create(
-          const_cast<ASTContext &>(*Context), SuperRep, UO_AddrOf,
-          Context->getPointerType(SuperRep->getType()), VK_RValue, OK_Ordinary,
-          SourceLocation(), false, FPOptions(Context->getLangOpts()));
+      SuperRep = new (Context) UnaryOperator(SuperRep, UO_AddrOf,
+                               Context->getPointerType(SuperRep->getType()),
+                                             VK_RValue, OK_Ordinary,
+                                             SourceLocation(), false);
       SuperRep = NoTypeInfoCStyleCastExpr(Context,
                                           Context->getPointerType(superType),
                                           CK_BitCast, SuperRep);
@@ -2733,10 +2732,10 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
                                                    superType, VK_LValue,
                                                    ILE, false);
       // struct objc_super *
-      SuperRep = UnaryOperator::Create(
-          const_cast<ASTContext &>(*Context), SuperRep, UO_AddrOf,
-          Context->getPointerType(SuperRep->getType()), VK_RValue, OK_Ordinary,
-          SourceLocation(), false, FPOptions(Context->getLangOpts()));
+      SuperRep = new (Context) UnaryOperator(SuperRep, UO_AddrOf,
+                               Context->getPointerType(SuperRep->getType()),
+                                             VK_RValue, OK_Ordinary,
+                                             SourceLocation(), false);
     }
     MsgExprs.push_back(SuperRep);
     break;
@@ -2810,10 +2809,10 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
       // we need the cast below. For example:
       // (struct objc_super *)&__rw_objc_super((id)self, (id)objc_getClass("SUPER"))
       //
-      SuperRep = UnaryOperator::Create(
-          const_cast<ASTContext &>(*Context), SuperRep, UO_AddrOf,
-          Context->getPointerType(SuperRep->getType()), VK_RValue, OK_Ordinary,
-          SourceLocation(), false, FPOptions(Context->getLangOpts()));
+      SuperRep = new (Context) UnaryOperator(SuperRep, UO_AddrOf,
+                               Context->getPointerType(SuperRep->getType()),
+                               VK_RValue, OK_Ordinary,
+                               SourceLocation(), false);
       SuperRep = NoTypeInfoCStyleCastExpr(Context,
                                Context->getPointerType(superType),
                                CK_BitCast, SuperRep);
@@ -3049,10 +3048,9 @@ Stmt *RewriteObjC::RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp) {
                                 nullptr, SC_Extern);
   DeclRefExpr *DRE = new (Context) DeclRefExpr(
       *Context, VD, false, getProtocolType(), VK_LValue, SourceLocation());
-  Expr *DerefExpr = UnaryOperator::Create(
-      const_cast<ASTContext &>(*Context), DRE, UO_AddrOf,
-      Context->getPointerType(DRE->getType()), VK_RValue, OK_Ordinary,
-      SourceLocation(), false, FPOptions(Context->getLangOpts()));
+  Expr *DerefExpr = new (Context) UnaryOperator(DRE, UO_AddrOf,
+                             Context->getPointerType(DRE->getType()),
+                             VK_RValue, OK_Ordinary, SourceLocation(), false);
   CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, DerefExpr->getType(),
                                                 CK_BitCast,
                                                 DerefExpr);
@@ -3877,10 +3875,9 @@ Stmt *RewriteObjC::RewriteLocalVariableExternalStorage(DeclRefExpr *DRE) {
   if (VarDecl *Var = dyn_cast<VarDecl>(VD))
     if (!ImportedLocalExternalDecls.count(Var))
       return DRE;
-  Expr *Exp = UnaryOperator::Create(const_cast<ASTContext &>(*Context), DRE,
-                                    UO_Deref, DRE->getType(), VK_LValue,
-                                    OK_Ordinary, DRE->getLocation(), false,
-                                    FPOptions(Context->getLangOpts()));
+  Expr *Exp = new (Context) UnaryOperator(DRE, UO_Deref, DRE->getType(),
+                                          VK_LValue, OK_Ordinary,
+                                          DRE->getLocation(), false);
   // Need parens to enforce precedence.
   ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(),
                                           Exp);
@@ -4435,12 +4432,11 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp,
   VarDecl *NewVD = VarDecl::Create(
       *Context, TUDecl, SourceLocation(), SourceLocation(),
       &Context->Idents.get(DescData), Context->VoidPtrTy, nullptr, SC_Static);
-  UnaryOperator *DescRefExpr = UnaryOperator::Create(
-      const_cast<ASTContext &>(*Context),
+  UnaryOperator *DescRefExpr = new (Context) UnaryOperator(
       new (Context) DeclRefExpr(*Context, NewVD, false, Context->VoidPtrTy,
                                 VK_LValue, SourceLocation()),
       UO_AddrOf, Context->getPointerType(Context->VoidPtrTy), VK_RValue,
-      OK_Ordinary, SourceLocation(), false, FPOptions(Context->getLangOpts()));
+      OK_Ordinary, SourceLocation(), false);
   InitExprs.push_back(DescRefExpr);
 
   // Add initializers for any closure decl refs.
@@ -4457,10 +4453,9 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp,
         if (HasLocalVariableExternalStorage(*I)) {
           QualType QT = (*I)->getType();
           QT = Context->getPointerType(QT);
-          Exp = UnaryOperator::Create(const_cast<ASTContext &>(*Context), Exp,
-                                      UO_AddrOf, QT, VK_RValue, OK_Ordinary,
-                                      SourceLocation(), false,
-                                      FPOptions(Context->getLangOpts()));
+          Exp = new (Context) UnaryOperator(Exp, UO_AddrOf, QT, VK_RValue,
+                                            OK_Ordinary, SourceLocation(),
+                                            false);
         }
       } else if (isTopLevelBlockPointerType((*I)->getType())) {
         FD = SynthBlockInitFunctionDecl((*I)->getName());
@@ -4475,10 +4470,9 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp,
         if (HasLocalVariableExternalStorage(*I)) {
           QualType QT = (*I)->getType();
           QT = Context->getPointerType(QT);
-          Exp = UnaryOperator::Create(const_cast<ASTContext &>(*Context), Exp,
-                                      UO_AddrOf, QT, VK_RValue, OK_Ordinary,
-                                      SourceLocation(), false,
-                                      FPOptions(Context->getLangOpts()));
+          Exp = new (Context) UnaryOperator(Exp, UO_AddrOf, QT, VK_RValue,
+                                            OK_Ordinary, SourceLocation(),
+                                            false);
         }
       }
       InitExprs.push_back(Exp);
@@ -4515,10 +4509,9 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp,
       // captured nested byref variable has its address passed. Do not take
       // its address again.
       if (!isNestedCapturedVar)
-        Exp = UnaryOperator::Create(
-            const_cast<ASTContext &>(*Context), Exp, UO_AddrOf,
-            Context->getPointerType(Exp->getType()), VK_RValue, OK_Ordinary,
-            SourceLocation(), false, FPOptions(Context->getLangOpts()));
+        Exp = new (Context) UnaryOperator(
+            Exp, UO_AddrOf, Context->getPointerType(Exp->getType()), VK_RValue,
+            OK_Ordinary, SourceLocation(), false);
       Exp = NoTypeInfoCStyleCastExpr(Context, castT, CK_BitCast, Exp);
       InitExprs.push_back(Exp);
     }
@@ -4534,10 +4527,9 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp,
   }
   NewRep = CallExpr::Create(*Context, DRE, InitExprs, FType, VK_LValue,
                             SourceLocation());
-  NewRep = UnaryOperator::Create(
-      const_cast<ASTContext &>(*Context), NewRep, UO_AddrOf,
-      Context->getPointerType(NewRep->getType()), VK_RValue, OK_Ordinary,
-      SourceLocation(), false, FPOptions(Context->getLangOpts()));
+  NewRep = new (Context) UnaryOperator(
+      NewRep, UO_AddrOf, Context->getPointerType(NewRep->getType()), VK_RValue,
+      OK_Ordinary, SourceLocation(), false);
   NewRep = NoTypeInfoCStyleCastExpr(Context, FType, CK_BitCast,
                                     NewRep);
   BlockDeclRefs.clear();

diff  --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index f8c6379eee91..6b919191d6d5 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -3365,14 +3365,6 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
     // are complete and we can parse the delayed portions of method
     // declarations and the lexed inline method definitions, along with any
     // delayed attributes.
-
-    // Save the state of Sema.FPFeatures, and change the setting
-    // to the levels specified on the command line.  Previous level
-    // will be restored when the RAII object is destroyed.
-    Sema::FPFeaturesStateRAII SaveFPFeaturesState(Actions);
-    FPOptions fpOptions(getLangOpts());
-    Actions.CurFPFeatures.getFromOpaqueInt(fpOptions.getAsOpaqueInt());
-
     SourceLocation SavedPrevTokLocation = PrevTokLocation;
     ParseLexedPragmas(getCurrentClass());
     ParseLexedAttributes(getCurrentClass());

diff  --git a/clang/lib/Parse/ParsePragma.cpp b/clang/lib/Parse/ParsePragma.cpp
index 3b5b7154d6a6..34232437528b 100644
--- a/clang/lib/Parse/ParsePragma.cpp
+++ b/clang/lib/Parse/ParsePragma.cpp
@@ -184,16 +184,6 @@ struct PragmaDetectMismatchHandler : public PragmaHandler {
   Sema &Actions;
 };
 
-struct PragmaFloatControlHandler : public PragmaHandler {
-  PragmaFloatControlHandler(Sema &Actions)
-      : PragmaHandler("float_control"), Actions(Actions) {}
-  void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
-                    Token &FirstToken) override;
-
-private:
-  Sema &Actions;
-};
-
 struct PragmaMSPointersToMembers : public PragmaHandler {
   explicit PragmaMSPointersToMembers() : PragmaHandler("pointers_to_members") {}
   void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
@@ -344,8 +334,6 @@ void Parser::initializePragmaHandlers() {
     PP.AddPragmaHandler(MSCommentHandler.get());
   }
 
-  FloatControlHandler = std::make_unique<PragmaFloatControlHandler>(Actions);
-  PP.AddPragmaHandler(FloatControlHandler.get());
   if (getLangOpts().MicrosoftExt) {
     MSDetectMismatchHandler =
         std::make_unique<PragmaDetectMismatchHandler>(Actions);
@@ -450,8 +438,6 @@ void Parser::resetPragmaHandlers() {
   PP.RemovePragmaHandler("clang", PCSectionHandler.get());
   PCSectionHandler.reset();
 
-  PP.RemovePragmaHandler(FloatControlHandler.get());
-  FloatControlHandler.reset();
   if (getLangOpts().MicrosoftExt) {
     PP.RemovePragmaHandler(MSDetectMismatchHandler.get());
     MSDetectMismatchHandler.reset();
@@ -660,22 +646,6 @@ void Parser::HandlePragmaFPContract() {
   ConsumeAnnotationToken();
 }
 
-void Parser::HandlePragmaFloatControl() {
-  assert(Tok.is(tok::annot_pragma_float_control));
-
-  // The value that is held on the PragmaFloatControlStack encodes
-  // the PragmaFloatControl kind and the MSStackAction kind
-  // into a single 32-bit word. The MsStackAction is the high 16 bits
-  // and the FloatControl is the lower 16 bits. Use shift and bit-and
-  // to decode the parts.
-  uintptr_t Value = reinterpret_cast<uintptr_t>(Tok.getAnnotationValue());
-  Sema::PragmaMsStackAction Action =
-      static_cast<Sema::PragmaMsStackAction>((Value >> 16) & 0xFFFF);
-  PragmaFloatControlKind Kind = PragmaFloatControlKind(Value & 0xFFFF);
-  SourceLocation PragmaLoc = ConsumeAnnotationToken();
-  Actions.ActOnPragmaFloatControl(PragmaLoc, Action, Kind);
-}
-
 void Parser::HandlePragmaFEnvAccess() {
   assert(Tok.is(tok::annot_pragma_fenv_access));
   tok::OnOffSwitch OOS =
@@ -695,8 +665,8 @@ void Parser::HandlePragmaFEnvAccess() {
     break;
   }
 
-  SourceLocation PragmaLoc = ConsumeAnnotationToken();
-  Actions.ActOnPragmaFEnvAccess(PragmaLoc, FPC);
+  Actions.ActOnPragmaFEnvAccess(FPC);
+  ConsumeAnnotationToken();
 }
 
 
@@ -2519,129 +2489,6 @@ void PragmaMSPragma::HandlePragma(Preprocessor &PP,
   PP.EnterToken(AnnotTok, /*IsReinject*/ false);
 }
 
-/// Handle the \#pragma float_control extension.
-///
-/// The syntax is:
-/// \code
-///   #pragma float_control(keyword[, setting] [,push])
-/// \endcode
-/// Where 'keyword' and 'setting' are identifiers.
-// 'keyword' can be: precise, except, push, pop
-// 'setting' can be: on, off
-/// The optional arguments 'setting' and 'push' are supported only
-/// when the keyword is 'precise' or 'except'.
-void PragmaFloatControlHandler::HandlePragma(Preprocessor &PP,
-                                             PragmaIntroducer Introducer,
-                                             Token &Tok) {
-  Sema::PragmaMsStackAction Action = Sema::PSK_Set;
-  SourceLocation FloatControlLoc = Tok.getLocation();
-  PP.Lex(Tok);
-  if (Tok.isNot(tok::l_paren)) {
-    PP.Diag(FloatControlLoc, diag::err_expected) << tok::l_paren;
-    return;
-  }
-
-  // Read the identifier.
-  PP.Lex(Tok);
-  if (Tok.isNot(tok::identifier)) {
-    PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
-    return;
-  }
-
-  // Verify that this is one of the float control options.
-  IdentifierInfo *II = Tok.getIdentifierInfo();
-  PragmaFloatControlKind Kind =
-      llvm::StringSwitch<PragmaFloatControlKind>(II->getName())
-          .Case("precise", PFC_Precise)
-          .Case("except", PFC_Except)
-          .Case("push", PFC_Push)
-          .Case("pop", PFC_Pop)
-          .Default(PFC_Unknown);
-  PP.Lex(Tok); // the identifier
-  if (Kind == PFC_Unknown) {
-    PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
-    return;
-  } else if (Kind == PFC_Push || Kind == PFC_Pop) {
-    if (Tok.isNot(tok::r_paren)) {
-      PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
-      return;
-    }
-    PP.Lex(Tok); // Eat the r_paren
-    Action = (Kind == PFC_Pop) ? Sema::PSK_Pop : Sema::PSK_Push;
-  } else {
-    if (Tok.is(tok::r_paren))
-      // Selecting Precise or Except
-      PP.Lex(Tok); // the r_paren
-    else if (Tok.isNot(tok::comma)) {
-      PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
-      return;
-    } else {
-      PP.Lex(Tok); // ,
-      if (!Tok.isAnyIdentifier()) {
-        PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
-        return;
-      }
-      StringRef PushOnOff = Tok.getIdentifierInfo()->getName();
-      if (PushOnOff == "on")
-        // Kind is set correctly
-        ;
-      else if (PushOnOff == "off") {
-        if (Kind == PFC_Precise)
-          Kind = PFC_NoPrecise;
-        if (Kind == PFC_Except)
-          Kind = PFC_NoExcept;
-      } else if (PushOnOff == "push") {
-        Action = Sema::PSK_Push_Set;
-      } else {
-        PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
-        return;
-      }
-      PP.Lex(Tok); // the identifier
-      if (Tok.is(tok::comma)) {
-        PP.Lex(Tok); // ,
-        if (!Tok.isAnyIdentifier()) {
-          PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
-          return;
-        }
-        StringRef ExpectedPush = Tok.getIdentifierInfo()->getName();
-        if (ExpectedPush == "push") {
-          Action = Sema::PSK_Push_Set;
-        } else {
-          PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
-          return;
-        }
-        PP.Lex(Tok); // the push identifier
-      }
-      if (Tok.isNot(tok::r_paren)) {
-        PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
-        return;
-      }
-      PP.Lex(Tok); // the r_paren
-    }
-  }
-  SourceLocation EndLoc = Tok.getLocation();
-  if (Tok.isNot(tok::eod)) {
-    PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
-        << "float_control";
-    return;
-  }
-
-  // Note: there is no accomodation for PP callback for this pragma.
-
-  // Enter the annotation.
-  auto TokenArray = std::make_unique<Token[]>(1);
-  TokenArray[0].startToken();
-  TokenArray[0].setKind(tok::annot_pragma_float_control);
-  TokenArray[0].setLocation(FloatControlLoc);
-  TokenArray[0].setAnnotationEndLoc(EndLoc);
-  // Create an encoding of Action and Value by shifting the Action into
-  // the high 16 bits then union with the Kind.
-  TokenArray[0].setAnnotationValue(reinterpret_cast<void *>(
-      static_cast<uintptr_t>((Action << 16) | (Kind & 0xFFFF))));
-  PP.EnterTokenStream(std::move(TokenArray), 1,
-                      /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
-}
-
 /// Handle the Microsoft \#pragma detect_mismatch extension.
 ///
 /// The syntax is:
@@ -2902,7 +2749,7 @@ void PragmaFPHandler::HandlePragma(Preprocessor &PP,
 
     auto *AnnotValue = new (PP.getPreprocessorAllocator())
         TokFPAnnotValue{*FlagKind, *FlagValue};
-    // Generate the fp annotation token.
+    // Generate the loop hint token.
     Token FPTok;
     FPTok.startToken();
     FPTok.setKind(tok::annot_pragma_fp);

diff  --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp
index 84166bbbdc7b..770402128395 100644
--- a/clang/lib/Parse/ParseStmt.cpp
+++ b/clang/lib/Parse/ParseStmt.cpp
@@ -354,13 +354,13 @@ StmtResult Parser::ParseStatementOrDeclarationAfterAttributes(
 
   case tok::annot_pragma_fp_contract:
     ProhibitAttributes(Attrs);
-    Diag(Tok, diag::err_pragma_file_or_compound_scope) << "fp_contract";
+    Diag(Tok, diag::err_pragma_fp_contract_scope);
     ConsumeAnnotationToken();
     return StmtError();
 
   case tok::annot_pragma_fp:
     ProhibitAttributes(Attrs);
-    Diag(Tok, diag::err_pragma_file_or_compound_scope) << "clang fp";
+    Diag(Tok, diag::err_pragma_fp_scope);
     ConsumeAnnotationToken();
     return StmtError();
 
@@ -369,12 +369,6 @@ StmtResult Parser::ParseStatementOrDeclarationAfterAttributes(
     HandlePragmaFEnvAccess();
     return StmtEmpty();
 
-  case tok::annot_pragma_float_control:
-    ProhibitAttributes(Attrs);
-    Diag(Tok, diag::err_pragma_file_or_compound_scope) << "float_control";
-    ConsumeAnnotationToken();
-    return StmtError();
-
   case tok::annot_pragma_opencl_extension:
     ProhibitAttributes(Attrs);
     HandlePragmaOpenCLExtension();
@@ -943,9 +937,6 @@ void Parser::ParseCompoundStatementLeadingPragmas() {
     case tok::annot_pragma_fenv_access:
       HandlePragmaFEnvAccess();
       break;
-    case tok::annot_pragma_float_control:
-      HandlePragmaFloatControl();
-      break;
     case tok::annot_pragma_ms_pointers_to_members:
       HandlePragmaMSPointersToMembers();
       break;

diff  --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp
index de809b9ee849..5fa23f2cdc13 100644
--- a/clang/lib/Parse/Parser.cpp
+++ b/clang/lib/Parse/Parser.cpp
@@ -752,9 +752,6 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs,
   case tok::annot_pragma_fenv_access:
     HandlePragmaFEnvAccess();
     return nullptr;
-  case tok::annot_pragma_float_control:
-    HandlePragmaFloatControl();
-    return nullptr;
   case tok::annot_pragma_fp:
     HandlePragmaFP();
     break;

diff  --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index 0d2877efe3ee..405b6c33d280 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -159,8 +159,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
           LangOpts.getMSPointerToMemberRepresentationMethod()),
       VtorDispStack(LangOpts.getVtorDispMode()), PackStack(0),
       DataSegStack(nullptr), BSSSegStack(nullptr), ConstSegStack(nullptr),
-      CodeSegStack(nullptr), FpPragmaStack(CurFPFeatures.getAsOpaqueInt()),
-      CurInitSeg(nullptr), VisContext(nullptr),
+      CodeSegStack(nullptr), CurInitSeg(nullptr), VisContext(nullptr),
       PragmaAttributeCurrentTargetDecl(nullptr),
       IsBuildingRecoveryCallExpr(false), Cleanup{}, LateTemplateParser(nullptr),
       LateTemplateParserCleanup(nullptr), OpaqueParser(nullptr), IdResolver(pp),

diff  --git a/clang/lib/Sema/SemaAttr.cpp b/clang/lib/Sema/SemaAttr.cpp
index 518ac0f070c1..8633581b6880 100644
--- a/clang/lib/Sema/SemaAttr.cpp
+++ b/clang/lib/Sema/SemaAttr.cpp
@@ -407,65 +407,6 @@ void Sema::ActOnPragmaDetectMismatch(SourceLocation Loc, StringRef Name,
   Consumer.HandleTopLevelDecl(DeclGroupRef(PDMD));
 }
 
-void Sema::ActOnPragmaFloatControl(SourceLocation Loc,
-                                   PragmaMsStackAction Action,
-                                   PragmaFloatControlKind Value) {
-  auto NewValue = FpPragmaStack.CurrentValue;
-  FPOptions NewFPFeatures(NewValue);
-  if ((Action == PSK_Push_Set || Action == PSK_Push || Action == PSK_Pop) &&
-      !CurContext->isTranslationUnit()) {
-    // Push and pop can only occur at file scope.
-    Diag(Loc, diag::err_pragma_fc_pp_scope);
-    return;
-  }
-  switch (Value) {
-  default:
-    llvm_unreachable("invalid pragma float_control kind");
-  case PFC_Precise:
-    CurFPFeatures.setFPPreciseEnabled(true);
-    NewValue = CurFPFeatures.getAsOpaqueInt();
-    FpPragmaStack.Act(Loc, Action, StringRef(), NewValue);
-    break;
-  case PFC_NoPrecise:
-    if (CurFPFeatures.getExceptionMode() == LangOptions::FPE_Strict)
-      Diag(Loc, diag::err_pragma_fc_noprecise_requires_noexcept);
-    else if (CurFPFeatures.allowFEnvAccess())
-      Diag(Loc, diag::err_pragma_fc_noprecise_requires_nofenv);
-    else
-      CurFPFeatures.setFPPreciseEnabled(false);
-    NewValue = CurFPFeatures.getAsOpaqueInt();
-    FpPragmaStack.Act(Loc, Action, StringRef(), NewValue);
-    break;
-  case PFC_Except:
-    if (!isPreciseFPEnabled())
-      Diag(Loc, diag::err_pragma_fc_except_requires_precise);
-    else
-      CurFPFeatures.setExceptionMode(LangOptions::FPE_Strict);
-    NewValue = CurFPFeatures.getAsOpaqueInt();
-    FpPragmaStack.Act(Loc, Action, StringRef(), NewValue);
-    break;
-  case PFC_NoExcept:
-    CurFPFeatures.setExceptionMode(LangOptions::FPE_Ignore);
-    NewValue = CurFPFeatures.getAsOpaqueInt();
-    FpPragmaStack.Act(Loc, Action, StringRef(), NewValue);
-    break;
-  case PFC_Push:
-    Action = Sema::PSK_Push_Set;
-    FpPragmaStack.Act(Loc, Action, StringRef(), NewFPFeatures.getAsOpaqueInt());
-    break;
-  case PFC_Pop:
-    if (FpPragmaStack.Stack.empty()) {
-      Diag(Loc, diag::warn_pragma_pop_failed) << "float_control"
-                                              << "stack empty";
-      return;
-    }
-    FpPragmaStack.Act(Loc, Action, StringRef(), NewFPFeatures.getAsOpaqueInt());
-    NewValue = FpPragmaStack.CurrentValue;
-    CurFPFeatures.getFromOpaqueInt(NewValue);
-    break;
-  }
-}
-
 void Sema::ActOnPragmaMSPointersToMembers(
     LangOptions::PragmaMSPointersToMembersKind RepresentationMethod,
     SourceLocation PragmaLoc) {
@@ -1007,16 +948,9 @@ void Sema::setExceptionMode(LangOptions::FPExceptionModeKind FPE) {
   CurFPFeatures.setExceptionMode(FPE);
 }
 
-void Sema::ActOnPragmaFEnvAccess(SourceLocation Loc,
-                                 LangOptions::FEnvAccessModeKind FPC) {
+void Sema::ActOnPragmaFEnvAccess(LangOptions::FEnvAccessModeKind FPC) {
   switch (FPC) {
   case LangOptions::FEA_On:
-    // Verify Microsoft restriction:
-    // You can't enable fenv_access unless precise semantics are enabled.
-    // Precise semantics can be enabled either by the float_control
-    // pragma, or by using the /fp:precise or /fp:strict compiler options
-    if (!isPreciseFPEnabled())
-      Diag(Loc, diag::err_pragma_fenv_requires_precise);
     CurFPFeatures.setAllowFEnvAccess();
     break;
   case LangOptions::FEA_Off:
@@ -1025,6 +959,7 @@ void Sema::ActOnPragmaFEnvAccess(SourceLocation Loc,
   }
 }
 
+
 void Sema::PushNamespaceVisibilityAttr(const VisibilityAttr *Attr,
                                        SourceLocation Loc) {
   // Visibility calculations will consider the namespace's visibility.

diff  --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 935ac93e9922..78d9322bf393 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -13455,13 +13455,13 @@ buildMemcpyForAssignmentOp(Sema &S, SourceLocation Loc, QualType T,
   // directly construct UnaryOperators here because semantic analysis
   // does not permit us to take the address of an xvalue.
   Expr *From = FromB.build(S, Loc);
-  From = UnaryOperator::Create(
-      S.Context, From, UO_AddrOf, S.Context.getPointerType(From->getType()),
-      VK_RValue, OK_Ordinary, Loc, false, S.CurFPFeatures);
+  From = new (S.Context) UnaryOperator(From, UO_AddrOf,
+                         S.Context.getPointerType(From->getType()),
+                         VK_RValue, OK_Ordinary, Loc, false);
   Expr *To = ToB.build(S, Loc);
-  To = UnaryOperator::Create(S.Context, To, UO_AddrOf,
-                             S.Context.getPointerType(To->getType()), VK_RValue,
-                             OK_Ordinary, Loc, false, S.CurFPFeatures);
+  To = new (S.Context) UnaryOperator(To, UO_AddrOf,
+                       S.Context.getPointerType(To->getType()),
+                       VK_RValue, OK_Ordinary, Loc, false);
 
   const Type *E = T->getBaseElementTypeUnsafe();
   bool NeedsCollectableMemCpy =
@@ -13703,9 +13703,9 @@ buildSingleCopyAssignRecursively(Sema &S, SourceLocation Loc, QualType T,
   // Create the pre-increment of the iteration variable. We can determine
   // whether the increment will overflow based on the value of the array
   // bound.
-  Expr *Increment = UnaryOperator::Create(
-      S.Context, IterationVarRef.build(S, Loc), UO_PreInc, SizeType, VK_LValue,
-      OK_Ordinary, Loc, Upper.isMaxValue(), S.CurFPFeatures);
+  Expr *Increment = new (S.Context)
+      UnaryOperator(IterationVarRef.build(S, Loc), UO_PreInc, SizeType,
+                    VK_LValue, OK_Ordinary, Loc, Upper.isMaxValue());
 
   // Construct the loop that copies all elements of this array.
   return S.ActOnForStmt(

diff  --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 7e8446c6f1ab..5b28015dba03 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -13662,6 +13662,14 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
   if (ResultTy.isNull() || LHS.isInvalid() || RHS.isInvalid())
     return ExprError();
 
+  if (ResultTy->isRealFloatingType() &&
+      (getLangOpts().getFPRoundingMode() != RoundingMode::NearestTiesToEven ||
+       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);
+    }
+
   // 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
@@ -14311,8 +14319,8 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
   if (Opc != UO_AddrOf && Opc != UO_Deref)
     CheckArrayAccess(Input.get());
 
-  auto *UO = UnaryOperator::Create(Context, Input.get(), Opc, resultType, VK,
-                                   OK, OpLoc, CanOverflow, CurFPFeatures);
+  auto *UO = new (Context)
+      UnaryOperator(Input.get(), Opc, resultType, VK, OK, OpLoc, CanOverflow);
 
   if (Opc == UO_Deref && UO->getType()->hasAttr(attr::NoDeref) &&
       !isa<ArrayType>(UO->getType().getDesugaredType(Context)))

diff  --git a/clang/lib/Sema/SemaExprObjC.cpp b/clang/lib/Sema/SemaExprObjC.cpp
index 11ab4db1e485..10a7cf3e22d0 100644
--- a/clang/lib/Sema/SemaExprObjC.cpp
+++ b/clang/lib/Sema/SemaExprObjC.cpp
@@ -4427,9 +4427,9 @@ Expr *Sema::stripARCUnbridgedCast(Expr *e) {
   } else if (UnaryOperator *uo = dyn_cast<UnaryOperator>(e)) {
     assert(uo->getOpcode() == UO_Extension);
     Expr *sub = stripARCUnbridgedCast(uo->getSubExpr());
-    return UnaryOperator::Create(Context, sub, UO_Extension, sub->getType(),
-                                 sub->getValueKind(), sub->getObjectKind(),
-                                 uo->getOperatorLoc(), false, CurFPFeatures);
+    return new (Context)
+        UnaryOperator(sub, UO_Extension, sub->getType(), sub->getValueKind(),
+                      sub->getObjectKind(), uo->getOperatorLoc(), false);
   } else if (GenericSelectionExpr *gse = dyn_cast<GenericSelectionExpr>(e)) {
     assert(!gse->isResultDependent());
 

diff  --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 57b650de3fee..fb5eff006fd3 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -13001,9 +13001,8 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc,
 
   if (Input->isTypeDependent()) {
     if (Fns.empty())
-      return UnaryOperator::Create(Context, Input, Opc, Context.DependentTy,
-                                   VK_RValue, OK_Ordinary, OpLoc, false,
-                                   CurFPFeatures);
+      return new (Context) UnaryOperator(Input, Opc, Context.DependentTy,
+                                         VK_RValue, OK_Ordinary, OpLoc, false);
 
     CXXRecordDecl *NamingClass = nullptr; // lookup ignores member operators
     UnresolvedLookupExpr *Fn = UnresolvedLookupExpr::Create(
@@ -14803,9 +14802,9 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found,
         if (Context.getTargetInfo().getCXXABI().isMicrosoft())
           (void)isCompleteType(UnOp->getOperatorLoc(), MemPtrType);
 
-        return UnaryOperator::Create(
-            Context, SubExpr, UO_AddrOf, MemPtrType, VK_RValue, OK_Ordinary,
-            UnOp->getOperatorLoc(), false, CurFPFeatures);
+        return new (Context) UnaryOperator(SubExpr, UO_AddrOf, MemPtrType,
+                                           VK_RValue, OK_Ordinary,
+                                           UnOp->getOperatorLoc(), false);
       }
     }
     Expr *SubExpr = FixOverloadedFunctionReference(UnOp->getSubExpr(),
@@ -14813,9 +14812,10 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found,
     if (SubExpr == UnOp->getSubExpr())
       return UnOp;
 
-    return UnaryOperator::Create(
-        Context, SubExpr, UO_AddrOf, Context.getPointerType(SubExpr->getType()),
-        VK_RValue, OK_Ordinary, UnOp->getOperatorLoc(), false, CurFPFeatures);
+    return new (Context) UnaryOperator(SubExpr, UO_AddrOf,
+                                     Context.getPointerType(SubExpr->getType()),
+                                       VK_RValue, OK_Ordinary,
+                                       UnOp->getOperatorLoc(), false);
   }
 
   if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(E)) {

diff  --git a/clang/lib/Sema/SemaPseudoObject.cpp b/clang/lib/Sema/SemaPseudoObject.cpp
index da777201af88..0ed45221177b 100644
--- a/clang/lib/Sema/SemaPseudoObject.cpp
+++ b/clang/lib/Sema/SemaPseudoObject.cpp
@@ -127,10 +127,12 @@ namespace {
       if (UnaryOperator *uop = dyn_cast<UnaryOperator>(e)) {
         assert(uop->getOpcode() == UO_Extension);
         e = rebuild(uop->getSubExpr());
-        return UnaryOperator::Create(
-            S.Context, e, uop->getOpcode(), uop->getType(), uop->getValueKind(),
-            uop->getObjectKind(), uop->getOperatorLoc(), uop->canOverflow(),
-            S.CurFPFeatures);
+        return new (S.Context) UnaryOperator(e, uop->getOpcode(),
+                                             uop->getType(),
+                                             uop->getValueKind(),
+                                             uop->getObjectKind(),
+                                             uop->getOperatorLoc(),
+                                             uop->canOverflow());
       }
 
       if (GenericSelectionExpr *gse = dyn_cast<GenericSelectionExpr>(e)) {
@@ -524,14 +526,12 @@ PseudoOpBuilder::buildIncDecOperation(Scope *Sc, SourceLocation opcLoc,
       (result.get()->isTypeDependent() || CanCaptureValue(result.get())))
     setResultToLastSemantic();
 
-  UnaryOperator *syntactic =
-      UnaryOperator::Create(S.Context, syntacticOp, opcode, resultType,
-                            VK_LValue, OK_Ordinary, opcLoc,
-                            !resultType->isDependentType()
-                                ? S.Context.getTypeSize(resultType) >=
-                                      S.Context.getTypeSize(S.Context.IntTy)
-                                : false,
-                            S.CurFPFeatures);
+  UnaryOperator *syntactic = new (S.Context) UnaryOperator(
+      syntacticOp, opcode, resultType, VK_LValue, OK_Ordinary, opcLoc,
+      !resultType->isDependentType()
+          ? S.Context.getTypeSize(resultType) >=
+                S.Context.getTypeSize(S.Context.IntTy)
+          : false);
   return complete(syntactic);
 }
 
@@ -1551,9 +1551,8 @@ ExprResult Sema::checkPseudoObjectIncDec(Scope *Sc, SourceLocation opcLoc,
                                          UnaryOperatorKind opcode, Expr *op) {
   // Do nothing if the operand is dependent.
   if (op->isTypeDependent())
-    return UnaryOperator::Create(Context, op, opcode, Context.DependentTy,
-                                 VK_RValue, OK_Ordinary, opcLoc, false,
-                                 CurFPFeatures);
+    return new (Context) UnaryOperator(op, opcode, Context.DependentTy,
+                                       VK_RValue, OK_Ordinary, opcLoc, false);
 
   assert(UnaryOperator::isIncrementDecrementOp(opcode));
   Expr *opaqueRef = op->IgnoreParens();
@@ -1637,10 +1636,9 @@ Expr *Sema::recreateSyntacticForm(PseudoObjectExpr *E) {
   Expr *syntax = E->getSyntacticForm();
   if (UnaryOperator *uop = dyn_cast<UnaryOperator>(syntax)) {
     Expr *op = stripOpaqueValuesFromPseudoObjectRef(*this, uop->getSubExpr());
-    return UnaryOperator::Create(Context, op, uop->getOpcode(), uop->getType(),
-                                 uop->getValueKind(), uop->getObjectKind(),
-                                 uop->getOperatorLoc(), uop->canOverflow(),
-                                 CurFPFeatures);
+    return new (Context) UnaryOperator(
+        op, uop->getOpcode(), uop->getType(), uop->getValueKind(),
+        uop->getObjectKind(), uop->getOperatorLoc(), uop->canOverflow());
   } else if (CompoundAssignOperator *cop
                = dyn_cast<CompoundAssignOperator>(syntax)) {
     Expr *lhs = stripOpaqueValuesFromPseudoObjectRef(*this, cop->getLHS());

diff  --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp
index f76994a6dab3..aa0d89ac09c3 100644
--- a/clang/lib/Sema/SemaStmt.cpp
+++ b/clang/lib/Sema/SemaStmt.cpp
@@ -394,11 +394,6 @@ StmtResult Sema::ActOnCompoundStmt(SourceLocation L, SourceLocation R,
                                    ArrayRef<Stmt *> Elts, bool isStmtExpr) {
   const unsigned NumElts = Elts.size();
 
-  // Mark the current function as usng floating point constrained intrinsics
-  if (getCurFPFeatures().isFPConstrained())
-    if (FunctionDecl *F = dyn_cast<FunctionDecl>(CurContext))
-      F->setUsesFPIntrin(true);
-
   // If we're in C89 mode, check that we don't have any decls after stmts.  If
   // so, emit an extension diagnostic.
   if (!getLangOpts().C99 && !getLangOpts().CPlusPlus) {

diff  --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index 187665be5255..3ead713b5e06 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -3779,29 +3779,6 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
       break;
     }
 
-    case FLOAT_CONTROL_PRAGMA_OPTIONS: {
-      if (Record.size() < 3) {
-        Error("invalid pragma pack record");
-        return Failure;
-      }
-      FpPragmaCurrentValue = Record[0];
-      FpPragmaCurrentLocation = ReadSourceLocation(F, Record[1]);
-      unsigned NumStackEntries = Record[2];
-      unsigned Idx = 3;
-      // Reset the stack when importing a new module.
-      FpPragmaStack.clear();
-      for (unsigned I = 0; I < NumStackEntries; ++I) {
-        FpPragmaStackEntry Entry;
-        Entry.Value = Record[Idx++];
-        Entry.Location = ReadSourceLocation(F, Record[Idx++]);
-        Entry.PushLocation = ReadSourceLocation(F, Record[Idx++]);
-        FpPragmaStrings.push_back(ReadString(Record, Idx));
-        Entry.SlotLabel = FpPragmaStrings.back();
-        FpPragmaStack.push_back(Entry);
-      }
-      break;
-    }
-
     case DECLS_TO_CHECK_FOR_DEFERRED_DIAGS:
       for (unsigned I = 0, N = Record.size(); I != N; ++I)
         DeclsToCheckForDeferredDiags.push_back(getGlobalDeclID(F, Record[I]));
@@ -7876,34 +7853,6 @@ void ASTReader::UpdateSema() {
       SemaObj->PackStack.CurrentPragmaLocation = PragmaPackCurrentLocation;
     }
   }
-  if (FpPragmaCurrentValue) {
-    // The bottom of the stack might have a default value. It must be adjusted
-    // to the current value to ensure that fp-pragma state is preserved after
-    // popping entries that were included/imported from a PCH/module.
-    bool DropFirst = false;
-    if (!FpPragmaStack.empty() && FpPragmaStack.front().Location.isInvalid()) {
-      assert(FpPragmaStack.front().Value ==
-                 SemaObj->FpPragmaStack.DefaultValue &&
-             "Expected a default pragma float_control value");
-      SemaObj->FpPragmaStack.Stack.emplace_back(
-          FpPragmaStack.front().SlotLabel, SemaObj->FpPragmaStack.CurrentValue,
-          SemaObj->FpPragmaStack.CurrentPragmaLocation,
-          FpPragmaStack.front().PushLocation);
-      DropFirst = true;
-    }
-    for (const auto &Entry :
-         llvm::makeArrayRef(FpPragmaStack).drop_front(DropFirst ? 1 : 0))
-      SemaObj->FpPragmaStack.Stack.emplace_back(
-          Entry.SlotLabel, Entry.Value, Entry.Location, Entry.PushLocation);
-    if (FpPragmaCurrentLocation.isInvalid()) {
-      assert(*FpPragmaCurrentValue == SemaObj->FpPragmaStack.DefaultValue &&
-             "Expected a default pragma float_control value");
-      // Keep the current values.
-    } else {
-      SemaObj->FpPragmaStack.CurrentValue = *FpPragmaCurrentValue;
-      SemaObj->FpPragmaStack.CurrentPragmaLocation = FpPragmaCurrentLocation;
-    }
-  }
 }
 
 IdentifierInfo *ASTReader::get(StringRef Name) {

diff  --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp
index e6d9396c8d00..ea21d5e33c2e 100644
--- a/clang/lib/Serialization/ASTReaderStmt.cpp
+++ b/clang/lib/Serialization/ASTReaderStmt.cpp
@@ -682,14 +682,10 @@ void ASTStmtReader::VisitParenListExpr(ParenListExpr *E) {
 
 void ASTStmtReader::VisitUnaryOperator(UnaryOperator *E) {
   VisitExpr(E);
-  bool hasFP_Features = Record.readInt();
-  assert(hasFP_Features == E->hasStoredFPFeatures());
   E->setSubExpr(Record.readSubExpr());
   E->setOpcode((UnaryOperator::Opcode)Record.readInt());
   E->setOperatorLoc(readSourceLocation());
   E->setCanOverflow(Record.readInt());
-  if (hasFP_Features)
-    E->setStoredFPFeatures(FPOptions(Record.readInt()));
 }
 
 void ASTStmtReader::VisitOffsetOfExpr(OffsetOfExpr *E) {
@@ -2904,8 +2900,7 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
       break;
 
     case EXPR_UNARY_OPERATOR:
-      S = UnaryOperator::CreateEmpty(Context,
-                                     Record[ASTStmtReader::NumExprFields]);
+      S = new (Context) UnaryOperator(Empty);
       break;
 
     case EXPR_OFFSETOF:

diff  --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index b2281abe5ba5..462f27578c0f 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -4139,26 +4139,6 @@ void ASTWriter::WritePackPragmaOptions(Sema &SemaRef) {
   Stream.EmitRecord(PACK_PRAGMA_OPTIONS, Record);
 }
 
-/// Write the state of 'pragma float_control' at the end of the module.
-void ASTWriter::WriteFloatControlPragmaOptions(Sema &SemaRef) {
-  // Don't serialize pragma float_control state for modules,
-  // since it should only take effect on a per-submodule basis.
-  if (WritingModule)
-    return;
-
-  RecordData Record;
-  Record.push_back(SemaRef.FpPragmaStack.CurrentValue);
-  AddSourceLocation(SemaRef.FpPragmaStack.CurrentPragmaLocation, Record);
-  Record.push_back(SemaRef.FpPragmaStack.Stack.size());
-  for (const auto &StackEntry : SemaRef.FpPragmaStack.Stack) {
-    Record.push_back(StackEntry.Value);
-    AddSourceLocation(StackEntry.PragmaLocation, Record);
-    AddSourceLocation(StackEntry.PragmaPushLocation, Record);
-    AddString(StackEntry.StackSlotLabel, Record);
-  }
-  Stream.EmitRecord(FLOAT_CONTROL_PRAGMA_OPTIONS, Record);
-}
-
 void ASTWriter::WriteModuleFileExtension(Sema &SemaRef,
                                          ModuleFileExtensionWriter &Writer) {
   // Enter the extension block.
@@ -4887,7 +4867,6 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot,
     WriteMSPointersToMembersPragmaOptions(SemaRef);
   }
   WritePackPragmaOptions(SemaRef);
-  WriteFloatControlPragmaOptions(SemaRef);
 
   // Some simple statistics
   RecordData::value_type Record[] = {

diff  --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp
index 12a9d27b9fd0..7c450bccc709 100644
--- a/clang/lib/Serialization/ASTWriterStmt.cpp
+++ b/clang/lib/Serialization/ASTWriterStmt.cpp
@@ -702,16 +702,10 @@ void ASTStmtWriter::VisitParenListExpr(ParenListExpr *E) {
 
 void ASTStmtWriter::VisitUnaryOperator(UnaryOperator *E) {
   VisitExpr(E);
-  bool HasFPFeatures = E->hasStoredFPFeatures();
-  // Write this first for easy access when deserializing, as they affect the
-  // size of the UnaryOperator.
-  Record.push_back(HasFPFeatures);
   Record.AddStmt(E->getSubExpr());
   Record.push_back(E->getOpcode()); // FIXME: stable encoding
   Record.AddSourceLocation(E->getOperatorLoc());
   Record.push_back(E->canOverflow());
-  if (HasFPFeatures)
-    Record.push_back(E->getStoredFPFeatures().getAsOpaqueInt());
   Code = serialization::EXPR_UNARY_OPERATOR;
 }
 

diff  --git a/clang/test/CodeGen/builtins-nvptx.c b/clang/test/CodeGen/builtins-nvptx.c
index 1f7a8c62ac2c..31c3ecdb1497 100644
--- a/clang/test/CodeGen/builtins-nvptx.c
+++ b/clang/test/CodeGen/builtins-nvptx.c
@@ -1,11 +1,11 @@
 // REQUIRES: nvptx-registered-target
-// RUN: %clang_cc1 -ffp-contract=off -triple nvptx-unknown-unknown -target-cpu sm_60 \
+// RUN: %clang_cc1 -triple nvptx-unknown-unknown -target-cpu sm_60 \
 // RUN:            -fcuda-is-device -S -emit-llvm -o - -x cuda %s \
 // RUN:   | FileCheck -check-prefix=CHECK -check-prefix=LP32 %s
-// RUN: %clang_cc1 -ffp-contract=off -triple nvptx64-unknown-unknown -target-cpu sm_60 \
+// RUN: %clang_cc1 -triple nvptx64-unknown-unknown -target-cpu sm_60 \
 // RUN:            -fcuda-is-device -S -emit-llvm -o - -x cuda %s \
 // RUN:   | FileCheck -check-prefix=CHECK -check-prefix=LP64 %s
-// RUN: %clang_cc1 -ffp-contract=off -triple nvptx64-unknown-unknown -target-cpu sm_61 \
+// RUN: %clang_cc1 -triple nvptx64-unknown-unknown -target-cpu sm_61 \
 // RUN:            -fcuda-is-device -S -emit-llvm -o - -x cuda %s \
 // RUN:   | FileCheck -check-prefix=CHECK -check-prefix=LP64 %s
 // RUN: %clang_cc1 -triple nvptx-unknown-unknown -target-cpu sm_53 \

diff  --git a/clang/test/CodeGen/constrained-math-builtins.c b/clang/test/CodeGen/constrained-math-builtins.c
index fe303eb0d5c2..b22cfe61d313 100644
--- a/clang/test/CodeGen/constrained-math-builtins.c
+++ b/clang/test/CodeGen/constrained-math-builtins.c
@@ -154,9 +154,9 @@ void bar(float f) {
   (double)f * f - f;
   (long double)-f * f + f;
 
-  // CHECK: call contract float @llvm.experimental.constrained.fmuladd.f32
-  // CHECK: fneg
-  // CHECK: call contract double @llvm.experimental.constrained.fmuladd.f64
-  // CHECK: fneg
-  // CHECK: call contract x86_fp80 @llvm.experimental.constrained.fmuladd.f80
+// CHECK: call float @llvm.experimental.constrained.fmuladd.f32
+// CHECK: fneg
+// CHECK: call double @llvm.experimental.constrained.fmuladd.f64
+// CHECK: fneg
+// CHECK: call x86_fp80 @llvm.experimental.constrained.fmuladd.f80
 };

diff  --git a/clang/test/CodeGen/fast-math.c b/clang/test/CodeGen/fast-math.c
index 6ebd65a22c92..6f98b8432746 100644
--- a/clang/test/CodeGen/fast-math.c
+++ b/clang/test/CodeGen/fast-math.c
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -ffast-math -ffp-contract=fast -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -ffast-math -emit-llvm -o - %s | FileCheck %s
 float f0, f1, f2;
 
 void foo(void) {

diff  --git a/clang/test/CodeGen/fp-contract-on-pragma.cpp b/clang/test/CodeGen/fp-contract-on-pragma.cpp
index 5f7463608660..812a7176b515 100644
--- a/clang/test/CodeGen/fp-contract-on-pragma.cpp
+++ b/clang/test/CodeGen/fp-contract-on-pragma.cpp
@@ -3,7 +3,7 @@
 // Is FP_CONTRACT honored in a simple case?
 float fp_contract_1(float a, float b, float c) {
 // CHECK: _Z13fp_contract_1fff
-// CHECK: tail call contract float @llvm.fmuladd
+// CHECK: tail call float @llvm.fmuladd
 #pragma clang fp contract(on)
   return a * b + c;
 }
@@ -31,7 +31,7 @@ T template_muladd(T a, T b, T c) {
 
 float fp_contract_3(float a, float b, float c) {
   // CHECK: _Z13fp_contract_3fff
-  // CHECK: tail call contract float @llvm.fmuladd
+  // CHECK: tail call float @llvm.fmuladd
   return template_muladd<float>(a, b, c);
 }
 
@@ -45,13 +45,13 @@ class fp_contract_4 {
 
 template class fp_contract_4<int>;
 // CHECK: _ZN13fp_contract_4IiE6methodEfff
-// CHECK: tail call contract float @llvm.fmuladd
+// CHECK: tail call float @llvm.fmuladd
 
 // Check file-scoped FP_CONTRACT
 #pragma clang fp contract(on)
 float fp_contract_5(float a, float b, float c) {
   // CHECK: _Z13fp_contract_5fff
-  // CHECK: tail call contract float @llvm.fmuladd
+  // CHECK: tail call float @llvm.fmuladd
   return a * b + c;
 }
 
@@ -69,8 +69,8 @@ float fp_contract_6(float a, float b, float c) {
 
 float fp_contract_7(float a, float b, float c) {
 // CHECK: _Z13fp_contract_7fff
-// CHECK:  %[[M:.+]] = fmul contract float %b, 2.000000e+00
-// CHECK-NEXT: fsub contract float %[[M]], %c
+// CHECK:  %[[M:.+]] = fmul float %b, 2.000000e+00
+// CHECK-NEXT: fsub float %[[M]], %c
 #pragma clang fp contract(on)
   return (a = 2 * b) - c;
 }

diff  --git a/clang/test/CodeGen/fp-contract-pragma.cpp b/clang/test/CodeGen/fp-contract-pragma.cpp
index 3a861ab613cd..805cc5d9c299 100644
--- a/clang/test/CodeGen/fp-contract-pragma.cpp
+++ b/clang/test/CodeGen/fp-contract-pragma.cpp
@@ -2,9 +2,9 @@
 
 // Is FP_CONTRACT honored in a simple case?
 float fp_contract_1(float a, float b, float c) {
-  // CHECK: _Z13fp_contract_1fff
-  // CHECK: tail call contract float @llvm.fmuladd
-#pragma STDC FP_CONTRACT ON
+// CHECK: _Z13fp_contract_1fff
+// CHECK: tail call float @llvm.fmuladd
+  #pragma STDC FP_CONTRACT ON
   return a * b + c;
 }
 
@@ -30,8 +30,8 @@ T template_muladd(T a, T b, T c) {
 }
 
 float fp_contract_3(float a, float b, float c) {
-  // CHECK: _Z13fp_contract_3fff
-  // CHECK: tail call contract float @llvm.fmuladd
+// CHECK: _Z13fp_contract_3fff
+// CHECK: tail call float @llvm.fmuladd
   return template_muladd<float>(a, b, c);
 }
 
@@ -44,13 +44,13 @@ template<typename T> class fp_contract_4 {
 
 template class fp_contract_4<int>;
 // CHECK: _ZN13fp_contract_4IiE6methodEfff
-// CHECK: tail call contract float @llvm.fmuladd
+// CHECK: tail call float @llvm.fmuladd
 
 // Check file-scoped FP_CONTRACT
 #pragma STDC FP_CONTRACT ON
 float fp_contract_5(float a, float b, float c) {
-  // CHECK: _Z13fp_contract_5fff
-  // CHECK: tail call contract float @llvm.fmuladd
+// CHECK: _Z13fp_contract_5fff
+// CHECK: tail call float @llvm.fmuladd
   return a * b + c;
 }
 
@@ -67,25 +67,25 @@ float fp_contract_6(float a, float b, float c) {
 // https://llvm.org/bugs/show_bug.cgi?id=25719
 
 float fp_contract_7(float a, float b, float c) {
-  // CHECK: _Z13fp_contract_7fff
-  // CHECK:  %[[M:.+]] = fmul contract float %b, 2.000000e+00
-  // CHECK-NEXT: fsub contract float %[[M]], %c
-#pragma STDC FP_CONTRACT ON
+// CHECK: _Z13fp_contract_7fff
+// CHECK:  %[[M:.+]] = fmul float %b, 2.000000e+00
+// CHECK-NEXT: fsub float %[[M]], %c
+  #pragma STDC FP_CONTRACT ON
   return (a = 2 * b) - c;
 }
 
 float fp_contract_8(float a, float b, float c) {
-  // CHECK: _Z13fp_contract_8fff
-  // CHECK: fneg contract float %c
-  // CHECK: tail call contract float @llvm.fmuladd
-#pragma STDC FP_CONTRACT ON
+// CHECK: _Z13fp_contract_8fff
+// CHECK: fneg float %c
+// CHECK: tail call float @llvm.fmuladd
+  #pragma STDC FP_CONTRACT ON
   return a * b - c;
 }
 
 float fp_contract_9(float a, float b, float c) {
-  // CHECK: _Z13fp_contract_9fff
-  // CHECK: fneg contract float %a
-  // CHECK: tail call contract float @llvm.fmuladd
-#pragma STDC FP_CONTRACT ON
+// CHECK: _Z13fp_contract_9fff
+// CHECK: fneg float %a
+// CHECK: tail call float @llvm.fmuladd
+  #pragma STDC FP_CONTRACT ON
   return c - a * b;
 }

diff  --git a/clang/test/CodeGen/fp-floatcontrol-class.cpp b/clang/test/CodeGen/fp-floatcontrol-class.cpp
deleted file mode 100644
index ce4e0eb01390..000000000000
--- a/clang/test/CodeGen/fp-floatcontrol-class.cpp
+++ /dev/null
@@ -1,21 +0,0 @@
-// RUN: %clang_cc1 -ffp-contract=on -triple %itanium_abi_triple -emit-llvm -o - %s | FileCheck %s
-// RUN: %clang_cc1 -ffp-contract=on -triple x86_64-linux-gnu -emit-llvm -o - %s | FileCheck %s
-// RUN: %clang_cc1 -ffp-contract=on -triple x86_64-unknown-unknown -emit-llvm -o - %s | FileCheck %s
-// Verify that float_control does not pertain to initializer expressions
-
-float y();
-float z();
-#pragma float_control(except, on)
-class ON {
-  float w = 2 + y() * z();
-  // CHECK-LABEL: define {{.*}} void @_ZN2ONC2Ev{{.*}}
-  //CHECK: call contract float {{.*}}llvm.fmuladd
-};
-ON on;
-#pragma float_control(except, off)
-class OFF {
-  float w = 2 + y() * z();
-  // CHECK-LABEL: define {{.*}} void @_ZN3OFFC2Ev{{.*}}
-  //CHECK: call contract float {{.*}}llvm.fmuladd
-};
-OFF off;

diff  --git a/clang/test/CodeGen/fp-floatcontrol-pragma.cpp b/clang/test/CodeGen/fp-floatcontrol-pragma.cpp
deleted file mode 100644
index caaab3ca4f84..000000000000
--- a/clang/test/CodeGen/fp-floatcontrol-pragma.cpp
+++ /dev/null
@@ -1,47 +0,0 @@
-// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -o - %s | FileCheck %s
-
-float fff(float x, float y) {
-// CHECK-LABEL: define float @_Z3fffff{{.*}}
-// CHECK: entry
-#pragma float_control(except, on)
-  float z;
-  z = z * z;
-  //CHECK: llvm.experimental.constrained.fmul{{.*}}
-  {
-    z = x * y;
-    //CHECK: llvm.experimental.constrained.fmul{{.*}}
-  }
-  {
-// This pragma has no effect since if there are any fp intrin in the
-// function then all the operations need to be fp intrin
-#pragma float_control(except, off)
-    z = z + x * y;
-    //CHECK: llvm.experimental.constrained.fmul{{.*}}
-  }
-  z = z * z;
-  //CHECK: llvm.experimental.constrained.fmul{{.*}}
-  return z;
-}
-float check_precise(float x, float y) {
-  // CHECK-LABEL: define float @_Z13check_preciseff{{.*}}
-  float z;
-  {
-#pragma float_control(precise, on)
-    z = x * y + z;
-    //CHECK: llvm.fmuladd{{.*}}
-  }
-  {
-#pragma float_control(precise, off)
-    z = x * y + z;
-    //CHECK: fmul fast float
-    //CHECK: fadd fast float
-  }
-  return z;
-}
-float fma_test1(float a, float b, float c) {
-// CHECK-LABEL define float @_Z9fma_test1fff{{.*}}
-#pragma float_control(precise, on)
-  float x = a * b + c;
-  //CHECK: fmuladd
-  return x;
-}

diff  --git a/clang/test/CodeGen/fp-floatcontrol-stack.cpp b/clang/test/CodeGen/fp-floatcontrol-stack.cpp
deleted file mode 100644
index 18ec0d4db653..000000000000
--- a/clang/test/CodeGen/fp-floatcontrol-stack.cpp
+++ /dev/null
@@ -1,253 +0,0 @@
-// RUN: %clang_cc1 -triple x86_64-linux-gnu -ffp-contract=on -DDEFAULT=1 -emit-llvm -o - %s | FileCheck --check-prefix=CHECK-DDEFAULT %s
-// RUN: %clang_cc1 -triple x86_64-linux-gnu -ffp-contract=on -DEBSTRICT=1 -ffp-exception-behavior=strict -emit-llvm -o - %s | FileCheck --check-prefix=CHECK-DEBSTRICT %s
-// RUN: %clang_cc1 -triple x86_64-linux-gnu -DFAST=1 -ffast-math -ffp-contract=fast -emit-llvm -o - %s | FileCheck --check-prefix=CHECK-FAST %s
-// RUN: %clang_cc1 -triple x86_64-linux-gnu -ffp-contract=on -DNOHONOR=1 -menable-no-infs -menable-no-nans -emit-llvm -o - %s | FileCheck --check-prefix=CHECK-NOHONOR %s
-
-#define FUN(n) \
-  (float z) { return n * z + n; }
-
-float fun_default FUN(1)
-//CHECK-LABEL: define {{.*}} @_Z11fun_defaultf{{.*}}
-#if DEFAULT
-//CHECK-DDEFAULT: call contract float @llvm.fmuladd{{.*}}
-#endif
-#if EBSTRICT
-// Note that backend wants constrained intrinsics used
-// throughout the function if they are needed anywhere in the function.
-// In that case, operations are built with constrained intrinsics operator
-// but using default settings for exception behavior and rounding mode.
-//CHECK-DEBSTRICT: llvm.experimental.constrained.fmul{{.*}}tonearest{{.*}}strict
-#endif
-#if FAST
-//CHECK-FAST: fmul fast float
-//CHECK-FAST: fadd fast float
-#endif
-
-#pragma float_control(push)
-#ifndef FAST
-// Rule: precise must be enabled
-#pragma float_control(except, on)
-#endif
-    float exc_on FUN(2)
-//CHECK-LABEL: define {{.*}} @_Z6exc_onf{{.*}}
-#if DEFAULT
-//CHECK-DDEFAULT: llvm.experimental.constrained.fmul{{.*}}
-#endif
-#if EBSTRICT
-//CHECK-DEBSTRICT: llvm.experimental.constrained.fmuladd{{.*}}tonearest{{.*}}strict
-#endif
-#if NOHONOR
-//CHECK-NOHONOR: nnan ninf contract float {{.*}}llvm.experimental.constrained.fmuladd{{.*}}tonearest{{.*}}strict
-#endif
-#if FAST
-//Not possible to enable float_control(except) in FAST mode.
-//CHECK-FAST: fmul fast float
-//CHECK-FAST: fadd fast float
-#endif
-
-#pragma float_control(pop)
-        float exc_pop FUN(5)
-//CHECK-LABEL: define {{.*}} @_Z7exc_popf{{.*}}
-#if DEFAULT
-//CHECK-DDEFAULT: call contract float @llvm.fmuladd{{.*}}
-#endif
-#if EBSTRICT
-//CHECK-DEBSTRICT: llvm.experimental.constrained.fmuladd{{.*}}tonearest{{.*}}strict
-#endif
-#if NOHONOR
-//CHECK-NOHONOR: call nnan ninf contract float @llvm.fmuladd{{.*}}
-#endif
-#if FAST
-//CHECK-FAST: fmul fast float
-//CHECK-FAST: fadd fast float
-#endif
-
-#pragma float_control(except, off)
-            float exc_off FUN(5)
-//CHECK-LABEL: define {{.*}} @_Z7exc_offf{{.*}}
-#if DEFAULT
-//CHECK-DDEFAULT: call contract float @llvm.fmuladd{{.*}}
-#endif
-#if EBSTRICT
-//CHECK-DEBSTRICT: call contract float @llvm.fmuladd{{.*}}
-#endif
-#if NOHONOR
-//CHECK-NOHONOR: call nnan ninf contract float @llvm.fmuladd{{.*}}
-#endif
-#if FAST
-//CHECK-FAST: fmul fast float
-//CHECK-FAST: fadd fast float
-#endif
-
-#pragma float_control(precise, on, push)
-                float precise_on FUN(3)
-//CHECK-LABEL: define {{.*}} @_Z10precise_onf{{.*}}
-#if DEFAULT
-//CHECK-DDEFAULT: contract float {{.*}}llvm.fmuladd{{.*}}
-#endif
-#if EBSTRICT
-//CHECK-DEBSTRICT: contract float {{.*}}llvm.fmuladd{{.*}}
-#endif
-#if NOHONOR
-// If precise is pushed then all fast-math should be off!
-//CHECK-NOHONOR: call contract float {{.*}}llvm.fmuladd{{.*}}
-#endif
-#if FAST
-//CHECK-FAST: contract float {{.*}}llvm.fmuladd{{.*}}
-#endif
-
-#pragma float_control(pop)
-                    float precise_pop FUN(3)
-//CHECK-LABEL: define {{.*}} @_Z11precise_popf{{.*}}
-#if DEFAULT
-//CHECK-DDEFAULT: contract float {{.*}}llvm.fmuladd{{.*}}
-#endif
-#if EBSTRICT
-//CHECK-DEBSTRICT: contract float {{.*}}llvm.fmuladd{{.*}}
-#endif
-#if NOHONOR
-//CHECK-NOHONOR: call nnan ninf contract float @llvm.fmuladd{{.*}}
-#endif
-#if FAST
-//CHECK-FAST: fmul fast float
-//CHECK-FAST: fadd fast float
-#endif
-#pragma float_control(precise, off)
-                        float precise_off FUN(4)
-//CHECK-LABEL: define {{.*}} @_Z11precise_offf{{.*}}
-#if DEFAULT
-// Note: precise_off enables fp_contract=fast and the instructions
-// generated do not include the contract flag, although it was enabled
-// in IRBuilder.
-//CHECK-DDEFAULT: fmul fast float
-//CHECK-DDEFAULT: fadd fast float
-#endif
-#if EBSTRICT
-//CHECK-DEBSTRICT: fmul fast float
-//CHECK-DEBSTRICT: fadd fast float
-#endif
-#if NOHONOR
-// fast math should be enabled, and contract should be fast
-//CHECK-NOHONOR: fmul fast float
-//CHECK-NOHONOR: fadd fast float
-#endif
-#if FAST
-//CHECK-FAST: fmul fast float
-//CHECK-FAST: fadd fast float
-#endif
-
-#pragma float_control(precise, on)
-                            float precise_on2 FUN(3)
-//CHECK-LABEL: define {{.*}} @_Z11precise_on2f{{.*}}
-#if DEFAULT
-//CHECK-DDEFAULT: llvm.fmuladd{{.*}}
-#endif
-#if EBSTRICT
-//CHECK-DEBSTRICT: contract float {{.*}}llvm.fmuladd{{.*}}
-#endif
-#if NOHONOR
-// fast math should be off, and contract should be on
-//CHECK-NOHONOR: contract float {{.*}}llvm.fmuladd{{.*}}
-#endif
-#if FAST
-//CHECK-FAST: contract float {{.*}}llvm.fmuladd{{.*}}
-#endif
-
-#pragma float_control(push)
-                                float precise_push FUN(3)
-//CHECK-LABEL: define {{.*}} @_Z12precise_pushf{{.*}}
-#if DEFAULT
-//CHECK-DDEFAULT: llvm.fmuladd{{.*}}
-#endif
-#if EBSTRICT
-//CHECK-DEBSTRICT: contract float {{.*}}llvm.fmuladd{{.*}}
-#endif
-#if NOHONOR
-//CHECK-NOHONOR: contract float {{.*}}llvm.fmuladd{{.*}}
-#endif
-#if FAST
-//CHECK-FAST: contract float {{.*}}llvm.fmuladd{{.*}}
-#endif
-
-#pragma float_control(precise, off)
-                                    float precise_off2 FUN(4)
-//CHECK-LABEL: define {{.*}} @_Z12precise_off2f{{.*}}
-#if DEFAULT
-//CHECK-DDEFAULT: fmul fast float
-//CHECK-DDEFAULT: fadd fast float
-#endif
-#if EBSTRICT
-//CHECK-DEBSTRICT: fmul fast float
-//CHECK-DEBSTRICT: fadd fast float
-#endif
-#if NOHONOR
-// fast math settings since precise is off
-//CHECK-NOHONOR: fmul fast float
-//CHECK-NOHONOR: fadd fast float
-#endif
-#if FAST
-//CHECK-FAST: fmul fast float
-//CHECK-FAST: fadd fast float
-#endif
-
-#pragma float_control(pop)
-                                        float precise_pop2 FUN(3)
-//CHECK-LABEL: define {{.*}} @_Z12precise_pop2f{{.*}}
-#if DEFAULT
-//CHECK-DDEFAULT: llvm.fmuladd{{.*}}
-#endif
-#if EBSTRICT
-//CHECK-DEBSTRICT: contract float {{.*}}llvm.fmuladd{{.*}}
-#endif
-#if NOHONOR
-//CHECK-NOHONOR: contract float {{.*}}llvm.fmuladd{{.*}}
-#endif
-#if FAST
-//CHECK-FAST: contract float {{.*}}llvm.fmuladd{{.*}}
-#endif
-
-#ifndef FAST
-// Rule: precise must be enabled
-#pragma float_control(except, on)
-#endif
-                                            float y();
-class ON {
-  // Settings for top level class initializer revert to command line
-  // source pragma's do not pertain.
-  float z = 2 + y() * 7;
-//CHECK-LABEL: define {{.*}} void @_ZN2ONC2Ev{{.*}}
-#if DEFAULT
-//CHECK-DDEFAULT: call contract float {{.*}}llvm.fmuladd
-#endif
-#if EBSTRICT
-//Currently, same as default [command line options not considered]
-//CHECK-DEBSTRICT: call contract float {{.*}}llvm.fmuladd
-#endif
-#if NOHONOR
-//CHECK-NOHONOR: call nnan ninf contract float @llvm.fmuladd{{.*}}
-#endif
-#if FAST
-//CHECK-FAST: fmul fast float
-//CHECK-FAST: fadd fast float
-#endif
-};
-ON on;
-#pragma float_control(except, off)
-class OFF {
-  float w = 2 + y() * 7;
-//CHECK-LABEL: define {{.*}} void @_ZN3OFFC2Ev{{.*}}
-#if DEFAULT
-//CHECK-DDEFAULT: call contract float {{.*}}llvm.fmuladd
-#endif
-#if EBSTRICT
-//CHECK-DEBSTRICT: call contract float {{.*}}llvm.fmuladd
-#endif
-#if NOHONOR
-//CHECK-NOHONOR: call nnan ninf contract float @llvm.fmuladd{{.*}}
-#endif
-#if FAST
-//CHECK-FAST: fmul fast float
-//CHECK-FAST: fadd fast float
-#endif
-};
-OFF off;

diff  --git a/clang/test/CodeGen/fpconstrained.c b/clang/test/CodeGen/fpconstrained.c
index 902d6b5baf49..0a890e2e702e 100644
--- a/clang/test/CodeGen/fpconstrained.c
+++ b/clang/test/CodeGen/fpconstrained.c
@@ -1,7 +1,7 @@
 // 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=FASTNOCONTRACT
+// 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
@@ -17,7 +17,6 @@ void foo() {
   // STRICTNOEXCEPT: llvm.experimental.constrained.fadd.f32(float %{{.*}}, float %{{.*}}, metadata !"round.dynamic", metadata !"fpexcept.ignore")
   // PRECISE: fadd contract float %{{.*}}, %{{.*}}
   // FAST: fadd fast
-  // FASTNOCONTRACT: fadd reassoc nnan ninf nsz arcp afn float
   f0 = f1 + f2;
 
   // CHECK: ret

diff  --git a/clang/test/CodeGen/fpconstrained.cpp b/clang/test/CodeGen/fpconstrained.cpp
index e914abcc6926..7aa34c98a487 100644
--- a/clang/test/CodeGen/fpconstrained.cpp
+++ b/clang/test/CodeGen/fpconstrained.cpp
@@ -1,7 +1,7 @@
 // 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=FASTNOCONTRACT
+// 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
@@ -20,17 +20,16 @@ float f0, f1, f2;
   // 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
-    // FASTNOCONTRACT: fadd reassoc nnan ninf nsz arcp afn float
-    f0 = f1 + f2;
+  // 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
+  // CHECK: ret void
   }
   }
   

diff  --git a/clang/test/CodeGenOpenCL/relaxed-fpmath.cl b/clang/test/CodeGenOpenCL/relaxed-fpmath.cl
index 757a2f410dc2..7676ee164ce4 100644
--- a/clang/test/CodeGenOpenCL/relaxed-fpmath.cl
+++ b/clang/test/CodeGenOpenCL/relaxed-fpmath.cl
@@ -8,12 +8,12 @@
 float spscalardiv(float a, float b) {
   // CHECK: @spscalardiv(
 
-  // NORMAL: fdiv contract float
+  // NORMAL: fdiv float
   // FAST: fdiv fast float
-  // FINITE: fdiv nnan ninf contract float
-  // UNSAFE: fdiv nnan nsz contract float
-  // MAD: fdiv contract float
-  // NOSIGNED: fdiv nsz contract float
+  // FINITE: fdiv nnan ninf float
+  // UNSAFE: fdiv nnan nsz float
+  // MAD: fdiv float
+  // NOSIGNED: fdiv nsz float
   return a / b;
 }
 // CHECK: attributes

diff  --git a/clang/test/CodeGenOpenCL/single-precision-constant.cl b/clang/test/CodeGenOpenCL/single-precision-constant.cl
index 061025d7a893..6ff7bd1bde2d 100644
--- a/clang/test/CodeGenOpenCL/single-precision-constant.cl
+++ b/clang/test/CodeGenOpenCL/single-precision-constant.cl
@@ -1,6 +1,6 @@
 // RUN: %clang_cc1 %s -cl-single-precision-constant -emit-llvm -o - | FileCheck %s
 
 float fn(float f) {
-  // CHECK: tail call contract float @llvm.fmuladd.f32(float %f, float 2.000000e+00, float 1.000000e+00)
+  // CHECK: tail call float @llvm.fmuladd.f32(float %f, float 2.000000e+00, float 1.000000e+00)
   return f*2. + 1.;
 }

diff  --git a/clang/test/Headers/nvptx_device_math_sin.c b/clang/test/Headers/nvptx_device_math_sin.c
index 83de8b02444a..75b998d59006 100644
--- a/clang/test/Headers/nvptx_device_math_sin.c
+++ b/clang/test/Headers/nvptx_device_math_sin.c
@@ -1,8 +1,8 @@
 // REQUIRES: nvptx-registered-target
 // RUN: %clang_cc1 -x c -internal-isystem %S/Inputs/include -fopenmp -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm-bc %s -o %t-ppc-host.bc
 // RUN: %clang_cc1 -x c -include __clang_openmp_device_functions.h -internal-isystem %S/../../lib/Headers/openmp_wrappers -internal-isystem %S/Inputs/include -fopenmp -triple nvptx64-nvidia-cuda -aux-triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix=SLOW
-// RUN: %clang_cc1 -x c -internal-isystem %S/Inputs/include -fopenmp -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm-bc %s -o %t-ppc-host.bc -ffast-math -ffp-contract=fast
-// RUN: %clang_cc1 -x c -include __clang_openmp_device_functions.h -internal-isystem %S/../../lib/Headers/openmp_wrappers -internal-isystem %S/Inputs/include -fopenmp -triple nvptx64-nvidia-cuda -aux-triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - -ffast-math -ffp-contract=fast | FileCheck %s --check-prefix=FAST
+// RUN: %clang_cc1 -x c -internal-isystem %S/Inputs/include -fopenmp -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm-bc %s -o %t-ppc-host.bc -ffast-math
+// RUN: %clang_cc1 -x c -include __clang_openmp_device_functions.h -internal-isystem %S/../../lib/Headers/openmp_wrappers -internal-isystem %S/Inputs/include -fopenmp -triple nvptx64-nvidia-cuda -aux-triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - -ffast-math | FileCheck %s --check-prefix=FAST
 // expected-no-diagnostics
 
 #include <math.h>

diff  --git a/clang/test/Headers/nvptx_device_math_sin.cpp b/clang/test/Headers/nvptx_device_math_sin.cpp
index ba5f6fc483d9..e4d25b40b1b9 100644
--- a/clang/test/Headers/nvptx_device_math_sin.cpp
+++ b/clang/test/Headers/nvptx_device_math_sin.cpp
@@ -1,8 +1,8 @@
 // REQUIRES: nvptx-registered-target
 // RUN: %clang_cc1 -x c++ -internal-isystem %S/Inputs/include -fopenmp -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm-bc %s -o %t-ppc-host.bc
 // RUN: %clang_cc1 -x c++ -include __clang_openmp_device_functions.h -internal-isystem %S/../../lib/Headers/openmp_wrappers -internal-isystem %S/Inputs/include -fopenmp -triple nvptx64-nvidia-cuda -aux-triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix=SLOW
-// RUN: %clang_cc1 -x c++ -internal-isystem %S/Inputs/include -fopenmp -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm-bc %s -o %t-ppc-host.bc -ffast-math -ffp-contract=fast
-// RUN: %clang_cc1 -x c++ -include __clang_openmp_device_functions.h -internal-isystem %S/../../lib/Headers/openmp_wrappers -internal-isystem %S/Inputs/include -fopenmp -triple nvptx64-nvidia-cuda -aux-triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - -ffast-math -ffp-contract=fast | FileCheck %s --check-prefix=FAST
+// RUN: %clang_cc1 -x c++ -internal-isystem %S/Inputs/include -fopenmp -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm-bc %s -o %t-ppc-host.bc -ffast-math
+// RUN: %clang_cc1 -x c++ -include __clang_openmp_device_functions.h -internal-isystem %S/../../lib/Headers/openmp_wrappers -internal-isystem %S/Inputs/include -fopenmp -triple nvptx64-nvidia-cuda -aux-triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - -ffast-math | FileCheck %s --check-prefix=FAST
 // expected-no-diagnostics
 
 #include <cmath>

diff  --git a/clang/test/PCH/pragma-floatcontrol.c b/clang/test/PCH/pragma-floatcontrol.c
deleted file mode 100644
index a0918dd53597..000000000000
--- a/clang/test/PCH/pragma-floatcontrol.c
+++ /dev/null
@@ -1,55 +0,0 @@
-// Test this without pch.
-// RUN: %clang_cc1 %s -include %s -verify -fsyntax-only -DSET
-// RUN: %clang_cc1 %s -include %s -verify -fsyntax-only -DPUSH
-// RUN: %clang_cc1 %s -include %s -verify -fsyntax-only -DPUSH_POP
-
-// Test with pch.
-// RUN: %clang_cc1 %s -DSET -emit-pch -o %t
-// RUN: %clang_cc1 %s -DSET -include-pch %t -emit-llvm -o - | FileCheck --check-prefix=CHECK-EBSTRICT %s
-// RUN: %clang_cc1 %s -DPUSH -emit-pch -o %t
-// RUN: %clang_cc1 %s -DPUSH -verify -include-pch %t
-// RUN: %clang_cc1 %s -DPUSH_POP -emit-pch -o %t
-// RUN: %clang_cc1 %s -DPUSH_POP -verify -include-pch %t
-
-#ifndef HEADER
-#define HEADER
-
-#ifdef SET
-#pragma float_control(except, on)
-#endif
-
-#ifdef PUSH
-#pragma float_control(precise, on)
-#pragma float_control(push)
-#pragma float_control(precise, off)
-#endif
-
-#ifdef PUSH_POP
-#pragma float_control(precise, on, push)
-#pragma float_control(push)
-#pragma float_control(pop)
-#endif
-#else
-
-#ifdef SET
-float fun(float a, float b) {
-  // CHECK-LABEL: define float @fun{{.*}}
-  //CHECK-EBSTRICT: llvm.experimental.constrained.fmul{{.*}}tonearest{{.*}}strict
-  //CHECK-EBSTRICT: llvm.experimental.constrained.fadd{{.*}}tonearest{{.*}}strict
-  return a * b + 2;
-}
-#pragma float_control(pop) // expected-warning {{#pragma float_control(pop, ...) failed: stack empty}}
-#pragma float_control(pop) // expected-warning {{#pragma float_control(pop, ...) failed: stack empty}}
-#endif
-
-#ifdef PUSH
-#pragma float_control(pop)
-#pragma float_control(pop) // expected-warning {{#pragma float_control(pop, ...) failed: stack empty}}
-#endif
-
-#ifdef PUSH_POP
-#pragma float_control(pop)
-#pragma float_control(pop) // expected-warning {{#pragma float_control(pop, ...) failed: stack empty}}
-#endif
-
-#endif //ifndef HEADER

diff  --git a/clang/test/Parser/fp-floatcontrol-syntax.cpp b/clang/test/Parser/fp-floatcontrol-syntax.cpp
deleted file mode 100644
index a0e0b020ddb6..000000000000
--- a/clang/test/Parser/fp-floatcontrol-syntax.cpp
+++ /dev/null
@@ -1,63 +0,0 @@
-// RUN: %clang_cc1 -fsyntax-only -verify -DCHECK_ERROR %s
-
-float function_scope(float a) {
-#pragma float_control(precise, on) junk // expected-warning {{extra tokens at end of '#pragma float_control' - ignored}}
-  return a;
-}
-
-#ifdef CHECK_ERROR
-#pragma float_control(push)
-#pragma float_control(pop)
-#pragma float_control(precise, on, push)
-void check_stack() {
-#pragma float_control(push)                   // expected-error {{can only appear at file scope}}
-#pragma float_control(pop)                    // expected-error {{can only appear at file scope}}
-#pragma float_control(precise, on, push)      // expected-error {{can only appear at file scope}}
-#pragma float_control(except, on, push)       // expected-error {{can only appear at file scope}}
-#pragma float_control(except, on, push, junk) // expected-error {{float_control is malformed}}
-  return;
-}
-#endif
-
-// RUN: %clang -c -fsyntax-only %s -DDEFAULT -Xclang -verify
-// RUN: %clang -c -fsyntax-only %s -ffp-model=precise -DPRECISE -Xclang -verify
-// RUN: %clang -c -fsyntax-only %s -ffp-model=strict -DSTRICT -Xclang -verify
-// RUN: %clang -c -fsyntax-only %s -ffp-model=fast -DFAST -Xclang -verify
-double a = 0.0;
-double b = 1.0;
-
-//FIXME At some point this warning will be removed, until then
-//      document the warning
-#ifdef FAST
-// expected-warning at +1{{pragma STDC FENV_ACCESS ON is not supported, ignoring pragma}}
-#pragma STDC FENV_ACCESS ON // expected-error{{'#pragma STDC FENV_ACCESS ON' is illegal when precise is disabled}}
-#else
-#pragma STDC FENV_ACCESS ON // expected-warning{{pragma STDC FENV_ACCESS ON is not supported, ignoring pragma}}
-#endif
-#ifdef STRICT
-#pragma float_control(precise, off) // expected-error {{'#pragma float_control(precise, off)' is illegal when except is enabled}}
-#else
-#pragma float_control(precise, off) // expected-error {{'#pragma float_control(precise, off)' is illegal when fenv_access is enabled}}
-#endif
-//RUN -ffp-model=strict
-//error: '#pragma float_control(precise, off)' is illegal when except is enabled
-//with default, fast or precise: no errors
-
-#pragma float_control(precise, on)
-#pragma float_control(except, on) // OK
-#ifndef STRICT
-#pragma float_control(except, on)
-#pragma float_control(precise, off) // expected-error {{'#pragma float_control(precise, off)' is illegal when except is enabled}}
-#endif
-int main() {
-#ifdef STRICT
-#pragma float_control(precise, off) // expected-error {{'#pragma float_control(precise, off)' is illegal when except is enabled}}
-#else
-#pragma float_control(precise, off) // expected-error {{'#pragma float_control(precise, off)' is illegal when except is enabled}}
-#endif
-#pragma float_control(except, on)
-  //  error: '#pragma float_control(except, on)' is illegal when precise is disabled
-  double x = b / a; // only used for fp flag setting
-  if (a == a)       // only used for fp flag setting
-    return 0;       //(int)x;
-}

diff  --git a/llvm/include/llvm/IR/IRBuilder.h b/llvm/include/llvm/IR/IRBuilder.h
index 6e431bc3ac0f..8a9312614875 100644
--- a/llvm/include/llvm/IR/IRBuilder.h
+++ b/llvm/include/llvm/IR/IRBuilder.h
@@ -244,8 +244,6 @@ class IRBuilderBase {
   /// Get the flags to be applied to created floating point ops
   FastMathFlags getFastMathFlags() const { return FMF; }
 
-  FastMathFlags &getFastMathFlags() { return FMF; }
-
   /// Clear the fast-math flags.
   void clearFastMathFlags() { FMF.clear(); }
 
@@ -334,16 +332,10 @@ class IRBuilderBase {
     IRBuilderBase &Builder;
     FastMathFlags FMF;
     MDNode *FPMathTag;
-    bool IsFPConstrained;
-    fp::ExceptionBehavior DefaultConstrainedExcept;
-    RoundingMode DefaultConstrainedRounding;
 
   public:
     FastMathFlagGuard(IRBuilderBase &B)
-        : Builder(B), FMF(B.FMF), FPMathTag(B.DefaultFPMathTag),
-          IsFPConstrained(B.IsFPConstrained),
-          DefaultConstrainedExcept(B.DefaultConstrainedExcept),
-          DefaultConstrainedRounding(B.DefaultConstrainedRounding) {}
+        : Builder(B), FMF(B.FMF), FPMathTag(B.DefaultFPMathTag) {}
 
     FastMathFlagGuard(const FastMathFlagGuard &) = delete;
     FastMathFlagGuard &operator=(const FastMathFlagGuard &) = delete;
@@ -351,9 +343,6 @@ class IRBuilderBase {
     ~FastMathFlagGuard() {
       Builder.FMF = FMF;
       Builder.DefaultFPMathTag = FPMathTag;
-      Builder.IsFPConstrained = IsFPConstrained;
-      Builder.DefaultConstrainedExcept = DefaultConstrainedExcept;
-      Builder.DefaultConstrainedRounding = DefaultConstrainedRounding;
     }
   };
 


        


More information about the cfe-commits mailing list