aboutsummaryrefslogtreecommitdiff
path: root/lib/Driver/Tools.cpp
diff options
context:
space:
mode:
authorChandler Carruth <chandlerc@gmail.com>2012-01-02 14:19:45 +0000
committerChandler Carruth <chandlerc@gmail.com>2012-01-02 14:19:45 +0000
commitabf07a7fb669dcb74040eef948d61dfe3c59ff17 (patch)
tree07bd4265036179237cb2cc51c788e48912716537 /lib/Driver/Tools.cpp
parent1e8a0678df724a28fe47e0034246f2604056a278 (diff)
Fix PR11685 by implementing -ffast-math and its various friends in the
Clang driver. This involves a bunch of silly option parsing code to try to carefully emulate GCC's options. Currently, this takes a conservative approach, and unless all of the unsafe optimizations are enabled, none of them are. The fine grained control doesn't seem particularly useful. If it ever becomes useful, we can add that to LLVM first, and then expose it here. This also fixes a few tiny bugs in the flag management around -fhonor-infinities and -fhonor-nans; the flags now form proper sets both for enabling and disabling, with the last flag winning. I've also implemented a moderately terrifying GCC feature where a language change is also provided by the '-ffast-math' flag by defining the __FAST_MATH__ preprocessor macro. This feature is tracked and serialized in the frontend but it isn't used yet. A subsequent patch will add the preprocessor macro and tests for it. I've manually tested that codegen appears to respect this, but I've not dug in enough to see if there is an easy way to test codegen options w/o relying on the particulars of LLVM's optimizations. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@147434 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Driver/Tools.cpp')
-rw-r--r--lib/Driver/Tools.cpp102
1 files changed, 84 insertions, 18 deletions
diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp
index 41ff1102bf..f678667c33 100644
--- a/lib/Driver/Tools.cpp
+++ b/lib/Driver/Tools.cpp
@@ -1435,18 +1435,90 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
getToolChain().IsStrictAliasingDefault()))
CmdArgs.push_back("-relaxed-aliasing");
- // Handle -f{no-}honor-infinities, -f{no-}honor-nans, and -ffinite-math-only.
- bool HonorInfinities = Args.hasFlag(options::OPT_fhonor_infinities,
- options::OPT_fno_honor_infinities);
- bool HonorNaNs = Args.hasFlag(options::OPT_fhonor_nans,
- options::OPT_fno_honor_nans);
- if (Args.hasArg(options::OPT_ffinite_math_only))
- HonorInfinities = HonorNaNs = false;
- if (!HonorInfinities)
- CmdArgs.push_back("-menable-no-infs");
- if (!HonorNaNs)
- CmdArgs.push_back("-menable-no-nans");
-
+ // Handle various floating point optimization flags, mapping them to the
+ // appropriate LLVM code generation flags. The pattern for all of these is to
+ // default off the codegen optimizations, and if any flag enables them and no
+ // flag disables them after the flag enabling them, enable the codegen
+ // optimization. This is complicated by several "umbrella" flags.
+ if (Arg *A = Args.getLastArg(options::OPT_ffast_math,
+ options::OPT_ffinite_math_only,
+ options::OPT_fno_finite_math_only,
+ options::OPT_fhonor_infinities,
+ options::OPT_fno_honor_infinities))
+ if (A->getOption().getID() != options::OPT_fno_finite_math_only &&
+ A->getOption().getID() != options::OPT_fhonor_infinities)
+ CmdArgs.push_back("-menable-no-infs");
+ if (Arg *A = Args.getLastArg(options::OPT_ffast_math,
+ options::OPT_ffinite_math_only,
+ options::OPT_fno_finite_math_only,
+ options::OPT_fhonor_nans,
+ options::OPT_fno_honor_nans))
+ if (A->getOption().getID() != options::OPT_fno_finite_math_only &&
+ A->getOption().getID() != options::OPT_fhonor_nans)
+ CmdArgs.push_back("-menable-no-nans");
+
+ // -fno-math-errno is default.
+ bool MathErrno = false;
+ if (Arg *A = Args.getLastArg(options::OPT_ffast_math,
+ options::OPT_fmath_errno,
+ options::OPT_fno_math_errno)) {
+ if (A->getOption().getID() == options::OPT_fmath_errno) {
+ CmdArgs.push_back("-fmath-errno");
+ MathErrno = true;
+ }
+ }
+
+ // There are several flags which require disabling very specific
+ // optimizations. Any of these being disabled forces us to turn off the
+ // entire set of LLVM optimizations, so collect them through all the flag
+ // madness.
+ bool AssociativeMath = false;
+ if (Arg *A = Args.getLastArg(options::OPT_ffast_math,
+ options::OPT_funsafe_math_optimizations,
+ options::OPT_fno_unsafe_math_optimizations,
+ options::OPT_fassociative_math,
+ options::OPT_fno_associative_math))
+ if (A->getOption().getID() != options::OPT_fno_unsafe_math_optimizations &&
+ A->getOption().getID() != options::OPT_fno_associative_math)
+ AssociativeMath = true;
+ bool ReciprocalMath = false;
+ if (Arg *A = Args.getLastArg(options::OPT_ffast_math,
+ options::OPT_funsafe_math_optimizations,
+ options::OPT_fno_unsafe_math_optimizations,
+ options::OPT_freciprocal_math,
+ options::OPT_fno_reciprocal_math))
+ if (A->getOption().getID() != options::OPT_fno_unsafe_math_optimizations &&
+ A->getOption().getID() != options::OPT_fno_reciprocal_math)
+ ReciprocalMath = true;
+ bool SignedZeros = true;
+ if (Arg *A = Args.getLastArg(options::OPT_ffast_math,
+ options::OPT_funsafe_math_optimizations,
+ options::OPT_fno_unsafe_math_optimizations,
+ options::OPT_fsigned_zeros,
+ options::OPT_fno_signed_zeros))
+ if (A->getOption().getID() != options::OPT_fno_unsafe_math_optimizations &&
+ A->getOption().getID() != options::OPT_fsigned_zeros)
+ SignedZeros = false;
+ bool TrappingMath = true;
+ if (Arg *A = Args.getLastArg(options::OPT_ffast_math,
+ options::OPT_funsafe_math_optimizations,
+ options::OPT_fno_unsafe_math_optimizations,
+ options::OPT_ftrapping_math,
+ options::OPT_fno_trapping_math))
+ if (A->getOption().getID() != options::OPT_fno_unsafe_math_optimizations &&
+ A->getOption().getID() != options::OPT_ftrapping_math)
+ TrappingMath = false;
+ if (!MathErrno && AssociativeMath && ReciprocalMath && !SignedZeros &&
+ !TrappingMath)
+ CmdArgs.push_back("-menable-unsafe-fp-math");
+
+ // We separately look for the '-ffast-math' flag, and if we find it, tell the
+ // frontend to provide the appropriate preprocessor macros. This is distinct
+ // from enabling any optimizations as it induces a language change which must
+ // survive serialization and deserialization, etc.
+ if (Args.hasArg(options::OPT_ffast_math))
+ CmdArgs.push_back("-ffast-math");
+
// Decide whether to use verbose asm. Verbose assembly is the default on
// toolchains which have the integrated assembler on by default.
bool IsVerboseAsmDefault = getToolChain().IsIntegratedAssemblerDefault();
@@ -1548,12 +1620,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
!getToolChain().getTriple().isOSDarwin()))
CmdArgs.push_back("-momit-leaf-frame-pointer");
- // -fno-math-errno is default.
- if (Args.hasFlag(options::OPT_fmath_errno,
- options::OPT_fno_math_errno,
- false))
- CmdArgs.push_back("-fmath-errno");
-
// Explicitly error on some things we know we don't support and can't just
// ignore.
types::ID InputType = Inputs[0].getType();