diff --git a/lib/Driver/ToolChains/Clang.cpp b/lib/Driver/ToolChains/Clang.cpp
index 813ad3c5a816bac657105dd549052c974377fdd9..58ab070fb50636e701bd4cd4f58d70f2f3be0755 100644
--- a/lib/Driver/ToolChains/Clang.cpp
+++ b/lib/Driver/ToolChains/Clang.cpp
@@ -1968,6 +1968,165 @@ static void CollectArgsForIntegratedAssembler(Compilation &C,
   }
 }
 
+static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
+                                       bool OFastEnabled, const ArgList &Args,
+                                       ArgStringList &CmdArgs) {
+  // Handle various floating point optimization flags, mapping them to the
+  // appropriate LLVM code generation flags. This is complicated by several
+  // "umbrella" flags, so we do this by stepping through the flags incrementally
+  // adjusting what we think is enabled/disabled, then at the end settting the
+  // LLVM flags based on the final state.
+  bool HonorINFs = true;
+  bool HonorNaNs = true;
+  // -fmath-errno is the default on some platforms, e.g. BSD-derived OSes.
+  bool MathErrno = TC.IsMathErrnoDefault();
+  bool AssociativeMath = false;
+  bool ReciprocalMath = false;
+  bool SignedZeros = true;
+  bool TrappingMath = true;
+  StringRef DenormalFPMath = "";
+  StringRef FPContract = "";
+
+  for (const Arg *A : Args) {
+    switch (A->getOption().getID()) {
+    // If this isn't an FP option skip the claim below
+    default: continue;
+
+    // Options controlling individual features
+    case options::OPT_fhonor_infinities:    HonorINFs = true;         break;
+    case options::OPT_fno_honor_infinities: HonorINFs = false;        break;
+    case options::OPT_fhonor_nans:          HonorNaNs = true;         break;
+    case options::OPT_fno_honor_nans:       HonorNaNs = false;        break;
+    case options::OPT_fmath_errno:          MathErrno = true;         break;
+    case options::OPT_fno_math_errno:       MathErrno = false;        break;
+    case options::OPT_fassociative_math:    AssociativeMath = true;   break;
+    case options::OPT_fno_associative_math: AssociativeMath = false;  break;
+    case options::OPT_freciprocal_math:     ReciprocalMath = true;    break;
+    case options::OPT_fno_reciprocal_math:  ReciprocalMath = false;   break;
+    case options::OPT_fsigned_zeros:        SignedZeros = true;       break;
+    case options::OPT_fno_signed_zeros:     SignedZeros = false;      break;
+    case options::OPT_ftrapping_math:       TrappingMath = true;      break;
+    case options::OPT_fno_trapping_math:    TrappingMath = false;     break;
+
+    case options::OPT_fdenormal_fp_math_EQ:
+      DenormalFPMath = A->getValue();
+      break;
+
+    // Validate and pass through -fp-contract option.
+    case options::OPT_ffp_contract: {
+      StringRef Val = A->getValue();
+      if (Val == "fast" || Val == "on" || Val == "off")
+        FPContract = Val;
+      else
+        D.Diag(diag::err_drv_unsupported_option_argument)
+            << A->getOption().getName() << Val;
+      break;
+    }
+
+    case options::OPT_ffinite_math_only:
+      HonorINFs = false;
+      HonorNaNs = false;
+      break;
+    case options::OPT_fno_finite_math_only:
+      HonorINFs = true;
+      HonorNaNs = true;
+      break;
+
+    case options::OPT_funsafe_math_optimizations:
+      AssociativeMath = true;
+      ReciprocalMath = true;
+      SignedZeros = false;
+      TrappingMath = false;
+      break;
+    case options::OPT_fno_unsafe_math_optimizations:
+      AssociativeMath = false;
+      ReciprocalMath = false;
+      SignedZeros = true;
+      TrappingMath = true;
+      // -fno_unsafe_math_optimizations restores default denormal handling
+      DenormalFPMath = "";
+      break;
+
+    case options::OPT_Ofast:
+      // If -Ofast is the optimization level, then -ffast-math should be enabled
+      if (!OFastEnabled)
+        continue;
+      LLVM_FALLTHROUGH;
+    case options::OPT_ffast_math:
+      HonorINFs = false;
+      HonorNaNs = false;
+      MathErrno = false;
+      AssociativeMath = true;
+      ReciprocalMath = true;
+      SignedZeros = false;
+      TrappingMath = false;
+      // If fast-math is set then set the fp-contract mode to fast.
+      FPContract = "fast";
+      break;
+    case options::OPT_fno_fast_math:
+      HonorINFs = true;
+      HonorNaNs = true;
+      // Turning on -ffast-math (with either flag) removes the need for
+      // MathErrno. However, turning *off* -ffast-math merely restores the
+      // toolchain default (which may be false).
+      MathErrno = TC.IsMathErrnoDefault();
+      AssociativeMath = false;
+      ReciprocalMath = false;
+      SignedZeros = true;
+      TrappingMath = true;
+      // -fno_fast_math restores default denormal and fpcontract handling
+      DenormalFPMath = "";
+      FPContract = "";
+      break;
+    }
+
+    // If we handled this option claim it
+    A->claim();
+  }
+
+  if (!HonorINFs)
+    CmdArgs.push_back("-menable-no-infs");
+
+  if (!HonorNaNs)
+    CmdArgs.push_back("-menable-no-nans");
+
+  if (MathErrno)
+    CmdArgs.push_back("-fmath-errno");
+
+  if (!MathErrno && AssociativeMath && ReciprocalMath && !SignedZeros &&
+      !TrappingMath)
+    CmdArgs.push_back("-menable-unsafe-fp-math");
+
+  if (!SignedZeros)
+    CmdArgs.push_back("-fno-signed-zeros");
+
+  if (ReciprocalMath)
+    CmdArgs.push_back("-freciprocal-math");
+
+  if (!TrappingMath)
+    CmdArgs.push_back("-fno-trapping-math");
+
+  if (!DenormalFPMath.empty())
+    CmdArgs.push_back(
+        Args.MakeArgString("-fdenormal-fp-math=" + DenormalFPMath));
+
+  if (!FPContract.empty())
+    CmdArgs.push_back(Args.MakeArgString("-ffp-contract=" + FPContract));
+
+  ParseMRecip(D, Args, CmdArgs);
+
+  // -ffast-math enables the __FAST_MATH__ preprocessor macro, but check for the
+  // individual features enabled by -ffast-math instead of the option itself as
+  // that's consistent with gcc's behaviour.
+  if (!HonorINFs && !HonorNaNs && !MathErrno && AssociativeMath &&
+      ReciprocalMath && !SignedZeros && !TrappingMath)
+    CmdArgs.push_back("-ffast-math");
+
+  // Handle __FINITE_MATH_ONLY__ similarly.
+  if (!HonorINFs && !HonorNaNs)
+    CmdArgs.push_back("-ffinite-math-only");
+}
+
 static void RenderAnalyzerOptions(const ArgList &Args, ArgStringList &CmdArgs,
                                   const llvm::Triple &Triple,
                                   const InputInfo &Input) {
@@ -2915,160 +3074,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
   if (Args.hasArg(options::OPT_fsplit_stack))
     CmdArgs.push_back("-split-stacks");
 
-  // Handle various floating point optimization flags, mapping them to the
-  // appropriate LLVM code generation flags. This is complicated by several
-  // "umbrella" flags, so we do this by stepping through the flags incrementally
-  // adjusting what we think is enabled/disabled, then at the end settting the
-  // LLVM flags based on the final state.
-  bool HonorInfs = true;
-  bool HonorNans = true;
-  // -fmath-errno is the default on some platforms, e.g. BSD-derived OSes.
-  bool MathErrno = getToolChain().IsMathErrnoDefault();
-  bool AssociativeMath = false;
-  bool ReciprocalMath = false;
-  bool SignedZeros = true;
-  bool TrappingMath = true;
-  StringRef DenormalFpMath = "";
-  StringRef FpContract = "";
-
-  for (Arg *A : Args) {
-    switch (A->getOption().getID()) {
-    // If this isn't an FP option skip the claim below
-    default:
-      continue;
-
-    // Options controlling individual features
-    case options::OPT_fhonor_infinities:    HonorInfs = true;        break;
-    case options::OPT_fno_honor_infinities: HonorInfs = false;       break;
-    case options::OPT_fhonor_nans:          HonorNans = true;        break;
-    case options::OPT_fno_honor_nans:       HonorNans = false;       break;
-    case options::OPT_fmath_errno:          MathErrno = true;        break;
-    case options::OPT_fno_math_errno:       MathErrno = false;       break;
-    case options::OPT_fassociative_math:    AssociativeMath = true;  break;
-    case options::OPT_fno_associative_math: AssociativeMath = false; break;
-    case options::OPT_freciprocal_math:     ReciprocalMath = true;   break;
-    case options::OPT_fno_reciprocal_math:  ReciprocalMath = false;  break;
-    case options::OPT_fsigned_zeros:        SignedZeros = true;      break;
-    case options::OPT_fno_signed_zeros:     SignedZeros = false;     break;
-    case options::OPT_ftrapping_math:       TrappingMath = true;     break;
-    case options::OPT_fno_trapping_math:    TrappingMath = false;    break;
-
-    case options::OPT_fdenormal_fp_math_EQ:
-      DenormalFpMath = A->getValue();
-      break;
-
-    // Validate and pass through -fp-contract option.
-    case options::OPT_ffp_contract: {
-      StringRef Val = A->getValue();
-      if (Val == "fast" || Val == "on" || Val == "off") {
-        FpContract = Val;
-      } else {
-        D.Diag(diag::err_drv_unsupported_option_argument)
-            << A->getOption().getName() << Val;
-      }
-      break;
-    }
-
-    case options::OPT_ffinite_math_only:
-      HonorInfs = false;
-      HonorNans = false;
-      break;
-    case options::OPT_fno_finite_math_only:
-      HonorInfs = true;
-      HonorNans = true;
-      break;
-
-    case options::OPT_funsafe_math_optimizations:
-      AssociativeMath = true;
-      ReciprocalMath = true;
-      SignedZeros = false;
-      TrappingMath = false;
-      break;
-    case options::OPT_fno_unsafe_math_optimizations:
-      AssociativeMath = false;
-      ReciprocalMath = false;
-      SignedZeros = true;
-      TrappingMath = true;
-      // -fno_unsafe_math_optimizations restores default denormal handling
-      DenormalFpMath = "";
-      break;
-
-    case options::OPT_Ofast:
-      // If -Ofast is the optimization level, then -ffast-math should be enabled
-      if (!OFastEnabled)
-        continue;
-      LLVM_FALLTHROUGH;
-    case options::OPT_ffast_math:
-      HonorInfs = false;
-      HonorNans = false;
-      MathErrno = false;
-      AssociativeMath = true;
-      ReciprocalMath = true;
-      SignedZeros = false;
-      TrappingMath = false;
-      // If fast-math is set then set the fp-contract mode to fast.
-      FpContract = "fast";
-      break;
-    case options::OPT_fno_fast_math:
-      HonorInfs = true;
-      HonorNans = true;
-      // Turning on -ffast-math (with either flag) removes the need for
-      // MathErrno. However, turning *off* -ffast-math merely restores the
-      // toolchain default (which may be false).
-      MathErrno = getToolChain().IsMathErrnoDefault();
-      AssociativeMath = false;
-      ReciprocalMath = false;
-      SignedZeros = true;
-      TrappingMath = true;
-      // -fno_fast_math restores default denormal and fpcontract handling
-      DenormalFpMath = "";
-      FpContract = "";
-      break;
-    }
-    // If we handled this option claim it
-    A->claim();
-  }
-
-  if (!HonorInfs)
-    CmdArgs.push_back("-menable-no-infs");
-
-  if (!HonorNans)
-    CmdArgs.push_back("-menable-no-nans");
-
-  if (MathErrno)
-    CmdArgs.push_back("-fmath-errno");
-
-  if (!MathErrno && AssociativeMath && ReciprocalMath && !SignedZeros &&
-      !TrappingMath)
-    CmdArgs.push_back("-menable-unsafe-fp-math");
-
-  if (!SignedZeros)
-    CmdArgs.push_back("-fno-signed-zeros");
-
-  if (ReciprocalMath)
-    CmdArgs.push_back("-freciprocal-math");
-
-  if (!TrappingMath)
-    CmdArgs.push_back("-fno-trapping-math");
-
-  if (!DenormalFpMath.empty())
-    CmdArgs.push_back(Args.MakeArgString("-fdenormal-fp-math="+DenormalFpMath));
-
-  if (!FpContract.empty())
-    CmdArgs.push_back(Args.MakeArgString("-ffp-contract="+FpContract));
-
-  ParseMRecip(D, Args, CmdArgs);
-
-  // -ffast-math enables the __FAST_MATH__ preprocessor macro, but check for the
-  // individual features enabled by -ffast-math instead of the option itself as
-  // that's consistent with gcc's behaviour.
-  if (!HonorInfs && !HonorNans && !MathErrno && AssociativeMath &&
-      ReciprocalMath && !SignedZeros && !TrappingMath)
-    CmdArgs.push_back("-ffast-math");
-
-  // Handle __FINITE_MATH_ONLY__ similarly.
-  if (!HonorInfs && !HonorNans)
-    CmdArgs.push_back("-ffinite-math-only");
+  RenderFloatingPointOptions(getToolChain(), D, OFastEnabled, Args, CmdArgs);
 
   // Decide whether to use verbose asm. Verbose assembly is the default on
   // toolchains which have the integrated assembler on by default.