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.